0

私は win32/MFC プロジェクトに取り組んでいます。ときどきいくつかの文字列を追加する必要があるカスタム CListCtrl コントロールがあります。CListCtrl に動的に追加されたアイテムに対して何らかの操作を実行する必要があります。

超基本的には、次のことを行う必要があります。

  1. 単一要素の追加を 検出します。
  2. _single items_ IMMEDIATELY AFTER (理想的には、InsertItem() 呼び出しの直後) を取得します。
  3. 単一アイテムの値をマップに保存します。これを使用して、他の操作を実行します。

メソッド DrawItem() をオーバーライドしてこれを行うことを考えました。しかし、OnDraw イベントは私の CListCtrl では利用できないようです

イベントは生成されません。

重要: MyCustomCListCtrl には " On Draw Fixed " プロパティがTrueに設定されていますが、" View " プロパティはレポートとして設定されていないことに注意してください。

したがって、ここここで説明されているように、NW_CUSTOMDRAW イベントを処理し、CustomDraw ハンドラーを作成することにしました。

ここでは、別のコード例を表示できます。

次に、CListCtrl から単一の itemID を取得する方法が必要です。
より正確には、NMHDR struct から単一のアイテム IDを取得する方法が必要です。

これどうやってするの?追加したLASTアイテムの ID しか取得できません。私が見つけられない単純な間違いだと確信しています。

以下のサンプルコード:

CList Ctrl を含むダイアログのソース:

/* file MyDlg.cpp */

#include "stdafx.h"
#include "MyDlg.h"

// MyDlg dialog

IMPLEMENT_DYNAMIC(MyDlg, CDialog)

MyDlg::MyDlg(CWnd* pParent)
    : CDialog(MyDlg::IDD, pParent)
{
}

MyDlg::~MyDlg()
{
}

void MyDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_LIST1, listView); /* listView is a MyCustomCListCtrl object */
}

BEGIN_MESSAGE_MAP(MyDlg, CDialog)
    ON_BN_CLICKED(IDC_BUTTON1, &MyDlg::OnBnClickedButton1) 
END_MESSAGE_MAP()

BOOL MyDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    return TRUE;
}

/* OnBnClickedButton1 handler add new strings to MyCustomCListCtrl object */

void MyDlg::OnBnClickedButton1()
{
    listView.InsertItem(0, "Hello,");
    listView.InsertItem(1, "World!");
}

私のカスタム CList Ctrl ソース:

/* file MyCustomCListCtrl.cpp */

#include "stdafx.h"
#include "MyCustomCListCtrl.h"

MyCustomCListCtrl::MyCustomCListCtrl()
{
}

MyCustomCListCtrl::~MyCustomCListCtrl()
{
}

BEGIN_MESSAGE_MAP(MyCustomCListCtrl, CListCtrl)
    //{{AFX_MSG_MAP(MyCustomCListCtrl)
    //}}AFX_MSG_MAP
    // ON_WM_DRAWITEM()                             /* WM_DRAWITEM NON-AVAILABLE */
    ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()

// 'Owner Draw Fixed' property is already TRUE
/*  void CTranslatedCListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    bool inside = true; /* Member function removed: I never enter here... */
}  */

void MyCustomCListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
    /* Here, I must retrieve single strings added to my MyCustomCListCtrl object */

    LPNMLISTVIEW plvInfo = (LPNMLISTVIEW)pNMHDR;
    LVITEM lvItem;

    lvItem.iItem = plvInfo->iItem;          /* Here I always get _the same_ ID: ID of last element...*/
    lvItem.iSubItem = plvInfo->iSubItem;    // subItem not used, for now...

    int MyID = 0;

    this->GetItem(&lvItem); // There mai be something error here?
    MyID = lvItem.iItem;

    CString str = this->GetItemText(MyID, 0); /* ...due to previous error, here I will always get the last string I have added("World!") */

    // Immediately after obtaining ALL IDS, I can Do My Work

    *pResult = 0;
}

どんな助けでも大歓迎です!

PS 次のようなヒントは教えないでください。

  1. 「自分のドロー固定」プロパティを True に設定します。
  2. 「ON_WMDRAWITEM()」という行が挿入されていることを確認してください
  3. CListCtrl をレポートとして変換します。

私はすでにすべてを試しました... :-)

ありがとうございます!

それ

4

2 に答える 2

4

まず、単一のアイテムの追加を検出する必要がある場合は、LVN_INSERTITEMメッセージを処理しないのはなぜですか? つまり、それがそのメッセージの目的です。代わりに NM_CUSTOMDRAW を処理するのは間違った方法です。コントロールが非表示の場合、ウィンドウが最小化されている場合、必ずしもその通知を受け取るとは限らないためです...

OnCustomDraw() では、常に同じ ID を取得します。これは、リスト コントロールが常にすべての表示項目を描画するため、最初に表示される項目の ID を取得するためです。そこにブレークポイントを設定すると、次の実行時にコントロールが更新され、最初に表示されているアイテムから描画が再開されます。

注: NM_CUSTOMDRAW を処理しているため、コントロールの表示部分に挿入されていない追加アイテムの通知はありません。前述したように、代わりに LVN_INSERITEM を処理する必要があります。

于 2012-05-20T08:57:53.113 に答える
0

まず第一に... このばかげた質問で貴重な時間を無駄にしていただきありがとうございます。イベントについては何も見つかりませんでしLVN_INSERTた。私は科学的なソフトウェアを書いています (ほとんどが Linux プラットフォームで)。私は長年の Win32 開発者ではないので、Win32 API について詳しく知りません。MyCustomCListCtrlあなたが提案したように、クラスのソースファイルを変更しました。以下のコードは、私が望むものを達成するための最良の(そしてより速い)方法のようです:

    /* file MyCustomCListCtrl.cpp */

    #include "stdafx.h"
    #include "MyCustomCListCtrl.h"

    MyCustomCListCtrl::MyCustomCListCtrl()
    {
    }

    MyCustomCListCtrl::~MyCustomCListCtrl()
    {
    }

    BEGIN_MESSAGE_MAP(MyCustomCListCtrl, CListCtrl)
        //{{AFX_MSG_MAP(MyCustomCListCtrl)
        //}}AFX_MSG_MAP
        ON_NOTIFY_REFLECT(LVN_INSERTITEM, OnLvnInsertItem)
    END_MESSAGE_MAP()

    ...

    afx_msg void CTranslatedListCtrl::OnLvnInsertItem(NMHDR* pNMHDR, LRESULT* pResult)
    {
        LPNMLISTVIEW plvInfo = (LPNMLISTVIEW)pNMHDR;
        CString str = this->GetItemText(plvInfo->iItem, 0);

        // Add Some Logic

        *pResult = 0;
    }

確認できますか?私が見る限り、それは機能しているようです。:-) 再度、感謝します!

それ

于 2012-05-21T09:21:02.813 に答える