Sign in to follow this  
Followers 0
schwim

_IsPressed conflicting with GUIGetMsg()?

10 posts in this topic

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 :graduated:

Share this post


Link to post
Share on other sites



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.

Share this post


Link to post
Share on other sites

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 :graduated: Anywho, I don't think anybody ever has to apologize for not immediately helping somebody. Beggars, choosers, gift-horses, and all that ;)

Share this post


Link to post
Share on other sites

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
WEnd

Please ask again if my explanation is not clear. :graduated:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

That is interesting... I didnt know that.

Share this post


Link to post
Share on other sites

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? :graduated:

schwim

Share this post


Link to post
Share on other sites

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. :graduated:

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._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Probably has to do with WM_SYSKEYDOWN, WM_SYSKEYUP, and TranslateMessage() converting those to WM_SYSCOMMAND. I would start looking there.

Share this post


Link to post
Share on other sites

#9 ·  Posted (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 by Manadar

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0