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
|
class WXDLLIMPEXP_CORE wxCheckListBox : public wxCheckListBoxBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// ctors
|
// ctors
|
||||||
wxCheckListBox();
|
wxCheckListBox();
|
||||||
wxCheckListBox(wxWindow *parent, wxWindowID id,
|
wxCheckListBox(wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos = wxDefaultPosition,
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
const wxSize& size = wxDefaultSize,
|
const wxSize& size = wxDefaultSize,
|
||||||
int nStrings = 0,
|
int nStrings = 0,
|
||||||
const wxString choices[] = NULL,
|
const wxString choices[] = NULL,
|
||||||
long style = 0,
|
long style = 0,
|
||||||
const wxValidator& validator = wxDefaultValidator,
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
const wxString& name = wxListBoxNameStr);
|
const wxString& name = wxListBoxNameStr);
|
||||||
wxCheckListBox(wxWindow *parent, wxWindowID id,
|
wxCheckListBox(wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos,
|
const wxPoint& pos,
|
||||||
const wxSize& size,
|
const wxSize& size,
|
||||||
const wxArrayString& choices,
|
const wxArrayString& choices,
|
||||||
long style = 0,
|
long style = 0,
|
||||||
const wxValidator& validator = wxDefaultValidator,
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
const wxString& name = wxListBoxNameStr);
|
const wxString& name = wxListBoxNameStr);
|
||||||
|
|
||||||
bool Create(wxWindow *parent, wxWindowID id,
|
bool Create(wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos = wxDefaultPosition,
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
const wxSize& size = wxDefaultSize,
|
const wxSize& size = wxDefaultSize,
|
||||||
int n = 0, const wxString choices[] = NULL,
|
int n = 0, const wxString choices[] = NULL,
|
||||||
long style = 0,
|
long style = 0,
|
||||||
const wxValidator& validator = wxDefaultValidator,
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
const wxString& name = wxListBoxNameStr);
|
const wxString& name = wxListBoxNameStr);
|
||||||
bool Create(wxWindow *parent, wxWindowID id,
|
bool Create(wxWindow *parent, wxWindowID id,
|
||||||
const wxPoint& pos,
|
const wxPoint& pos,
|
||||||
const wxSize& size,
|
const wxSize& size,
|
||||||
const wxArrayString& choices,
|
const wxArrayString& choices,
|
||||||
@@ -55,35 +55,35 @@ public:
|
|||||||
const wxValidator& validator = wxDefaultValidator,
|
const wxValidator& validator = wxDefaultValidator,
|
||||||
const wxString& name = wxListBoxNameStr);
|
const wxString& name = wxListBoxNameStr);
|
||||||
|
|
||||||
// override base class virtuals
|
// items may be checked
|
||||||
virtual void Delete(unsigned int n);
|
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 );
|
// we create our items ourselves and they have non-standard size,
|
||||||
|
// so we need to override these functions
|
||||||
// items may be checked
|
virtual wxOwnerDrawn *CreateLboxItem(size_t n);
|
||||||
virtual bool IsChecked(unsigned int uiIndex) const;
|
virtual bool MSWOnMeasure(WXMEASUREITEMSTRUCT *item);
|
||||||
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);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// pressing space or clicking the check box toggles the item
|
// pressing space or clicking the check box toggles the item
|
||||||
void OnKeyDown(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
void OnLeftClick(wxMouseEvent& 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:
|
wxSize DoGetBestClientSize() const;
|
||||||
size_t m_nItemHeight; // height of checklistbox items (the same for all)
|
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckListBox)
|
DECLARE_DYNAMIC_CLASS_NO_COPY(wxCheckListBox)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_CHECKLST_H
|
#endif //_CHECKLST_H
|
||||||
|
@@ -86,8 +86,16 @@ public:
|
|||||||
virtual int GetSelection() const;
|
virtual int GetSelection() const;
|
||||||
virtual int GetSelections(wxArrayInt& aSelections) 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
|
#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 MSWOnMeasure(WXMEASUREITEMSTRUCT *item);
|
||||||
bool MSWOnDraw(WXDRAWITEMSTRUCT *item);
|
bool MSWOnDraw(WXDRAWITEMSTRUCT *item);
|
||||||
|
|
||||||
@@ -99,6 +107,12 @@ public:
|
|||||||
|
|
||||||
// get the index of the given item
|
// get the index of the given item
|
||||||
int GetItemIndex(wxOwnerDrawn *item) const { return m_aItems.Index(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
|
#endif // wxUSE_OWNER_DRAWN
|
||||||
|
|
||||||
// Windows-specific code to update the horizontal extent of the listbox, if
|
// Windows-specific code to update the horizontal extent of the listbox, if
|
||||||
@@ -147,7 +161,9 @@ protected:
|
|||||||
virtual void DoSetFirstItem(int n);
|
virtual void DoSetFirstItem(int n);
|
||||||
virtual void DoSetItemClientData(unsigned int n, void* clientData);
|
virtual void DoSetItemClientData(unsigned int n, void* clientData);
|
||||||
virtual void* DoGetItemClientData(unsigned int n) const;
|
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;
|
bool m_updateHorizontalExtent;
|
||||||
virtual void OnInternalIdle();
|
virtual void OnInternalIdle();
|
||||||
|
@@ -56,6 +56,16 @@
|
|||||||
// get item (converted to right type)
|
// get item (converted to right type)
|
||||||
#define GetItem(n) ((wxCheckListBoxItem *)(GetItem(n)))
|
#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
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -125,68 +135,68 @@ IMPLEMENT_DYNAMIC_CLASS(wxCheckListBox, wxListBox)
|
|||||||
|
|
||||||
class wxCheckListBoxItem : public wxOwnerDrawn
|
class wxCheckListBoxItem : public wxOwnerDrawn
|
||||||
{
|
{
|
||||||
friend class WXDLLIMPEXP_FWD_CORE wxCheckListBox;
|
|
||||||
public:
|
public:
|
||||||
// ctor
|
// ctor
|
||||||
wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex);
|
wxCheckListBoxItem(wxCheckListBox *parent);
|
||||||
|
|
||||||
// drawing functions
|
// drawing functions
|
||||||
virtual bool OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus stat);
|
virtual bool OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus stat);
|
||||||
|
|
||||||
// simple accessors and operations
|
// simple accessors and operations
|
||||||
bool IsChecked() const { return m_bChecked; }
|
wxCheckListBox *GetParent() const
|
||||||
|
{ return m_parent; }
|
||||||
|
|
||||||
void Check(bool bCheck);
|
int GetIndex() const
|
||||||
void Toggle() { Check(!IsChecked()); }
|
{ 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:
|
private:
|
||||||
bool m_bChecked;
|
wxCheckListBox *m_parent;
|
||||||
wxCheckListBox *m_pParent;
|
bool m_checked;
|
||||||
size_t m_nIndex;
|
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(wxCheckListBoxItem);
|
wxDECLARE_NO_COPY_CLASS(wxCheckListBoxItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex)
|
wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox *parent)
|
||||||
{
|
{
|
||||||
m_bChecked = false;
|
m_parent = parent;
|
||||||
m_pParent = pParent;
|
m_checked = false;
|
||||||
m_nIndex = nIndex;
|
|
||||||
|
|
||||||
// we don't initialize m_nCheckHeight/Width vars because it's
|
wxSize size = wxRendererNative::Get().GetCheckBoxSize(parent);
|
||||||
// done in OnMeasure while they are used only in OnDraw and we
|
size.x += 2 * CHECKMARK_EXTRA_SPACE + CHECKMARK_LABEL_SPACE;
|
||||||
// know that there will always be OnMeasure before OnDraw
|
|
||||||
|
|
||||||
SetMarginWidth(::GetSystemMetrics(SM_CXMENUCHECK));
|
SetMarginWidth(size.GetWidth());
|
||||||
|
SetBackgroundColour(parent->GetBackgroundColour());
|
||||||
SetBackgroundColour(pParent->GetBackgroundColour());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc,
|
bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc,
|
||||||
wxODAction act, wxODStatus stat)
|
wxODAction act, wxODStatus stat)
|
||||||
{
|
{
|
||||||
// first draw the label
|
// first draw the label
|
||||||
if ( IsChecked() )
|
|
||||||
stat = (wxOwnerDrawn::wxODStatus)(stat | wxOwnerDrawn::wxODChecked);
|
|
||||||
|
|
||||||
if ( !wxOwnerDrawn::OnDrawItem(dc, rc, act, stat) )
|
if ( !wxOwnerDrawn::OnDrawItem(dc, rc, act, stat) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
|
|
||||||
// now draw the check mark part
|
// now draw the check mark part
|
||||||
|
wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
|
||||||
HDC hdc = GetHdcOf(*impl);
|
HDC hdc = GetHdcOf(*impl);
|
||||||
|
|
||||||
int nBmpWidth = ::GetSystemMetrics(SM_CXMENUCHECK),
|
wxSize size = wxRendererNative::Get().GetCheckBoxSize(GetParent());
|
||||||
nBmpHeight = ::GetSystemMetrics(SM_CYMENUCHECK);
|
|
||||||
|
|
||||||
|
|
||||||
// first create bitmap in a memory DC
|
// first create bitmap in a memory DC
|
||||||
MemoryHDC hdcMem(hdc);
|
MemoryHDC hdcMem(hdc);
|
||||||
CompatibleBitmap hBmpCheck(hdc, nBmpWidth, nBmpHeight);
|
CompatibleBitmap hBmpCheck(hdc, size.GetWidth(), size.GetHeight());
|
||||||
|
|
||||||
// then draw a check mark into it
|
// then draw a check mark into it
|
||||||
{
|
{
|
||||||
@@ -197,70 +207,21 @@ bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc,
|
|||||||
flags |= wxCONTROL_CHECKED;
|
flags |= wxCONTROL_CHECKED;
|
||||||
|
|
||||||
wxDCTemp dcMem(hdcMem);
|
wxDCTemp dcMem(hdcMem);
|
||||||
wxRendererNative::Get().DrawCheckBox(
|
wxRendererNative::Get().DrawCheckBox(GetParent(), dcMem, wxRect(size), flags);
|
||||||
m_pParent, dcMem, wxRect(0, 0, nBmpWidth, nBmpHeight), flags);
|
|
||||||
} // select hBmpCheck out of hdcMem
|
} // select hBmpCheck out of hdcMem
|
||||||
|
|
||||||
// shift check mark 2 pixel to the right and bottom, looks better like this
|
// finally draw bitmap to screen
|
||||||
int x = rc.GetX() + 2,
|
|
||||||
y = rc.GetY() + 2;
|
|
||||||
|
|
||||||
// finally draw bitmap to screen: uses image list functions to blend
|
// position of check mark bitmap
|
||||||
// the bitmap with the background colour (better for the selected items)
|
int x = rc.GetX() + CHECKMARK_EXTRA_SPACE;
|
||||||
HIMAGELIST himl = ImageList_Create(nBmpWidth, nBmpHeight,
|
int y = rc.GetY() + (rc.GetHeight() - size.GetHeight()) / 2;
|
||||||
ILC_COLOR32 | ILC_MASK, 1, 1);
|
|
||||||
ImageList_Add(himl, hBmpCheck, NULL);
|
|
||||||
|
|
||||||
UINT fStyle = stat & wxOwnerDrawn::wxODSelected ? ILD_SELECTED : ILD_NORMAL;
|
UINT uState = stat & wxOwnerDrawn::wxODSelected ? wxDSB_SELECTED : wxDSB_NORMAL;
|
||||||
ImageList_Draw(himl, 0, hdc, x, y, fStyle);
|
wxDrawStateBitmap(hdc, hBmpCheck, x, y, uState);
|
||||||
|
|
||||||
ImageList_Destroy(himl);
|
|
||||||
|
|
||||||
if (stat & wxODHasFocus)
|
|
||||||
wxRendererNative::Get().DrawFocusRect(m_pParent, dc, rc);
|
|
||||||
|
|
||||||
return true;
|
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
|
// implementation of wxCheckListBox class
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -319,63 +280,40 @@ bool wxCheckListBox::Create(wxWindow *parent, wxWindowID id,
|
|||||||
style | wxLB_OWNERDRAW, validator, name);
|
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/retrieve item
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
// create a check list box 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);
|
wxCheckListBoxItem *pItem = new wxCheckListBoxItem(this);
|
||||||
return pItem;
|
return pItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return item size
|
// return item size
|
||||||
// ----------------
|
// ----------------
|
||||||
bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
|
bool wxCheckListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
|
||||||
{
|
{
|
||||||
if ( wxListBox::MSWOnMeasure(item) ) {
|
if ( wxListBox::MSWOnMeasure(item) )
|
||||||
MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item;
|
{
|
||||||
|
MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item;
|
||||||
|
|
||||||
// add place for the check mark
|
wxSize size = wxRendererNative::Get().GetCheckBoxSize(this);
|
||||||
pStruct->itemWidth += wxOwnerDrawn::GetDefaultMarginWidth();
|
size.x += 2 * CHECKMARK_EXTRA_SPACE;
|
||||||
pStruct->itemHeight += 1;
|
size.y += 2 * CHECKMARK_EXTRA_SPACE;
|
||||||
|
|
||||||
// save item height
|
// add place for the check mark
|
||||||
m_nItemHeight = pStruct->itemHeight;
|
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
|
// check items
|
||||||
// -----------
|
// -----------
|
||||||
|
|
||||||
@@ -391,6 +329,15 @@ void wxCheckListBox::Check(unsigned int uiIndex, bool bCheck)
|
|||||||
wxCHECK_RET( IsValid(uiIndex), wxT("bad wxCheckListBox index") );
|
wxCHECK_RET( IsValid(uiIndex), wxT("bad wxCheckListBox index") );
|
||||||
|
|
||||||
GetItem(uiIndex)->Check(bCheck);
|
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
|
// process events
|
||||||
@@ -401,33 +348,33 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event)
|
|||||||
// what do we do?
|
// what do we do?
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
None,
|
NONE,
|
||||||
Toggle,
|
TOGGLE,
|
||||||
Set,
|
SET,
|
||||||
Clear
|
CLEAR
|
||||||
} oper;
|
} oper;
|
||||||
|
|
||||||
switch ( event.GetKeyCode() )
|
switch ( event.GetKeyCode() )
|
||||||
{
|
{
|
||||||
case WXK_SPACE:
|
case WXK_SPACE:
|
||||||
oper = Toggle;
|
oper = TOGGLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_NUMPAD_ADD:
|
case WXK_NUMPAD_ADD:
|
||||||
case '+':
|
case '+':
|
||||||
oper = Set;
|
oper = SET;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WXK_NUMPAD_SUBTRACT:
|
case WXK_NUMPAD_SUBTRACT:
|
||||||
case '-':
|
case '-':
|
||||||
oper = Clear;
|
oper = CLEAR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
oper = None;
|
oper = NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( oper != None )
|
if ( oper != NONE )
|
||||||
{
|
{
|
||||||
wxArrayInt selections;
|
wxArrayInt selections;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -447,22 +394,17 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event)
|
|||||||
|
|
||||||
for ( int i = 0; i < count; i++ )
|
for ( int i = 0; i < count; i++ )
|
||||||
{
|
{
|
||||||
wxCheckListBoxItem *item = GetItem(selections[i]);
|
int nItem = selections[i];
|
||||||
if ( !item )
|
|
||||||
{
|
|
||||||
wxFAIL_MSG( wxT("no wxCheckListBoxItem?") );
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( oper )
|
switch ( oper )
|
||||||
{
|
{
|
||||||
case Toggle:
|
case TOGGLE:
|
||||||
item->Toggle();
|
Toggle(nItem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Set:
|
case SET:
|
||||||
case Clear:
|
case CLEAR:
|
||||||
item->Check( oper == Set );
|
Check(nItem, oper == SET);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -471,7 +413,7 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event)
|
|||||||
|
|
||||||
// we should send an event as this has been done by the user and
|
// we should send an event as this has been done by the user and
|
||||||
// not by the program
|
// not by the program
|
||||||
item->SendEvent();
|
SendEvent(nItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // nothing to do
|
else // nothing to do
|
||||||
@@ -483,11 +425,21 @@ void wxCheckListBox::OnKeyDown(wxKeyEvent& event)
|
|||||||
void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
|
void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
// clicking on the item selects it, clicking on the checkmark toggles
|
// 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
|
// people expect to get "kill focus" event for the currently
|
||||||
// focused control before getting events from the other controls
|
// focused control before getting events from the other controls
|
||||||
@@ -498,24 +450,43 @@ void wxCheckListBox::OnLeftClick(wxMouseEvent& event)
|
|||||||
SetFocus();
|
SetFocus();
|
||||||
if ( FindFocus() == this )
|
if ( FindFocus() == this )
|
||||||
{
|
{
|
||||||
wxCheckListBoxItem *item = GetItem(nItem);
|
Toggle(nItem);
|
||||||
item->Toggle();
|
SendEvent(nItem);
|
||||||
item->SendEvent();
|
|
||||||
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// implement default behaviour: clicking on the item selects it
|
// implement default behavior on click outside of client zone
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSize wxCheckListBox::DoGetBestSize() const
|
wxSize wxCheckListBox::DoGetBestClientSize() const
|
||||||
{
|
{
|
||||||
wxSize best = wxListBox::DoGetBestSize();
|
wxSize best = wxListBox::DoGetBestClientSize();
|
||||||
best.x += wxOwnerDrawn::GetDefaultMarginWidth(); // add room for the checkbox
|
|
||||||
|
// 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);
|
CacheBestSize(best);
|
||||||
return best;
|
return best;
|
||||||
}
|
}
|
||||||
|
@@ -490,7 +490,7 @@ int wxListBox::DoInsertItems(const wxArrayStringsAdapter & items,
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxListBox::DoListHitTest(const wxPoint& point) const
|
int wxListBox::DoHitTestList(const wxPoint& point) const
|
||||||
{
|
{
|
||||||
LRESULT lRes = ::SendMessage(GetHwnd(), LB_ITEMFROMPOINT,
|
LRESULT lRes = ::SendMessage(GetHwnd(), LB_ITEMFROMPOINT,
|
||||||
0, MAKELPARAM(point.x, point.y));
|
0, MAKELPARAM(point.x, point.y));
|
||||||
@@ -683,12 +683,73 @@ bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
|
|||||||
|
|
||||||
#if wxUSE_OWNER_DRAWN
|
#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
|
// drawing
|
||||||
// -------
|
// -------
|
||||||
|
|
||||||
// space beneath/above each row in pixels
|
namespace
|
||||||
// "standard" checklistbox use 1 here, some might prefer 2. 0 is ugly.
|
{
|
||||||
#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
|
// space beneath/above each row in pixels
|
||||||
|
static const int LISTBOX_EXTRA_SPACE = 1;
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
// the height is the same for all items
|
// the height is the same for all items
|
||||||
// TODO should be changed for LBS_OWNERDRAWVARIABLE style listboxes
|
// TODO should be changed for LBS_OWNERDRAWVARIABLE style listboxes
|
||||||
@@ -712,7 +773,7 @@ bool wxListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
|
|||||||
wxDCTemp dc((WXHDC)hdc);
|
wxDCTemp dc((WXHDC)hdc);
|
||||||
dc.SetFont(GetFont());
|
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();
|
pStruct->itemWidth = dc.GetCharWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,50 +45,57 @@ bool wxOwnerDrawn::OnDrawItem(wxDC& dc, const wxRect& rc,
|
|||||||
if ( !IsOwnerDrawn() )
|
if ( !IsOwnerDrawn() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// set the font and colors
|
|
||||||
wxFont font;
|
|
||||||
GetFontToUse(font);
|
|
||||||
|
|
||||||
wxColour colText, colBack;
|
|
||||||
GetColourToUse(stat, colText, colBack);
|
|
||||||
|
|
||||||
wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
|
wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl();
|
||||||
HDC hdc = GetHdcOf(*impl);
|
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));
|
AutoHBRUSH hbr(wxColourToPalRGB(colBack));
|
||||||
SelectInHDC selBrush(hdc, hbr);
|
SelectInHDC selBrush(hdc, hbr);
|
||||||
|
|
||||||
RECT rectFill;
|
::FillRect(hdc, &rect, hbr);
|
||||||
wxCopyRectToRECT(rc, rectFill);
|
|
||||||
::FillRect(hdc, &rectFill, hbr);
|
|
||||||
|
|
||||||
// using native API because it recognizes '&'
|
// using native API because it recognizes '&'
|
||||||
|
|
||||||
wxString text = GetName();
|
wxString text = GetName();
|
||||||
|
|
||||||
SIZE sizeRect;
|
SIZE sizeRect;
|
||||||
::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect);
|
::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect);
|
||||||
|
|
||||||
int flags = DST_PREFIXTEXT;
|
int flags = DST_PREFIXTEXT;
|
||||||
if ( (stat & wxODDisabled) && !(stat & wxODSelected) )
|
if ( (stat & wxODDisabled) && !(stat & wxODSelected) )
|
||||||
flags |= DSS_DISABLED;
|
flags |= DSS_DISABLED;
|
||||||
|
|
||||||
if ( (stat & wxODHidePrefix) )
|
if ( (stat & wxODHidePrefix) )
|
||||||
flags |= DSS_HIDEPREFIX;
|
flags |= DSS_HIDEPREFIX;
|
||||||
|
|
||||||
int x = rc.x + GetMarginWidth();
|
int x = rc.x + GetMarginWidth();
|
||||||
int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2;
|
int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2;
|
||||||
int cx = rc.GetWidth() - GetMarginWidth();
|
int cx = rc.GetWidth() - GetMarginWidth();
|
||||||
int cy = sizeRect.cy;
|
int cy = sizeRect.cy;
|
||||||
|
|
||||||
::DrawState(hdc, NULL, NULL, (LPARAM)text.wx_str(),
|
::DrawState(hdc, NULL, NULL, (LPARAM)text.wx_str(),
|
||||||
text.length(), x, y, cx, cy, flags);
|
text.length(), x, y, cx, cy, flags);
|
||||||
|
|
||||||
|
} // reset to default the font, colors and brush
|
||||||
|
|
||||||
|
if (stat & wxODHasFocus)
|
||||||
|
::DrawFocusRect(hdc, &rect);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user