WildByDesign Posted Monday at 11:43 PM Posted Monday at 11:43 PM This is more of a question for anyone with more familiarity with subclassing. So I don't necessarily need code examples in return, unless of course that helps to explain things more. I have subclasses for some individual handles for some specific window classes. However, for this question, I am referring specifically to the main GUI window. For example, instead of: GUIRegisterMsg($WM_ACTIVATE, __GUIDarkMenu_WM_ACTIVATE) GUIRegisterMsg($WM_WINDOWPOSCHANGED, __GUIDarkMenu_WM_WINDOWPOSCHANGED) GUIRegisterMsg($WM_MEASUREITEM, __GUIDarkMenu_WM_MEASUREITEM) GUIRegisterMsg($WM_DRAWITEM, __GUIDarkMenu_WM_DRAWITEM) I have successfully switched to the following: ;... $g_pMenuWndProc = DllCallbackRegister("__GUIDarkTheme_MenuProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($g_hGui, DllCallbackGetPtr($g_pMenuWndProc), 1) ;... Func __GUIDarkTheme_MenuProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) #forceref $iID, $pData Local $sContinue = $GUI_RUNDEFMSG Switch $iMsg Case $WM_ACTIVATE $sContinue = __GUIDarkMenu_WM_ACTIVATE($hWnd, $iMsg, $wParam, $lParam) Case $WM_DRAWITEM $sContinue = __GUIDarkMenu_WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam) Case $WM_MEASUREITEM $sContinue = __GUIDarkMenu_WM_MEASUREITEM($hWnd, $iMsg, $wParam, $lParam) Case $WM_WINDOWPOSCHANGED $sContinue = __GUIDarkMenu_WM_WINDOWPOSCHANGED($hWnd, $iMsg, $wParam, $lParam) EndSwitch If $sContinue = $GUI_RUNDEFMSG Then Return __WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>__GUIDarkTheme_MenuProc This is works perfectly well. But I am wondering now about expanding. Those all cover the functionality needed for subclassing the GUI menubar. I am wondering if I can (or even should?) use another window procedure for the other GUI handle related window messages. I have GUIRegisterMsg for $WM_NOTIFY, $WM_CTLCOLORLISTBOX, $WM_CTLCOLOREDIT, and $WM_SIZE. And since they are not related to GUI menubar, this I why I am curious about another procedure. And so this leads to my question from the title: Can you have two or more subclasses for the same GUI handle? For the record, I have never had success subclassing $WM_SIZE for the main GUI handle. I have only had success with GUIRegisterMsg and $WM_SIZE. Thank you for your time.
Solution MattyD Posted Tuesday at 05:49 PM Solution Posted Tuesday at 05:49 PM Yeah its certainly possible, but its not what you'd normally see. There is also a risk of one of one subclass consuming messages which you might need up the chain. expandcollapse popup#include <WinAPI.au3> #include <WindowsConstants.au3> #include <GUIConstants.au3> Global Const $tagMINMAXINFO = "struct;long ptReserved[2];long ptMaxSize[2];long ptMaxPosition[2];long ptMinTrackSize[2];long ptMaxTrackSize[2];endstruct" Global $__g_hWndProc = DllCallbackRegister("WndProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $__g_pWndProc = DllCallbackGetPtr($__g_hWndProc) Global $__g_hWndProc2 = DllCallbackRegister("WndProc2", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") Global $__g_pWndProc2 = DllCallbackGetPtr($__g_hWndProc2) Global $__g_hGui = GUICreate("Test", 400, 200, -1, -1, $WS_OVERLAPPEDWINDOW) _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc, 1) _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc2, 2) GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete($__g_hGui) DllCallbackFree($__g_hWndProc) DllCallbackFree($__g_hWndProc2) Func WndProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Switch $iMsg Case $WM_ERASEBKGND _WinAPI_FillRect($wParam, _WinAPI_GetClientRect($hWnd), _WinAPI_GetStockObject($BLACK_BRUSH)) Return True Case $WM_DESTROY _WinAPI_RemoveWindowSubclass($hWnd, $__g_pWndProc, $iID) Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case Else Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch EndFunc Func WndProc2($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Switch $iMsg Case $WM_GETMINMAXINFO ;Limit resizing Local $tMINMAXINFO = DllStructCreate($tagMINMAXINFO, $lParam) $tMINMAXINFO.ptMinTrackSize(1) = 200 $tMINMAXINFO.ptMinTrackSize(2) = 100 $tMINMAXINFO.ptMaxTrackSize(1) = 500 $tMINMAXINFO.ptMaxTrackSize(2) = 300 Return 0 Case $WM_DESTROY _WinAPI_RemoveWindowSubclass($hWnd, $__g_pWndProc2, $iID) Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Case Else Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch EndFunc WildByDesign 1
WildByDesign Posted Wednesday at 12:16 AM Author Posted Wednesday at 12:16 AM Thank you, Matty. That answered my question perfectly and the example is very helpful. You always have an excellent way of making complex things look so much easier. And this example is the best for me to follow and learn from. I really appreciate your help. MattyD 1
argumentum Posted Wednesday at 12:49 AM Posted Wednesday at 12:49 AM (edited) _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc2, 2) A latent question would be: that UINT_PTR , how can I make it unique for my UDF, as to not interfere with other scripts ? can I pass TimerInit() ? 🤯 Edit: I guess something higher than 10000 as a Const, like 54437 or whatever, to be known as reserved. Edited Wednesday at 01:34 AM by argumentum answered Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
pixelsearch Posted Wednesday at 01:47 AM Posted Wednesday at 01:47 AM 58 minutes ago, argumentum said: A latent question would be: that UINT_PTR , how can I make it unique for my UDF, as to not interfere with other scripts ? Hello. If not mistaken, the subclass ID doesn't have to be unique, for example this should work : _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc, 1) _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc2, 1) And this should work too : _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc, 1) _WinAPI_SetWindowSubclass($__g_hGui, $__g_pWndProc, 2) It's the combination of the subclass procedure + subclass ID that matters, so it shouldn't matter if the user already uses the same subclass ID in his own subclassing functions, @MattyD what's your opinion, because I may be totally wrong on this. Thanks argumentum 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
MattyD Posted Wednesday at 01:22 PM Posted Wednesday at 01:22 PM yep, you are correct. In fact, its the triplet which is used as an identifier when registering the subclass. It's a combo of window handle + Subclass proc ptr + subclass id. Apparently you may wish to subclass a window multiple times, but using the same subclass proc. You could set the SubClassID to associated hwnds or object ptrs or something. But this is an edge case. I've used CtrlIds for the SubclassID before when subclassing things like buttons, but there's no hard and fast rule. If we're not using the subclassid param for anything meaningful then we should probably just use 0. (In hindsight I should have done that in the example!) argumentum and pixelsearch 2
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now