Jump to content

Need help with registered function


 Share

Recommended Posts

I have a script that uses both a While 1 ... WEnd loop and an On_WM_COMMAND registered function. I've discovered that the registered WM_COMMAND is cycling multiple times for each click on the GUI. I've tried various combinations change that, but my result is always the same. I've prepared this simplified example to demonstrate the behavior. (The simple 300 x 200 graphic is shown below.)

#include <GUIConstants.au3>

$GUI = GUICreate("Main", 300, 200, 300, 300)
GUICtrlSetState(-1,$GUI_DISABLE)
$image = GUICtrlCreatePic(@ScriptDir&"\Image.bmp",0,0,300,200)
GUICtrlSetState(-1,$GUI_DISABLE)

$OnGraphic = GUICtrlCreateGraphic(30, 20, 70, 70)
GUICtrlSetTip(-1, " On " )                   ; show tooltip as a test
$OffGraphic = GUICtrlCreateGraphic(140, 20, 70, 70)
GUICtrlSetTip(-1, " Off " )                  ; show tooltip as a test

$regularButton1 = GUICtrlCreateButton("Yes", 40, 160, 30, 20)
$regularButton2 = GUICtrlCreateButton("No", 80, 160, 30, 20)
$exit = GUICtrlCreateButton("X", 280, 10, 16, 16)

$display = GUICtrlCreateInput("", 70, 100, 60, 20)
$state = GUICtrlCreateInput("", 120, 160, 60, 20)

GUISetState()

;===========================================
GUIRegisterMsg($WM_COMMAND, "On_WM_COMMAND")
;===========================================

While 1
    $gMsg = GUIGetMsg()           ; read button click
    Switch $gMsg
        Case $regularButton1
            GUICtrlSetData($state, "Yes")
        Case $regularButton2
            GUICtrlSetData($state, "No")
        Case $exit
            Exit
    EndSwitch
WEnd

Func On_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iNotifyCode = BitShift($wParam, 16), $iID = BitAnd($wParam, 0x0000FFFF)
            MsgBox(32, "Entry", "On_WM_Command", 1)                 ;<<<<<<<<<<<< need to investigat multiple cycles
        If $iID = $OnGraphic Then 
            GUICtrlSetData( $display, "On" )
        EndIf
        If $iID = $OffGraphic Then 
            GUICtrlSetData( $display, "Off" )
        EndIf
EndFunc
It's probably obvious, but the While 1 Loop handles the defined graphical buttons, and the registered function handles regular buttons. Have I left something out? Or is this behavior normal? If so, why?

Thanks for any assistance.

Link to comment
Share on other sites

Why do you use ON_WM_COMMAND to begin with?? Wouldn't this be better=

#include <GUIConstants.au3>

$GUI = GUICreate("Main", 300, 200, 300, 300)
GUICtrlSetState(-1,$GUI_DISABLE)
$image = GUICtrlCreatePic(@ScriptDir&"\Image.bmp",0,0,300,200)
GUICtrlSetState(-1,$GUI_DISABLE)

$OnGraphic = GUICtrlCreateGraphic(30, 20, 70, 70)
GUICtrlSetTip(-1, " On " )              ; show tooltip as a test
$OffGraphic = GUICtrlCreateGraphic(140, 20, 70, 70)
GUICtrlSetTip(-1, " Off " )             ; show tooltip as a test

$regularButton1 = GUICtrlCreateButton("Yes", 40, 160, 30, 20)
$regularButton2 = GUICtrlCreateButton("No", 80, 160, 30, 20)
$exit = GUICtrlCreateButton("X", 280, 10, 16, 16)

$display = GUICtrlCreateInput("", 70, 100, 60, 20)
$state = GUICtrlCreateInput("", 120, 160, 60, 20)

GUISetState()

While 1
    $gMsg = GUIGetMsg()         ; read button click
    Switch $gMsg
        Case $regularButton1
            GUICtrlSetData($state, "Yes")
        Case $regularButton2
            GUICtrlSetData($state, "No")
        Case $OnGraphic
            GUICtrlSetData( $display, "On" )
        Case $OffGraphic
            GUICtrlSetData( $display, "Off" )
        Case $exit
            Exit
    EndSwitch
WEnd

Edit:Spelling

Edited by AdmiralAlkex
Link to comment
Share on other sites

Why do you use ON_WM_COMMAND to begin with?? Wouldn't this be better=

Yes, you would think that simplification would work. Unfortunately, the response time to rapid clicking on the graphic buttons is unacceptable. Here's a much clearer example, which loses clicks:

#include <GUIConstants.au3>
Opt("WinWaitDelay", 10)    ;10 milliseconds (DOESN'T HELP)

$GUI = GUICreate("Main", 300, 200, 300, 300)
GUICtrlSetState(-1,$GUI_DISABLE)
$image = GUICtrlCreatePic(@ScriptDir&"\Image.bmp",0,0,300,200)
GUICtrlSetState(-1,$GUI_DISABLE)

$OnGraphic = GUICtrlCreateGraphic(30, 20, 70, 70)
GUICtrlSetTip(-1, " On " )             ; show tooltip as a test
$OffGraphic = GUICtrlCreateGraphic(140, 20, 70, 70)
GUICtrlSetTip(-1, " Off " )            ; show tooltip as a test

$regularButton1 = GUICtrlCreateButton("Yes", 40, 160, 30, 20)
$regularButton2 = GUICtrlCreateButton("No", 80, 160, 30, 20)
$exit = GUICtrlCreateButton("X", 280, 10, 16, 16)
$reset = GUICtrlCreateButton("reset", 240, 100, 60, 20)
$display = GUICtrlCreateInput("", 40, 100, 200, 20)
$state = GUICtrlCreateInput("", 120, 160, 100, 20)

GUISetState()

While 1
    $gMsg = GUIGetMsg()        ; read button click
    Switch $gMsg
        Case $regularButton1
            GUICtrlSetData($state, "Yes")
        Case $regularButton2
            GUICtrlSetData($state, "No")
        Case $OnGraphic
            GUICtrlSetData( $display, GUICtrlRead($display) & "On" )
        Case $OffGraphic
            GUICtrlSetData( $display, GUICtrlRead($display) & "Off" )
        Case $reset
            GUICtrlSetData( $display, "" )
        Case $exit
            Exit
    EndSwitch
WEnd

Think in terms of a game in which you click five times rapidly on a symbol. The script only receives two -- maybe three -- of the clicks. I posted a question a few weeks ago here, and the $WM_Command method emerged as the apparent solution. The only drawback I'm aware of is the extra cycling I described above.

Thanks for the response. I certainly look forward to any other suggestions of methods.

Link to comment
Share on other sites

Every control sends various notifications to the parent window through WM_NOTIFY and WM_COMMAND messages. That's why there are means to get notification code and control id/handle, so you could filter out the stuff you don't need.

Why is that a drawback, exactly?

"be smart, drink your wine"

Link to comment
Share on other sites

Why is that a drawback, exactly?

Thanks for your response.

The drawback is that in my full script, I also have ControlSends to another window. Between those and the mouse clicks, the $WM_Command processing function gets flooded with these multiple notifications -- sort of like an echo effect: one user action invokes several notifications. I developed the simplified example in my first post to try to isolate and understand what was going on.

As I said in my original post, I'm unsure why I get three cycles in response to one click in my example script. Is it mouse click down, mouse click up? ... and then what? And by "filtering", do you mean only responding to notifications that are recognized? Or is there a way to suppress unneeded notifications?

Link to comment
Share on other sites

If you want to see what flooded really means, check how many WM_NOTIFY messages are generated when you move mouse over a virtual listview which has some columns, and the sad part is that all of them actually have to be handled for it to work. 3 messages aren't worth even a single drop in my book, especially when/if you're really interested only in one of them :D

If you mean 3 WM_COMMAND messages in your example script when you click Yes/No button, then they are - a button sends BN_CLICKED notification when you click it. Then, input box sends EN_UPDATE notification that its display is about to change (because of GUICtrlSetData), and after that it sends EN_CHANGE notification to report that its display has changed.

It's obvious that you have no previous experience with Win32 GUI programming (and maybe programming in general), so it's hard for you to wrap your mind around this whole concept of working with windows messages (and maybe even about constructing a logic flow in your script with the help of conditional statements If...Then, Switch...Case, etc.). Which is why I don't know what to say, because to me all this seems pretty clear.

Generally speaking, you have a function that gets called on multiple events. If you want something to be executed only on specific event for specific control, you simply make it so, you have all the tools. Who cares how many times the function got called in total.

At the start of the function, you know control ID of the control which sent the notification, and the notification code itself. If you have multiple GUI windows, you can also add GUI handle ($hWnd) to your logic.

Even in your example script, GUICtrlSetData($display, "On") or GUICtrlSetData($display, "Off") only happens when corresponding graphic control is clicked. To make sure of that you should also be checking the $iNotifyCode, because as I said, a control can send several various notifications (doesn't happen in this particular case, but that doesn't mean it can't happen in other cases), and unless you absolutely want something to happen for each one of them, you have to check for that. If you have multiple GUIs, lets say their handles are stored in global variables $hGui1 and $hGui2, and you only want to tinker with the controls in 1st one, before everything else simply do a

If $hWnd <> $hGui1 Then Return

That's about it. I can't believe such things really need so many words...

Edited by Siao

"be smart, drink your wine"

Link to comment
Share on other sites

It's obvious that you have no previous experience with Win32 GUI programming ...

Ouch! I was hoping that wasn't so apparent. Truth is, I never looked at a Win32GUI until about eight weeks ago. In these weeks, however, I've been amazed at what GUIs constructed with AutoIt can be made to do.

From your perspective, I guess it's painful to watch neophytes stumble through many of these things. It's a complicated runtime environment on the PC. One only has to read a few passages of MSDN2 documentation to be amazed that it all can ever work (mostly). Only through some coaching and redirection do folks like me ever stand a chance at moving upward. I do appreciate you taking the time to explain what you have. Like stopping to ask directions in a strange city, a little help can go a long way.

Regarding the flood of notifications, I've done more monitoring of my main application and have found -- unbelievable to me -- that there are over 100 notifications per second. So something else is triggering them. I'm in the process of disabling sections of the script to find the culprit(s). Overall, the script is structured just the way my example is, so until I find the exact cause, I remain baffled by the situation.

Thanks again for your help.

Link to comment
Share on other sites

Well, I've gotten to the bottom of the flood of notifications. It is due to a keystroke detection method I put in last week:

I just read the input control contents on each cycle of my While 1 ... WEnd loop and compare to the previous contents

That method was the apparent "best method" to be able to detect individual keystrokes. (What I had hoped for was the ability to receive WM_CHAR directly from the OS, but I understand that direct mode is not available in AutoIt.) My error was clearing the input control and placing focus on it -- even if nothing had been entered. Having those two steps inside an If statement put things back to "normal".

So, unless another method is suggested, I'll tune my loop delay and live with all the extraneous notifications.

Link to comment
Share on other sites

I guess it's painful to watch neophytes stumble through many of these things.

Nah, pain is those critters who keep posting trivial questions without even bothering to look it up in the helpfile (or failing real bad at doing it). If it's not in the helpfile and hasn't been answered in the forums a hundred times over, I don't mind.

Thing is that I kind of go by the assumption that if I know something, most coders with minimal experience could figure it out without much problems too. Not even mentioning the solutions I pillage from Google, and that resource is available for all. :D

Regarding WM_CHAR, and to suggest anything we'd have to see more of your script, or know why do you need this key detection for... depending on that, some ways may be better than others.

"be smart, drink your wine"

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...