mdf4356 Posted February 16, 2023 Posted February 16, 2023 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?
mdf4356 Posted February 16, 2023 Author Posted February 16, 2023 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?
argumentum Posted February 17, 2023 Posted February 17, 2023 9 hours ago, mdf4356 said: ["^s" ..you could load a string from an ini file. I don't see the problem. $Ctrl_S = iniread() Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Moderators Melba23 Posted February 17, 2023 Moderators Posted February 17, 2023 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  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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Â
mdf4356 Posted February 19, 2023 Author Posted February 19, 2023 (edited) Bingo! _WinAPI_RegisterHotKey - works with virtual-key codes regardless of keyboard layout expandcollapse popup#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 February 19, 2023 by mdf4356 ioa747 and argumentum 2
ioa747 Posted February 19, 2023 Posted February 19, 2023 (edited)   3 hours ago, mdf4356 said: How to do similar result on the application level? something like that expandcollapse popup#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 February 19, 2023 by ioa747 I know that I know nothing
argumentum Posted February 19, 2023 Posted February 19, 2023 4 hours ago, ioa747 said: Local $VK_ESCAPE = 0x1B ; Virtual-key code for Esc key ...if you look at _IsPressed() , the codes are text but the values are there, so Int(0x & "HEX") should do it Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
mistersquirrle Posted February 19, 2023 Posted February 19, 2023 On that note, there's also #include <WinAPIvkeysConstants.au3> This file already has all (or a lot of) the VK_ codes mapped We ought not to misbehave, but we should look as though we could.
Solution ioa747 Posted February 19, 2023 Solution Posted February 19, 2023 now is OK?  because I didn't understand and now, and before, the MsgBox is coming expandcollapse popup#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  mdf4356 1 I know that I know nothing
mdf4356 Posted February 19, 2023 Author Posted February 19, 2023 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. expandcollapse popup#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
argumentum Posted February 19, 2023 Posted February 19, 2023 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. mdf4356 and ioa747 2 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now