0

CListCtrl実行時に、MFC を使用して単一列のカスタム(またはCMFCListCtrlCheckListBox将来的に複数の列を追加できるようにしたい)を作成しようとしています。スタイルを使用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
            }
        }
    }
4

1 に答える 1