Jump to content
Advert

_GUIRegisterMsgTell() - A wrapper UDF for GUIRegisterMsg


Go to solution Solved by argumentum,

Recommended Posts

Posted (edited)
#include-once ; #include <_GUIRegisterMsgTell.au3>
;~ #AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7

Global Const $__g_sGUIRegisterMsgTell_VERSION = "0.0.0.2"
Global $__g_iGUIRegisterMsgDebugOn = 0


; #FUNCTION# ====================================================================================================================
; Name...........: _GUIRegisterMsgTell
; Description ...: A wrapper for GUIRegisterMsg that registers Windows messages, tracks their assigned functions,
;                  maintains a history of the last 3 assignments, and allows historical pruning.
; Syntax.........: _GUIRegisterMsgTell([$msgID = Default[, $function = Default[, $iPruneIndex = 0]]])
; Parameters ....: $msgID       - [optional] The Windows message ID to intercept.
;                                 If omitted operates in "Dump Mode".
;                  $function    - [optional] The name of the user-defined function to call, or the function itself.
;                                 If omitted, operates in "Retrieve Mode" (Returns current function).
;                                 If set to < -1 (e.g., -2, -3), operates in "Peek Mode" (Returns historical function natively).
;                                 If set to "-1", operates in "Restore Mode" (Reverts to previous function).
;                                 If set to "" (empty string), it explicitly unregisters the message ID.
;                  $iPruneIndex - [optional] Disables standard modes and enters "Prune Mode". Clears a specific history slot
;                                 (replaces with "") while leaving the rest of the chain/timeline intact.
;                                 1 = Clears the Previous (Prior) function slot.
;                                 2 = Clears the Oldest function slot.
; Return values .: Dump Mode ($msgID is a Keyword):
;                    Success - Returns the internal Map of registered messages. (@error = 0, @extended = 2)
;                  Retrieve Mode ($function is a Keyword):
;                    Success - Returns the currently active function name. (@error = 0, @extended = 0)
;                    Failure - Returns "" if the ID has never been touched. (@error = 0, @extended = 1)
;                  Peek Mode ($function < -1):
;                    Success - Returns the historical function name at that depth. (@error = 0, @extended = 0)
;                    Failure - Returns "" if that history depth doesn't exist. (@error = 0, @extended = 4)
;                  Restore Mode ($function = -1):
;                    Success - Reverts to the previous function and returns 1. (@error = 0, @extended = 0)
;                    Failure - Returns 0 if there is no history to restore. (@error = 0, @extended = 3)
;                  Prune Mode ($iPruneIndex > 0):
;                    Success - Returns 1 after replacing that historical tier with "". (@error = 0, @extended = 0)
;                    Failure - Returns 0 if the target history slot doesn't exist. (@error = 0, @extended = 5 or 6)
;                  Register Mode ($msgID and $function provided, $iPruneIndex = 0):
;                    Success - Returns 1 (Return value passed through from native GUIRegisterMsg).
;                    Failure - Returns 0 (Return value passed through from native GUIRegisterMsg).
; Author ........: argumentum ( blame me )
; Related .......: GUIRegisterMsg
; Link ..........: https://www.autoitscript.com/forum/topic/213746-_guiregistermsgtell-a-wrapper-udf-for-guiregistermsg/
; Examples ......: _GUIRegisterMsgTell($WM_COMMAND, "MY_WM_COMMAND") ; Register a specific function
;                  Local $sCurrentFunc = _GUIRegisterMsgTell($WM_COMMAND) ; Retrieve a specific message's function
;                  Local $mAllFuncs = _GUIRegisterMsgTell() ; return the tracking Map
; ===============================================================================================================================
Func _GUIRegisterMsgTell($msgID = Default, $function = Default, $iPruneIndex = 0)
    Local Static $mFuncs[]
    Local $sRestOfStack, $iPipePos, $aHistory, $sFuncName, $sKey = String($msgID)

    ; Dump Mode
    If IsKeyword($msgID) Then
        Return SetError(0, 2, $mFuncs)
    EndIf

    ; Prune Mode (Housekeeping for specific history depth)
    If $iPruneIndex > 0 Then
        If Not MapExists($mFuncs, $sKey) Then Return SetError(0, 5, 0)
        $aHistory = StringSplit($mFuncs[$sKey], "|")
        If ($iPruneIndex + 1) > $aHistory[0] Then Return SetError(0, 6, 0)
        Local $sNewStack = ""
        For $i = 1 To $aHistory[0]
            If $i = ($iPruneIndex + 1) Then
                $sNewStack &= "|" ; Leave the slot completely blank to preserve timeline integrity
            Else
                $sNewStack &= $aHistory[$i] & "|"
            EndIf
        Next
        $mFuncs[$sKey] = StringTrimRight($sNewStack, 1)
        Return SetError(0, 0, 1)
    EndIf

    ; Retrieve Mode
    If IsKeyword($function) Then
        If MapExists($mFuncs, $sKey) Then Return SetError(0, 0, StringSplit($mFuncs[$sKey], "|")[1])
        Return SetError(0, 1, "")
    EndIf

    ; Peek Mode (< -1)
    If (IsNumber($function) And $function < -1) Or StringRegExp(String($function), "^-[2-9]\d*$") Then
        If Not MapExists($mFuncs, $sKey) Or Not StringInStr($mFuncs[$sKey], "|") Then Return SetError(0, 4, "")
        $aHistory = StringSplit($mFuncs[$sKey], "|")
        Local $iTarget = Abs(Int($function)) ; -2 becomes 2, -3 becomes 3
        If $iTarget > $aHistory[0] Then Return SetError(0, 4, "") ; Slot depth doesn't exist
        Return SetError(0, 0, $aHistory[$iTarget])
    EndIf

    ; Restore Mode (-1)
    If $function = -1 Or $function = "-1" Then
        If Not MapExists($mFuncs, $sKey) Then Return SetError(0, 3, 0)
        Local $sStack = $mFuncs[$sKey] ; If we have history, shift it
        If StringInStr($sStack, "|") Then
            $sStack = StringMid($sStack, StringInStr($sStack, "|") + 1)
            $mFuncs[$sKey] = $sStack
            Local $sRestoredFunc = StringSplit($sStack, "|")[1]
            Return __GUIRegisterMsgDebug($msgID, $sRestoredFunc)
        Else ; No history? Just clear it
            $mFuncs[$sKey] = ""
            Return __GUIRegisterMsgDebug($msgID, "")
        EndIf
    EndIf

    ; Register Mode
    $sFuncName = (VarGetType($function) = "UserFunction" ? FuncName($function) : $function)
    If MapExists($mFuncs, $sKey) Then
        $aHistory = StringSplit($mFuncs[$sKey], "|")
        Local $sCurrent = $aHistory[1]
        If $sCurrent <> $sFuncName Then
            If $sFuncName == "" Then
                $iPipePos = StringInStr($mFuncs[$sKey], "|") ; Remove the active function. Do not push it to history.
                $sRestOfStack = ($iPipePos > 0 ? StringMid($mFuncs[$sKey], $iPipePos + 1) : "")
                If $sRestOfStack == "" Then
                    $mFuncs[$sKey] = "" ; Leave a footprint. Do not use MapRemove.
                Else
                    $mFuncs[$sKey] = "|" & $sRestOfStack ; Sync active slot as empty, retain older history
                EndIf
            Else
                If $sCurrent == "" Then ; Overwriting a vacant active slot
                    $iPipePos = StringInStr($mFuncs[$sKey], "|")
                    $sRestOfStack = ($iPipePos > 0 ? StringMid($mFuncs[$sKey], $iPipePos + 1) : "")
                    Local $sNextFunc = ($sRestOfStack <> "" ? StringSplit($sRestOfStack, "|")[1] : "")

                    If $sNextFunc = $sFuncName Then
                        $mFuncs[$sKey] = $sRestOfStack ; Collapse duplicate
                    Else
                        $mFuncs[$sKey] = $sFuncName & ($sRestOfStack <> "" ? "|" & $sRestOfStack : "")
                    EndIf
                Else ; push history down normally (Archive)
                    $mFuncs[$sKey] = $sFuncName & "|" & $mFuncs[$sKey]
                EndIf
            EndIf

            ; enforce the 3-tier history cap
            Local $aTemp = StringSplit($mFuncs[$sKey], "|")
            Local $iMax = ($aTemp[0] > 3 ? 3 : $aTemp[0])
            Local $sTmpStack = ""
            For $i = 1 To $iMax
                $sTmpStack &= $aTemp[$i] & "|"
            Next
            $mFuncs[$sKey] = StringTrimRight($sTmpStack, 1)
        EndIf
    Else
        If $sFuncName <> "" Then
            $mFuncs[$sKey] = $sFuncName
        EndIf
    EndIf

    Return __GUIRegisterMsgDebug($msgID, $function)
EndFunc   ;==>_GUIRegisterMsgTell


; #FUNCTION# ====================================================================================================================
; Name...........: _GUIRegisterMsgTell_Version
; Description ...: Returns the current version string of the UDF.
; Syntax.........: _GUIRegisterMsgTell_Version()
; Return values .: Success - Returns the version string.
; ===============================================================================================================================
Func _GUIRegisterMsgTell_Version()
    Return $__g_sGUIRegisterMsgTell_VERSION
EndFunc   ;==>_GUIRegisterMsgTell_Version


; #FUNCTION# ====================================================================================================================
; Name...........: _GUIRegisterMsgDebugOn
; Description ...: Enables or disables console debugging for the UDF.
; Syntax.........: _GUIRegisterMsgDebugOn([$iVal = Default])
; Parameters ....: $iVal - [optional] 1 to enable, 0 to disable. If Default, just returns current status.
; Return values .: Success - Returns the current debug status (1 or 0).
; ===============================================================================================================================
Func _GUIRegisterMsgDebugOn($iVal = Default)
    If Not IsKeyword($iVal) Then $__g_iGUIRegisterMsgDebugOn = Int($iVal)
    Return $__g_iGUIRegisterMsgDebugOn
EndFunc   ;==>_GUIRegisterMsgDebugOn


; #FUNCTION# ====================================================================================================================
; Name...........: _GUIRegisterMsgTell_Dump
; Description ...: Generates a status report of internal registrations and history, optionally printing to console.
; Syntax.........: _GUIRegisterMsgTell_Dump([$iConsoleWrite = True])
; Parameters ....: $iConsoleWrite - [optional] If True, prints the report to the console. Defaults to True.
; Return values .: Returns the formatted status string. Preserves original error/extended codes.
; ===============================================================================================================================
Func _GUIRegisterMsgTell_Dump($iConsoleWrite = True, $iErr = @error, $iExt = @extended)
    Local $mDump = _GUIRegisterMsgTell() ; Dump Mode returns the map
    Local $sStr, $aKeys = MapKeys($mDump)

    $sStr = @CRLF & "- ======================================================================" & @CRLF
    $sStr &= "-  _GUIRegisterMsgTell() - ACTIVE REGISTRATIONS & HISTORY" & @CRLF
    $sStr &= "- ======================================================================" & @CRLF

    If UBound($aKeys) = 0 Then
        $sStr &= "- No messages have been tracked yet." & @CRLF
        $sStr &= "- ======================================================================" & @CRLF & @CRLF
        If $iConsoleWrite Then ConsoleWrite($sStr)
        Return SetError($iErr, $iExt, $sStr)
    EndIf

    For $sKey In $aKeys
        Local $aHistory = StringSplit($mDump[$sKey], "|")
        $sStr &= "- Message ID [ " & $sKey & " ]" & @CRLF
        $sStr &= "-    â”œâ”€â”€ Active:   " & ($aHistory[1] = "" ? '("")' : $aHistory[1]) & @CRLF
        $sStr &= "-    â”œâ”€â”€ Previous: " & ($aHistory[0] >= 2 ? ($aHistory[2] = "" ? '("")' : $aHistory[2]) : "(None)") & @CRLF
        $sStr &= "-    â””── Oldest:   " & ($aHistory[0] >= 3 ? ($aHistory[3] = "" ? '("")' : $aHistory[3]) : "(None)") & @CRLF
        $sStr &= "- ----------------------------------------------------------------------" & @CRLF
    Next
    $sStr &= "- ======================================================================" & @CRLF & @CRLF
    If $iConsoleWrite Then ConsoleWrite($sStr)
    Return SetError($iErr, $iExt, $sStr)
EndFunc   ;==>_GUIRegisterMsgTell_Dump


; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __GUIRegisterMsgDebug
; Description ...: Internal wrapper for GUIRegisterMsg that optionally writes register events to the console.
; Syntax.........: __GUIRegisterMsgDebug($msgID, $function)
; Parameters ....: $msgID   - The Windows message ID to intercept.
;                  $function - The function name or pointer to register.
; Return values .: Returns the success of the native GUIRegisterMsg function.
; ===============================================================================================================================
Func __GUIRegisterMsgDebug($msgID, $function)
    If $__g_iGUIRegisterMsgDebugOn Then ConsoleWrite('++ _GUIRegisterMsgDebug(' & $msgID & ', "' & (VarGetType($function) = "UserFunction" ? FuncName($function) : String($function)) & '")' & @CRLF)
    Return GUIRegisterMsg($msgID, $function)
EndFunc   ;==>__GUIRegisterMsgDebug

Am working on my code and, is the message ID registered prior to my script by another script/UDF ? 🤔

Using this UDF in your code will help us all have a way to know if that message was registered :)

Edit:
for example, something like this ?

...
#include <GUIDarkTheme.au3> ; https://www.autoitscript.com/forum/topic/213613-guidarktheme-udf/
...
Func _MsgGui_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $wParam
    Local $hWndFrom, $iCode, $tNMHDR;, $hWndListView
    $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $g_hWndListView
            Switch $iCode
                Case $NM_DBLCLK ; Sent by a list-view control when the user double-clicks an item with the main mouse button
                    AdlibRegister(ListView_Event_OnDBLCLK, 20)
            EndSwitch
    EndSwitch
    If _GUIRegisterMsgTell($WM_NOTIFY, -2) = "__GUIDarkTheme_WM_NOTIFY" Then Return __GUIDarkTheme_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_MsgGui_WM_NOTIFY
...

 

Edited by argumentum
more

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting  image.gif.922e3a93535f431de08b31ee669cc446.gif
autoit_scripter_blue_userbar.png

  • argumentum changed the title to _GUIRegisterMsgTell() - A wrapper UDF for GUIRegisterMsg
Advert

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
×
×
  • Create New...