Jump to content

Recommended Posts

Posted (edited)

GUIRegisterMsg20 is an extended version of GUIRegisterMsg, and GUIRegisterMsgEx is an extended version of GUIRegisterMsg20.

Example A:

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

__ExampleA()
Func __ExampleA()
    Local $hGUI1 = GUICreate("Window A", 300, 200, 100, 100)
    GUISetState(@SW_SHOW, $hGUI1)

    Local $hGUI2 = GUICreate("Window B", 300, 200, 450, 100)
    GUISetState(@SW_SHOW, $hGUI2)

    GUIRegisterMsgEx($hGUI1, $WM_LBUTTONDOWN, __OnLeftClickWindowA)
    GUIRegisterMsgEx($hGUI2, $WM_LBUTTONDOWN, __OnLeftClickWindowB)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                Exit
        EndSwitch
    WEnd
    GUIDelete($hGUI2)
    GUIDelete($hGUI1)
EndFunc

Func __OnLeftClickWindowA($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
    ConsoleWrite("-> Clicked on Window A! (Handle: " & $hWnd & ")" & @CRLF)
    Return "GUI_RUNDEFMSG"
EndFunc

Func __OnLeftClickWindowB($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
    ConsoleWrite("-> Clicked on Window B! (Handle: " & $hWnd & ")" & @CRLF)
    Return "GUI_RUNDEFMSG"
EndFunc

Example B:

#include <GuiConstants.au3>
#include <GuiHeader.au3>
#include <WinAPI.au3>
#include <Misc.au3>
#include <WinAPITheme.au3>
#include <GuiListView.au3>
#include "GUIRegisterMsgEx.au3"

AutoItSetOption("MustDeclareVars", 1)

__ExampleB()
Func __ExampleB()
    Local $hGUI = GUICreate("Header Subclass Framework Test", 500, 400)
    GUISetBkColor(0x000000)

    Local $idListView_A = GUICtrlCreateListView("Items List|SubItems1|SubItems2", 10, 10, 480, 150, $LVS_REPORT, _
                                                            BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT, $LVS_EX_HEADERDRAGDROP))
    GUICtrlSetBkColor($idListView_A, 0x121212)
    GUICtrlSetColor($idListView_A, 0xFFFFFF)

    Local $hListView_A = GUICtrlGetHandle($idListView_A)
    Local $hHeader_A = _GUICtrlListView_GetHeader($hListView_A)

    GUICtrlCreateListViewItem("item_A1|item_B1|item_C1", $idListView_A)
    GUICtrlCreateListViewItem("item_A2|item_B2|item_C2", $idListView_A)
    GUICtrlCreateListViewItem("item_A3|item_B3|item_C3", $idListView_A)
    _GUICtrlListView_SetColumnWidth($idListView_A, 2, $LVSCW_AUTOSIZE_USEHEADER)

    GUIRegisterMsgEx($hListView_A, $WM_NOTIFY, "MY_WM_NOTIFY", $hHeader_A)
    GUIRegisterMsgEx($hHeader_A, $WM_MOUSEMOVE, "MY_WM_NOTIFY", $hHeader_A)
    GUIRegisterMsgEx($hHeader_A, $WM_MOUSELEAVE, "MY_WM_NOTIFY", $hHeader_A)
    GUISetState(@SW_SHOW, $hGUI)

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    GUIDelete($hGUI)
EndFunc

Func MY_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
    Local Static $bHover = False, $tPoint
    Local $hBrush

    Switch $iMsg
        Case $WM_NOTIFY
            Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
            Local $hFrom = $tNMHDR.hWndFrom
            Switch $tNMHDR.Code
                Case $NM_CUSTOMDRAW
                    If _WinAPI_GetClassName($hFrom) = "sysheader32" Then
                        Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
                        Switch $tCustDraw.dwDrawStage
                            Case $CDDS_PREPAINT
                                Return $CDRF_NOTIFYITEMDRAW

                            Case $CDDS_ITEMPREPAINT
                                Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tCustDraw, "Left"))
                                _WinAPI_SetBkMode($tCustDraw.hDC, 1)
                                _WinAPI_SetTextColor($tCustDraw.hDC, 0xFFFFFF)

                                If $bHover And _WinAPI_PtInRect($tRect, $tPoint) Then
                                    $hBrush = _WinAPI_CreateSolidBrush(_IsPressed(0x01) ? 0x00008B : 0x0000FF)
                                Else
                                    $hBrush = _WinAPI_CreateSolidBrush(0x202020)
                               EndIf
                                _WinAPI_InflateRect($tRect, -1, 0)
                                _WinAPI_FillRect($tCustDraw.hDC, $tRect, $hBrush)
                                _WinAPI_DeleteObject($hBrush)

                                _WinAPI_InflateRect($tRect, -5, -2)

                                GUIRegisterMsgEx_Bypass($tCustDraw.hWndFrom, True)              ;~~ same as doing _WinAPI_RemoveWindowSubclass() to prevent crashes....
                                Local $text = _GUICtrlHeader_GetItemText($tCustDraw.hWndFrom, $tCustDraw.dwItemSpec)
                                GUIRegisterMsgEx_Bypass($tCustDraw.hWndFrom, False, $pData)     ;~~ same as doing _WinAPI_SetWindowSubclass()

                                _WinAPI_DrawText($tCustDraw.hDC, $text, $tRect, BitOR($DT_LEFT, $DT_NOCLIP))
                                Return $CDRF_SKIPDEFAULT
                        EndSwitch
                    EndIf
            EndSwitch

        Case $WM_MOUSEMOVE
            If $pData = $hWnd Then
                $bHover = True
                $tPoint = _WinAPI_GetMousePos(True, $hWnd)
                _WinAPI_InvalidateRect($hWnd, 0, False)
                _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE)
            EndIf

        Case $WM_MOUSELEAVE
            If $pData = $hWnd Then
                $bHover = False
                _WinAPI_InvalidateRect($hWnd, 0, False)
            EndIf
    EndSwitch
    Return "GUI_RUNDEFMSG"
EndFunc

 

GUIRegisterMsgEx.au3

 

Edited by jugador
Posted

This is really neat. I do feel like if you are extending something, you should give a few points about what has been improved over the previous UDF.

I like the technique that you use with $__g_bThreadLocked to call DefSubclassProc if the procedure is still within the user function/proc. This is clearly intended to prevent subclass procedure lockups/crashes. Very smart. :)

The GUIRegisterMsgEx_Bypass() is nice too. I assume this was related to the subclass crashes that we talked about before with the Header. I'm glad that you found a way to avoid those subclass lockups.

Posted (edited)

@WildByDesign I used $__g_bThreadLocked as an extra precautionary measure. The code runs fine without it and shows no abnormalities. 

Need to remove $__g_bThreadLocked or else _DateProc will not work.
also changed "GUI_RUNDEFMSG" to 0xCAFEBABE in this version.

Example C:

;~ https://www.autoitscript.com/forum/topic/213268-samplecontrolsau3-in-dark-mode/

#include <WindowsConstants.au3>
#include <GuiConstants.au3>
#include <GuiDateTimePicker.au3>
#include <GuiMonthCal.au3>
#include <WinAPI.au3>
#include <WinAPISysWin.au3>
#include <WinAPITheme.au3>
#include "GUIRegisterMsgEx.au3"

Opt("MustDeclareVars", True)
Global Const $PRF_CLIENT = 0x0004, $COLOR_BORDER = 0x404040, $COLOR_BG_DARK = 0x202020, $COLOR_TEXT_LIGHT = 0xFFFFFF, $COLOR_BORDER_LIGHT = 0xD8D8D8
Global $g_bHover = False

__ExampleC()
Func __ExampleC()
    Local $hGUI = GUICreate("Sample GUI", 400, 240)

    Local $idDate = GUICtrlCreateDate("", 15, 15, 200, 24)
    Local $hDate = GUICtrlGetHandle($idDate)

    Local $aMessages = [$WM_PAINT, $WM_ERASEBKGND, $WM_SETFOCUS, $WM_KILLFOCUS, $WM_MOUSEMOVE, $WM_MOUSELEAVE]
    For $iMsg In $aMessages
        GUIRegisterMsgEx($hDate, $iMsg, "_DateProc")
    Next
    GUIRegisterMsgEx($hGUI, $WM_NOTIFY, "_WM_NOTIFY")

    GUISetState()

    While True
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
        EndSwitch
    WEnd
    GUIDelete()
EndFunc   ;==>Example

Func _DateProc($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
    Switch $iMsg
        Case $WM_PAINT
            Local $tPaint = DllStructCreate($tagPAINTSTRUCT)
            Local $hDC = _WinAPI_BeginPaint($hWnd, $tPaint)

            Local $tClient = _WinAPI_GetClientRect($hWnd)
            Local $iW = $tClient.Right
            Local $iH = $tClient.Bottom

            ; --- Memory DC for flicker-free rendering ---
            Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
            Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iW, $iH)
            Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap)

            ; 1. Let Windows draw the light-mode control into memory DC
           _SendMessage($hWnd, $WM_PRINTCLIENT, $hMemDC, $PRF_CLIENT)

            ; 2. Invert all pixels (background becomes black, text white, selection orange)
            Local $tRect = DllStructCreate($tagRECT)
            $tRect.right = $iW
            $tRect.bottom = $iH
            _WinAPI_InvertRect($hMemDC, $tRect)

            ; --- 3. PIXEL HACK: destroy orange highlight & set background color ---
            Local $iSize = $iW * $iH
            Local $tPixels = DllStructCreate("dword c[" & $iSize & "]")
            ; Load pixel array directly from bitmap memory
            Local $iBytes = DllCall("gdi32.dll", "long", "GetBitmapBits", "handle", $hBitmap, "long", $iSize * 4, "ptr", DllStructGetPtr($tPixels))[0]

            If $iBytes = $iSize * 4 Then
                Local $iPixel, $r, $g, $b, $iGray
                For $i = 1 To $iSize
                    $iPixel = $tPixels.c(($i))

                    ; Split into color channels
                    $b = BitAND($iPixel, 0xFF)
                    $g = BitAND(BitShift($iPixel, 8), 0xFF)
                    $r = BitAND(BitShift($iPixel, 16), 0xFF)

                    ; Convert to grayscale (orange becomes mid-gray)
                    $iGray = Int(($r + $g + $b) / 3)

                    ; Very dark pixel = inverted white background
                    If $iGray < 15 Then
                        $iPixel = $COLOR_BG_DARK ; Replace with exact GUI background color
                    Else
                        ; Grayscale value for text (white) and selection (gray)
                        $iPixel = BitOR(BitShift($iGray, -16), BitShift($iGray, -8), $iGray)
                    EndIf

                    $tPixels.c(($i)) = $iPixel
                Next
                ; Write cleaned pixels back into the bitmap
                DllCall("gdi32.dll", "long", "SetBitmapBits", "handle", $hBitmap, "long", $iSize * 4, "ptr", DllStructGetPtr($tPixels))
            EndIf
            ; --- END PIXEL HACK ---

            ; --- Border color (hover effect) ---
            Local $iBorderColor = $COLOR_BORDER
            If _WinAPI_GetFocus() = $hWnd Then $iBorderColor = $COLOR_BORDER
            Local $tCursorPos = DllStructCreate($tagPOINT)
            DllCall("user32.dll", "bool", "GetCursorPos", "struct*", $tCursorPos)
            DllCall("user32.dll", "bool", "ScreenToClient", "hwnd", $hWnd, "struct*", $tCursorPos)
            If $tCursorPos.X >= 0 And $tCursorPos.X <= $iW And $tCursorPos.Y >= 0 And $tCursorPos.Y <= $iH Then
                $iBorderColor = $COLOR_BORDER_LIGHT
            EndIf

            ; --- Draw border ---
            Local $hPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($iBorderColor))
            Local $hNullBr = _WinAPI_GetStockObject(5)
            Local $hOldPen = _WinAPI_SelectObject($hMemDC, $hPen)
            Local $hOldBr = _WinAPI_SelectObject($hMemDC, $hNullBr)
            DllCall("gdi32.dll", "bool", "Rectangle", "handle", $hMemDC, "int", 0, "int", 0, "int", $iW, "int", $iH)
            _WinAPI_SelectObject($hMemDC, $hOldPen)
            _WinAPI_SelectObject($hMemDC, $hOldBr)
            _WinAPI_DeleteObject($hPen)

            ; --- Copy finished result to screen in one step (no flicker) ---
            _WinAPI_BitBlt($hDC, 0, 0, $iW, $iH, $hMemDC, 0, 0, $SRCCOPY)

            ; --- Cleanup ---
            _WinAPI_SelectObject($hMemDC, $hOldBmp)
            _WinAPI_DeleteObject($hBitmap)
            _WinAPI_DeleteDC($hMemDC)
            _WinAPI_EndPaint($hWnd, $tPaint)
            Return 0

        Case $WM_ERASEBKGND
            Return 1

        Case $WM_SETFOCUS, $WM_KILLFOCUS
            _WinAPI_InvalidateRect($hWnd, 0, False)

        Case $WM_MOUSEMOVE
            If Not $g_bHover Then
                $g_bHover = True
                _WinAPI_InvalidateRect($hWnd, 0, False)
            EndIf

        Case $WM_MOUSELEAVE
            $g_bHover = False
            _WinAPI_InvalidateRect($hWnd, 0, False)
    EndSwitch
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>_DateProc

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hWndFrom = HWnd($tNMHDR.hWndFrom)
    Local $iCode = $tNMHDR.Code
    If _WinAPI_GetClassName($hWndFrom) = "SysDateTimePick32" Then
        Switch $iCode
            Case $NM_SETFOCUS
                _WinAPI_SetThemeAppProperties(0)

            Case $DTN_DROPDOWN
                _WinAPI_SetWindowTheme($hWndFrom, "", "")
                _SendMessage($hWndFrom, $DTM_SETMCCOLOR, 4, $COLOR_BG_DARK)

                Local $iCtrl = _GUICtrlDTP_GetMonthCal($hWndFrom)
                _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TEXT,         $COLOR_TEXT_LIGHT)
                _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TITLEBK,      $COLOR_BG_DARK)
                _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TITLETEXT,    $COLOR_TEXT_LIGHT)
                _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_MONTHBK,      $COLOR_BG_DARK)
                _GUICtrlMonthCal_SetColor($iCtrl, $MCSC_TRAILINGTEXT, $COLOR_TEXT_LIGHT)
        EndSwitch
    EndIf
    Return "GUI_RUNDEFMSG"
EndFunc   ;==>_WM_NOTIFY

Func _ColorToCOLORREF($iColor) ;RGB to BGR
    Local $iR = BitAND(BitShift($iColor, 16), 0xFF)
    Local $iG = BitAND(BitShift($iColor, 8), 0xFF)
    Local $iB = BitAND($iColor, 0xFF)
    Return BitOR(BitShift($iB, -16), BitShift($iG, -8), $iR)
EndFunc   ;==>_ColorToCOLORREF

Example D:

;~ https://www.autoitscript.com/forum/topic/212545-resizable-dragable-windows-controls/page/2/#findComment-1539579

#include <guiConstants.au3>
#include <winapi.au3>
#include <MenuConstants.au3>
#include "GUIRegisterMsgEx.au3"

Opt("MustDeclareVars", True)

Global $hGUI, $bRestore

__ExampleD()
Func __ExampleD()
  $hGUI = GUICreate("WM_NCHITTEST", 300, 200, -1, -1, $WS_OVERLAPPEDWINDOW)
  Local $idBtn = GUICtrlCreateButton("Button 1", 4, 4, 80, 80, $WS_CLIPSIBLINGS)
  Local $idBtn2 = GUICtrlCreateButton("Button 2", 90, 4, 80, 80, $WS_CLIPSIBLINGS)
  Local $idLockButtons = GUICtrlCreateCheckbox("Lock Buttons", 200, 20, 80, 20)

  GUIRegisterMsgEx($hGUI, $WM_SYSCOMMAND, "WM_SYSCOMMAND")

  GUIRegisterMsgEx($idBtn, $WM_NCHITTEST, "ButtonMoveProc")
  GUIRegisterMsgEx($idBtn, $WM_SETCURSOR, "ButtonMoveProc")
  GUIRegisterMsgEx($idBtn, $WM_WINDOWPOSCHANGING, "ButtonMoveProc")

  GUIRegisterMsgEx($idBtn2, $WM_NCHITTEST, "ButtonMoveProc")
  GUIRegisterMsgEx($idBtn2, $WM_SETCURSOR, "ButtonMoveProc")
  GUIRegisterMsgEx($idBtn2, $WM_WINDOWPOSCHANGING, "ButtonMoveProc")
  GUISetState()

  Local $iMsg
  While True
    $iMsg = GUIGetMsg()
    Switch $iMsg
      Case $GUI_EVENT_CLOSE
        ExitLoop
      Case $idLockButtons
        If GUICtrlRead($iMsg) = $GUI_CHECKED Then
          ; True to disable
          GUIRegisterMsgEx_Bypass($idBtn, True)
          GUIRegisterMsgEx_Bypass($idBtn2, True)
        Else
          ; False to re-enable
          GUIRegisterMsgEx_Bypass($idBtn, False)
          GUIRegisterMsgEx_Bypass($idBtn2, False)
        EndIf
      Case $idBtn, $idBtn2
        ConsoleWrite("Click " & GUICtrlRead($iMsg) & @CRLF)
      Case $GUI_EVENT_RESTORE
        $bRestore = False
    EndSwitch
  WEnd

  GUIDelete()
EndFunc   ;==>Example

Func ButtonMoveProc($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
  Local $tPos, $aPos, $iRet, $aPoint[2], $iSrc, $iEvent, $hCursor

  Switch $iMsg
    Case $WM_NCHITTEST
      $aPos = WinGetPos($hWnd)
      $aPoint[0] = BitAND($lParam, 0xFFFF)
      $aPoint[1] = BitShift($lParam, 16)

      $iRet = $HTCAPTION
      If $aPoint[0] - $aPos[0] < 10 Then $iRet = $HTLEFT
      If $aPoint[0] - $aPos[0] > ($aPos[2] - 10) Then $iRet = $HTRIGHT

      If $aPoint[1] - $aPos[1] < 10 Then
        Switch $iRet
          Case $HTLEFT
            $iRet = $HTTOPLEFT
          Case $HTRIGHT
            $iRet = $HTTOPRIGHT
          Case Else
            $iRet = $HTTOP
        EndSwitch
      ElseIf $aPoint[1] - $aPos[1] > ($aPos[3] - 10) Then
        Switch $iRet
          Case $HTLEFT
            $iRet = $HTBOTTOMLEFT
          Case $HTRIGHT
            $iRet = $HTBOTTOMRIGHT
          Case Else
            $iRet = $HTBOTTOM
        EndSwitch
      EndIf
      Return $iRet

    Case $WM_SETCURSOR
      $iSrc = BitAND($lParam, 0xFFFF)
      $iEvent = BitShift($lParam, 16)
      If $iSrc = $HTCAPTION And $iEvent = $WM_LBUTTONDOWN Then
        _WinAPI_RedrawWindow($hWnd, 0, 0, $RDW_INVALIDATE + $RDW_FRAME)
        $hCursor = _WinAPI_LoadCursor(0, $OCR_SIZEALL)
        _WinAPI_SetCursor($hCursor)
        Return True
      EndIf

    Case $WM_WINDOWPOSCHANGING
      If $bRestore Then
        ConsoleWrite("WM_WINDOWPOSCHANGING" & @CRLF)
        $tPos = DllStructCreate($tagWINDOWPOS, $lParam)
        $aPos = ControlGetPos($hGUI, "", $hWnd)
        ConsoleWrite($aPos[0] & "/" & $aPos[1] & "/" & $aPos[2] & "/" & $aPos[3] & @CRLF)
        $tPos.X = $aPos[0]
        $tPos.Y = $aPos[1]
        $tPos.CX = $aPos[2]
        $tPos.CY = $aPos[3]
        Return 0
      EndIf
  EndSwitch
  Return "GUI_RUNDEFMSG"
EndFunc   ;==>ButtonMoveProc

Func WM_SYSCOMMAND($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
  If $wParam = $SC_RESTORE Then
    ConsoleWrite("---Start Restore---" & @CRLF)
    $bRestore = True
  EndIf
  Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_SYSCOMMAND

 

Edited by jugador
Posted (edited)
1 hour ago, jugador said:

I used $__g_bThreadLocked as an extra precautionary measure. The code runs fine without it and shows no abnormalities

I was shocked by how often it would hit $__g_bThreadLocked when I tried it with GUIDarkTheme UDF. It hit it often enough to cause flickering of controls. Sometimes they would be left with light mode color. Especially the WM_CTLCOLOR* messages.

In particular, it would hit it constantly during GUI resizing. AutoIt does not handle GUI resizing very well in general even without subclassing.

Edited by WildByDesign
Posted
20 hours ago, jugador said:

also changed "GUI_RUNDEFMSG" to 0xCAFEBABE in this version.

I tested your latest updated UDF with all 4 of your examples and everything works smoothly and perfectly. Nice work! :)

I am curious about the change from "GUI_RUNDEFMSG" to 0xCAFEBABE. If you don't mind me asking...

Was there a performance difference from comparing string "GUI_RUNDEFMSG" over 0xCAFEBABE value?

Or were there problems that caused the need for this?

It is not a problem, but I am just curious. I assumed that using $GUI_RUNDEFMSG would be more compatible with users' existing functions. But I suppose users would have to make a change to their functions anyway by adding $idSubClass, $pData to their function parameters.

 

Posted (edited)

@WildByDesign

0xCAFEBABE is the "magic number" that specifies the first four bytes of every valid compiled Java class file.

Checking strings this way ($mResult <> "GUI_RUNDEFMSG") is bad, so used a "magic number". There is nothing special about it. 
However, if you want to use "GUI_RUNDEFMSG", then have to do this way ($mResult == "GUI_RUNDEFMSG").

As for $idSubClass and $pData, I don't like using global variables too much. Used $pData to store a handle or pointer for tracking. 
If want, there is no harm in doing it this way: Local $mResult = Call($sUserFunc, $hWnd, $iMsg, $wParam, $lParam)

Update code to match GUIRegisterMsg 4 param.

Edit:

On second thought, it's best to keep all 6 param of SetWindowSubclass.
So change back to 6 param.
 

Edited by jugador
  • 2 weeks later...
Posted

I've been thinking about this UDF some more. I really like how it cleans up so nicely on exit and the usage of maps is very helpful.

But I'm wondering about controls that are created and destroyed during usage of the GUI.

For example, I am wondering if there is an easier way to handle $WM_DESTROY. It is easy enough to remove those subclasses with _WinAPI_RemoveWindowSubclass(). However, I am wondering if there is an easier way to remove these from the map during regular GUI usage for controls that are created and destroyed.

Could (should?) something like this be handled in the UDF?

Case $WM_DESTROY
    ; remove subclass
    DllCall("comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $hWnd, "ptr", DllCallbackGetPtr($__g_hCallback), "uint_ptr", $sID)
    ; remove entry from map
    ; - remove entry from map here
    ; return default proc
    Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)

Anyway, just an idea. :)

Posted (edited)

to RemoveWindowSubclass:

Case $WM_DESTROY
    GUIRegisterMsgEx($hWnd, $iMsg, "")  ; remove subclass
    Return "GUI_RUNDEFMSG"              ; return default proc

 

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPIGdi.au3>
#include <Timers.au3>
#include "GUIRegisterMsgEx.au3"

Local $hGUI = GUICreate("Demo", 400, 200)
GUISetState(@SW_SHOW, $hGUI)

GUIRegisterMsgEx($hGUI, $WM_CREATE, "_MySubclassProc")
GUIRegisterMsgEx($hGUI, $WM_DESTROY, "_MySubclassProc")

_MySubclassProc($hGUI, $WM_CREATE, 0, 0, 0, 0)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ConsoleWrite("--> Calling GUIDelete..." & @CRLF)
            GUIDelete($hGUI)
            ExitLoop
    EndSwitch
WEnd
ConsoleWrite("--> Script exit." & @CRLF)


Func _MySubclassProc($hWnd, $iMsg, $wParam, $lParam, $iid, $Pdata)
    Local Static $hCustomBrush = 0
    Local Static $hTimer = 0
    Switch $iMsg
        Case $WM_CREATE
            $hCustomBrush = _WinAPI_CreateSolidBrush(0x252525)
            $hTimer = _Timer_SetTimer($hWnd, 1000)
            ConsoleWrite("($WM_CREATE)" & @CRLF)

        Case $WM_DESTROY
            ConsoleWrite("($WM_DESTROY)" & @CRLF)

            _Timer_KillTimer($hWnd, $hTimer)
            ConsoleWrite("   --> _Timer_KillTimer" & @CRLF)

            GUIRegisterMsgEx($hWnd, $iMsg, "")
            ConsoleWrite("   --> RemoveWindowSubclass" & @CRLF)

            If $hCustomBrush Then _WinAPI_DeleteObject($hCustomBrush)
            ConsoleWrite("   --> _WinAPI_DeleteObject" & @CRLF)
    EndSwitch
    Return "GUI_RUNDEFMSG"
EndFunc

 

Edited by jugador

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