Jump to content

Recommended Posts

Posted

I haven’t seen it before, but I’m thinking maybe adding doublebuffer to the TreeView control should fix it. I can have that applied through the UDF.

I will post an update later with doublebuffer applied to see if it helps.

Posted

I cannot reproduce the artifact issue on my main system. I just uploaded version 1.2.1 which automatically adds TVS_EX_DOUBLEBUFFER to any TreeView controls.

Can you both please test it and see if it helps with this issue?

Posted (edited)

You can overpaint the size grips in edit, listvew and treeview.

I used in my example $WM_PAINT in _SubclassProc function:

...
        Case $WM_PAINT
            Local $sClass = StringLower(_WinAPI_GetClassName($hWnd))
            If $sClass = "syslistview32" Or $sClass = "systreeview32" Or $sClass = "edit" Then ; hide Sizegrip boxes
                Local $iRet = _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)

                ; Overpaint sizegrip boxes if visible
                Local $iWinStyle = _WinAPI_GetWindowLong($hWnd, $GWL_STYLE)
                If BitAND($iWinStyle, $WS_HSCROLL) And BitAND($iWinStyle, $WS_VSCROLL) Then
                    Local $hDC = _WinAPI_GetWindowDC($hWnd) ; GetWindowDC statt GetDC!
                    Local $tWnd = _WinAPI_GetWindowRect($hWnd)
                    Local $tClient = _WinAPI_GetClientRect($hWnd)
                    Local $iScrollW = _WinAPI_GetSystemMetrics($SM_CXVSCROLL)
                    Local $iScrollH = _WinAPI_GetSystemMetrics($SM_CYHSCROLL)
                    
                    ; convert client-area to Window coordinates
                    Local $tPt = DllStructCreate($tagPOINT)
                    $tPt.X = $tClient.right
                    $tPt.Y = $tClient.bottom
                    DllCall("user32.dll", "bool", "ClientToScreen", "hwnd", $hWnd, "struct*", $tPt)
                                    
                    ; direct relativ coordinates
                    Local $tCorner = DllStructCreate($tagRECT), $delta = (_WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE) And $WS_EX_CLIENTEDGE ? 4 : 1)
                    $tCorner.left   = $tClient.right  + $delta
                    $tCorner.top    = $tClient.bottom + $delta
                    $tCorner.right  = $tCorner.left + $iScrollW
                    $tCorner.bottom = $tCorner.top  + $iScrollH
                    
                    Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_TITLE_DARK))
                    _WinAPI_FillRect($hDC, $tCorner, $hBrush)
                    _WinAPI_DeleteObject($hBrush)
                    _WinAPI_ReleaseDC($hWnd, $hDC)
                EndIf
                Return $iRet
            Else
                Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam)
            EndIf
...

I didn't test it for DPI <> 1 aka 96 if $tCorner is properly calculated.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted
11 hours ago, UEZ said:

You can overpaint the size grips in edit, listvew and treeview.

I used in my example $WM_PAINT in _SubclassProc function:

This is fantastic. Thank you. Painting over the size grips for those controls is a subtle but nice added touch to the overall look. I will have to overhaul my subclassing methods to apply this change so it may take a few days. I appreciate it.

I do have a question for you. I've been meaning to ask you this for a few days now:

How could we subclass multiple ListView headers?

For example, if a user chooses to use this UDF in a project with multiple ListView controls.

There are many ListView header subclassing examples in the forum, but they all target one specific handle. I like the technique that you use based on class name:

If $iCode = $NM_CUSTOMDRAW And StringLower(__WinAPI_GetClassName($hWndFrom)) = "msctls_trackbar32" Then

I was able to successfully use that same technique for the date time picker control:

If __WinAPI_GetClassName($hWndFrom) = "SysDateTimePick32" Then

I did try to use the same technique for SysListView32 class but it failed to subclass the ListView header. I was able to confirm that I was obtaining the correct header handle for each ListView.

Do you know if it is possible to use this same class name technique to support subclassing multiple ListView headers?

Posted
3 hours ago, jpm said:

It is for me almost perfect for the modern darkmode the border are too strong for listview

I agree. Some of the newer control themes from Windows 11 (24H2/25H2) DarkMode_DarkTheme look better, while some look worse. I will change the ListView to use the older DarkMode_Explorer theme since the border is less contrast.

3 hours ago, jpm said:

can you tidies all .au3 with Scite Ctrl-T ?

Yes, absolutely. I will have to make a habit for myself to ensure that I run Tidy before each release.

Posted (edited)
14 hours ago, argumentum said:

..same "washing" :(

Thanks for letting me know. That sizebox definitely should not be showing like that. I'll look into painting over the others as well.

EDIT: Actually, now that I think of it, is that the ModernDark example?

I have a feeling that I may not have the right background color for the sizebox because I change most of the colors when materials are applied.

Edited by WildByDesign
Posted
2 hours ago, WildByDesign said:

This is fantastic. Thank you. Painting over the size grips for those controls is a subtle but nice added touch to the overall look. I will have to overhaul my subclassing methods to apply this change so it may take a few days. I appreciate it.

I do have a question for you. I've been meaning to ask you this for a few days now:

How could we subclass multiple ListView headers?

For example, if a user chooses to use this UDF in a project with multiple ListView controls.

There are many ListView header subclassing examples in the forum, but they all target one specific handle. I like the technique that you use based on class name:

If $iCode = $NM_CUSTOMDRAW And StringLower(__WinAPI_GetClassName($hWndFrom)) = "msctls_trackbar32" Then

I was able to successfully use that same technique for the date time picker control:

If __WinAPI_GetClassName($hWndFrom) = "SysDateTimePick32" Then

I did try to use the same technique for SysListView32 class but it failed to subclass the ListView header. I was able to confirm that I was obtaining the correct header handle for each ListView.

Do you know if it is possible to use this same class name technique to support subclassing multiple ListView headers?

To handle all headers generically you need something like my _SubclassProc() and NM_CUSTOMDRAW notification to manage ListView headers. Since $hWndFrom contains the actual handle of the sending control, the StringLower(_WinAPI_GetClassName($hWndFrom)) = "sysheader32" check automatically matches all ListView headers regardless of how many ListViews you have.

If you need per-ListView differentiation, you can check the header's parent:

Case "sysheader32"
    ; Optionally identify which ListView this header belongs to:
    Local $hParentListView = _WinAPI_GetParent($hFrom)
    ; Apply different colors per ListView if needed
    ; Otherwise the generic class name check handles all of them uniformly

I hope it helps you.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)
10 hours ago, UEZ said:

To handle all headers generically you need something like my _SubclassProc() and NM_CUSTOMDRAW notification to manage ListView headers. Since $hWndFrom contains the actual handle of the sending control, the StringLower(_WinAPI_GetClassName($hWndFrom)) = "sysheader32" check automatically matches all ListView headers regardless of how many ListViews you have.

This was very helpful, thank you. :)

I was able to get a subclass procedure working (similar to yours) and it is subclassing multiple ListView headers perfectly now. So this is great and I plan to expand on it some more now that I understand how it works better.

Are there limitations to what types of controls can be added to the _SubclassProc() function?

For example, since the slider control (msctls_trackbar32) subclassing also uses WM_NOTIFY, I was hoping that I could add it using the same technique. However, it failed for me. Using GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") does work, but using _SubclassProc() instead does not seem to work for me.

Edited by WildByDesign
Posted (edited)
12 hours ago, WildByDesign said:

Are there limitations to what types of controls can be added to the _SubclassProc() function?

Any control that has its own HWND can be subclassed.

12 hours ago, WildByDesign said:

For example, since the slider control (msctls_trackbar32) subclassing also uses WM_NOTIFY, I was hoping that I could add it using the same technique. However, it failed for me. Using GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") does work, but using _SubclassProc() instead does not seem to work for me.

WM_NOTIFY is always sent upward - from the control to its parent window.

When you subclass the trackbar itself, you're watching messages sent to the trackbar - but WM_NOTIFY from the trackbar is sent away from it, never back into it. The trackbar will never see its own WM_NOTIFY.

GUIRegisterMsg works because it hooks into the main GUI window's message pump, which is exactly where those notifications land.

 

You need to attach the subclass proc to the parent HWND (your GUI), not the trackbar:

; Subclass the main GUI window to catch child-control notifications
Local $hGUI = GUICreate("Test", 400, 300)
Local $hSlider = GUICtrlCreateSlider(10, 10, 200, 30)
Local $hSliderHWND = GUICtrlGetHandle($hSlider)

_WinAPI_SetWindowSubclass(WinGetHandle($hGUI), $g_pSubclassProc, 1, 0)

Then inside _SubclassProc, branch on $hFrom to identify which child sent the notification:

...
Case $WM_NOTIFY
    Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
    Local $hFrom = $tNMHDR.hWndFrom
    Local $iCode = $tNMHDR.Code

    Switch StringLower(_WinAPI_GetClassName($hFrom))
        Case "sysheader32"
            ; ... existing header handling
        Case "msctls_trackbar32"
            Switch $iCode
                Case $TRBN_THUMBPOSCHANGING
                    ; handle slider
            EndSwitch
    EndSwitch
...

 

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted
37 minutes ago, UEZ said:

WM_NOTIFY is always sent upward — from the control to its parent window.

When you subclass the trackbar itself, you're watching messages sent to the trackbar — but WM_NOTIFY from the trackbar is sent away from it, never back into it. The trackbar will never see its own WM_NOTIFY.

GUIRegisterMsg works because it hooks into the main GUI window's message pump, which is exactly where those notifications land.

I know that English is not your first language, from my understanding. However, you have excellent teaching skills! You explained that in such a way that I was able to understand and learn from very quickly. Much of that was a mystery to me before. I appreciate how gracious you are with your time to help others. Cheers! 🍷

Following your suggestions, everything is working perfectly now. And now that I understand how it works, I should be able to add more controls in a well organized way.

Since my method runs through all of the window/control handles to auto-detect, I just added the _WinAPI_SetWindowSubclass() function under the 'AutoIt v3 GUI' case. Although I should probably add some checks to ensure that it is only done with top-level window and not any child GUI windows. I haven't looked into it that far yet.

What was interesting to me, though, is that I was able to remove _WinAPI_SetWindowSubclass() from the 'msctls_trackbar32' case/control and it still subclasses perfectly. But as you said, it would be because of the direction that those window messages go. I still have a lot to learn but this is very interesting.

Posted

As far as I'm concerned, the DarkMode project is complete for now. You're well on your way to building a great UDF!

Keep it up.

 

16 minutes ago, WildByDesign said:

I know that English is not your first language, from my understanding.

That's right. I usually have to switch back and forth between three languages every day, which isn't easy, but there are some great tools out there that make the work easier when it comes to phrasing things. 😉

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

@UEZ There are two other questions that I have wanted to ask you for a while now:

I notice that you quite often use StringLower in your switches when comparing class names in a few areas. Is this a choice specifically for improving performance of running through the switches?

Regarding window procedure functions. We can have many individual window procedure functions for different controls or we can have one big window procedure function for all subclassed controls. Would there be any difference in overall performance?

Edited by WildByDesign

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