AndyS19 Posted December 12, 2017 Posted December 12, 2017 I have a script that traps ^A and ^C accelerator keys via the GUISetAccelerators() function, and in the key handlers, I check to see if the focus is on the control that I want the keys to operate on. However, when I see that I'm not on that control, I want to pass the ^C and ^A back to the system so I can copy and past data on other controls. Here is my test script. I have it applying ^A and ^C only to the ListView control. When I put focus on the Input control, I want to be able to copy and paste normally. expandcollapse popupOpt("GUICloseOnESC", 1) ; ESC does not close the GUI Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt('MustDeclareVars', 1) OnAutoItExitRegister("ExitStageLeft") #include <Array.au3> #include <GuiListBox.au3> #include <GUIConstantsEx.au3> #include <ListBoxConstants.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> Global $hGUI, $iInput, $iList, $hInput, $hList _Main() Func _Main() Local $str, $parts $hGUI = GUICreate("", 250, 500) $iInput = GUICtrlCreateInput("2", 90, 5, 50, 20) $hInput = GUICtrlGetHandle($iInput) $iList = GUICtrlCreateListView("First Column ", 5, 30, 240, 470, $LBS_EXTENDEDSEL) $hList = GUICtrlGetHandle($iList) For $ndx = 1 To 100 $str = StringFormat("%s ABC", $ndx) Local $ret = _GUICtrlListView_AddItem($hList, $str) Next setupSpecialKeysHandlers() GUISetOnEvent($GUI_EVENT_CLOSE, "ExitStageLeft") GUISetState(@SW_SHOW) While (1) Sleep(250) WEnd EndFunc ;==>_Main Func ExitStageLeft() Exit (1) EndFunc ;==>ExitStageLeft Func setupSpecialKeysHandlers() Local $aAccelKeys[1][2] Local $ar, $parts, $key, $handler, $id ; Create a table of Special keys and their handlers $ar = StringSplit("", "") _ArrayAdd($ar, "{ENTER} - handle_ENTER_key ") _ArrayAdd($ar, "^a - handle_CTRL_A_key ") _ArrayAdd($ar, "^c - handle_CTRL_C_key ") ReDim $aAccelKeys[UBound($ar) - 1][2] ; Now, create $aAccelKeys array with the table data. ; For each entry, create a Dummy GUI and associate its ; ID with the special key. For $ndx = 1 To UBound($ar) - 1 $parts = StringSplit($ar[$ndx], "-", 2) $key = StringStripWS($parts[0], 8) $handler = StringStripWS($parts[1], 8) $id = GUICtrlCreateDummy() $aAccelKeys[$ndx - 1][0] = $key $aAccelKeys[$ndx - 1][1] = $id GUICtrlSetOnEvent($id, $handler) Next ; Dump the contents of the $aAccelKeys array For $ndx = 0 To UBound($aAccelKeys) - 1 logMsg("$aAccelKeys" _ & " [" & $ndx & "][0] = " & StringFormat("%-8s", $aAccelKeys[$ndx][0]) _ & " [" & $ndx & "][1] = " & $aAccelKeys[$ndx][1]) Next GUISetAccelerators($aAccelKeys) ; Setup the Special keys hooks EndFunc ;==>setupSpecialKeysHandlers Func logMsg($msg, $lnum = @ScriptLineNumber) ConsoleWrite("+++:" & $lnum & ": " & $msg & @CRLF) EndFunc ;==>logMsg Func handle_ENTER_key() logMsg("+++: handle_ENTER_key() entered") EndFunc ;==>handle_ENTER_key Func handle_CTRL_A_key() logMsg("+++: handle_CTRL_A_key() entered") If (Not isCtrlFocused($hList)) Then Return selectAllGLVItems() EndFunc ;==>handle_CTRL_A_key Func handle_CTRL_C_key() logMsg("+++: handle_CTRL_C_key() entered") If (isCtrlFocused($hList)) Then extractSelListViewGamesToClip() Else EndIf EndFunc ;==>handle_CTRL_C_key Func isCtrlFocused($hWnd) Local $hCtrl $hCtrl = ControlGetHandle($hGUI, "", ControlGetFocus($hGUI)) Return ($hWnd = $hCtrl) ? True : False EndFunc ;==>isCtrlFocused Func selectAllGLVItems() Local $hWnd = $hList, $iIndex For $iIndex = 0 To _GUICtrlListView_GetItemCount($hWnd) _GUICtrlListView_SetItemSelected($hWnd, $iIndex) Next EndFunc ;==>selectAllGLVItems Func extractSelListViewGamesToClip() Local $hWnd = $hList Local $iIndex, $item, $str, $sep = "" $str = "" For $iIndex = 0 To _GUICtrlListView_GetItemCount($hWnd) If (_GUICtrlListView_GetItemSelected($hWnd, $iIndex)) Then $item = _GUICtrlListView_GetItemText($hWnd, $iIndex) $str &= $sep & $item $sep = @CRLF EndIf Next ClipPut($str) logMsg("Copied " & StringLen($str) & " bytes to the Clipboard:" & @CRLF & $str) EndFunc ;==>extractSelListViewGamesToClip
benners Posted December 12, 2017 Posted December 12, 2017 There's probably a better way to detect the clicks but this is my attempt. expandcollapse popupOpt("GUICloseOnESC", 1) ; ESC does not close the GUI Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Opt('MustDeclareVars', 1) OnAutoItExitRegister("ExitStageLeft") #include <Array.au3> #include <EditConstants.au3> #include <GuiListBox.au3> #include <GUIConstantsEx.au3> #include <ListBoxConstants.au3> #include <WindowsConstants.au3> #include <GuiListView.au3> Global $hGUI, $iInput, $iList, $hInput, $hList Global $b_KeysActive = False ; initial state of the accelerators GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY') ; register for the listview clicks GUIRegisterMsg($WM_COMMAND, "ED_WM_COMMAND") ; register for input clicks _Main() Func _Main() $hGUI = GUICreate("", 250, 500) $iInput = GUICtrlCreateInput("2", 90, 5, 50, 20) $hInput = GUICtrlGetHandle($iInput) $iList = GUICtrlCreateListView("First Column ", 5, 30, 240, 470, $LBS_EXTENDEDSEL) $hList = GUICtrlGetHandle($iList) For $i = 1 To 100 _GUICtrlListView_AddItem($hList, 'ABC ' & $i) Next GUISetOnEvent($GUI_EVENT_CLOSE, "ExitStageLeft") GUISetState(@SW_SHOW) While (1) Sleep(250) WEnd EndFunc ;==>_Main Func ExitStageLeft() Exit (1) EndFunc ;==>ExitStageLeft Func setupSpecialKeysHandlers() If $b_KeysActive Then Return ; do nothing if the accelerator keys have been activated Local Static $i_FirstRun = 0 ; set a variable to check for array update Local Static $aAccelKeys[3][2] = _ ; create the initial array [['{ENTER}', 'handle_ENTER_key'], _ ['^a', 'handle_CTRL_A_key'], _ ['^c', 'handle_CTRL_C_key']] If Not $i_FirstRun Then ; set the accelerator keys and create the dummys Local $handler, $id ; Now, update $aAccelKeys array with the table data. ; For each entry, create a Dummy GUI and associate its ; ID with the special key. For $i = 0 To UBound($aAccelKeys) - 1 $handler = $aAccelKeys[$i][1] ; set the event handler $id = GUICtrlCreateDummy() ; create dummy control $aAccelKeys[$i][1] = $id ; replace the handle with the dummy id GUICtrlSetOnEvent($id, $handler) logMsg("$aAccelKeys" _ & " [" & $i & "][0] = " & StringFormat("%-8s", $aAccelKeys[$i][0]) _ & " [" & $i & "][1] = " & $aAccelKeys[$i][1]) Next $i_FirstRun = 1 ; update the static so the array is not created again after first run $b_KeysActive = True ; update global that keys are active EndIf GUISetAccelerators($aAccelKeys) ; Setup the Special keys hooks EndFunc ;==>setupSpecialKeysHandlers Func logMsg($msg, $lnum = @ScriptLineNumber) ConsoleWrite("+++:" & $lnum & ": " & $msg & @CRLF) EndFunc ;==>logMsg Func handle_ENTER_key() logMsg("+++: handle_ENTER_key() entered") EndFunc ;==>handle_ENTER_key Func handle_CTRL_A_key() logMsg("+++: handle_CTRL_A_key() entered") If (Not isCtrlFocused($hList)) Then Return selectAllGLVItems() EndFunc ;==>handle_CTRL_A_key Func handle_CTRL_C_key() logMsg("+++: handle_CTRL_C_key() entered") If (isCtrlFocused($hList)) Then extractSelListViewGamesToClip() Else EndIf EndFunc ;==>handle_CTRL_C_key Func isCtrlFocused($hWnd) Local $hCtrl $hCtrl = ControlGetHandle($hGUI, "", ControlGetFocus($hGUI)) Return ($hWnd = $hCtrl) ? True : False EndFunc ;==>isCtrlFocused Func selectAllGLVItems() Local $hWnd = $hList, $iIndex For $iIndex = 0 To _GUICtrlListView_GetItemCount($hWnd) _GUICtrlListView_SetItemSelected($hWnd, $iIndex) Next EndFunc ;==>selectAllGLVItems Func extractSelListViewGamesToClip() Local $hWnd = $hList Local $iIndex, $item, $str, $sep = "" $str = "" For $iIndex = 0 To _GUICtrlListView_GetItemCount($hWnd) If (_GUICtrlListView_GetItemSelected($hWnd, $iIndex)) Then $item = _GUICtrlListView_GetItemText($hWnd, $iIndex) $str &= $sep & $item $sep = @CRLF EndIf Next ClipPut($str) logMsg("Copied " & StringLen($str) & " bytes to the Clipboard:" & @CRLF & $str) EndFunc ;==>extractSelListViewGamesToClip Func WM_NOTIFY($hWnd, $msg, $wParam, $lParam) Local $tNMHDR, $IdFrom, $iCode $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $IdFrom = DllStructGetData($tNMHDR, 'IdFrom') $iCode = DllStructGetData($tNMHDR, 'Code') Switch $IdFrom Case $iList Switch $iCode Case $NM_CLICK setupSpecialKeysHandlers() EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func ED_WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $iCode = BitShift($wParam, 16) Switch $lParam Case $hInput Switch $iCode Case $EN_SETFOCUS GUISetAccelerators(0) ; turn off the accelerators $b_KeysActive = False ; update the global that keys are inactive EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>ED_WM_COMMAND
AndyS19 Posted December 13, 2017 Author Posted December 13, 2017 That looks like what I need, thank you. I have to make this code expansible because in my actual script, I have more than 100 GUI controls! I'm going to add some code to create an array of control ID/handles for only the controls that I want my special ^A and ^C keys to operate on. If the interrupting control is not in the list, I'll turn off the accelerators, if it's in the list, I'll turn the accelerators on. Thank you for your help.
Earthshine Posted December 14, 2017 Posted December 14, 2017 If all 100 controls are on one form then you are doing it wrong btw My resources are limited. You must ask the right questions
AndyS19 Posted December 18, 2017 Author Posted December 18, 2017 Actually, the form has 3 Tabs, is almost 14,000 lines and includes more than 50 UDF files . It's for managing Timekeeper assignments and payments via CSV files. If there's a better way, I'd be interested to try it.
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