Giter VIP home page Giter VIP logo

Comments (4)

PBfordev avatar PBfordev commented on June 19, 2024 1

I will submit a PR dealing with checkboxes and item selection rectangle soon.

from wxwidgets.

PBfordev avatar PBfordev commented on June 19, 2024

Since I did not see anything related to drawing checkboxes in the wxListCtrl code, I tested if it is not a limitation of the native listview. I used https://github.com/ysc3839/win32-darkmode/tree/delayload, where I made a single change:

diff --git a/win32-darkmode/win32-darkmode.cpp b/win32-darkmode/win32-darkmode.cpp
index efe249c..28536b1 100644
--- a/win32-darkmode/win32-darkmode.cpp
+++ b/win32-darkmode/win32-darkmode.cpp
@@ -115,6 +115,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 		switch (wmId)
 		{
 		case IDM_ABOUT:
+			ListView_SetExtendedListViewStyle(g_hWndListView, ListView_GetExtendedListViewStyle(g_hWndListView) | LVS_EX_CHECKBOXES);
 			DialogBoxW(g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
 			break;
 		case IDM_EXIT:

I.e., use checkboxes for the listview after selecting About from the Help menu.

The checkboxes are displayed properly:
listview-dark-checkboxes

Since the listctrl sample is rather complex and uses custom drawing, I tested also with the minimal sample:

diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
index 5f32257c6b..923eb27f4a 100644
--- a/samples/minimal/minimal.cpp
+++ b/samples/minimal/minimal.cpp
@@ -26,6 +26,8 @@
     #include "wx/wx.h"
 #endif
 
+#include <wx/listctrl.h>
+
 // ----------------------------------------------------------------------------
 // resources
 // ----------------------------------------------------------------------------
@@ -175,6 +177,16 @@ MyFrame::MyFrame(const wxString& title)
     CreateStatusBar(2);
     SetStatusText("Welcome to wxWidgets!");
 #endif // wxUSE_STATUSBAR
+    wxListCtrl* listCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
+
+    listCtrl->AppendColumn("Item");
+    listCtrl->AppendColumn("SubItem");    
+    for ( long i = 0; i < 10; ++i )
+    {
+        listCtrl->InsertItem(i, wxString::Format("Item %ld", i));
+        listCtrl->SetItem(i, 1, wxString::Format("SubItem %ld", i));
+    }
+    listCtrl->EnableCheckBoxes();
 }

But still no checkboxes. So it seems the issue is on wxWidgets side here.

BTW, the issue label "windows-11" should be probably changed to "dark mode".

from wxwidgets.

MaartenBent avatar MaartenBent commented on June 19, 2024

Because I added the checkboxes to wxListCtrl this caught my attention and had a look at it.
I can indeed reproduce it on Windows 10. It seems in dark mode, everything is drawn manually. So the checkboxes also need to be drawn. I tried some guestimated sizes and this seems to work all right:

diff --git "a/src/msw/listctrl.cpp" "b/src/msw/listctrl.cpp"
index 9aad796b90..9754c9fd61 100644
--- "a/src/msw/listctrl.cpp"
+++ "b/src/msw/listctrl.cpp"
@@ -36,8 +36,10 @@
 #endif
 
 #include "wx/imaglist.h"
+#include "wx/renderer.h"
 #include "wx/vector.h"
 
+#include "wx/msw/dc.h"
 #include "wx/msw/private.h"
 #include "wx/msw/uxtheme.h"
 #include "wx/msw/private/customdraw.h"
@@ -3047,7 +3049,7 @@ RECT GetCustomDrawnItemRect(const NMCUSTOMDRAW& nmcd)
     return rc;
 }
 
-bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
+bool HandleSubItemPrepaint(wxListCtrl* listctrl, LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
 {
     NMCUSTOMDRAW& nmcd = pLVCD->nmcd;
 
@@ -3072,6 +3074,23 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
         rc.right = rc2.left;
     }
 
+    if ( listctrl->HasCheckBoxes() )
+    {
+        wxDCTemp dc((WXHDC)hdc);
+
+        int cbSize = listctrl->FromDIP(13);
+        int cbX = listctrl->FromDIP(2);
+        int cbY = rc.top + ((rc.bottom - rc.top) / 2 - cbSize / 2);
+
+        int flags = 0;
+        if ( listctrl->IsItemChecked(item) )
+            flags |= wxCONTROL_CHECKED;
+
+        wxRendererNative::Get().DrawCheckBox(listctrl, dc, wxRect(cbX, cbY, cbSize, cbSize), flags);
+
+        rc.left += listctrl->FromDIP(16);
+    }
+
     // This mysterious offset is necessary for the owner drawn items to align
     // with the non-owner-drawn ones. Note that it's intentionally *not* scaled
     // by DPI factor because it doesn't seem to depend on the resolution.
@@ -3167,7 +3186,7 @@ void HandleItemPostpaint(NMCUSTOMDRAW nmcd)
 // for consistency.
 //
 // pLVCD->clrText and clrTextBk should contain the colours to use
-void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
+void HandleItemPaint(wxListCtrl* listctrl, LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
 {
     NMCUSTOMDRAW& nmcd = pLVCD->nmcd; // just a shortcut
 
@@ -3240,7 +3259,7 @@ void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
     for ( int col = 0; col < colCount; col++ )
     {
         pLVCD->iSubItem = col;
-        HandleSubItemPrepaint(pLVCD, hfont, colCount);
+        HandleSubItemPrepaint(listctrl, pLVCD, hfont, colCount);
     }
 
     ::SetTextColor(hdc, colTextOld);
@@ -3264,7 +3283,7 @@ WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
                             ? wxColourToRGB(attr->GetBackgroundColour())
                             : wxColourToRGB(listctrl->GetBackgroundColour());
 
-        HandleItemPaint(pLVCD, nullptr);
+        HandleItemPaint(listctrl, pLVCD, nullptr);
         return CDRF_SKIPDEFAULT;
     }
 
@@ -3294,7 +3313,7 @@ WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
             // with recent comctl32.dll versions (5 and 6, it uses to work with
             // 4.something) so we have to draw the item entirely ourselves in
             // this case
-            HandleItemPaint(pLVCD, GetHfontOf(font));
+            HandleItemPaint(listctrl, pLVCD, GetHfontOf(font));
             return CDRF_SKIPDEFAULT;
         }
 
@@ -3315,7 +3334,7 @@ WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
     if ( listctrl->IsSystemThemeDisabled() &&
             pLVCD->clrTextBk == ::GetSysColor(COLOR_BTNFACE) )
     {
-        HandleItemPaint(pLVCD, nullptr);
+        HandleItemPaint(listctrl, pLVCD, nullptr);
         return CDRF_SKIPDEFAULT;
     }
 

from wxwidgets.

PBfordev avatar PBfordev commented on June 19, 2024

It seems in dark mode, everything is drawn manually. So the checkboxes also need to be drawn.

Thanks I did not know that and thanks for the code as well. I tried an alternate approach, at 225% DPI my checkboxes are a bit smaller than yours but mine look a bit better (not jagged).

diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp
index 2b5ed314a4..cec64a26ee 100644
--- a/src/msw/listctrl.cpp
+++ b/src/msw/listctrl.cpp
@@ -3047,7 +3047,7 @@ RECT GetCustomDrawnItemRect(const NMCUSTOMDRAW& nmcd)
     return rc;
 }
 
-bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
+bool HandleSubItemPrepaint(wxListCtrl* listctrl, LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
 {
     NMCUSTOMDRAW& nmcd = pLVCD->nmcd;
 
@@ -3072,6 +3072,25 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
         rc.right = rc2.left;
     }
 
+    if ( listctrl->HasCheckBoxes() )
+    {
+        const HIMAGELIST himl = ListView_GetImageList(hwndList, LVSIL_STATE);
+
+        if ( himl && ImageList_GetImageCount(himl) >= 2 )
+        {
+            int x, y, width, height;
+
+            ImageList_GetIconSize(himl, &width, &height);
+            x = listctrl->FromDIP(2);
+            y = rc.top + ((rc.bottom - rc.top) / 2 - height/ 2);
+            // when using any style flag (ILD_TRANSPARENT, ILD_SELECTED, ILD_FOCUS), the checkboxes
+            // for selected items are drawn with a blue background, which we want to avoid
+            ImageList_Draw(himl, listctrl->IsItemChecked(item) ? 1 : 0, hdc, x, y, 0);
+            
+            rc.left += x + width + listctrl->FromDIP(1);
+        }
+    }
+
     // This mysterious offset is necessary for the owner drawn items to align
     // with the non-owner-drawn ones. Note that it's intentionally *not* scaled
     // by DPI factor because it doesn't seem to depend on the resolution.
@@ -3167,7 +3186,7 @@ void HandleItemPostpaint(NMCUSTOMDRAW nmcd)
 // for consistency.
 //
 // pLVCD->clrText and clrTextBk should contain the colours to use
-void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
+void HandleItemPaint(wxListCtrl* listctrl, LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
 {
     NMCUSTOMDRAW& nmcd = pLVCD->nmcd; // just a shortcut
 
@@ -3240,7 +3259,7 @@ void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
     for ( int col = 0; col < colCount; col++ )
     {
         pLVCD->iSubItem = col;
-        HandleSubItemPrepaint(pLVCD, hfont, colCount);
+        HandleSubItemPrepaint(listctrl, pLVCD, hfont, colCount);
     }
 
     ::SetTextColor(hdc, colTextOld);
@@ -3264,7 +3283,7 @@ WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
                             ? wxColourToRGB(attr->GetBackgroundColour())
                             : wxColourToRGB(listctrl->GetBackgroundColour());
 
-        HandleItemPaint(pLVCD, nullptr);
+        HandleItemPaint(listctrl, pLVCD, nullptr);
         return CDRF_SKIPDEFAULT;
     }
 
@@ -3294,7 +3313,7 @@ WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
             // with recent comctl32.dll versions (5 and 6, it uses to work with
             // 4.something) so we have to draw the item entirely ourselves in
             // this case
-            HandleItemPaint(pLVCD, GetHfontOf(font));
+            HandleItemPaint(listctrl, pLVCD, GetHfontOf(font));
             return CDRF_SKIPDEFAULT;
         }
 
@@ -3315,7 +3334,7 @@ WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
     if ( listctrl->IsSystemThemeDisabled() &&
             pLVCD->clrTextBk == ::GetSysColor(COLOR_BTNFACE) )
     {
-        HandleItemPaint(pLVCD, nullptr);
+        HandleItemPaint(listctrl, pLVCD, nullptr);
         return CDRF_SKIPDEFAULT;
     }

Regardless of the approach, there is still a problem with the item selection rect. The checkbox is not covered by it, when the control has images in the first column, the selection rect does not even cover the whole image, it's offset to the right.

But there are quite a few visual glitches in wxListCtrl in MSW dark mode, Besides #23772 and #23846; I found few more today when comparing the appearance in light and dark modes when in report view. But I guess that is for another Issue.

from wxwidgets.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.