CListCtrl
実行時に、MFC を使用して単一列のカスタム(またはCMFCListCtrl
、CheckListBox
将来的に複数の列を追加できるようにしたい)を作成しようとしています。スタイルを使用LVS_EX_CHECKBOXES
すると、すべてのアイテムにチェックボックスが強制されます。目的のコントロールは次のようになります (item1 と item3 にはチェックボックスがありますが、item2 にはありません)。
ユーザーの観点から、目的のリスト コントロールは次のように作成する必要があります。
int main() {
MyCListCtrl list_control;
list_control.AddItem("item1", true) // true indicates checkbox presence
list_control.AddItem("item2", false) // false - item without checkbox
list_control.AddItem("item3", true) // true indicates checkbox presence
}
これまでのところ、このようなコントロールを作成できましたが、追加すると、基本クラスのメソッドLVS_OWNERDRAWFIXED
を呼び出すときに失敗したアサーションがトリガーされます。CListCtrl::DrawItem
// MyCListCtrl.h
class MyCListCtrl : public CListCtrl {
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) override {
// if the item should be without a checkbox, here I want to move it a few pixels
// to the left so that the checkbox is hidden
...
CListCtrl::DrawItem(lpDrawItemStruct); // call base's DrawItem - without this
// there's no exception but the listbox appears empty
}
};
BOOL MyCDialogEx::OnInitDialog() {
CDialogEx::OnInitDialog();
...
// list being defined somewhere in the header file
list->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_NOCOLUMNHEADER |
LVS_OWNERDRAWFIXED, // for DrawItem invocation
rect, this, SOME_ID);
list->SetExtendedStyle(list->GetExtendedStyle() | LVS_EX_CHECKBOXES);
// add 1 mandatory column because of LVS_REPORT style
LVCOLUMN lvColumn;
lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvColumn.fmt = LVCFMT_LEFT;
lvColumn.cx = rect.Width() - 20; // also, how to make this column fit the width exactly?
lvColumn.pszText = nullptr;
list->InsertColumn(0, &lvColumn);
// for now only add 1 testing item and make his checkbox disappear by moving the
// whole item to the left in DrawItem method (called by the system), so that the text
// is aligned to the left list border
list->InsertItem(0, "item1");
...
}
これは私の(機能していない)ソリューションがどのように見えるかです。これを解決する方法を知っている場合は、もっと簡単な方法でも教えてください。ありがとう。
編集
@Landstalker の助けを借りて、カスタム描画でチェックボックスを消去できるようになりましたが、テキストを左に移動する必要があります (上の図のように、存在しないチェックボックスの代わりになります) )。現在のソリューションの結果は次のとおりです。
これは、次のように NM_CUSTOMDRAW メッセージを処理することによって実現されます。
void MyCListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = CDRF_DODEFAULT; // default windows painting
LPNMLVCUSTOMDRAW lpn = (LPNMLVCUSTOMDRAW)pNMHDR;
if (CDDS_PREPAINT == lpn->nmcd.dwDrawStage)
{
*pResult = CDRF_NOTIFYITEMDRAW; // notify on every item
}
else if (CDDS_ITEMPREPAINT == lpn->nmcd.dwDrawStage)
{
int row = lpn->nmcd.dwItemSpec;
if (row == 1) {
lpn->nmcd.rc.left -= 16; // not working
lpn->rcText.left -= 16; // not working
SetItemState(row, INDEXTOSTATEIMAGEMASK(0),
LVIS_STATEIMAGEMASK); // erase checkbox
}
}
}