]> git.saurik.com Git - wxWidgets.git/commitdiff
Correct drawing of check marks for owner-drawn items without bitmaps.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 23 Jan 2010 13:21:52 +0000 (13:21 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 23 Jan 2010 13:21:52 +0000 (13:21 +0000)
Standard check mark was not drawn correctly for check/radio items without
bitmaps.

Closes #11480.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63225 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/menuitem.h
src/msw/menuitem.cpp

index a4cbaa820de3e779a4da7bd5fe86df5a82eceeee..38ad3ed2c68a9661d8514f84ea26736bb013d5f7 100644 (file)
@@ -118,6 +118,10 @@ protected:
     virtual void GetFontToUse(wxFont& font) const;
     virtual void GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& colBack) const;
 
+private:
+    // helper function for draw std menu check mark
+    void DrawStdCheckMark(HDC hdc, const RECT* rc, wxODStatus stat);
+
 #endif // wxUSE_OWNER_DRAWN
 
 private:
index 83af40f8b3cefd79bf2fdd924e1e99f94cf2f7e8..b9bc84585b02e3703e3793d52873efd3c2a6df33 100644 (file)
@@ -1021,54 +1021,7 @@ bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
     {
         if ( stat & wxODChecked )
         {
-        #if wxUSE_UXTHEME
-            wxUxThemeEngine* theme = MenuDrawData::GetUxThemeEngine();
-            if ( theme )
-            {
-                wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU");
-
-                POPUPCHECKBACKGROUNDSTATES stateCheckBg = (stat & wxODDisabled)
-                                                            ? MCB_DISABLED
-                                                            : MCB_NORMAL;
-
-                theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPCHECKBACKGROUND,
-                                           stateCheckBg, &rcImg, NULL);
-
-                // check mark will be drawn centered on the background
-
-                POPUPCHECKSTATES stateCheck = (stat & wxODDisabled)
-                                                ? MC_CHECKMARKDISABLED
-                                                : MC_CHECKMARKNORMAL;
-
-                theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPCHECK,
-                                           stateCheck, &rcImg, NULL);
-            }
-            else
-        #endif // wxUSE_UXTHEME
-            {
-                int cx = imgWidth;
-                int cy = rcImg.bottom - rcImg.top;
-
-                // what goes on: DrawFrameControl creates a b/w mask,
-                // then we copy it to screen to have right colors
-
-                // first create a monochrome bitmap in a memory DC
-                HDC hdcMem = ::CreateCompatibleDC(hdc);
-                HBITMAP hbmpCheck = ::CreateBitmap(cx, cy, 1, 1, 0);
-                ::SelectObject(hdcMem, hbmpCheck);
-
-                // then draw a check mark into it
-                RECT rect = { 0, 0, cx, cy };
-                if ( rc.GetHeight() > 0 )
-                {
-                    ::DrawFrameControl(hdcMem, &rect, DFC_MENU, DFCS_MENUCHECK);
-                }
-
-                // finally copy it to screen DC and clean up
-                ::BitBlt(hdc, rcImg.left, rcImg.top, cx, cy, hdcMem, 0, 0, SRCCOPY);
-
-                ::DeleteDC(hdcMem);
-            }
+            DrawStdCheckMark(hdc, &rcImg, stat);
         }
     }
     else
@@ -1120,6 +1073,119 @@ bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc,
 
 }
 
+namespace
+{
+
+// helper function for draw coloured check mark
+void DrawColorCheckMark(HDC hdc, int x, int y, int cx, int cy, HDC hdcCheckMask, int idxColor)
+{
+    const COLORREF colBlack = RGB(0, 0, 0);
+    const COLORREF colWhite = RGB(255, 255, 255);
+
+    COLORREF colOldText = ::SetTextColor(hdc, colBlack);
+    COLORREF colOldBack = ::SetBkColor(hdc, colWhite);
+    int prevMode = SetBkMode(hdc, TRANSPARENT);
+
+    // memory DC for color bitmap
+    MemoryHDC hdcMem(hdc);
+    CompatibleBitmap hbmpMem(hdc, cx, cy);
+    SelectInHDC selMem(hdcMem, hbmpMem);
+
+    RECT rect = { 0, 0, cx, cy };
+    ::FillRect(hdcMem, &rect, ::GetSysColorBrush(idxColor));
+
+    const COLORREF colCheck = ::GetSysColor(idxColor);
+    if ( colCheck == colWhite )
+    {
+        ::BitBlt(hdc, x, y, cx, cy, hdcCheckMask, 0, 0, MERGEPAINT);
+        ::BitBlt(hdc, x, y, cx, cy, hdcMem, 0, 0, SRCAND);
+    }
+    else
+    {
+        if ( colCheck != colBlack )
+        {
+            const DWORD ROP_DSna = 0x00220326;  // dest = (NOT src) AND dest
+            ::BitBlt(hdcMem, 0, 0, cx, cy, hdcCheckMask, 0, 0, ROP_DSna);
+        }
+
+        ::BitBlt(hdc, x, y, cx, cy, hdcCheckMask, 0, 0, SRCAND);
+        ::BitBlt(hdc, x, y, cx, cy, hdcMem, 0, 0, SRCPAINT);
+    }
+
+    ::SetBkMode(hdc, prevMode);
+    ::SetBkColor(hdc, colOldBack);
+    ::SetTextColor(hdc, colOldText);
+}
+
+} // anonymous namespace
+
+void wxMenuItem::DrawStdCheckMark(HDC hdc, const RECT* rc, wxODStatus stat)
+{
+#if wxUSE_UXTHEME
+    wxUxThemeEngine* theme = MenuDrawData::GetUxThemeEngine();
+    if ( theme )
+    {
+        wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU");
+
+        POPUPCHECKBACKGROUNDSTATES stateCheckBg = (stat & wxODDisabled)
+                                                    ? MCB_DISABLED
+                                                    : MCB_NORMAL;
+
+        theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPCHECKBACKGROUND,
+                                   stateCheckBg, rc, NULL);
+
+        // check mark will be drawn centered on the background
+
+        POPUPCHECKSTATES stateCheck;
+        if ( GetKind() == wxITEM_CHECK )
+        {
+            stateCheck = (stat & wxODDisabled) ? MC_CHECKMARKDISABLED
+                                               : MC_CHECKMARKNORMAL;
+        }
+        else
+        {
+            stateCheck = (stat & wxODDisabled) ? MC_BULLETDISABLED
+                                               : MC_BULLETNORMAL;
+        }
+
+        theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPCHECK,
+                                   stateCheck, rc, NULL);
+    }
+    else
+#endif // wxUSE_UXTHEME
+    {
+        int cx = rc->right - rc->left;
+        int cy = rc->bottom - rc->top;
+
+        // first create mask of check mark
+        MemoryHDC hdcMask(hdc);
+        MonoBitmap hbmpMask(cx, cy);
+        SelectInHDC selMask(hdcMask,hbmpMask);
+
+        // then draw a check mark into it
+        UINT stateCheck = (GetKind() == wxITEM_CHECK) ? DFCS_MENUCHECK
+                                                      : DFCS_MENUBULLET;
+        RECT rect = { 0, 0, cx, cy };
+        ::DrawFrameControl(hdcMask, &rect, DFC_MENU, stateCheck);
+
+        // first draw shadow if disabled
+        if ( (stat & wxODDisabled) && !(stat & wxODSelected) )
+        {
+            DrawColorCheckMark(hdc, rc->left + 1, rc->top + 1,
+                               cx, cy, hdcMask, COLOR_3DHILIGHT);
+        }
+
+        // then draw a check mark
+        int color = COLOR_MENUTEXT;
+        if ( stat & wxODDisabled )
+            color = COLOR_BTNSHADOW;
+        else if ( stat & wxODSelected )
+            color = COLOR_HIGHLIGHTTEXT;
+
+        DrawColorCheckMark(hdc, rc->left, rc->top, cx, cy, hdcMask, color);
+    }
+}
+
 void wxMenuItem::GetFontToUse(wxFont& font) const
 {
     font = GetFont();