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
This commit is contained in:
@@ -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
|
||||
|
@@ -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();
|
||||
|
@@ -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; }
|
||||
|
||||
void Check(bool bCheck);
|
||||
void Toggle() { Check(!IsChecked()); }
|
||||
int GetIndex() const
|
||||
{ return m_parent->GetItemIndex(const_cast<wxCheckListBoxItem*>(this)); }
|
||||
|
||||
void SendEvent();
|
||||
wxString GetName() const
|
||||
{ return m_parent->GetString(GetIndex()); }
|
||||
|
||||
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
|
||||
|
||||
// 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);
|
||||
// position of check mark bitmap
|
||||
int x = rc.GetX() + CHECKMARK_EXTRA_SPACE;
|
||||
int y = rc.GetY() + (rc.GetHeight() - size.GetHeight()) / 2;
|
||||
|
||||
UINT fStyle = stat & wxOwnerDrawn::wxODSelected ? ILD_SELECTED : ILD_NORMAL;
|
||||
ImageList_Draw(himl, 0, hdc, x, y, fStyle);
|
||||
|
||||
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,63 +280,40 @@ 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 true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
if ( nItem != wxNOT_FOUND )
|
||||
{
|
||||
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 ( 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;
|
||||
}
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
wxMSWImpl::wxTextColoursChanger textCol(hdc, colText, colBack);
|
||||
wxMSWImpl::wxBkModeChanger bkMode(hdc, wxBRUSHSTYLE_TRANSPARENT);
|
||||
{
|
||||
// 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);
|
||||
|
||||
|
||||
AutoHBRUSH hbr(wxColourToPalRGB(colBack));
|
||||
SelectInHDC selBrush(hdc, hbr);
|
||||
AutoHBRUSH hbr(wxColourToPalRGB(colBack));
|
||||
SelectInHDC selBrush(hdc, hbr);
|
||||
|
||||
RECT rectFill;
|
||||
wxCopyRectToRECT(rc, rectFill);
|
||||
::FillRect(hdc, &rectFill, hbr);
|
||||
::FillRect(hdc, &rect, hbr);
|
||||
|
||||
// using native API because it recognizes '&'
|
||||
// using native API because it recognizes '&'
|
||||
|
||||
wxString text = GetName();
|
||||
wxString text = GetName();
|
||||
|
||||
SIZE sizeRect;
|
||||
::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect);
|
||||
SIZE sizeRect;
|
||||
::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect);
|
||||
|
||||
int flags = DST_PREFIXTEXT;
|
||||
if ( (stat & wxODDisabled) && !(stat & wxODSelected) )
|
||||
flags |= DSS_DISABLED;
|
||||
int flags = DST_PREFIXTEXT;
|
||||
if ( (stat & wxODDisabled) && !(stat & wxODSelected) )
|
||||
flags |= DSS_DISABLED;
|
||||
|
||||
if ( (stat & wxODHidePrefix) )
|
||||
flags |= DSS_HIDEPREFIX;
|
||||
if ( (stat & wxODHidePrefix) )
|
||||
flags |= DSS_HIDEPREFIX;
|
||||
|
||||
int x = rc.x + GetMarginWidth();
|
||||
int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2;
|
||||
int cx = rc.GetWidth() - GetMarginWidth();
|
||||
int cy = sizeRect.cy;
|
||||
int x = rc.x + GetMarginWidth();
|
||||
int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2;
|
||||
int cx = rc.GetWidth() - GetMarginWidth();
|
||||
int cy = sizeRect.cy;
|
||||
|
||||
::DrawState(hdc, NULL, NULL, (LPARAM)text.wx_str(),
|
||||
text.length(), x, y, cx, cy, flags);
|
||||
::DrawState(hdc, NULL, NULL, (LPARAM)text.wx_str(),
|
||||
text.length(), x, y, cx, cy, flags);
|
||||
|
||||
} // reset to default the font, colors and brush
|
||||
|
||||
if (stat & wxODHasFocus)
|
||||
::DrawFocusRect(hdc, &rect);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user