This is the mail archive of the
cygwin-apps
mailing list for the Cygwin project.
[PATCH setup 05/13] Custom draw checkboxes in ListView control
- From: Jon Turney <jon dot turney at dronecode dot org dot uk>
- To: cygwin-apps at cygwin dot com
- Cc: Jon Turney <jon dot turney at dronecode dot org dot uk>
- Date: Sun, 5 Aug 2018 23:08:43 +0100
- Subject: [PATCH setup 05/13] Custom draw checkboxes in ListView control
- References: <20180805220851.270212-1-jon.turney@dronecode.org.uk>
Future work: What does this look like when a theme is in used? Does the row
size need to be slightly adjusted to ensure it accomodates checkbox height?
v2:
erase to background colour before drawing checkbox
---
ListView.cc | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ListView.h | 7 ++++++
choose.cc | 16 +++++++-------
3 files changed, 78 insertions(+), 8 deletions(-)
diff --git a/ListView.cc b/ListView.cc
index 97ee44c..e3f1e44 100644
--- a/ListView.cc
+++ b/ListView.cc
@@ -289,6 +289,69 @@ ListView::OnNotify (NMHDR *pNmHdr, LRESULT *pResult)
return true;
}
break;
+
+ case NM_CUSTOMDRAW:
+ {
+ NMLVCUSTOMDRAW *pNmLvCustomDraw = (NMLVCUSTOMDRAW *)pNmHdr;
+
+ switch(pNmLvCustomDraw->nmcd.dwDrawStage)
+ {
+ case CDDS_PREPAINT:
+ *pResult = CDRF_NOTIFYITEMDRAW;
+ return true;
+ case CDDS_ITEMPREPAINT:
+ *pResult = CDRF_NOTIFYSUBITEMDRAW;
+ return true;
+ case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
+ {
+ LRESULT result = CDRF_DODEFAULT;
+ int iCol = pNmLvCustomDraw->iSubItem;
+ int iRow = pNmLvCustomDraw->nmcd.dwItemSpec;
+
+ switch (headers[iCol].type)
+ {
+ default:
+ case ListView::ControlType::text:
+ result = CDRF_DODEFAULT;
+ break;
+
+ case ListView::ControlType::checkbox:
+ {
+ // get the subitem text
+ char buf[3];
+ ListView_GetItemText(hWndListView, iRow, iCol, buf, _countof(buf));
+
+ // map the subitem text to a checkbox state
+ UINT state = DFCS_BUTTONCHECK | DFCS_FLAT;
+ if (buf[0] == '\0') // empty
+ {
+ result = CDRF_DODEFAULT;
+ break;
+ }
+ else if (buf[0] == 'y') // yes
+ state |= DFCS_CHECKED;
+ else if ((buf[0] == 'n') && (buf[1] == 'o')) // no
+ state |= 0;
+ else // n/a
+ state |= DFCS_INACTIVE;
+
+ // erase and draw a checkbox
+ RECT r;
+ ListView_GetSubItemRect(hWndListView, iRow, iCol, LVIR_BOUNDS, &r);
+ HBRUSH hBrush = CreateSolidBrush(ListView_GetBkColor(hWndListView));
+ FillRect(pNmLvCustomDraw->nmcd.hdc, &r, hBrush);
+ DeleteObject(hBrush);
+ DrawFrameControl(pNmLvCustomDraw->nmcd.hdc, &r, DFC_BUTTON, state);
+
+ result = CDRF_SKIPDEFAULT;
+ }
+ break;
+ }
+ *pResult = result;
+ return true;
+ }
+ }
+ }
}
// We don't care.
diff --git a/ListView.h b/ListView.h
index d339011..3aabc3f 100644
--- a/ListView.h
+++ b/ListView.h
@@ -36,11 +36,18 @@ typedef std::vector<ListViewLine *> ListViewContents;
class ListView
{
public:
+ enum class ControlType
+ {
+ text,
+ checkbox,
+ };
+
class Header
{
public:
const char *text;
int fmt;
+ ControlType type;
int width;
int hdr_width;
};
diff --git a/choose.cc b/choose.cc
index c86294a..c65a107 100644
--- a/choose.cc
+++ b/choose.cc
@@ -132,14 +132,14 @@ ChooserPage::~ChooserPage ()
}
static ListView::Header pkg_headers[] = {
- {"Package", LVCFMT_LEFT},
- {"Current", LVCFMT_LEFT},
- {"New", LVCFMT_LEFT},
- {"Bin?", LVCFMT_LEFT},
- {"Src?", LVCFMT_LEFT},
- {"Categories", LVCFMT_LEFT},
- {"Size", LVCFMT_RIGHT},
- {"Description", LVCFMT_LEFT},
+ {"Package", LVCFMT_LEFT, ListView::ControlType::text},
+ {"Current", LVCFMT_LEFT, ListView::ControlType::text},
+ {"New", LVCFMT_LEFT, ListView::ControlType::text},
+ {"Bin?", LVCFMT_LEFT, ListView::ControlType::checkbox},
+ {"Src?", LVCFMT_LEFT, ListView::ControlType::checkbox},
+ {"Categories", LVCFMT_LEFT, ListView::ControlType::text},
+ {"Size", LVCFMT_RIGHT, ListView::ControlType::text},
+ {"Description", LVCFMT_LEFT, ListView::ControlType::text},
{0}
};
--
2.17.0