Jump to content

GUIRegisterMsg replacement for GUICtrlSetOnEvent and GUIGetMsg


BrewManNH
 Share

Recommended Posts

Here's a little snippet that I wrote up that demonstrates a way to eliminate the message loop and onevent modes of detecting control and GUI events. I was inspired to attempt this by this feature request and the answer that Valik gave when he rejected it. I wasn't sure how to write the wrapper that he said could be done to do this, so I dug into windows messages to see what I could come up with.

This snippet uses 3 different windows messages for various controls and for the GUI events. I have also included code that shows that you can use this in conjunction with GUIGetMsg, it should work just as well alongside OnEvent mode as well. You will probably have to play around with it to get it to work with every different type of control that AutoIt can make. I originally had a combo box in the GUI, but they work strangely because an event is fired every time the GUI gets focus and the combo is the last control actioned.

I hope this is informative to some and if there's a way of doing this easier, I'd love to know.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <MenuConstants.au3>
GUIRegisterMsg($WM_COMMAND, "_WM_EXTRACTOR")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_EXTRACTOR")
GUIRegisterMsg($WM_HSCROLL, "_WM_EXTRACTOR")
$GUI = GUICreate("Test GUI", 200, 200, -1, -1, BitOR($WS_THICKFRAME, $gui_ss_default_gui))
$Button = GUICtrlCreateButton("Test", 20, 20)
$Button2 = GUICtrlCreateButton(" Another Test ", 20, 100)
$Slider = GUICtrlCreateSlider(20, 60, 150)
$hSlider = GUICtrlGetHandle($Slider)
GUISetState()
While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $Button
            MsgBox(0, "", "You pressed the button marked TEST")
        Case $Button2
            MsgBox(0, "", "You pressed the button marked 'Another Test'")
    EndSwitch
WEnd
Func _WM_EXTRACTOR($hWnd, $iMsg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Local $hCtrl = $lParam
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $WM_HSCROLL
            Switch $lParam
                Case $hSlider
                    ConsoleWrite("+Slider moved to: " & GUICtrlRead($Slider) & @LF)
            EndSwitch
        Case $WM_VSCROLL
        Case $WM_COMMAND
            Switch $nID
                Case $Button
                    ConsoleWrite(">Button Test pressed" & @LF)
                Case $Button2
                    ConsoleWrite(">Button Another Test pressed" & @LF)
                Case Else
                    MsgBox(0, "MY_WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @LF & _
                            "MsgID" & @TAB & ":" & $msg & @LF & _
                            "wParam" & @TAB & ":" & $wParam & @LF & _
                            "lParam" & @TAB & ":" & $lParam & @LF & @LF & _
                            "WM_COMMAND - Infos:" & @LF & _
                            "-----------------------------" & @LF & _
                            "Code" & @TAB & ":" & $nNotifyCode & @LF & _
                            "CtrlID" & @TAB & ":" & $nID & @LF & _
                            "CtrlHWnd" & @TAB & ":" & $hCtrl)
            EndSwitch
        Case $WM_SYSCOMMAND
            Switch $wParam
                Case $SC_CLOSE
                    ConsoleWrite("!Exit pressed" & @LF)
                    Exit
                Case $SC_RESTORE
                    ConsoleWrite("!Restore window" & @LF)
                Case $SC_MINIMIZE
                    ConsoleWrite("!Minimize Window" & @LF)
                Case $SC_MOUSEMENU + 3
                    ConsoleWrite("!System menu pressed" & @LF)
                Case $SC_MOVE
                    ConsoleWrite("!System menu Move Option pressed" & @LF)
                    Return 0
                Case $SC_SIZE
                    ConsoleWrite("!System menu Size Option pressed" & @LF)
                    Return 0
                Case $SC_MOUSEMENU + 2 ; This and the following case statements are only valid when the GUI is resizable
                    ConsoleWrite("!Right side of GUI clicked" & @LF)
                    Return 0
                Case $SC_MOUSEMENU + 1
                    ConsoleWrite("!Left side of GUI clicked" & @LF)
                    Return 0
                Case $SC_MOUSEMENU + 8
                    ConsoleWrite("!Lower Right corner of GUI clicked" & @LF)
                    Return 0
                Case $SC_MOUSEMENU + 7
                    ConsoleWrite("!Lower Left corner of GUI clicked" & @LF)
                    Return 0
                Case $SC_MOUSEMENU + 6
                    ConsoleWrite("!Bottom side of GUI clicked" & @LF)
                    Return 0
                Case Else
                    MsgBox(0, "MY_WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @LF & _
                            "MsgID" & @TAB & ":" & $msg & @LF & _
                            "wParam" & @TAB & ":" & $wParam & @LF & _
                            "lParam" & @TAB & ":" & $lParam & @LF & @LF & _
                            "WM_COMMAND - Infos:" & @LF & _
                            "-----------------------------" & @LF & _
                            "Code" & @TAB & ":" & $nNotifyCode & @LF & _
                            "CtrlID" & @TAB & ":" & $nID & @LF & _
                            "CtrlHWnd" & @TAB & ":" & $hCtrl)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_EXTRACTOR
Edited by BrewManNH

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

You're probably right about that. I'll request for it to be moved, that makes more sense to have it in there.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Here's an updated version of the same code as above, but using a single function to handle all 3 types of Windows messages. I'm sure there's a Windows constant for the 2 numbers I used in the Switch statement for $iMsg, but I wasn't able to find out what it was. The 273 is used to activate the button control function, which also works on combobox controls, the 274 is the GUI messages for things like the sysmenu and the close button. If anyone knows the variables for those 2 numbers, please let me know.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
GUIRegisterMsg($WM_COMMAND, "_WM_EXTRACTOR")
GUIRegisterMsg($WM_SYSCOMMAND, "_WM_EXTRACTOR")
GUIRegisterMsg($WM_HSCROLL, "_WM_EXTRACTOR")
$GUI = GUICreate("Test GUI", 200, 200, -1, -1, BitOR($WS_THICKFRAME, $gui_ss_default_gui))
$Button = GUICtrlCreateButton("Test", 20, 20)
$Button2 = GUICtrlCreateButton(" Another Test ", 20, 100)
$Slider = GUICtrlCreateSlider(20, 60, 150)
$hSlider = GUICtrlGetHandle($Slider)
GUISetState()
While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $Button
            MsgBox(0, "", "You pressed the button marked TEST")
        Case $Button2
            MsgBox(0, "", "You pressed the button marked 'Another Test'")
    EndSwitch
WEnd
Func _WM_EXTRACTOR($hWnd, $iMsg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Local $hCtrl = $lParam
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $WM_HSCROLL
            Switch $lParam
                Case $hSlider
                    ConsoleWrite("+Slider moved to: " & GUICtrlRead($Slider) & @LF)
            EndSwitch
        Case $WM_VSCROLL
        Case 273
            Switch $nID
                Case $Button
                    ConsoleWrite(">Button Test pressed" & @LF)
                Case $Button2
                    ConsoleWrite(">Button Another Test pressed" & @LF)
                Case Else
                    MsgBox(0, "MY_WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @LF & _
                            "MsgID" & @TAB & ":" & $msg & @LF & _
                            "wParam" & @TAB & ":" & $wParam & @LF & _
                            "lParam" & @TAB & ":" & $lParam & @LF & @LF & _
                            "WM_COMMAND - Infos:" & @LF & _
                            "-----------------------------" & @LF & _
                            "Code" & @TAB & ":" & $nNotifyCode & @LF & _
                            "CtrlID" & @TAB & ":" & $nID & @LF & _
                            "CtrlHWnd" & @TAB & ":" & $hCtrl)
            EndSwitch
        Case 274
            Switch $wParam
                Case 0xf060
                    ConsoleWrite("!Exit pressed" & @LF)
                    Exit
                Case 0xF120
                    ConsoleWrite("!Restore window" & @LF)
                Case 0xF020
                    ConsoleWrite("!Minimize Window" & @LF)
                Case 0xF093
                    ConsoleWrite("!System menu pressed" & @LF)
                Case 0xF010
                    ConsoleWrite("!System menu Move Option pressed" & @LF)
                    Return 0
                Case 0xF000
                    ConsoleWrite("!System menu Size Option pressed" & @LF)
                    Return 0
                Case 0xF002 ; This and the following case statements are only valid when the GUI is resizable
                    ConsoleWrite("!Right side of GUI clicked" & @LF)
                    Return 0
                Case 0xf001
                    ConsoleWrite("!Left side of GUI clicked" & @LF)
                    Return 0
                Case 0xF008
                    ConsoleWrite("!Lower Right corner of GUI clicked" & @LF)
                    Return 0
                Case 0xF007
                    ConsoleWrite("!Lower Left corner of GUI clicked" & @LF)
                    Return 0
                Case 0xF006
                    ConsoleWrite("!Bottom side of GUI clicked" & @LF)
                    Return 0
                Case Else
                    MsgBox(0, "MY_WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @LF & _
                            "MsgID" & @TAB & ":" & $msg & @LF & _
                            "wParam" & @TAB & ":" & $wParam & @LF & _
                            "lParam" & @TAB & ":" & $lParam & @LF & @LF & _
                            "WM_COMMAND - Infos:" & @LF & _
                            "-----------------------------" & @LF & _
                            "Code" & @TAB & ":" & $nNotifyCode & @LF & _
                            "CtrlID" & @TAB & ":" & $nID & @LF & _
                            "CtrlHWnd" & @TAB & ":" & $hCtrl)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_EXTRACTOR

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

Nice idea BrewManNH and a good example for those who are keen to learn how GUIRegisterMsg works.

UDF List:

 
_AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Yeah, that's the ones I was looking for. They're in WindowsConstants.au3 but in Hex so it threw me off. :D So, replace 274 with $WM_SYSCOMMAND and 273 with $WM_COMMAND, which makes perfect sense because that's what messages I am looking for at those points in the script.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

This is really cool.. now I won't have to cram *everything* in my main loop any more, functions are not blocking GUI messages e.g.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")
GUIRegisterMsg($WM_SYSCOMMAND, "MY_SYS_COMMAND")
GUIRegisterMsg($WM_HSCROLL, "WM_HVSCROLL")
$GUI = GUICreate("Test GUI", 200, 200, -1, -1, BitOR($WS_THICKFRAME, $gui_ss_default_gui))
$Button = GUICtrlCreateButton("Test", 20, 20)
$Button2 = GUICtrlCreateButton(" Another Test ", 20, 100)
$Slider = GUICtrlCreateSlider(20, 60, 150)
$hSlider = GUICtrlGetHandle($Slider)
GUISetState()


Global $iStopTest = 0
_Test()

While 1
    Sleep(100)
WEnd

Func _Test()
    While 1
        If $iStopTest Then
            ConsoleWrite('_test function stopped!' &@lf)
            ExitLoop
        EndIf
        Sleep(1000)
        ConsoleWrite(@HOUR&@MIN&@SEC& " working..." &@lf)
    WEnd
EndFunc

Func MY_SYS_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Local $hCtrl = $lParam
    Switch $wParam
        Case 0xf060
            ConsoleWrite("!Exit pressed" & @LF)
            Exit
        Case 0xF120
            ConsoleWrite("!Restore window" & @LF)
        Case 0xF020
            ConsoleWrite("!Minimize Window" & @LF)
    EndSwitch
    Return $GUI_RUNDEFMSG ; Only workout clicking on the button
EndFunc   ;==>MY_SYS_COMMAND

Func MY_WM_COMMAND($hWnd, $msg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Local $hCtrl = $lParam
    Switch $nID
        Case $Button
            MsgBox(0, "", "You pressed the button marked TEST, stopping '_Test' function")
            $iStopTest = 1
        Case $Button2
            MsgBox(0, "", "You pressed the button marked 'Another Test'")
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_WM_COMMAND

Func WM_HVSCROLL($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $WM_HSCROLL
            Switch $lParam
                Case $hSlider
                    ConsoleWrite("+Slider moved to: " & GUICtrlRead($Slider) & @LF)
            EndSwitch
        Case $WM_VSCROLL
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_HVSCROLL
Link to comment
Share on other sites

I have often used WM_COMMAND messages to add extra functionality to controls like edit and combo boxes. However this has inspired me to start and re-write some of my GUIs to give users a clean way to stop long blocking functions, by allowing them to click a button on the GUI which will exit the function in a controlled way.

Thank you BrewManNH

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

In case anyone was wondering how this method of reading controls could be used to stop blocking functions as mentioned by Bowmore above, try using the code below to simulate how this can be used to bypass long looping functions, or functions that take a long time to process. I've also added OnEvent mode functions so you can test it using both methods.

If you run this script and then press the Test button (with the GUIRegisterMsg for WM_SYSCOMMAND commented out) the script will loop for 10 seconds and you won't be able to exit the GUI until that loop has finished. With that message uncommented, it will exit immediately. Also, you can see that you can still action the other controls while the loop is running.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1) ; <<<<<<<<<<< comment this out to use MessageLoop mode
GUIRegisterMsg($WM_COMMAND, "_WM_EXTRACTOR")
;~ GUIRegisterMsg($WM_SYSCOMMAND, "_WM_EXTRACTOR") ; Try exiting the GUI after pressing the Test button, with this commented out, before 10 seconds has passed
GUIRegisterMsg($WM_HSCROLL, "_WM_EXTRACTOR")
$GUI = GUICreate("Test GUI", 200, 200, -1, -1, BitOR($WS_THICKFRAME, $gui_ss_default_gui))
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
$Button = GUICtrlCreateButton("Test", 20, 20)
GUICtrlSetOnEvent(-1, "_Button")
$Button2 = GUICtrlCreateButton(" Another Test ", 20, 100)
GUICtrlSetOnEvent(-1, "_Button2")
$Slider = GUICtrlCreateSlider(20, 60, 150)
$hSlider = GUICtrlGetHandle($Slider)
GUISetState()
While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $Button
            MsgBox(0, "", "You pressed the button marked TEST")
            For $I = 1 To 1000
                Sleep(1)
            Next
        Case $Button2
            MsgBox(0, "", "You pressed the button marked 'Another Test'")
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
Func _WM_EXTRACTOR($hWnd, $iMsg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0x0000FFFF)
    Local $hCtrl = $lParam
    #forceref $hWnd, $iMsg, $wParam, $lParam
    Switch $iMsg
        Case $WM_HSCROLL
            Switch $lParam
                Case $hSlider
                    ConsoleWrite("+Slider moved to: " & GUICtrlRead($Slider) & @LF)
            EndSwitch
        Case $WM_VSCROLL
        Case 273
            Switch $nID
                Case $Button
                    ConsoleWrite(">Button Test pressed" & @LF)
                Case $Button2
                    ConsoleWrite(">Button Another Test pressed" & @LF)
                Case Else
                    MsgBox(0, "MY_WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @LF & _
                            "MsgID" & @TAB & ":" & $msg & @LF & _
                            "wParam" & @TAB & ":" & $wParam & @LF & _
                            "lParam" & @TAB & ":" & $lParam & @LF & @LF & _
                            "WM_COMMAND - Infos:" & @LF & _
                            "-----------------------------" & @LF & _
                            "Code" & @TAB & ":" & $nNotifyCode & @LF & _
                            "CtrlID" & @TAB & ":" & $nID & @LF & _
                            "CtrlHWnd" & @TAB & ":" & $hCtrl)
            EndSwitch
        Case 274
            Switch $wParam
                Case 0xf060
                    ConsoleWrite("!Exit pressed" & @LF)
                    Exit
                Case 0xF120
                    ConsoleWrite("!Restore window" & @LF)
                Case 0xF020
                    ConsoleWrite("!Minimize Window" & @LF)
                Case 0xF093
                    ConsoleWrite("!System menu pressed" & @LF)
                Case 0xF010
                    ConsoleWrite("!System menu Move Option pressed" & @LF)
                    Return 0
                Case 0xF000
                    ConsoleWrite("!System menu Size Option pressed" & @LF)
                    Return 0
                Case 0xF002 ; This and the following case statements are only valid when the GUI is resizable
                    ConsoleWrite("!Right side of GUI clicked" & @LF)
                    Return 0
                Case 0xf001
                    ConsoleWrite("!Left side of GUI clicked" & @LF)
                    Return 0
                Case 0xF008
                    ConsoleWrite("!Lower Right corner of GUI clicked" & @LF)
                    Return 0
                Case 0xF007
                    ConsoleWrite("!Lower Left corner of GUI clicked" & @LF)
                    Return 0
                Case 0xF006
                    ConsoleWrite("!Bottom side of GUI clicked" & @LF)
                    Return 0
                Case Else
                    MsgBox(0, "MY_WM_COMMAND", "GUIHWnd" & @TAB & ":" & $hWnd & @LF & _
                            "MsgID" & @TAB & ":" & $msg & @LF & _
                            "wParam" & @TAB & ":" & $wParam & @LF & _
                            "lParam" & @TAB & ":" & $lParam & @LF & @LF & _
                            "WM_COMMAND - Infos:" & @LF & _
                            "-----------------------------" & @LF & _
                            "Code" & @TAB & ":" & $nNotifyCode & @LF & _
                            "CtrlID" & @TAB & ":" & $nID & @LF & _
                            "CtrlHWnd" & @TAB & ":" & $hCtrl)
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_EXTRACTOR
Func _Button()
    MsgBox(0, "", "You pressed the button marked TEST")
    For $I = 1 To 1000
        Sleep(1)
    Next
EndFunc   ;==>_Button
Func _Button2()
    MsgBox(0, "", "You pressed the button marked 'Another Test'")
EndFunc   ;==>_Button2
Func _Exit()
    Exit
EndFunc

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

  • Moderators

BrewManNH,

Have you ever seen the Interrupting a running function tutorial in the Wiki? :D

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 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

 

Link to comment
Share on other sites

BrewManNH,

Have you ever seen the Interrupting a running function tutorial in the Wiki? :D

M23

I've read it many times. I was just explaining how this method could be done with the code I posted in case anyone else hasn't seen it. Also, this example deals with a lot more than just interrupting a function with Windows Messages, but Bowmore's comment prompted me to explain what he was referring to.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

@Bowmore

That's precisely what I was hinting at, albeit more eloquently put. :D

I've successfully updated a project of mine using this method. there's with one caveat though. Any long looping routines inside a WM_COMMAND message can deadlock the whole WM_COMMAND message, which in worse case scenario leads to application freezing, leaving one to wait till the routine finishes or killing the process.

But... of course, with GUICreateDummy() there's a nifty little work around. You'll need GUIOnEvent(), (I don't think this is possible with GUIGetMsg()..).

#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Global $hGUI, $edtData, $btnStart, $btnClose, $lbStatus, $dummyCallBlockingFunction

; this variable is checked inside our "BlockingFunction"
; if it is false then the routine stops
Global $fRUNNING = False

_Example_GUIOnEvent()

Func _Example_GUIOnEvent()
    ; OnEventMode because it's not possible to use GUIGetMsg() when a function is
    Opt("GUIOnEventMode", 1)

    $hGUI = GUICreate("WM_SYSCOMMAND/WM_COMMAND Example", 300, 141, 192, 204, BitOR($WS_THICKFRAME, $gui_ss_default_gui))
    $edtData = GUICtrlCreateEdit("", 8, 16, 290, 57)
    $btnStart = GUICtrlCreateButton("Start", 0, 88, 75, 25)
    $btnClose = GUICtrlCreateButton("Close", 80, 88, 75, 25)
    $lbStatus = GUICtrlCreateLabel("Ready", 0, 120, 196, 17, $SS_SUNKEN)
    $dummyCallBlockingFunction = GUICtrlCreateDummy()

    ; All "BlockingFunctions" e.g. functions that have long looping routines should have
    ; a dummy control to pass the burden to this will allow other message to be processed
    ; we don't need to set GUICtrlOnEvent for other controls because they will by processed
    ; by WM_COMMAND and WM_SYSCOMMAND
    GUICtrlSetOnEvent($dummyCallBlockingFunction, "BlockingFunction")

    ; handles all GUICtrl*Create and _GUICtrl*Create events
    GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

    ; handles GUI_EVENT_CLOSE, etc events
    GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")

    GUISetState(@SW_SHOW)

    While 1
        Sleep(100)
    WEnd
EndFunc

Func Close()
    GUICtrlSetData($edtData, "Shutting down..." &@CRLF)
    Sleep(1000)
    Exit
EndFunc

Func BlockingFunction()
    $fRUNNING = True
    GUICtrlSetData($btnStart, "Stop")
    GUICtrlSetData($lbStatus, "Started!" &@lf)
    GUICtrlSetData($edtData, @HOUR &":"& @MIN &":"& @SEC & " Inializing test.." &@CRLF)
    While 1
        If $fRUNNING = False Then ExitLoop
        GUICtrlSetData($edtData, @HOUR &":"& @MIN &":"& @SEC & " Running test: Quantum spacetime" &@CRLF)
        Sleep(1000)
        GUICtrlSetData($edtData, @HOUR &":"& @MIN &":"& @SEC & " Running test: Splitting atoms" &@CRLF)
        Sleep(100)
    WEnd
    GUICtrlSetData($edtData, @HOUR &":"& @MIN &":"& @SEC & " Testing aborted by user" &@CRLF)
    GUICtrlSetData($lbStatus, "Stopped!" &@lf)
    $fRUNNING = False
    GUICtrlSetData($btnStart ,"Start")
EndFunc

Func WM_SYSCOMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode
    #forceref $hWnd, $iMsg, $iwParam, $ilParam, $hWndFrom, $iIDFrom, $iCode
    $hWndFrom = $ilParam
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word
    Switch $iwParam
        Case 0xF060 ;SC_CLOSE
            ConsoleWrite("!Close window" & @LF)
            Close()
        Case 0xF120 ;SC_RESTORE
            ConsoleWrite("!Restore window" & @LF)
        Case 0xF020 ;SC_MAXIMIZE
            ConsoleWrite("!Maximize window" & @LF)
    EndSwitch
    Return $GUI_RUNDEFMSG ; Only workout clicking on the button
EndFunc   ;==>MY_SYS_COMMAND

Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode
    #forceref $hWnd, $iMsg, $iwParam, $ilParam, $hWndFrom, $iIDFrom, $iCode
    $hWndFrom = $ilParam
    $iIDFrom = BitAND($iwParam, 0xFFFF) ; Low Word
    $iCode = BitShift($iwParam, 16) ; Hi Word

    ; $hWndFrom is equal to @GUI_CtrlHandle
    ; $iIDFrom is equal to  @GUI_CtrlId

    Switch $iIDFrom
        Case $btnStart
            ; "Blocking functions" need to be passed onto a dummy control
            ; so that we can process other messages
            If Not $fRUNNING Then
                GUICtrlSendToDummy($dummyCallBlockingFunction, 1)
            Else
                $fRUNNING = False
            EndIf
        Case $btnClose
            ; Non blocking functions don't need a dummy control
            Close()
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc
Link to comment
Share on other sites

  • Moderators

WinkleDoodle,

You should never put "long looping routines" inside any WM_ message handler. When the Help file for GUIRegisterMsg tells you:

"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 !!!"

it means what it says! :oops:

Windows relies on the free passage of these messages - you block the flow at your peril. :D

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 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

 

Link to comment
Share on other sites

  • Moderators

WinkleDoodle,

Your funeral. :D

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 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

 

Link to comment
Share on other sites

This is a simple example of what I had in mind in my post above.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Global $__gbRun = False

GUIRegisterMsg($WM_COMMAND, "MY_WM_COMMAND")

$GUI = GUICreate("Test GUI", 100, 100, -1, -1, BitOR($WS_THICKFRAME, $gui_ss_default_gui))
$Button = GUICtrlCreateButton("Start", 40, 20, 50, 20)
GUISetState()

While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button
            GUICtrlSetData($Button, "Stop")
            $__gbRun = True
            _LongFunc()
           $__gbRun = False
           GUICtrlSetData($Button, "Start")
    EndSwitch
WEnd

Func _LongFunc()
    While 1
        If $__gbRun = False Then
            If MsgBox(262452, "Warning", "Do you really want to stop the process?") = 6 Then
                ;clean up code goes here
                ExitLoop
            Else
                 $__gbRun = True
            EndIf
       EndIf
       ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : _LongFunc = ' & "Running" & @CRLF &  '>Error code: ' & @error & @CRLF) ;### Debug Console
      Sleep(1000)
   WEnd
EndFunc ;==>_LongFunc

Func MY_WM_COMMAND($hWnd, $msg, $wParam, $lParam)
Local $nNotifyCode = BitShift($wParam, 16)
Local $nID = BitAND($wParam, 0x0000FFFF)
Local $hCtrl = $lParam

   Switch $nID
        Case $Button
             If GUICtrlRead($Button) = "Stop" And $__gbRun = True Then
                $__gbRun = False
                ConsoleWrite(">Button Start/Stop pressed" & @LF)
                Return 0
             EndIf
   EndSwitch
   Return $GUI_RUNDEFMSG
EndFunc ;==>MY_WM_COMMAND
;
Edited by Bowmore

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

  • 3 months later...

Just to be clear on the blocking function. Does this only have to do with loops or blocks like msgbox inside the result of a registerMsg.

Example: Will this fire off the function _aboutPage() and close out the WM_SYSCOMMAND Function - IE Non Blocking?

Func _WM_SYSCOMMAND($hGUI, $iMsg, $wParam, $lParam)
If $iMsg = $WM_SYSCOMMAND Then
  If _WinAPI_LoWord($wParam) = 0x3000 Then ; About item selected from menu
   _aboutPage()
  EndIf
EndIf
EndFunc   ;==>_WM_SYSCOMMAND
Link to comment
Share on other sites

It should jump to the _aboutPage function, it depends on what is in that function as to whether you lock up or not. Try it and see, just don't put an endless Do/While loop in the function and it will probably be ok. The MsgBox function hasn't ever caused a lock up for me using windows messages, this demo uses the MsgBox function in it without crashing it, but that's not to say it can't.

Just remember, a Windows message handler like this can't interrupt another windows message function until the first windows message function has ended. What I mean by this is, in this demo, if you put _Button() under the consolewrite for the $Button windows message, it will jump to the _Button function, but no other windows messages can be handled until that function ends, 10 seconds later.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

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