Sign in to follow this  
Followers 0
DarkBoost

Assistance with GUIRegisterMsg()

9 posts in this topic

I discovered GUIRegisterMsg() and looking for assistance with the below example, obviously $WM_COMMAND is not the correct command and having difficulty with additional supported commands example "GUIRegisterMsg($WM_INPUT..." and "GUIRegisterMsg(WM_INPUT..." failed with undeclared variable messages however using codes like this "GUIRegisterMsg(0x0005..." worked.

Any advice would be greatly appreciated:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1) ;1=Enabled

Global $input[5], $msg

GUICreate("", 300, 70)
$input[1] = GUICtrlCreateInput("", 10, 10, 135, 20)
$input[2] = GUICtrlCreateInput("", 10, 40, 135, 20)
$input[3] = GUICtrlCreateLabel("", 155, 10, 135, 20)
$input[4] = GUICtrlCreateLabel("", 155, 40, 135, 20)
GUICtrlSetBkColor($input[3], 0xCCCCCC)
GUICtrlSetBkColor($input[4], 0xCCCCCC)
GUIRegisterMsg($WM_COMMAND, "input_top")
GUIRegisterMsg($WM_COMMAND, "input_bottom")
GUISetState()

Do
    $msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE

Func input_top()
    Local $read
    $read = GUICtrlRead($input[1])
    GUICtrlSetData($input[3], $read)
EndFunc ;==>INPUT: Top

Func input_bottom()
    Local $read
    $read = GUICtrlRead($input[2])
    GUICtrlSetData($input[4], $read)
EndFunc ;==>INPUT: Bottom

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

DarkBoost,

Not quite...... :evil:

For a start, all functions called by GUIRegisterMsg must begin something like this:

Func MY_WM_COMMAND($hWnd, $Msg, $wParam, $lParam)

or you stand no chance!

Please explain what you want to do and we will see what we can develop together. ;)

M23

Edit: Clarity.

Edited by Melba23

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

#3 ·  Posted (edited)

Cheers... In my example I am trying to execute the GUIRegisterMsg() and update the Label only when the user enters text in the specified Input field.

Hope that makes sense ;)

Would be awesome if it was as easy as: GUIRegisterMsg($input[1], "input_top")

Edited by DarkBoost

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

DarkBoost,

Would be awesome if it was as easy as: GUIRegisterMsg($input[1], "message_top")

Well, it is a bit more complicated than that - but not too difficult: :evil:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3> ; Added to get the value of $EN_CHANGE for our function

Opt("MustDeclareVars", 1) ;1=Enabled

Global $input[5], $msg

GUICreate("", 300, 70)
$input[1] = GUICtrlCreateInput("", 10, 10, 135, 20)
$input[2] = GUICtrlCreateInput("", 10, 40, 135, 20)
$input[3] = GUICtrlCreateLabel("", 155, 10, 135, 20)
$input[4] = GUICtrlCreateLabel("", 155, 40, 135, 20)
GUICtrlSetBkColor($input[3], 0xCCCCCC)
GUICtrlSetBkColor($input[4], 0xCCCCCC)
GUISetState()

GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")

Do
    $msg = GUIGetMsg()
Until $msg = $GUI_EVENT_CLOSE

Func MY_WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

    Local $iIDFrom = BitAND($wParam, 0xFFFF) ; LoWord - this gives the control which sent the message
    Local $iCode = BitShift($wParam, 16)     ; HiWord - this gives the message that was sent
    If $iCode = $EN_CHANGE Then ; If we have the correct message
        Switch $iIDFrom ; See if it comes from one of the inputs
            Case $input[1]
                GUICtrlSetData($input[3], GUICtrlRead($input[1]))
            Case $input[2]
                GUICtrlSetData($input[4], GUICtrlRead($input[2]))
        EndSwitch
    EndIf
EndFunc ;==>MY_WM_COMMAND

Ask if there is anything you do not understand. :evil:

I learnt how to do this by studying the many examples on the forum - you will soon pick it up. But do read the Help file page carefully, especially this bit:

"Warning: blocking of running user functions which executes window messages with commands such as "Msgbox()" can lead to unexpected behavior, the return to the system should be as fast as possible !!!"

You will crash if you stay in the function too long. I often use the function to set a flag which I then pick up elsewhere in the script to start functions which might take a bit of time.

M23

Edit:

You do not actually need GUIRegisterMsg to do this, by the way: :idea:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1) ;1=Enabled

Global $input[5], $msg

GUICreate("", 300, 70)
$input[1] = GUICtrlCreateInput("", 10, 10, 135, 20)
$input[2] = GUICtrlCreateInput("", 10, 40, 135, 20)
$input[3] = GUICtrlCreateLabel("", 155, 10, 135, 20)
$input[4] = GUICtrlCreateLabel("", 155, 40, 135, 20)
GUICtrlSetBkColor($input[3], 0xCCCCCC)
GUICtrlSetBkColor($input[4], 0xCCCCCC)
GUISetState()

Do

    $msg = GUIGetMsg()

    If GUICtrlRead($input[1]) <> GUICtrlRead($input[3]) Then GUICtrlSetData($input[3], GUICtrlRead($input[1]))
    If GUICtrlRead($input[2]) <> GUICtrlRead($input[4]) Then GUICtrlSetData($input[4], GUICtrlRead($input[2]))

Until $msg = $GUI_EVENT_CLOSE

But it is a good learning exercise!

Happy New Year. ;)

M23

Edited by Melba23

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

Thank you for taking the time to write this and to show the alternative method, I am really trying to understand how GUIRegisterMsg() works.

a.) GUIRegisterMsg() acts like a HotKey which calls a Function when something in the GUI changes = true/false ?

b.) $hWnd, $Msg, $wParam, $lParam are like Array results containing data relating to the change that was made in the GUI = true/false ?

I am lost with BitAND and BitShift, do not understand what they are doing

I checked $EN_CHANGE in #include <EditConstants.au3> shows as "Global Const $EN_CHANGE = 0x300" but do not understand what this means

I apologise for the questions, just want to understand rather than keep asking for solutions.

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

On my XP this scripts works.

The remark, "!!! To make the user function workable you have to define it with maximum 4 function parameters otherwise the function won't be called !!!", is found in the Help file under the GUIRegisterMsg function.

This means you have to define it with a minimum of zero parameters up to a maximum 4 parameters otherwise the function won't be called !!!

;#include <GUIConstantsEx.au3>
;#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1) ;1=Enabled

Global $input[5], $msg

GUICreate("", 300, 70)
$input[1] = GUICtrlCreateInput("", 10, 10, 135, 20)
$input[2] = GUICtrlCreateInput("", 10, 40, 135, 20)
$input[3] = GUICtrlCreateLabel("", 155, 10, 135, 20)
$input[4] = GUICtrlCreateLabel("", 155, 40, 135, 20)
GUICtrlSetBkColor($input[3], 0xCCCCCC)
GUICtrlSetBkColor($input[4], 0xCCCCCC)

GUIRegisterMsg(0x0111, "Input") ; $WM_COMMAND from WindowsConstants.au3

GUISetState()

Do
Until GUIGetMsg() = -3 ; $GUI_EVENT_CLOSE from GUIConstantsEx.au3


; Remarks Help File - !!! To make the user function workable you have to define it
;   with maximum 4 function parameters otherwise the function won't be called !!!
Func Input()
    Local $read
    $read = GUICtrlRead($input[1])
    GUICtrlSetData($input[3], $read)
    $read = GUICtrlRead($input[2])
    GUICtrlSetData($input[4], $read)
EndFunc ;==>Input
Edited by Malkey

Share this post


Link to post
Share on other sites

DarkBoost,

This is how I understand GUIRegisterMsg - purists might quibble over detail, but it works for hobbyists like me! :evil:

Windows works by sending messages to everything on the system, so that everything knows what is going on. By messages, I mean things like the $GUI_EVENT_CLOSE we look for when we exit a GUI - but the possible range is much, much wider; change of focus, change of state, mouseclicks, mousemoves, key presses, etc, etc, etc.

GUIRegisterMsg allows us to intercept certain of these messages as they flash round, allowing us to see who sent what. The function we call must have a maximium of 4 parameters because that is the format Windows uses itself.

Let us look at the example I gave above: we used GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND") - which translates as "Whenever a WM_COMMAND message is sent, please intercept it and pass it through the MY_WM_COMMAND function in this script". The actual message title is denoted by the constant $WM_COMMAND which is stored in WindowsConstant.au3 #include file.

The function itself has the normal 4 parameters - $hWnd, $iMsg, $wParam, $lParam - which relate to the following:

$hWnd - the GUI which sent the message

$iMsg - the code for the mesasge sent

$wParam, $iParam - details of what exactly the message is about. this varies according to the message and details can be found in MSDN.

In the example, we needed to look at $wParam, because for the WM_COMMAND message this parameter holds the details of the particular control which was involved and the sub-message it sent. We can ignore the GUI and the main message in this case - WM_COMMAND is a huge set and as we are interested in the control we need not worry about the GUI - if we correctly identify the control, it can only come from our GUI! But in other cases, this is vital information, as you can imagine.

In this particular case, the low bytes of the $wParam parameter give us the control and the high bytes the message (MSDN is the bible here). The Bit* operators allow us to extract these values:

Local $iIDFrom = BitAND($wParam, 0xFFFF) ; LoWord - this gives the control which sent the message
Local $iCode = BitShift($wParam, 16)     ; HiWord - this gives the message that was sent

We now know which control sent the message and what the sub-message was - so we check if it is one we are looking for and if it is we do whatever we need to do:

If $iCode = $EN_CHANGE Then ; If we have the correct message
    Switch $iIDFrom ; See if it was one of our controls
        Case $input[1]
        Case $input[2]

When we have finished, the message gets passed along the chain of all the other message handlers so all the other controls in the system can see if they are interested too. That is why you must not hold up the message for too long - otherwise the system gets behind and becomes unstable.

In some cases you might actually want to stop the message going further - my UDF for preventing the focus lines on controls is a good example - so we add a Return line to the function which stops it dead. In the focus case this was to prevent the system adding the dotted lines around the control - passing the message on was exactly what I was trying to prevent. :evil:

Right, that is enough for you to be getting on with after a night spent seeing in the New Year. ;) As I said earlier, look out for examples in the forum and see if you can work out what they are doing. Then try to write a few simple ones on your own - it is the best way to learn.

Have fun. You know where we are if you need help.

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

This is how I understand - purists might quibble over detail, but it works for hobbyists like me! :evil:

Melba, a really good explanation of GUIRegisterMsg() ;), couldn't see anything I understand differently. This is worth a line in my signature :evil:!

On my XP this scripts works.

Yep, but what it does is read the $input[1] and $input[3] controls value ANY time a WM_COMMAND is sent, even if it is not targeted at $input[1]. Better try something like this (added a ConsoleWrite() function for debugging, this is how I always determine which iCode means what, get focus, lose focus, change of input, click, etc...):

#cs ----------------------------------------------------------------------------

    AutoIt Version: 3.3.2.0
    Author:         myName

    Script Function:
    Template AutoIt script.

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here

;#include <GUIConstantsEx.au3>
;#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1) ;1=Enabled

Global $input[5], $msg

GUICreate("", 300, 70)
$input[1] = GUICtrlCreateInput("", 10, 10, 135, 20)
$input[2] = GUICtrlCreateInput("", 10, 40, 135, 20)
$input[3] = GUICtrlCreateLabel("", 155, 10, 135, 20)
$input[4] = GUICtrlCreateLabel("", 155, 40, 135, 20)
GUICtrlSetBkColor($input[3], 0xCCCCCC)
GUICtrlSetBkColor($input[4], 0xCCCCCC)

GUIRegisterMsg(0x0111, "Input") ; $WM_COMMAND from WindowsConstants.au3

GUISetState()

Do
Until GUIGetMsg() = -3 ; $GUI_EVENT_CLOSE from GUIConstantsEx.au3


; Remarks Help File - !!! To make the user function workable you have to define it
;   with maximum 4 function parameters otherwise the function won't be called !!!
Func Input($hWnd, $msg, $wParam, $lParam)

    Local $iIDFrom = BitAND($wParam, 0xFFFF) ; LoWord - this gives the control which sent the message
    Local $iCode = BitShift($wParam, 16) ; HiWord - this gives the message that was sent
    Local $read

    ConsoleWrite($hWnd & @TAB & $iIDFrom & @TAB & $iCode & @CRLF) ; Debug, start the program, see which iCode performs which task

    Switch $iIDFrom
        Case $input[1]
            Switch $iCode
                Case 256 ; Input gets focus, found it by looking at the consolewrite() results
                    GUICtrlSetData($input[1], "")
                    GUICtrlSetData($input[3], "")
                Case 512 ; Input losses focus
                    $read = GUICtrlRead($input[1])
                    GUICtrlSetData($input[3], $read)
            EndSwitch

        Case $input[2]
            Switch $iCode
                Case 256 ; Input gets focus
                    GUICtrlSetData($input[2], "")
                    GUICtrlSetData($input[4], "")
                Case 512 ; Input losses focus
                    $read = GUICtrlRead($input[2])
                    GUICtrlSetData($input[4], $read)
            EndSwitch
    EndSwitch

EndFunc   ;==>Input

Share this post


Link to post
Share on other sites

Melba23 Thank for taking the time to write this, it is very well written and informative. This has given me alot to process and now time to practice.

KaFu That is a great tip using the ConsoleWrite() for debugging, cheers

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