Events 如何处理NM_CUSTOMDRAW事件以检索列表项

Events 如何处理NM_CUSTOMDRAW事件以检索列表项,events,mfc,ondraw,win32gui,clistctrl,Events,Mfc,Ondraw,Win32gui,Clistctrl,我正在做一个win32/MFC项目。 我有一个自定义的CListCtrl控件,我必须不时地添加一些字符串。 我绝对需要对动态添加到CListCtrl的项目执行一些操作 基本上,我需要: 检测单个元素的添加 在调用InsertItem()之后立即检索_singleitems u) 将单个项目的值存储在映射中,我将使用该映射执行其他操作 我考虑过重写DrawItem()方法。但OnDraw事件似乎不适用于我的CListCtrl 事件从未生成。 重要提示:请注意,MyCustomCListCtrl的“

我正在做一个win32/MFC项目。 我有一个自定义的CListCtrl控件,我必须不时地添加一些字符串。 我绝对需要对动态添加到CListCtrl的项目执行一些操作

基本上,我需要:

  • 检测单个元素的添加
  • 在调用InsertItem()之后立即检索_singleitems u)
  • 将单个项目的值存储在映射中,我将使用该映射执行其他操作 我考虑过重写DrawItem()方法。但OnDraw事件似乎不适用于我的CListCtrl

    事件从未生成。

    重要提示:请注意,MyCustomCListCtrl的“绘制时固定”属性设置为True,但“查看”属性未设置为报表

    因此,我决定处理NW_CUSTOMDRAW事件,编写我的CUSTOMDRAW处理程序,如下所述:

    您可以查看另一个代码示例

    然后,我需要一种从CListCtrl检索单个ItemID的方法。
    更准确地说,我需要一种从NMHDR结构获取单个项ID的方法

    我该怎么做? 我只能获得我添加的最后一项的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;
    }
    
    感谢您的帮助

    附言。 请不要给我这样的提示:

  • 将“自己绘制固定”属性设置为True
  • 检查是否已插入行“onwmdrawItem()”
  • 将CListCtrl转换为报告 我什么都试过了…:-)

    谢谢大家


    首先,如果需要检测单个项目的添加,为什么不处理该消息?我是说,这就是那个信息的目的。相反,处理NM_CUSTOMDRAW是错误的方法,因为如果控件被隐藏,窗口最小化

    在OnCustomDraw()中,您总是获得相同的ID:这是因为列表控件总是绘制所有可见项,因此您获得第一个可见项的ID。如果在此处设置断点,则在下次运行时,控件将刷新,图形将从第一个可见项重新开始


    注意:由于您正在处理NM_CUSTOMDRAW,因此不会收到任何未插入控件可见部分的添加项通知!因此,正如我提到的,您应该处理LVN_INSERTITEM。

    首先,如果您需要检测单个项目的添加,为什么不处理消息?我是说,这就是那个信息的目的。相反,处理NM_CUSTOMDRAW是错误的方法,因为如果控件被隐藏,窗口最小化

    在OnCustomDraw()中,您总是获得相同的ID:这是因为列表控件总是绘制所有可见项,因此您获得第一个可见项的ID。如果在此处设置断点,则在下次运行时,控件将刷新,图形将从第一个可见项重新开始


    注意:由于您正在处理NM_CUSTOMDRAW,因此不会收到任何未插入控件可见部分的添加项通知!因此,正如我提到的,您应该处理LVN\U插入项。

    首先。。。谢谢你把宝贵的时间浪费在这个愚蠢的问题上。 我从未发现任何关于
    LVN\u 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;
        }
    
    你能证实吗? 据我所见,这似乎奏效了。:-) 再次感谢


    首先是。。。谢谢你把宝贵的时间浪费在这个愚蠢的问题上。 我从未发现任何关于
    LVN\u 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;
        }
    
    你能证实吗? 据我所见,这似乎奏效了。:-) 再次感谢