2

ラジオ ボタンのコレクションのように、CListCtrl に常に選択された項目が必要です。

私はスタイルを使用しました:LVS_SHOWSELALWAYS|LVS_SINGLESEL

このようなスタイルを探していますが、これを見つけることができませんでした。

4

4 に答える 4

2

WM_LBUTTONDOWN を処理します。CListCtrl 派生クラスで、追加します。

MyListCtrl.cpp:

BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
    UINT uHitFlags;
    int nItem = HitTest(point, &uHitFlags);

    if (uHitFlags & LVHT_NOWHERE)
    {
        // eat the message by just returning
        return;
    }

    CListCtrl::OnLButtonDown(nFlags, point);
}

これにより、マウスクリックがコントロールに移動してメッセージを食べるのを防ぎます。プログラムで選択を削除することはできますが、ユーザーが項目の下の空白の領域をクリックして選択を削除することはできません。

于 2013-09-13T20:15:50.790 に答える
1

これに対する組み込みのサポートはないと思います。

最初から選択できる部分は簡単です。リストにデータを入力した後で項目を選択するだけです。

// Populate the list
// ...

c_MyList.SetItemState(nItem, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);

もう 1 つの部分は、ユーザーがすべてのアイテムの外側をクリックしたときにすべてのアイテムの選択が解除されないようにすることです。リストが項目の選択を解除しているかどうかは簡単に検出できますが、項目が選択状態を失っている理由はわかりません。つまり、別のアイテムを選択するために選択を解除するのか、すべてのアイテムを選択しないままにするのかはわかりません。その理由は、コントロールが最初に「アイテム X の選択が解除されました」という通知を送信し、次に「アイテム Y が選択されました」という通知を送信するためです。項目が選択されていない場合、最初の項目は取得されますが、2 番目の項目は取得されません。

私が考えたちょっとしたアイデアは、NM_CLICK 通知をキャッチして、コントロールがアイテムの選択を解除しないようにすることです。問題は、すべての選択/選択解除通知の後にNM_CLICK が送信されることです。

だから、これは私が思いついた小さなハックです: 項目が選択された状態を失ったとき、その項目インデックスを保存します。次に、NM_CLICK 通知で、アクティブ化されたアイテムが -1 の場合、最後に選択されていないアイテムを再度選択します。

void CMyDialog::OnLvnItemchangedListaEjesPane(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

    if (pNMLV->uChanged & LVIF_STATE)
    {
        UINT oldSelectionState = (pNMLV->uOldState & LVIS_SELECTED);
        UINT newSelectionState = (pNMLV->uNewState & LVIS_SELECTED);

        if ( oldSelectionState == LVIS_SELECTED && newSelectionState == 0 )
        {   // Deselect item
            m_LastDeselectedItem = pNMLV->iItem;
        }
        // ...
    }

    *pResult = 0;
}

void CMyDialog::OnNMClickListaEjesPane(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

    if (pNMItemActivate->iItem == -1)
    {
        c_ListaEjes.SetItemState(m_LastDeselectedItem, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
    }
    *pResult = 0;
}

実際にはアイテムの選択を解除してから再度選択するため、ニーズに完全には合わない場合があります。

独自の CListCtrl サブクラスを作成してクリックをインターセプトし、null 選択を強制するかどうかを確認して防止するなど、おそらくより良い解決策がありますが、余分な作業を行う価値があるかどうかを判断する必要があります。

于 2012-10-26T08:26:13.127 に答える
0

これは、clistctrl を設計するときにダイアログ エディターで簡単に実行できます。プロパティの [常に選択を表示] オプションと [単一選択] オプションを true に設定します。コードでこれを行いたい場合は、正しい方法がありますが、場所が間違っている可能性があります。OnInitDialog をオーバーライドし、最初に CDialog::OnInitDialog を呼び出してから、新しいスタイルを設定します (ModifyStyle を使用)。問題は、基本クラスがスタイルの変更をオーバーライドしていることです。それ以外にも、MFC はその直感性で知られていないことがいくつかあります。

于 2012-10-25T15:47:53.437 に答える