Jump to content

How to use GUISetAccelerators for multiply language layouts? - (Moved)


Go to solution Solved by ioa747,

Recommended Posts

I broke my mind and need help.ūüėį I have dummy buttons and real menu items simultaneously like this:

Dim $aMainForm_AccelTable[5][2] = [["^s", $SubMenuItemSave], _          ; Ctrl+S
                                   ["^+s", $SubMenuItemSaveAs], _       ; Ctrl+Shift+S
                                   ["^o", $SubMenuItemOpen], _          ; Ctrl+O
                                   ["+!s", $SubMenuItemStartStop], _    ; Shift-Alt-S
                                   ["{ENTER}", $FakeGUIEnter]]          ; Enter

I use GUISetAccelerators to initialize hotkeys like CTRL+S for Save, CTRL+O for Open, and so on. It works perfectly if your system language is English. However, if it is Cyrillic or another non-Latin script, GUISetAccelerators may return 0, meaning that if your system has more than one language, the first initialization will be risky.

One solution is to check if the keyboard layout is set to EN using _WinAPI_SetKeyboardLayout and set it to EN if it is not. However, if the user doesn't use EN at all, I need to use local alphabetic characters for hotkeys, or else all the hotkeys in the set accelerators array will be lost (like F1, for example).

I imagine that one solution is to use the ASCII table and choose the right character based on the keyboard layout. But this approach may not be very elegant. Does anyone know of a simpler and more elegant solution?

Link to post
Share on other sites

Thank you for your help. I see that your solution was to switch the language if it is not English and then return to the previous language. I tried a similar approach, but in my case, it is not useful since my app is a simple text editor, and I don't know when the user will be using hotkeys with their local language.

However, I think I may have found a solution in Key Mapping. Can you investigate _WinAPI_MapVirtualKey?

Link to post
Share on other sites
  • Moderators

Moved to the appropriate AutoIt General Help and Support forum, as the Developer General Discussion forum very clearly states:

Quote

General development and scripting discussions.


Do not create AutoIt-related topics here, use the AutoIt General Help and Support or AutoIt Technical Discussion forums.

Moderation Team

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to post
Share on other sites

Bingo! _WinAPI_RegisterHotKey - works with virtual-key codes regardless of keyboard layout

#include <APISysConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

Opt('TrayAutoPause', 0)

OnAutoItExitRegister('OnAutoItExit')

Local $hWnd = GUICreate('Test message' & StringReplace(@ScriptName, '.au3', '()'))

GUIRegisterMsg($WM_HOTKEY, 'WM_HOTKEY')

; https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
$VK_S = 0x53        ; Virtual-key code for S key
$VK_O = 0x4F        ; Virtual-key code for O key
$VK_ESCAPE = 0x1B   ; Virtual-key code for Esc key

#cs
<APIConstants.au3> or <APISysConstants.au3>
$MOD_ALT = 0x0001
$MOD_CONTROL = 0x0002
$MOD_NOREPEAT = 0x4000
$MOD_SHIFT = 0x0004
$MOD_WIN = 0x0008
#ce

_WinAPI_RegisterHotKey($hWnd, 1, $MOD_CONTROL, $VK_S)                   ; Ctrl+S
_WinAPI_RegisterHotKey($hWnd, 2, BitOR($MOD_CONTROL, $MOD_SHIFT), $VK_S); Ctrl+Shift+S
_WinAPI_RegisterHotKey($hWnd, 3, $MOD_CONTROL, $VK_O)                   ; Ctrl+O
_WinAPI_RegisterHotKey($hWnd, 4, BitOR($MOD_SHIFT, $MOD_ALT), $VK_S)    ; Shift-Alt-S
_WinAPI_RegisterHotKey($hWnd, 0, 0, $VK_ESCAPE)                         ; ESC

While 1
    Sleep(1000)
WEnd

Func WM_HOTKEY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Switch $wParam
        Case 1
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+S')
        Case 2
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+Shift+S')
        Case 3
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+O')
        Case 4
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Shift-Alt-S')
        Case 0
            MsgBox($MB_SYSTEMMODAL, '', 'You pressed ESC')
            Exit
    EndSwitch
EndFunc   ;==>WM_HOTKEY

Func OnAutoItExit()
    _WinAPI_UnregisterHotKey($hWnd, 1)
    _WinAPI_UnregisterHotKey($hWnd, 2)
    _WinAPI_UnregisterHotKey($hWnd, 3)
    _WinAPI_UnregisterHotKey($hWnd, 4)
    _WinAPI_UnregisterHotKey($hWnd, 0)
EndFunc   ;==>OnAutoItExit

If you want to switch to the main loop? It's pretty simple:

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case 1
            MsgBox($MB_SYSTEMMODAL, 'Main loop', 'You pressed Ctrl+S')
        Case 2
            MsgBox($MB_SYSTEMMODAL, 'Main loop', 'You pressed Ctrl+Shift+S')
        Case 3
            MsgBox($MB_SYSTEMMODAL, 'Main loop', 'You pressed Ctrl+O')
        Case 4
            MsgBox($MB_SYSTEMMODAL, 'Main loop', 'You pressed Shift-Alt-S')
    EndSwitch
WEnd

Func WM_HOTKEY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Switch $wParam
        Case 1
            $nMsg = 1
        Case 2
            $nMsg = 2
        Case 3
            $nMsg = 3
        Case 4
            $nMsg = 4
        Case 0
            MsgBox($MB_SYSTEMMODAL, '', 'You pressed ESC')
            Exit
    EndSwitch
EndFunc   ;==>WM_HOTKEY

ioa747 TNX for help!

But it works on the system level, defines a system-wide hotkeys. How to do similar result on the application level?

Edited by mdf4356
Link to post
Share on other sites

  

3 hours ago, mdf4356 said:

How to do similar result on the application level?

something like that

#include <APISysConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

Opt('TrayAutoPause', 0)

OnAutoItExitRegister('OnAutoItExit')
Local $hWnd = GUICreate('Test message' & StringReplace(@ScriptName, '.au3', '()'))
Local $Register, $RegisterOld

GUIRegisterMsg($WM_HOTKEY, 'WM_HOTKEY')

While 1
    If WinActive("[CLASS:Notepad]") Then
        $Register = 1
    Else
        $Register = 0
    EndIf

    If $Register <> $RegisterOld Then
        $RegisterOld = $Register
        _RegisterHotKey($Register)
    EndIf


    Sleep(500)
WEnd

Func _RegisterHotKey($Swich = 0)

    ; https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
    Local $VK_S = 0x53    ; Virtual-key code for S key
    Local $VK_O = 0x4F    ; Virtual-key code for O key
    Local $VK_ESCAPE = 0x1B ; Virtual-key code for Esc key

    #cs
    <APIConstants.au3> or <APISysConstants.au3>
    $MOD_ALT = 0x0001
    $MOD_CONTROL = 0x0002
    $MOD_NOREPEAT = 0x4000
    $MOD_SHIFT = 0x0004
    $MOD_WIN = 0x0008
    #ce

    If $Swich = 1 Then
        _WinAPI_RegisterHotKey($hWnd, 1, $MOD_CONTROL, $VK_S)               ; Ctrl+S
        _WinAPI_RegisterHotKey($hWnd, 2, BitOR($MOD_CONTROL, $MOD_SHIFT), $VK_S) ; Ctrl+Shift+S
        _WinAPI_RegisterHotKey($hWnd, 3, $MOD_CONTROL, $VK_O)           ; Ctrl+O
        _WinAPI_RegisterHotKey($hWnd, 4, BitOR($MOD_SHIFT, $MOD_ALT), $VK_S) ; Shift-Alt-S
        _WinAPI_RegisterHotKey($hWnd, 0, 0, $VK_ESCAPE)                 ; ESC
        ConsoleWrite("--> RegisterHotKey" & @CRLF)
    Else
        _WinAPI_UnregisterHotKey($hWnd, 1)
        _WinAPI_UnregisterHotKey($hWnd, 2)
        _WinAPI_UnregisterHotKey($hWnd, 3)
        _WinAPI_UnregisterHotKey($hWnd, 4)
        _WinAPI_UnregisterHotKey($hWnd, 0)
        ConsoleWrite("RegisterHotKey <--" & @CRLF)
    EndIf

EndFunc   ;==>_RegisterHotKey

Func WM_HOTKEY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Switch $wParam
        Case 1
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+S')
        Case 2
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+Shift+S')
        Case 3
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+O')
        Case 4
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Shift-Alt-S')
        Case 0
            MsgBox($MB_SYSTEMMODAL, '', 'You pressed ESC')
            Exit
    EndSwitch
EndFunc   ;==>WM_HOTKEY

Func OnAutoItExit()
    _RegisterHotKey(0)
EndFunc   ;==>OnAutoItExit

 

Edited by ioa747
Link to post
Share on other sites
  • Solution

now is OK?   because I didn't understand  :huh2:

and now, and before, the MsgBox is coming

#include <APISysConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>
#include <WinAPIvkeysConstants.au3>

Opt('TrayAutoPause', 0)

OnAutoItExitRegister('OnAutoItExit')
Local $hWnd = GUICreate('Test message' & StringReplace(@ScriptName, '.au3', '()'))
Local $Register, $RegisterOld

GUIRegisterMsg($WM_HOTKEY, 'WM_HOTKEY')

While 1
    If WinActive("[CLASS:Notepad]") Then
        $Register = 1
    Else
        $Register = 0
    EndIf

    If $Register <> $RegisterOld Then
        $RegisterOld = $Register
        _RegisterHotKey($Register)
    EndIf


    Sleep(500)
WEnd

Func _RegisterHotKey($Swich = 0)
    #cs
    ; https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
    Local $VK_S = 0x53    ; Virtual-key code for S key
    Local $VK_O = 0x4F    ; Virtual-key code for O key
    Local $VK_ESCAPE = 0x1B ; Virtual-key code for Esc key

    
    <APIConstants.au3> or <APISysConstants.au3>
    $MOD_ALT = 0x0001
    $MOD_CONTROL = 0x0002
    $MOD_NOREPEAT = 0x4000
    $MOD_SHIFT = 0x0004
    $MOD_WIN = 0x0008
    #ce

    If $Swich = 1 Then
        _WinAPI_RegisterHotKey($hWnd, 1, $MOD_CONTROL, $VK_S)               ; Ctrl+S
        _WinAPI_RegisterHotKey($hWnd, 2, BitOR($MOD_CONTROL, $MOD_SHIFT), $VK_S) ; Ctrl+Shift+S
        _WinAPI_RegisterHotKey($hWnd, 3, $MOD_CONTROL, $VK_O)           ; Ctrl+O
        _WinAPI_RegisterHotKey($hWnd, 4, BitOR($MOD_SHIFT, $MOD_ALT), $VK_S) ; Shift-Alt-S
        _WinAPI_RegisterHotKey($hWnd, 0, 0, $VK_ESCAPE)                 ; ESC
        ConsoleWrite("--> RegisterHotKey" & @CRLF)
    Else
        _WinAPI_UnregisterHotKey($hWnd, 1)
        _WinAPI_UnregisterHotKey($hWnd, 2)
        _WinAPI_UnregisterHotKey($hWnd, 3)
        _WinAPI_UnregisterHotKey($hWnd, 4)
        _WinAPI_UnregisterHotKey($hWnd, 0)
        ConsoleWrite("RegisterHotKey <--" & @CRLF)
    EndIf

EndFunc   ;==>_RegisterHotKey

Func WM_HOTKEY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Switch $wParam
        Case 1
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+S')
        Case 2
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+Shift+S')
        Case 3
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+O')
        Case 4
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Shift-Alt-S')
        Case 0
            MsgBox($MB_SYSTEMMODAL, '', 'You pressed ESC')
            Exit
    EndSwitch
EndFunc   ;==>WM_HOTKEY

Func OnAutoItExit()
    _RegisterHotKey(0)
EndFunc   ;==>OnAutoItExit

 

Link to post
Share on other sites
1 hour ago, ioa747 said:

now is OK?  

Yes, everything is ok. I made some modifications to make it more relevant to my specific case so that I can quickly implement it into my code.

#include <MsgBoxConstants.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>
#include <WinAPIvkeysConstants.au3>
#include <GUIConstantsEx.au3>

Opt('TrayAutoPause', 0)
OnAutoItExitRegister('OnAutoItExit')

Local $bWinActiveFlag0, $bWinActiveFlag1

Local $hWnd = GUICreate('Test message' & StringReplace(@ScriptName, '.au3', 400, 400))
GUISetState(@SW_SHOW, $hWnd)

GUIRegisterMsg($WM_HOTKEY, 'WM_HOTKEY')

#Region ### MAIN LOOP
While 1
    _IsWinActive($hWnd)
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
#EndRegion ### MAIN LOOP

Func _IsWinActive($hWnd)
    If WinActive($hWnd) Then $bWinActiveFlag0 = True
    If $bWinActiveFlag0 <> $bWinActiveFlag1 Then $bWinActiveFlag1 = _RegisterHotKey($bWinActiveFlag0)
    $bWinActiveFlag0 = False
EndFunc

Func _RegisterHotKey($bFlag)
    If $bFlag Then
        _WinAPI_RegisterHotKey($hWnd, 1, $MOD_CONTROL, $VK_S)               ; Ctrl+S
        _WinAPI_RegisterHotKey($hWnd, 2, BitOR($MOD_CONTROL, $MOD_SHIFT), $VK_S) ; Ctrl+Shift+S
        _WinAPI_RegisterHotKey($hWnd, 3, $MOD_CONTROL, $VK_O)           ; Ctrl+O
        _WinAPI_RegisterHotKey($hWnd, 4, BitOR($MOD_SHIFT, $MOD_ALT), $VK_S) ; Shift-Alt-S
        _WinAPI_RegisterHotKey($hWnd, 0, 0, $VK_ESCAPE)                 ; ESC
        ConsoleWrite("--> RegisterHotKey" & @CRLF)
    Else
        _WinAPI_UnregisterHotKey($hWnd, 1)
        _WinAPI_UnregisterHotKey($hWnd, 2)
        _WinAPI_UnregisterHotKey($hWnd, 3)
        _WinAPI_UnregisterHotKey($hWnd, 4)
        _WinAPI_UnregisterHotKey($hWnd, 0)
        ConsoleWrite("RegisterHotKey <--" & @CRLF)
    EndIf
    Return $bFlag
EndFunc   ;==>_RegisterHotKey

Func WM_HOTKEY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Switch $wParam
        Case 1
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+S')
        Case 2
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+Shift+S')
        Case 3
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Ctrl+O')
        Case 4
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed Shift-Alt-S')
        Case 0
            MsgBox($MB_SYSTEMMODAL, 'WM_HOTKEY Function', 'You pressed ESC')
            Exit
    EndSwitch
EndFunc   ;==>WM_HOTKEY

Func OnAutoItExit()
    _RegisterHotKey(False)
EndFunc   ;==>OnAutoItExit

argumentum

Sorry, but I don't understand the purpose of using hexadecimal letters that are not suitable for escape characters or other similar purposes.

2 hours ago, argumentum said:

...if you look at _IsPressed() , the codes are text but the values are there, so Int(0x & "HEX") should do it :)

mistersquirrle

Thanks for advice, I included those constants too

Link to post
Share on other sites
11 hours ago, mdf4356 said:

; https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
$VK_S = 0x53        ; Virtual-key code for S key
$VK_O = 0x4F        ; Virtual-key code for O key
$VK_ESCAPE = 0x1B   ; Virtual-key code for Esc key

 

1 hour ago, mdf4356 said:

I don't understand the purpose of using

...just an idea...

1 hour ago, mdf4356 said:

mistersquirrle

Thanks for advice, I included those constants too

..and the idea is that you don't have to go far as they are in the help file. Again, just an idea.

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...