Jetrunner Posted August 27, 2013 Share Posted August 27, 2013 (edited) I'm trying to modify my Edit field to accept the keys Ctrl + A to select all text, the same as right clicking and hitting select all. I managed to do it, but now every time I hit the keys, it produces an error noise. I want to continuously check for these keys, so I looped them together with my GUI. I've tried removing the registry entry for the Ding.wav sound, and then replacing it after my _IsPressed event, but it wasn't working (and editing the registry just to remove the Ding.wav sound seems messy, what if the program or OS crashed and their error noise stopped working for their entire OS?) I did some reading on StackOverflow, and it looks like there are some solutions (albeit, not always great ones) to do this in C++ and other languages. I don't really understand them that well, but it seems like there may be a function for expected keys so you don't cause an error (or ding noise) when pressed. Is there any way to do this with AutoIt? The other threads I've found so far don't seem to have a solution that would work for me. expandcollapse popup#include <GuiConstantsEx.au3> ;for main GUI elements #include <GUIEdit.au3> ; for Edit controls (e.g. Select All) #include <Constants.au3> ;for CMD related functions #include <WindowsConstants.au3> ;for vertial-only scrolling edit box #include <Misc.au3> ;for ispressed function (key pressed) Global $hDLL = DllOpen("user32.dll") GUICreate("MyProgramName", 400, 420) $editfield = GUICtrlCreateEdit("Enter text here", 0, 0, 400, 320, $WS_VSCROLL) Func selectAll() ; ; FIX POTENTIAL ERROR: ----> add code to check that edit field is the GUI item in focus! (to ensure we only select text when user expects it) _GUICtrlEdit_SetSel($editfield,0,-1) ;uses GUIEdit.au3 EndFunc ; >>>>> OTHER IRRELEVANT FUNCTIONS HERE <<<< mainGUI_loop() Func mainGUI_loop() While 1 ; NOTE: FIX DING NOISE SOMEHOW! (following If statement produces noise...) If ((_IsPressed("41", $hDLL)) AND (_IsPressed("11", $hDLL))) Then ; Ctrl + A does (Select All) on text in edit box. selectAll() While ((_IsPressed("41", $hDLL)) AND (_IsPressed("11", $hDLL))) ;prevent accidental double-presses? Sleep(250) ;make sure is not stalling script (modify sleep timer to check) WEnd EndIf Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ProcessClose ( $fPID ) Exit Case $exititem ProcessClose ( $fPID ) Exit ; >>>>> OTHER IRRELEVENT GUI CODE HERE... <<<<< EndSwitch WEnd EndFunc Edited August 27, 2013 by Jetrunner Link to comment Share on other sites More sharing options...
Jetrunner Posted August 28, 2013 Author Share Posted August 28, 2013 For the record, I just tried to do it with GUISetAccelerators instead of _IsPressed, and while that removes the ding, it presents another problem: it works anywhere in the window. It also breaks an input box I've got in the GUI from accepting Ctrl+A to select all text in the input box as would be default (now it only applies to the edit box... meaning it seems accelerators "steal" or override input from other functions???). Sorry if my Array for AccelKeys isn't right, I'm still trying to figure out arrays. [] Local $AccelKeys[2][2] = [["^a", $editfield],["^a", $editfield]] GUISetAccelerators($AccelKeys) mainGUI_loop() ; =========================== ; Main GUI Loop. !!!!! ..... ; =========================== Func mainGUI_loop() While 1 Switch GUIGetMsg() ;test of accelerator key(s) Case $editfield ;MsgBox("","title","Ctrl + A pressed - now what?","") ;debug only selectAll() ; >>>>> OTHER IRRELEVENT CODE HERE... <<<<< EndSwitch WEnd EndFunc EDIT: on second thought, it appears GUISetAccelerators is only meant to be used with buttons? I want to use Ctrl + A to select all text (in any text field that is in focus), and then Enter to submit the entered text (to a function). Local $AccelKeys[2][2] = [["^a", $editfield],["{Enter}", $nameInput]] $keysPressed = GUISetAccelerators($AccelKeys) mainGUI_loop() Func mainGUI_loop() While 1 Switch GUIGetMsg() ;BROKEN: Case $keysPressed selectAll() MsgBox("","","executed");debug only ;^ still broken. ; <!-- ==== Other irrelevant code ==== --> EndSwitch WEnd EndFunc I can't seem to find a way to get my Case to recognize that my cursor is in the edit field, instead of a button being pressed like the help file example. Even if I code it get get the user's focus (mouse/text cursor location and/or selected GUI tab), I still don't know if there's a way to check it with my Case switch (or case select, either), because as I said it doesn't seem to do anything like that in the example, (and all GUISetAccelerators will return is 0 or 1, which I don't seem to be able to get to work with multiple buttons). Anyway, so far it seems I'm either stuck with these new problems, or the old problem of not having a way to take user key inputs without having Ding.wav noises flying around everywhere. Link to comment Share on other sites More sharing options...
AZJIO Posted August 28, 2013 Share Posted August 28, 2013 http://pastebin.com/iasqvvsN Taz77 1 My other projects or all Link to comment Share on other sites More sharing options...
NewPlaza Posted August 28, 2013 Share Posted August 28, 2013 ; >>>>> OTHER IRRELEVANT FUNCTIONS HERE <<<< Not too irrelevant..... >Running AU3Check (1.54.22.0) from:C:Program Files (x86)AutoIt3 C:ScrapNew AutoIt v3 Script.au3(33,34) : WARNING: $fPID: possibly used before declaration. ProcessClose ( $fPID ) ~~~~~~~~~~~~~~~~~~~~~~~^ C:ScrapNew AutoIt v3 Script.au3(35,23) : WARNING: $exititem: possibly used before declaration. Case $exititem ~~~~~~~~~~~~~~~^ C:ScrapNew AutoIt v3 Script.au3(33,34) : ERROR: $fPID: undeclared global variable. ProcessClose ( $fPID ) ~~~~~~~~~~~~~~~~~~~~~~~^ C:ScrapNew AutoIt v3 Script.au3(35,23) : ERROR: $exititem: undeclared global variable. Case $exititem ~~~~~~~~~~~~~~~^ C:ScrapNew AutoIt v3 Script.au3 - 2 error(s), 2 warning(s) Link to comment Share on other sites More sharing options...
Jetrunner Posted August 28, 2013 Author Share Posted August 28, 2013 (edited) http://pastebin.com/iasqvvsN I tried this (again?). Not sure if I used this right, but I get the same problem I got when I originally tried GUISetAccelerators, where it simultaneously disables another text field's default "Ctrl + A to select all" functionality (the latter being an input field with GUICtrlCreateInput). So I fix one thing (edit field select all) but break another (input box select all). Here is my re-worked code (based on AZJIO's code): expandcollapse popup; ==================================================== ; INCLUDES ; ==================================================== #include <GuiConstantsEx.au3> ;for main GUI elements #include <GUIEdit.au3> ; for Edit controls (e.g. Select All) #include <Constants.au3> ;for CMD related functions #include <WindowsConstants.au3> ;for vertial-only scrolling edit box #include <Misc.au3> ;for ispressed function #include <File.au3> ;for writing new file #include <GuiComboBox.au3> ;for advanced combo box features (apparently adding/removing items, in a way that you'd expect it to behave normally, is "advanced") #include <EditConstants.au3> ; for edit & input (???) because it was included in Select all example (by AZJIO: http://pastebin.com/iasqvvsN) making sure nothing breaks. Global $hDLL = DllOpen("user32.dll") ; ==================================================== ; GUI LAYOUT ; ==================================================== ; GUI GUICreate("MyProgramName", 400, 420) ; For custom icon: ; GUISetIcon(@SystemDir & "\mspaint.exe", 0) ; >>> File menu' and sub-menus' code goes here. <<< ; EDIT FIELD $editfield = GUICtrlCreateEdit("Enter text to speak here", 0, 0, 400, 320, $WS_VSCROLL) ; INPUT FIELD $NameInput = GUICtrlCreateInput($myName, 131, 370, 130, 20) ; >>> Other button code goes here <<< ; ==================================================== ; FUNCTIONS ; ==================================================== ; >>> Other functions go here <<< Func selectAll() ; global $nDummy = GUICtrlCreateDummy() Dim $aAccelKeys[1][2] = [["^a", $nDummy]] GUISetAccelerators($aAccelKeys) EndFunc ; >>> Function calls and calls to other functions go here. <<< ; myFunction() selectAll() mainGUI_loop() Func mainGUI_loop() While 1 Switch GUIGetMsg() Case $nDummy GUICtrlSendMsg($editfield, $EM_SETSEL, 0, -1) Case $GUI_EVENT_CLOSE ProcessClose ( $fPID ) Exit Case $exititem ProcessClose ( $fPID ) Exit ; >>> Other Cases go here (button presses, etc.) <<< EndSwitch WEnd EndFunc Oh and this gem... ; >>>>> OTHER IRRELEVANT FUNCTIONS HERE <<<< Not too irrelevant..... It's largely for the sake of brevity, I have hundreds of lines of code. I could give you every piece of my code, but if you bothered to read what I already posted here, and my question, then you'd realize they really are irrelevant. So unless you were going to just rely on the SciTE debugger instead of using your eyes, or think that I should give my entire programs' source code up, for help on one single problem (after solving dozens myself and working on this for almost a week), then I see no reason why you think they are necessary for this discussion. I've painstakingly trimmed out all most of the fat. It makes it easier to read. Edited August 28, 2013 by Jetrunner Link to comment Share on other sites More sharing options...
AZJIO Posted August 28, 2013 Share Posted August 28, 2013 (edited) Jetrunner To find the error you have to prepare a special example. Perhaps in the process, you will understand a mistake. Maybe for you it will be a novelty, but I at the time of writing the program simultaneously creating dozens of scripts to test separately any part before paste it into the script. You save your time, but you don't save time ten people who could help you. Edited August 28, 2013 by AZJIO My other projects or all Link to comment Share on other sites More sharing options...
Jetrunner Posted August 28, 2013 Author Share Posted August 28, 2013 (edited) Jetrunner To find the error you have to prepare a special example. Perhaps in the process, you will understand a mistake. Maybe for you it will be a novelty, but I at the time of writing the program simultaneously creating dozens of scripts to test separately any part before paste it into the script. You save your time, but you don't save time ten people who could help you. I'm not sure I understand what you are saying, exactly. However, I did test my scripts before trimming them and pasting the important parts here. I got no compile errors. The only errors I found were unwanted and/or unexpected functionality in the actual program. I'm not trying to fix a syntax error here. Edited August 28, 2013 by Jetrunner Link to comment Share on other sites More sharing options...
Solution dragan Posted August 28, 2013 Solution Share Posted August 28, 2013 (edited) Here's an example: #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiEdit.au3> #include <WinAPI.au3> $Form1 = GUICreate("Form1", 600, 400) $Edit1 = GUICtrlCreateEdit("Some text in Edit1" & @CRLF & "focus me, and press CTRL+A", 0, 0, 300, 400) $Edit2 = GUICtrlCreateEdit("Some text in Edit2" & @CRLF & "focus me, and press CTRL+A", 300, 0, 300, 400) GUISetState(@SW_SHOW) Global $hSelAll = GUICtrlCreateDummy() Dim $AccelKeys[1][2] = [["^a", $hSelAll]] GUISetAccelerators($AccelKeys, $Form1) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $hSelAll _SelectAllTextInEdit() EndSwitch WEnd Func _SelectAllTextInEdit();will make select all text in eny focused edit, as long as it is edit inside $Form1 winhandle because we bound GUISetAccelerators to $Form1 Local $theHandle = _WinAPI_GetFocus() Local $TheClass = _WinAPI_GetClassName($theHandle) If $TheClass = 'Edit' Then _GUICtrlEdit_SetSel($theHandle, 0, -1) EndFunc Edited August 28, 2013 by dragan ss26 and Jetrunner 2 Link to comment Share on other sites More sharing options...
Jetrunner Posted August 28, 2013 Author Share Posted August 28, 2013 (edited) Here's an example: It works, tried it earlier today. But... I decided I wanted to try it without using the #include WinAPI.au3 (possibly save some overhead?). I re-worked it a bit, and here is my solution (see my selectAllgo() function): expandcollapse popup; ==================================================== ; INCLUDES (some used for functions i've trimmed out) ; ==================================================== #include <GuiConstantsEx.au3> ;for main GUI elements ;#include <WinAPI.au3> ;for finding window focus. NOT REQUIRED if using this method... #include <GUIEdit.au3> ; for Edit controls (e.g. Select All) #include <WindowsConstants.au3> ;for vertial-only scrolling edit box #include <Constants.au3> ;for CMD related functions #include <File.au3> ;for writing new file #include <GuiComboBox.au3> ;for "advanced" combo box features Global $hDLL = DllOpen("user32.dll") ; ==================================================== ; GUI LAYOUT ; ==================================================== ; GUI $mainGUI = GUICreate("My Program Title", 400, 420) ; EDIT FIELD $editfield = GUICtrlCreateEdit("Enter text here", 0, 0, 400, 120, $WS_VSCROLL) ; INPUT FIELD $nameInput = GUICtrlCreateInput($myName, 0, 200, 200, 120) ; >>> Other GUI buttons and controls were here. <<< ; ==================================================== ; DECLARE FUNCTIONS (all except main gui loop) ; ==================================================== ; >>> Other functions were here <<< Func selectAllsetup() ; Create dummy to use as target for select all functions & set up accelerator keys. Global $dummyCtrl = GUICtrlCreateDummy() Global $AccelKeys[1][2] = [["^a", $dummyCtrl]] GUISetAccelerators($AccelKeys, $mainGUI) EndFunc Func selectAllgo() ; NOTE: It appears AutoIt and/or Windows identify any field such as "input" or "edit" all as being "edit" class. (makes sense, you are editing text) $focusedControl = ControlGetFocus ( "My Program Title", "" ) ; find control that is in keyboard focus. Local $i = 1 ; edit to 0 if any "edit" field's ClassNameNN starts with 0. (check the id with AutoIt v3 Window Info) While $i <= 2 ; insert total number of edit fields here (or highest expected number, or variable depicting such) If $focusedControl == ("Edit" & $i) Then $theHandle = ControlGetHandle ( "", "", "Edit" & $i) _GUICtrlEdit_SetSel($theHandle, 0, -1) EndIf $i = $i + 1 WEnd EndFunc ; ==================================================== ; USE FUNCTIONS ; ==================================================== ; >>> Other functions were here <<< selectAllsetup() mainGUI_loop() ; ; ================================================= ; Main GUI Loop. !!!!! ..... !!!!! ..... !!!!! ; ================================================= ; Func mainGUI_loop() While 1 Switch GUIGetMsg() Case $dummyCtrl selectAllgo() ; <----- Actually select all! Case $GUI_EVENT_CLOSE ProcessClose ( $festivalProcessID ) Exit Case $exititem ProcessClose ( $festivalProcessID ) Exit ; >>> Other Cases were here. <<< EndSwitch WEnd EndFunc ^This works flawlessly (and, thankfully, still without the Ding.wav sound) for programs with edit fields and input boxes. However, if you want to have selectable text in your ComboBox (i.e. drop down menu), I tried the following: ; >>> Snip snip <<< ; COMBO $comboOptionDefault = "Select Option" $myInputCombo = GUICtrlCreateCombo($comboOptionDefault, 131, 346, 120, 100) ; >>> Snip snip <<< Func selectAllgo() Local $i = 1 ; edit to 0 if ClassNameNN starts with 0. (check the id with AutoIt v3 Window Info) While $i <= 2 ; insert total number of edit fields here (or highest expected number) ;MsgBox(0, "Value of $i is:", $i) If $focusedControl == ("Edit" & $i) Then $theHandle = ControlGetHandle ( "", "", "Edit" & $i) _GUICtrlEdit_SetSel($theHandle, 0, -1) MsgBox("","test1","this section done1") EndIf If $focusedControl == ("ComboBox" & $i) Then $theHandle = ControlGetHandle ( "", "", "ComboBox" & $i) _GUICtrlEdit_SetSel($theHandle, 0, -1) MsgBox("","test2","this section done2") EndIf $i = $i + 1 WEnd EndFunc ; >>> Snip snip <<< Which didn't work! While I can move my cursor around in the ComboBox, I still can't use Ctrl + A to select text (even if I remove the 1st if statement in selectAllgo() that handles Edit class controls). Of course, it still works for the edit boxes. I tested the 2nd if statement by adding a MsgBox, and it wasn't even doing it at all. (why???) To fix it, I had to do this: Func selectAllgo() $focusedControl = ControlGetFocus ( "My Program Title", "" ) ; such as "Edit1" or "Edit2" etc. Local $i = 1 ; edit to 0 if ClassNameNN starts with 0. (check the id with AutoIt v3 Window Info) While $i <= 3 ; insert total number of edit fields here (or highest expected number) If $focusedControl == ("Edit" & $i) Then ; "Edit" apparently can also work with ComboBox fields. $theHandle = ControlGetHandle ( "", "", "Edit" & $i) _GUICtrlEdit_SetSel($theHandle, 0, -1) ;MsgBox("","test1","this section done1");debug only EndIf $i = $i + 1 WEnd EndFunc In otherwords, I found out, and took advantage of the fact that AutoIt (somewhat-counterintuitively) lets me select the ComboBox (the third field with text and movable cursor) with "Edit3" instead of "ComboBox1". So I changed my max number for $i. I'm not sure if it's just a way it names things, but in this case, it appears it does not recognize "ComboBox1" as a legitimate control name/id, despite that being its name in the AutoIt Window Info tool. In any case, the above code works. I'm just not 100% sure why (because the control id/name thing doesn't make sense to me). Edited August 28, 2013 by Jetrunner Link to comment Share on other sites More sharing options...
dragan Posted August 28, 2013 Share Posted August 28, 2013 I think this is much better solution (if you still wanna use it WITHOUT WinApi.au3), also CTRL+A works for combo by default: #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <GuiEdit.au3> $Form1 = GUICreate("Form1", 600, 400) $Edit1 = GUICtrlCreateEdit("Some text in Edit1" & @CRLF & "focus me, and press CTRL+A", 0, 0, 300, 350) $Edit2 = GUICtrlCreateEdit("Some text in Edit2" & @CRLF & "focus me, and press CTRL+A", 300, 0, 300, 350) $Combo1 = GUICtrlCreateCombo('', 0, 360, 600);CTRL+A already works for combo, by default. GUICtrlSetData(-1, 'Some Data 1|Some Data 2|Some Data 3|Some Data 4|Some Data 5|Some Data 6', 'Some Data 1') GUISetState(@SW_SHOW) Global $hSelAll = GUICtrlCreateDummy() Dim $AccelKeys[1][2] = [["^a", $hSelAll]] GUISetAccelerators($AccelKeys, $Form1) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $hSelAll _SelectAllTextInEdit() EndSwitch WEnd Func _SelectAllTextInEdit();will make select all text in eny focused edit, as long as it is edit inside $Form1 winhandle because we bound GUISetAccelerators to $Form1 Local $theHandle = DllCall("user32.dll", "hwnd", "GetFocus") If NOT @error Then $TheClass = DllCall("user32.dll", "int", "GetClassNameW", "hwnd", $theHandle[0], "wstr", "", "int", 4096) If NOT @error Then If $TheClass[2] = 'Edit' Then _GUICtrlEdit_SetSel($theHandle[0], 0, -1) EndIf EndIf EndFunc ss26 and Jetrunner 2 Link to comment Share on other sites More sharing options...
Jetrunner Posted August 28, 2013 Author Share Posted August 28, 2013 (edited) That works, too. I wouldn't have thought of using DLL's. I guess I have some more reading to do. You've proven again that there's more than one way to code. And it does work by default, but if you code things a certain way, the default way will break. Oh, also: I'm just not 100% sure why (because the control id/name thing doesn't make sense to me). I since read this in the help file: CLASSNN - The ClassnameNN value as used in previous versions of AutoIt, such as "Edit1" (emphasis/color added) Not sure if that was my problem, but maybe knowing that will help others. Edited August 28, 2013 by Jetrunner Link to comment Share on other sites More sharing options...
dragan Posted August 29, 2013 Share Posted August 29, 2013 last script I posted should work for combo anyway - why? - well because combo ACTS as "Edit" while typing values. So if you use the code I posted, you should be able to mark all text even under your circumstances where you build things "a certain way". Link to comment Share on other sites More sharing options...
Jetrunner Posted August 29, 2013 Author Share Posted August 29, 2013 (edited) Yeah, I've noticed through this that Edit boxes, Input boxes, and Combo boxes, are all being recognized as "Edit" class, so as long as one gets that point across properly in their code, they should all work. I marked your >Post # 8 as best answer because it seems the easiest to understand and implement for a new user (and works on all controls... i.e. any focused text field... as it seems all your examples do). Thanks for the help. Edited August 29, 2013 by Jetrunner Link to comment Share on other sites More sharing options...
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