schwim Posted October 12, 2011 Posted October 12, 2011 Howdy all, I'm having a problem with the _IsPressed function exhibiting some odd behavior. Using this script: #include <GUIConstantsEx.au3> #include <misc.au3> Opt('MustDeclareVars', 1) Global $mainWin = GUICreate("pressedtest", 150, 100) Global $button1 = GUICtrlCreateButton("Button1",55,10) Global $button2 = GUICtrlCreateButton("Button2",55,40) GUISetState() While 1 Global $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE GUIDelete() Exit Case $button1 MsgBox(0,"","Button1!") Case $button2 While(NOT _IsPressed('01')) sleep(10) WEnd GUISetBkColor(Random(0x000000, 0xFFFFFF, 1), $mainWin) EndSwitch WEnd When one clicks on Button2, the Is_Pressed loop begins, which waits for a left mouse click. Left clicking anywhere on the screen will exit the loop, change the GUI's background color, and the click will register with whatever GUI element that you clicked on. The exception to this, however, seems to be the close button and the titlebar of the script window. Single-clicking the titlebar after clicking Button2 has no effect whatsoever. Single-clicking the close button after clicking Button2 will have no immediate discernible affect, however clicking on another non-titlebar window element after clicking on the close button will then cause the script to exit. Double-clicking on the close button after clicking Button2 will also cause the script to exit (although two consecutive single-clicks will be ignored). Is this expected behavior, some peculiarity with the way that Windows (in my case, Windows 7 x64 SP1) handles mouse clicks on the titlebar elements differently? I ran into this while trying to create an informative yet unobtrusive tooltip for a combo box that can be triggered by an GUI event (i.e. someone trying to advance through a script without first selecting a dropdown element), using the following prototype script: #include <GUIConstantsEx.au3> #include <misc.au3> Opt('MustDeclareVars', 1) Opt('WinTitleMatchMode', 4) _Main() Func _Main() GUICreate("tooltiptest", 400, 296) Local $combo = GUICtrlCreateCombo("1", 110, 120, 200) GUICtrlSetData($combo,"2|3|4") GUISetState() While 1 Local $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE GUIDelete() Exit Case $combo MyTooltip(110,120,"test") EndSwitch sleep(10) WEnd EndFunc Func MyTooltip($x, $y, $msg) Local $winLoc = WinGetPos("[ACTIVE]") ToolTip ($msg, $winLoc[0]+$x+15, $winLoc[1]+$y+30, Default, 0, 1) While(NOT _IsPressed('01')) sleep(10) WEnd ToolTip("") EndFunc If someone can think of a better way to do that, I guess I wouldn't really care about the _IsPressed issue
Mikeman27294 Posted October 13, 2011 Posted October 13, 2011 One thing I noticed, was that you are declaring your variable $msg inside the while loop. That means that every time the loop runs, it declares the variable. Declare it at the top of the script. A good place to do this is between the includes and the GUI creation. Anyway, I have never had any problems with the _IsPressed and GUIGetMsg functions conflicting. Right now, I gotta head over to bed, but I will take a look at the script in more detail tomorrow. Right now, I am just too tired, sorry.
schwim Posted October 13, 2011 Author Posted October 13, 2011 Yeap, these were just quick-n-dirty proof of concept scripts that I cranked out, so I wasn't following my standard coding best practices Anywho, I don't think anybody ever has to apologize for not immediately helping somebody. Beggars, choosers, gift-horses, and all that
Moderators Melba23 Posted October 13, 2011 Moderators Posted October 13, 2011 schwim,Windows Button controls only react as the mouse button is released - so when you get to your _IsPressed loop the condition is already True and you enter the Sleep loop. At this point the script become unresponsive because you are not polling GUIGetMsg - clicking other elements lets you exit the loop and "restart" the GUI. Try using this slightly modified version and see if it makes it clearer:#include <GUIConstantsEx.au3> #include <misc.au3> Opt('MustDeclareVars', 1) Global $mainWin = GUICreate("pressedtest", 150, 100) Global $button1 = GUICtrlCreateButton("Button1", 55, 10) Global $button2 = GUICtrlCreateButton("Button2", 55, 40) GUISetState() While 1 Global $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE GUIDelete() Exit Case $button1 MsgBox(0, "", "Button1!") Case $button2 ConsoleWrite("I'm here and the mouse button is NOT pressed" & @CRLF) While (Not _IsPressed('01')) Sleep(10) WEnd ConsoleWrite("I'm here as the mouse button has been pressed again" & @CRLF) GUISetBkColor(Random(0x000000, 0xFFFFFF, 1), $mainWin) EndSwitch WEndPlease ask again if my explanation is not clear. M23 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
Mikeman27294 Posted October 14, 2011 Posted October 14, 2011 That is interesting... I didnt know that.
schwim Posted October 14, 2011 Author Posted October 14, 2011 M23, thanks for the help! I think I can see where you are coming from. However, I'm still confused as to why GUIGetMsg doesn't eventually handle the GUI_EVENT_CLOSE event. Running your modified code, I press Button2 and get the "NOT pressed" message after I release the mouse button. I then click Button1 and get the "pressed again" (and background color change) as I click, and then I get the "Button1!" popup as I release the button. Which makes total sense. However, if I follow the same sequence of steps, and click the close button instead of Button1, nothing happens. No message in the console, no application closing, nada. Unless, perhaps, the GUI events are all stored in a queue, and the call that _IsPressed is making to the GetAsyncKeyState in user32.dll pops the close event off of the queue and doesn't return it? But in that case why does the Button1 event fire off? schwim
Moderators Melba23 Posted October 14, 2011 Moderators Posted October 14, 2011 schwim, Trying your sequence it seems that a single mouse click on the title bar is not recognised by the script - however a double-click is recognised. I can only surmise that it is because you are clicking on the title bar of your GUI rather than within the client area. But I am afraid I am out of my depth here, you need someone who really understands the message queue and the sequence of messages sent by the various GUI elements. Sorry I cannot explain in any more depth - I am just a hobbyist coder. M23 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
Valik Posted October 14, 2011 Posted October 14, 2011 Probably has to do with WM_SYSKEYDOWN, WM_SYSKEYUP, and TranslateMessage() converting those to WM_SYSCOMMAND. I would start looking there.
jvanegmond Posted October 14, 2011 Posted October 14, 2011 (edited) Firstly, the titlebar clicking. The problem here is that as soon as you click the title bar Windows interprets this as an attempt to move the window (dragging the titlebar). Every time you move a GUI window, the program/thread which created the window (not just an AutoIt problem) is paused. There's no real workaround for this (I think). Reproducer:#include <GUIConstantsEx.au3> #include <misc.au3> Opt('MustDeclareVars', 1) Global $mainWin = GUICreate("Move me bro", 150, 100) GUISetState() While 1 Global $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE Exit EndSwitch ConsoleWrite(@SEC & @CRLF) WEnd You'll see no more seconds elapsing as soon as you move the GUI around. Hold mouse down on titlebar for same effect. The double click thing is probably because a single click is a move and a double click is a double click. Herp. The GUI close problem needs no further comment. Edit: One idea to solve your problem is to make a fake titlebar using normal GUI elements such as colored labels. Not ideal but still. Edited October 14, 2011 by Manadar github.com/jvanegmond
martin Posted October 15, 2011 Posted October 15, 2011 I don't think the thread is halted, just the message queue is blocked. #include <GUIConstantsEx.au3> #include <misc.au3> #include <timers.au3> Opt('MustDeclareVars', 1) Global $mainWin = GUICreate("Move me bro", 150, 100) GUISetState() _Timer_SetTimer($mainWin, 1000, "upadteTime") While 1 Global $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd func upadteTime($a, $b, $c, $d) ConsoleWrite(@SEC & @CRLF) EndFunc ;==> Maybe follow Valik's suggestion? Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
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