]> git.saurik.com Git - wxWidgets.git/commitdiff
Improve wxCheckListBox appearance under Vista/Win7.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 23 Jan 2010 13:22:00 +0000 (13:22 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 23 Jan 2010 13:22:00 +0000 (13:22 +0000)
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
include/wx/msw/listbox.h
src/msw/checklst.cpp
src/msw/listbox.cpp
src/msw/ownerdrw.cpp

index 4a9ab2281585d5700ff7e19b1a546a4d4dc5d446..31601d86bf1ac88713bff87754c0610be3592949 100644 (file)
@@ -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
index 47a94037b35712c6649aef27164a10dc23ddf8e7..d8572170ab87ef45da4c1dd440d53dec1a534360 100644 (file)
@@ -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();
index fc61953d6071446e900b6ea121d9f4ee98871582..cfa3fa73bd79801b14faf2b2539f7e7fa58c2418 100644 (file)
 // 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<wxCheckListBoxItem*>(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<unsigned int>(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<wxCheckListBox*>(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;
 }
index 89b64fbeeaf264b8d5f1279d4c4cdbdd37ed710f..29e2e7440136ae32d729d25b129cc84667066e91 100644 (file)
@@ -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();
     }
 
index 3c70d2408e24e6a4ca5fbd1a8ff1783944ed49ab..04fbc28368ef018c95ef4a857f49358f6fcdff8f 100644 (file)
@@ -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;
 }