PauloBuchsbaum Posted December 20, 2009 Share Posted December 20, 2009 (edited) A great trouble in a GUI environment in AutoIt is that most controls are not clickable.It's a big trouble, because it's very normal the user needs to access a specific field/control.There is no easy way to do this, because AutoIt doesn't launch a event when a user click a mouse over most controls, except for few controls, like buttons.I've found in this forum a nice solution Clickable Label in order to accept click on Label Control.Fortunately, the same approach suits any control.expandcollapse popup#include <guiconstants.au3> Dim $Main = GUICreate("MyGui", 300, 100) Dim $Name = EditLabel(20,"Name") ; "Name" field Dim $Address = EditLabel(50,"Address") ; "Address" field GUISetState() ; Shows GUI While 1 $imsg = GUIGetMsg() ; get event Select Case $imsg = $GUI_EVENT_CLOSE ; The user has clicked on X Exit Case _IsPressed('01') ; Other left click IF _CtrlClick($Main, "", $Name) = 1 Then ; "Name" field's click GUICtrlSetState ($Name , $GUI_FOCUS) Elseif _CtrlClick($Main, "", $Address) = 1 Then ; "Address" field's click GUICtrlSetState ($Address, $GUI_FOCUS) Endif EndSelect WEnd ;***************************************************************** ; _ClickContr() ; Is the left button click inside a Control $Contr in the GUI $GUI, returns 1 ;*************************************************************** Func _ClickContr($GUI, $Text, $Contr) Local $Opt = Opt("MouseCoordMode", 2) ; Relative coords Local $Pos = ControlGetPos($GUI, $Text, $Contr) ; Control dimensions Local $Mouse = MouseGetPos() ; Mouse position If IsArray($Mouse) And IsArray($Pos) Then ; Mouse is inside the control? If $Mouse[0] >= $Pos[0] And $Mouse[0] <= $Pos[0] + $Pos[2] And $Mouse[1] >= $Pos[1] And $Mouse[1] <= $Pos[1] + $Pos[3] Then Return 1 EndIf EndIf Return 0 EndFunc ;************************************************* ; _IsPressed() ; Is the left mouse was clicked, returns 1 ;************************************************ Func _IsPressed($s_hexKey, $v_dll = 'user32.dll') Local $a_R = DllCall($v_dll, "int", "GetAsyncKeyState", "int", '0x' & $s_hexKey) If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1 Return 0 EndFunc Edited December 20, 2009 by PauloBuc Link to comment Share on other sites More sharing options...
Mat Posted December 20, 2009 Share Posted December 20, 2009 The style $SS_NOTIFY allows you to trigger an event on a static click (so pics, icons and labels... You could also simplify what you've got by using GUIGetCursorInfo. Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
PauloBuchsbaum Posted December 21, 2009 Author Share Posted December 21, 2009 Thanks, Mat. You are right. I've researched for a solution and I just find a complex one. Unfortunately. Yours it's better and simple. Now the code is shorter... #include <guiconstants.au3> #include <StaticConstants.au3> Dim $Main = GUICreate("MyGui", 300, 100) Dim $Name = EditLabel(20,"Name") ; "Name" field Dim $Address = EditLabel(50,"Address") ; "Address" field GUISetState() ; Shows GUI While 1 $imsg = GUIGetMsg() ; get event Select Case $imsg = $GUI_EVENT_CLOSE ; click on X Exit Case $imsg = $Name GUICtrlSetState ($Name , $GUI_FOCUS) Case $imsg = $Address GUICtrlSetState ($Address, $GUI_FOCUS) EndSelect WEnd Func EditLabel($Alt,$Lab) Local $Aux GUICtrlCreateLabel($Lab, 10, $Alt, 100, 20) $Aux = GUICtrlCreateInput("",130, $Alt, 100,20,$SS_NOTIFY) Return $Aux EndFunc Link to comment Share on other sites More sharing options...
Mat Posted December 21, 2009 Share Posted December 21, 2009 I was thinking you could also do this: #include <GUIConstantsEx.au3> Local $Main = GUICreate("MyGui", 300, 100) Local $First = GUICtrlCreateLabel ("Test 1: Label", 2, 2, 100, 20) Local $Second = GUICtrlCreateInput ("Test 2: Input", 2, 24, 100, 20) GUISetState() Local $iMsg, $aCur While 1 $aCur = GUIGetCursorInfo() $imsg = GUIGetMsg() If ($iMsg = $GUI_EVENT_PRIMARYUP) Then $iMsg = $aCur[4] Switch $iMsg Case $GUI_EVENT_CLOSE Exit Case $First ConsoleWrite ("Label clciked" & @CRLF) Case $Second ConsoleWrite ("Input clicked" & @CRLF) EndSwitch WEnd But there is probably a more accurate method using windos messages. Mat AutoIt Project Listing Link to comment Share on other sites More sharing options...
PauloBuchsbaum Posted December 22, 2009 Author Share Posted December 22, 2009 (edited) Mat, Thanks for your attention! Your example works smoothly. However, in my real program, with many edit, label, combo, buttons and checkboxes fields, this method is not trustable. I need to click 2 or 3 times to the program notices the click. I've used two options, with or without $SS_NOTIFY in control creation. The click's behaviour is unpredictable. My original way to do that (inspired in a old post cited) it's not pretty, but works flawless in real code. My purpose is just to allow the user edit any field that he wants, without no forced order. In my real program, I keep a global variable with the active field to force tight validation control. I know how to set the focus in a control, but I don't know how to get the control that has focus. So I've decided that the program knows all the time which control is active, updating a variable in all events. PS: I don't have enough practice about Windows Messages management in order to I try by myself do the "right" way. expandcollapse popup#include <guiconstants.au3> Dim $Main = GUICreate("MyGui", 300, 100) Dim $Name = EditLabel(20,"Name") ; "Name" field Dim $Address = EditLabel(50,"Address") ; "Address" field GUISetState() ; Shows GUI While 1 $imsg = GUIGetMsg() ; get event Select Case $imsg = $GUI_EVENT_CLOSE ; The user has clicked on X Exit Case _IsPressed('01') ; Other left click IF _CtrlClick($Main, "", $Name) = 1 Then ; "Name" field's click GUICtrlSetState ($Name , $GUI_FOCUS) Elseif _CtrlClick($Main, "", $Address) = 1 Then ; "Address" field's click GUICtrlSetState ($Address, $GUI_FOCUS) Endif EndSelect WEnd ;***************************************************************** ; _ClickContr() ; Is the left button click inside a Control $Contr in the GUI $GUI, returns 1 ;*************************************************************** Func _ClickContr($GUI, $Text, $Contr) Local $Opt = Opt("MouseCoordMode", 2) ; Relative coords Local $Pos = ControlGetPos($GUI, $Text, $Contr) ; Control dimensions Local $Mouse = MouseGetPos() ; Mouse position If IsArray($Mouse) And IsArray($Pos) Then ; Mouse is inside the control? If $Mouse[0] >= $Pos[0] And $Mouse[0] <= $Pos[0] + $Pos[2] And $Mouse[1] >= $Pos[1] And $Mouse[1] <= $Pos[1] + $Pos[3] Then Return 1 EndIf EndIf Return 0 EndFunc ;************************************************* ; _IsPressed() ; Is the left mouse was clicked, returns 1 ;************************************************ Func _IsPressed($s_hexKey, $v_dll = 'user32.dll') Local $a_R = DllCall($v_dll, "int", "GetAsyncKeyState", "int", '0x' & $s_hexKey) If Not @error And BitAND($a_R[0], 0x8000) = 0x8000 Then Return 1 Return 0 EndFunc ;************************************************* ; EditLabel ; Label + Edit ;************************************************ Func EditLabel($Alt,$Lab) Local $Aux GUICtrlCreateLabel($Lab, 10, $Alt, 100, 20) $Aux = GUICtrlCreateInput("",130, $Alt, 100,20) Return $Aux EndFunc Edited December 22, 2009 by PauloBuchsbaum Link to comment Share on other sites More sharing options...
picea892 Posted December 22, 2009 Share Posted December 22, 2009 There are many many ways to do this. The problem with searching the forum is you come up with code that is 4 years old. _ispressed is now part of the misc udf and there are lots of other changes. Here are two ways to get guictrl focus. One is a hybrid of Mat and your approach, the other is the window message method you were talking about. #include <guiconstants.au3> #Include <Misc.au3> Global $dll = DllOpen("user32.dll") Dim $Main = GUICreate("MyGui", 300, 100) Dim $Name = EditLabel(20,"Name") ; "Name" field Dim $Address = EditLabel(50,"Address") ; "Address" field GUISetState() ; Shows GUI While 1 $imsg = GUIGetMsg() ; get event Select Case $imsg = $GUI_EVENT_CLOSE ; The user has clicked on X Exit Case _IsPressed('01',$dll) ; Other left click $hov=GUIGetCursorInfo($Main) IF $hov[4]=$name Then ; "Name" field's click GUICtrlSetState ($Name , $GUI_FOCUS) Elseif $hov[4]= $Address Then ; "Address" field's click GUICtrlSetState ($Address, $GUI_FOCUS) Endif EndSelect WEnd ;************************************************* ; EditLabel ; Label + Edit ;************************************************ Func EditLabel($Alt,$Lab) Local $Aux GUICtrlCreateLabel($Lab, 10, $Alt, 100, 20) $Aux = GUICtrlCreateInput("",130, $Alt, 100,20) Return $Aux EndFunc expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <EditConstants.au3> Global $Main = GUICreate("MyGui", 300, 100) Global $Name = EditLabel(20,"Name") ; "Name" field Global $Address = EditLabel(50,"Address") ; "Address" field Global $hLabel = GUICtrlCreateLabel("", 10, 0, 200, 20) GUISetState() ; Catch focus passing to $InputLDescrition GUIRegisterMsg($WM_COMMAND, "ED_WM_COMMAND") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func ED_WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $iCode = BitShift($wParam, 16) Switch $lParam Case GUICtrlGetHandle($Name) Switch $iCode Case $EN_SETFOCUS GUICtrlSetData($hLabel, "Name edit has focus") Case $EN_KILLFOCUS ; GUICtrlSetData($hLabel, "Edit does not have focus") EndSwitch Case GUICtrlGetHandle($Address) Switch $iCode Case $EN_SETFOCUS GUICtrlSetData($hLabel, "Address edit has focus") Case $EN_KILLFOCUS ; GUICtrlSetData($hLabel, "Edit does not have focus") EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>ED_WM_COMMAND ;************************************************* ; EditLabel ; Label + Edit ;************************************************ Func EditLabel($Alt,$Lab) Local $Aux GUICtrlCreateLabel($Lab, 10, $Alt, 100, 20) $Aux = GUICtrlCreateInput("",130, $Alt, 100,20) Return $Aux EndFunc Link to comment Share on other sites More sharing options...
PauloBuchsbaum Posted December 22, 2009 Author Share Posted December 22, 2009 Picea892, Very thanks for your post. Both solutions works perfectly in my real program. It can be posted before this feature, but it's not easy find it using search engine. A proper post title it's always useful! I've liked very much the first solution, because it's simpler than windows message handling solution. PS: I didn't understand with AutoIt developers choose make the input and other controls not selectable by default. It's the normal behaviour in any form design in most programming languages. 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