From 85ee88cd536cbf8b347e58f84b160b60204ed157 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 23 Jan 2010 13:22:00 +0000 Subject: [PATCH] Improve wxCheckListBox appearance under Vista/Win7. Fix the items alignment and also code cleanup: fix indentation, remove magic numbers &c. Closes #10286. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63226 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/checklst.h | 84 +++++------ include/wx/msw/listbox.h | 20 ++- src/msw/checklst.cpp | 285 +++++++++++++++++--------------------- src/msw/listbox.cpp | 71 +++++++++- src/msw/ownerdrw.cpp | 67 +++++---- 5 files changed, 291 insertions(+), 236 deletions(-) diff --git a/include/wx/msw/checklst.h b/include/wx/msw/checklst.h index 4a9ab22815..31601d86bf 100644 --- a/include/wx/msw/checklst.h +++ b/include/wx/msw/checklst.h @@ -22,32 +22,32 @@ class WXDLLIMPEXP_FWD_CORE wxCheckListBoxItem; // fwd decl, defined in checklst. class WXDLLIMPEXP_CORE wxCheckListBox : public wxCheckListBoxBase { public: - // ctors - wxCheckListBox(); - wxCheckListBox(wxWindow *parent, wxWindowID id, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - int nStrings = 0, - const wxString choices[] = NULL, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxListBoxNameStr); - wxCheckListBox(wxWindow *parent, wxWindowID id, - const wxPoint& pos, - const wxSize& size, - const wxArrayString& choices, - long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxListBoxNameStr); + // ctors + wxCheckListBox(); + wxCheckListBox(wxWindow *parent, wxWindowID id, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int nStrings = 0, + const wxString choices[] = NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxListBoxNameStr); + wxCheckListBox(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + const wxArrayString& choices, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxListBoxNameStr); - bool Create(wxWindow *parent, wxWindowID id, + bool Create(wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, int n = 0, const wxString choices[] = NULL, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxListBoxNameStr); - bool Create(wxWindow *parent, wxWindowID id, + bool Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, const wxArrayString& choices, @@ -55,35 +55,35 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxListBoxNameStr); - // override base class virtuals - virtual void Delete(unsigned int n); + // items may be checked + virtual bool IsChecked(unsigned int uiIndex) const; + virtual void Check(unsigned int uiIndex, bool bCheck = true); + virtual void Toggle(unsigned int uiIndex); - virtual bool SetFont( const wxFont &font ); - - // items may be checked - virtual bool IsChecked(unsigned int uiIndex) const; - virtual void Check(unsigned int uiIndex, bool bCheck = true); - - // accessors - size_t GetItemHeight() const { return m_nItemHeight; } - - // we create our items ourselves and they have non-standard size, - // so we need to override these functions - virtual wxOwnerDrawn *CreateLboxItem(size_t n); - virtual bool MSWOnMeasure(WXMEASUREITEMSTRUCT *item); + // we create our items ourselves and they have non-standard size, + // so we need to override these functions + virtual wxOwnerDrawn *CreateLboxItem(size_t n); + virtual bool MSWOnMeasure(WXMEASUREITEMSTRUCT *item); protected: - // pressing space or clicking the check box toggles the item - void OnKeyDown(wxKeyEvent& event); - void OnLeftClick(wxMouseEvent& event); + // pressing space or clicking the check box toggles the item + void OnKeyDown(wxKeyEvent& event); + void OnLeftClick(wxMouseEvent& event); - wxSize DoGetBestSize() const; + // send an "item checked" event + void SendEvent(unsigned int uiIndex) + { + wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, GetId()); + event.SetInt(uiIndex); + event.SetEventObject(this); + event.SetString(GetString(uiIndex)); + ProcessCommand(event); + } -private: - size_t m_nItemHeight; // height of checklistbox items (the same for all) + wxSize DoGetBestClientSize() const; - DECLARE_EVENT_TABLE() - DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckListBox) + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckListBox) }; #endif //_CHECKLST_H diff --git a/include/wx/msw/listbox.h b/include/wx/msw/listbox.h index 47a94037b3..d8572170ab 100644 --- a/include/wx/msw/listbox.h +++ b/include/wx/msw/listbox.h @@ -86,8 +86,16 @@ public: virtual int GetSelection() const; virtual int GetSelections(wxArrayInt& aSelections) const; - // wxCheckListBox support + // return the index of the item at this position or wxNOT_FOUND + int HitTest(const wxPoint& pt) const { return DoHitTestList(pt); } + int HitTest(wxCoord x, wxCoord y) const { return DoHitTestList(wxPoint(x, y)); } + + // ownerdrawn wxListBox and wxCheckListBox support #if wxUSE_OWNER_DRAWN + // override base class virtuals + virtual void Delete(unsigned int n); + virtual bool SetFont(const wxFont &font); + bool MSWOnMeasure(WXMEASUREITEMSTRUCT *item); bool MSWOnDraw(WXDRAWITEMSTRUCT *item); @@ -99,6 +107,12 @@ public: // get the index of the given item int GetItemIndex(wxOwnerDrawn *item) const { return m_aItems.Index(item); } + + // get rect of the given item index + bool GetItemRect(size_t n, wxRect& rect) const; + + // redraw the given item + bool RefreshItem(size_t n); #endif // wxUSE_OWNER_DRAWN // Windows-specific code to update the horizontal extent of the listbox, if @@ -147,7 +161,9 @@ protected: virtual void DoSetFirstItem(int n); virtual void DoSetItemClientData(unsigned int n, void* clientData); virtual void* DoGetItemClientData(unsigned int n) const; - virtual int DoListHitTest(const wxPoint& point) const; + + // this can't be called DoHitTest() because wxWindow already has this method + virtual int DoHitTestList(const wxPoint& point) const; bool m_updateHorizontalExtent; virtual void OnInternalIdle(); diff --git a/src/msw/checklst.cpp b/src/msw/checklst.cpp index fc61953d60..cfa3fa73bd 100644 --- a/src/msw/checklst.cpp +++ b/src/msw/checklst.cpp @@ -56,6 +56,16 @@ // get item (converted to right type) #define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n))) +namespace +{ + // space around check mark bitmap in pixels + static const int CHECKMARK_EXTRA_SPACE = 1; + + // space betwen check bitmap and text label + static const int CHECKMARK_LABEL_SPACE = 2; + +} // anonymous namespace + // ============================================================================ // implementation // ============================================================================ @@ -125,68 +135,68 @@ IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox) class wxCheckListBoxItem : public wxOwnerDrawn { -friend class WXDLLIMPEXP_FWD_CORE wxCheckListBox; public: // ctor - wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex); + wxCheckListBoxItem(wxCheckListBox *parent); // drawing functions virtual bool OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus stat); // simple accessors and operations - bool IsChecked() const { return m_bChecked; } + wxCheckListBox *GetParent() const + { return m_parent; } + + int GetIndex() const + { return m_parent->GetItemIndex(const_cast(this)); } - void Check(bool bCheck); - void Toggle() { Check(!IsChecked()); } + wxString GetName() const + { return m_parent->GetString(GetIndex()); } - void SendEvent(); - virtual wxString GetName() const { return m_pParent->GetString(m_nIndex); } + bool IsChecked() const + { return m_checked; } + + void Check(bool bCheck) + { m_checked = bCheck; } + + void Toggle() + { Check(!IsChecked()); } private: - bool m_bChecked; - wxCheckListBox *m_pParent; - size_t m_nIndex; + wxCheckListBox *m_parent; + bool m_checked; wxDECLARE_NO_COPY_CLASS(wxCheckListBoxItem); }; -wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex) +wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox *parent) { - m_bChecked = false; - m_pParent = pParent; - m_nIndex = nIndex; + m_parent = parent; + m_checked = false; - // we don't initialize m_nCheckHeight/Width vars because it's - // done in OnMeasure while they are used only in OnDraw and we - // know that there will always be OnMeasure before OnDraw + wxSize size = wxRendererNative::Get().GetCheckBoxSize(parent); + size.x += 2 * CHECKMARK_EXTRA_SPACE + CHECKMARK_LABEL_SPACE; - SetMarginWidth(::GetSystemMetrics(SM_CXMENUCHECK)); - - SetBackgroundColour(pParent->GetBackgroundColour()); + SetMarginWidth(size.GetWidth()); + SetBackgroundColour(parent->GetBackgroundColour()); } bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus stat) { // first draw the label - if ( IsChecked() ) - stat = (wxOwnerDrawn::wxODStatus)(stat | wxOwnerDrawn::wxODChecked); - if ( !wxOwnerDrawn::OnDrawItem(dc, rc, act, stat) ) return false; - wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); // now draw the check mark part + wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); HDC hdc = GetHdcOf(*impl); - int nBmpWidth = ::GetSystemMetrics(SM_CXMENUCHECK), - nBmpHeight = ::GetSystemMetrics(SM_CYMENUCHECK); - + wxSize size = wxRendererNative::Get().GetCheckBoxSize(GetParent()); // first create bitmap in a memory DC MemoryHDC hdcMem(hdc); - CompatibleBitmap hBmpCheck(hdc, nBmpWidth, nBmpHeight); + CompatibleBitmap hBmpCheck(hdc, size.GetWidth(), size.GetHeight()); // then draw a check mark into it { @@ -197,70 +207,21 @@ bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc, flags |= wxCONTROL_CHECKED; wxDCTemp dcMem(hdcMem); - wxRendererNative::Get().DrawCheckBox( - m_pParent, dcMem, wxRect(0, 0, nBmpWidth, nBmpHeight), flags); + wxRendererNative::Get().DrawCheckBox(GetParent(), dcMem, wxRect(size), flags); } // select hBmpCheck out of hdcMem - // shift check mark 2 pixel to the right and bottom, looks better like this - int x = rc.GetX() + 2, - y = rc.GetY() + 2; - - // finally draw bitmap to screen: uses image list functions to blend - // the bitmap with the background colour (better for the selected items) - HIMAGELIST himl = ImageList_Create(nBmpWidth, nBmpHeight, - ILC_COLOR32 | ILC_MASK, 1, 1); - ImageList_Add(himl, hBmpCheck, NULL); + // finally draw bitmap to screen - UINT fStyle = stat & wxOwnerDrawn::wxODSelected ? ILD_SELECTED : ILD_NORMAL; - ImageList_Draw(himl, 0, hdc, x, y, fStyle); + // position of check mark bitmap + int x = rc.GetX() + CHECKMARK_EXTRA_SPACE; + int y = rc.GetY() + (rc.GetHeight() - size.GetHeight()) / 2; - ImageList_Destroy(himl); - - if (stat & wxODHasFocus) - wxRendererNative::Get().DrawFocusRect(m_pParent, dc, rc); + UINT uState = stat & wxOwnerDrawn::wxODSelected ? wxDSB_SELECTED : wxDSB_NORMAL; + wxDrawStateBitmap(hdc, hBmpCheck, x, y, uState); return true; } -// change the state of the item and redraw it -void wxCheckListBoxItem::Check(bool check) -{ - m_bChecked = check; - - // index may be changed because new items were added/deleted - if ( m_pParent->GetItemIndex(this) != (int)m_nIndex ) - { - // update it - int index = m_pParent->GetItemIndex(this); - - wxASSERT_MSG( index != wxNOT_FOUND, wxT("what does this item do here?") ); - - m_nIndex = (size_t)index; - } - - HWND hwndListbox = (HWND)m_pParent->GetHWND(); - - RECT rcUpdate; - - if ( ::SendMessage(hwndListbox, LB_GETITEMRECT, - m_nIndex, (LPARAM)&rcUpdate) == LB_ERR ) - { - wxLogDebug(wxT("LB_GETITEMRECT failed")); - } - - ::InvalidateRect(hwndListbox, &rcUpdate, FALSE); -} - -// send an "item checked" event -void wxCheckListBoxItem::SendEvent() -{ - wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, m_pParent->GetId()); - event.SetInt(m_nIndex); - event.SetEventObject(m_pParent); - event.SetString(m_pParent->GetString(m_nIndex)); - m_pParent->ProcessCommand(event); -} - // ---------------------------------------------------------------------------- // implementation of wxCheckListBox class // ---------------------------------------------------------------------------- @@ -319,62 +280,39 @@ bool wxCheckListBox::Create(wxWindow *parent, wxWindowID id, style | wxLB_OWNERDRAW, validator, name); } -// misc overloaded methods -// ----------------------- - -void wxCheckListBox::Delete(unsigned int n) -{ - wxCHECK_RET( IsValid(n), - wxT("invalid index in wxListBox::Delete") ); - - wxListBox::Delete(n); - - // free memory - delete m_aItems[n]; - - m_aItems.RemoveAt(n); -} - -bool wxCheckListBox::SetFont( const wxFont &font ) -{ - unsigned int i; - for ( i = 0; i < m_aItems.GetCount(); i++ ) - m_aItems[i]->SetFont(font); - - wxListBox::SetFont(font); - - return true; -} - // create/retrieve item // -------------------- // create a check list box item -wxOwnerDrawn *wxCheckListBox::CreateLboxItem(size_t nIndex) +wxOwnerDrawn *wxCheckListBox::CreateLboxItem(size_t WXUNUSED(n)) { - wxCheckListBoxItem *pItem = new wxCheckListBoxItem(this, nIndex); - return pItem; + wxCheckListBoxItem *pItem = new wxCheckListBoxItem(this); + return pItem; } // return item size // ---------------- bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item) { - if ( wxListBox::MSWOnMeasure(item) ) { - MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item; + if ( wxListBox::MSWOnMeasure(item) ) + { + MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item; - // add place for the check mark - pStruct->itemWidth += wxOwnerDrawn::GetDefaultMarginWidth(); - pStruct->itemHeight += 1; + wxSize size = wxRendererNative::Get().GetCheckBoxSize(this); + size.x += 2 * CHECKMARK_EXTRA_SPACE; + size.y += 2 * CHECKMARK_EXTRA_SPACE; - // save item height - m_nItemHeight = pStruct->itemHeight; + // add place for the check mark + pStruct->itemWidth += size.GetWidth(); - return true; - } + if ( pStruct->itemHeight < static_cast(size.GetHeight()) ) + pStruct->itemHeight = size.GetHeight(); - return false; -} + return true; + } + + return false; + } // check items // ----------- @@ -391,6 +329,15 @@ void wxCheckListBox::Check(unsigned int uiIndex, bool bCheck) wxCHECK_RET( IsValid(uiIndex), wxT("bad wxCheckListBox index") ); GetItem(uiIndex)->Check(bCheck); + RefreshItem(uiIndex); +} + +void wxCheckListBox::Toggle(unsigned int uiIndex) +{ + wxCHECK_RET( IsValid(uiIndex), wxT("bad wxCheckListBox index") ); + + GetItem(uiIndex)->Toggle(); + RefreshItem(uiIndex); } // process events @@ -401,33 +348,33 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event) // what do we do? enum { - None, - Toggle, - Set, - Clear + NONE, + TOGGLE, + SET, + CLEAR } oper; switch ( event.GetKeyCode() ) { case WXK_SPACE: - oper = Toggle; + oper = TOGGLE; break; case WXK_NUMPAD_ADD: case '+': - oper = Set; + oper = SET; break; case WXK_NUMPAD_SUBTRACT: case '-': - oper = Clear; + oper = CLEAR; break; default: - oper = None; + oper = NONE; } - if ( oper != None ) + if ( oper != NONE ) { wxArrayInt selections; int count = 0; @@ -447,22 +394,17 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event) for ( int i = 0; i < count; i++ ) { - wxCheckListBoxItem *item = GetItem(selections[i]); - if ( !item ) - { - wxFAIL_MSG( wxT("no wxCheckListBoxItem?") ); - continue; - } + int nItem = selections[i]; switch ( oper ) { - case Toggle: - item->Toggle(); + case TOGGLE: + Toggle(nItem); break; - case Set: - case Clear: - item->Check( oper == Set ); + case SET: + case CLEAR: + Check(nItem, oper == SET); break; default: @@ -471,7 +413,7 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event) // we should send an event as this has been done by the user and // not by the program - item->SendEvent(); + SendEvent(nItem); } } else // nothing to do @@ -483,11 +425,21 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event) void wxCheckListBox::OnLeftClick(wxMouseEvent& event) { // clicking on the item selects it, clicking on the checkmark toggles - if ( event.GetX() <= wxOwnerDrawn::GetDefaultMarginWidth() ) + + int nItem = HitTest(event.GetX(), event.GetY()); + + if ( nItem != wxNOT_FOUND ) { - int nItem = HitTest(event.GetX(), event.GetY()); + wxRect rect; + GetItemRect(nItem, rect); + + // convert item rect to check mark rect + wxSize size = wxRendererNative::Get().GetCheckBoxSize(this); + rect.x += CHECKMARK_EXTRA_SPACE; + rect.y += (rect.GetHeight() - size.GetHeight()) / 2; + rect.SetSize(size); - if ( nItem != wxNOT_FOUND ) + if ( rect.Contains(event.GetX(), event.GetY()) ) { // people expect to get "kill focus" event for the currently // focused control before getting events from the other controls @@ -498,24 +450,43 @@ void wxCheckListBox::OnLeftClick(wxMouseEvent& event) SetFocus(); if ( FindFocus() == this ) { - wxCheckListBoxItem *item = GetItem(nItem); - item->Toggle(); - item->SendEvent(); + Toggle(nItem); + SendEvent(nItem); + + // scroll one item down if the item is the last one + // and isn't visible at all + int h; + GetClientSize(NULL, &h); + if ( rect.GetBottom() > h ) + ScrollLines(1); } } - //else: it's not an error, just click outside of client zone + else + { + // implement default behaviour: clicking on the item selects it + event.Skip(); + } } else { - // implement default behaviour: clicking on the item selects it + // implement default behavior on click outside of client zone event.Skip(); } } -wxSize wxCheckListBox::DoGetBestSize() const +wxSize wxCheckListBox::DoGetBestClientSize() const { - wxSize best = wxListBox::DoGetBestSize(); - best.x += wxOwnerDrawn::GetDefaultMarginWidth(); // add room for the checkbox + wxSize best = wxListBox::DoGetBestClientSize(); + + // add room for the checkbox + wxSize size = wxRendererNative::Get().GetCheckBoxSize(const_cast(this)); + size.x += 2 * CHECKMARK_EXTRA_SPACE; + size.y += 2 * CHECKMARK_EXTRA_SPACE; + + best.x += size.GetWidth(); + if ( best.y < size.GetHeight() ) + best.y = size.GetHeight(); + CacheBestSize(best); return best; } diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp index 89b64fbeea..29e2e74401 100644 --- a/src/msw/listbox.cpp +++ b/src/msw/listbox.cpp @@ -490,7 +490,7 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items, return n; } -int wxListBox::DoListHitTest(const wxPoint& point) const +int wxListBox::DoHitTestList(const wxPoint& point) const { LRESULT lRes = ::SendMessage(GetHwnd(), LB_ITEMFROMPOINT, 0, MAKELPARAM(point.x, point.y)); @@ -683,12 +683,73 @@ bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) #if wxUSE_OWNER_DRAWN +// misc overloaded methods +// ----------------------- + +void wxListBox::Delete(unsigned int n) +{ + wxCHECK_RET( IsValid(n), + wxT("invalid index in wxListBox::Delete") ); + + wxListBoxBase::Delete(n); + + // free memory + delete m_aItems[n]; + m_aItems.RemoveAt(n); +} + +bool wxListBox::SetFont(const wxFont &font) +{ + unsigned int i; + for ( i = 0; i < m_aItems.GetCount(); i++ ) + m_aItems[i]->SetFont(font); + + wxListBoxBase::SetFont(font); + + return true; +} + +bool wxListBox::GetItemRect(size_t n, wxRect& rect) const +{ + wxCHECK_MSG( IsValid(n), false, + wxT("invalid index in wxListBox::GetItemRect") ); + + RECT rc; + + if ( ListBox_GetItemRect(GetHwnd(), n, &rc) != LB_ERR ) + { + rect = wxRectFromRECT(rc); + return true; + } + else + { + // couldn't retrieve rect: for example, item isn't visible + return false; + } +} + +bool wxListBox::RefreshItem(size_t n) +{ + wxRect rect; + if ( !GetItemRect(n, rect) ) + return false; + + RECT rc; + wxCopyRectToRECT(rect, rc); + + return ::InvalidateRect((HWND)GetHWND(), &rc, FALSE) == TRUE; +} + + // drawing // ------- -// space beneath/above each row in pixels -// "standard" checklistbox use 1 here, some might prefer 2. 0 is ugly. -#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1) +namespace +{ + // space beneath/above each row in pixels + static const int LISTBOX_EXTRA_SPACE = 1; + +} // anonymous namespace // the height is the same for all items // TODO should be changed for LBS_OWNERDRAWVARIABLE style listboxes @@ -712,7 +773,7 @@ bool wxListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item) wxDCTemp dc((WXHDC)hdc); dc.SetFont(GetFont()); - pStruct->itemHeight = dc.GetCharHeight() + 2*OWNER_DRAWN_LISTBOX_EXTRA_SPACE; + pStruct->itemHeight = dc.GetCharHeight() + 2 * LISTBOX_EXTRA_SPACE; pStruct->itemWidth = dc.GetCharWidth(); } diff --git a/src/msw/ownerdrw.cpp b/src/msw/ownerdrw.cpp index 3c70d2408e..04fbc28368 100644 --- a/src/msw/ownerdrw.cpp +++ b/src/msw/ownerdrw.cpp @@ -45,50 +45,57 @@ bool wxOwnerDrawn::OnDrawItem(wxDC& dc, const wxRect& rc, if ( !IsOwnerDrawn() ) return true; - // set the font and colors - wxFont font; - GetFontToUse(font); - - wxColour colText, colBack; - GetColourToUse(stat, colText, colBack); - wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); HDC hdc = GetHdcOf(*impl); - SelectInHDC selFont(hdc, GetHfontOf(font)); + RECT rect; + wxCopyRectToRECT(rc, rect); + + { + // set the font and colors + wxFont font; + GetFontToUse(font); + + wxColour colText, colBack; + GetColourToUse(stat, colText, colBack); + + SelectInHDC selFont(hdc, GetHfontOf(font)); + + wxMSWImpl::wxTextColoursChanger textCol(hdc, colText, colBack); + wxMSWImpl::wxBkModeChanger bkMode(hdc, wxBRUSHSTYLE_TRANSPARENT); + - wxMSWImpl::wxTextColoursChanger textCol(hdc, colText, colBack); - wxMSWImpl::wxBkModeChanger bkMode(hdc, wxBRUSHSTYLE_TRANSPARENT); + AutoHBRUSH hbr(wxColourToPalRGB(colBack)); + SelectInHDC selBrush(hdc, hbr); + ::FillRect(hdc, &rect, hbr); - AutoHBRUSH hbr(wxColourToPalRGB(colBack)); - SelectInHDC selBrush(hdc, hbr); + // using native API because it recognizes '&' - RECT rectFill; - wxCopyRectToRECT(rc, rectFill); - ::FillRect(hdc, &rectFill, hbr); + wxString text = GetName(); - // using native API because it recognizes '&' + SIZE sizeRect; + ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect); - wxString text = GetName(); + int flags = DST_PREFIXTEXT; + if ( (stat & wxODDisabled) && !(stat & wxODSelected) ) + flags |= DSS_DISABLED; - SIZE sizeRect; - ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect); + if ( (stat & wxODHidePrefix) ) + flags |= DSS_HIDEPREFIX; - int flags = DST_PREFIXTEXT; - if ( (stat & wxODDisabled) && !(stat & wxODSelected) ) - flags |= DSS_DISABLED; + int x = rc.x + GetMarginWidth(); + int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2; + int cx = rc.GetWidth() - GetMarginWidth(); + int cy = sizeRect.cy; - if ( (stat & wxODHidePrefix) ) - flags |= DSS_HIDEPREFIX; + ::DrawState(hdc, NULL, NULL, (LPARAM)text.wx_str(), + text.length(), x, y, cx, cy, flags); - int x = rc.x + GetMarginWidth(); - int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2; - int cx = rc.GetWidth() - GetMarginWidth(); - int cy = sizeRect.cy; + } // reset to default the font, colors and brush - ::DrawState(hdc, NULL, NULL, (LPARAM)text.wx_str(), - text.length(), x, y, cx, cy, flags); + if (stat & wxODHasFocus) + ::DrawFocusRect(hdc, &rect); return true; } -- 2.49.0