我正在开发一个win32 / MFC项目。 我有一个自定义的CListCtrl控件,我必须不时添加一些字符串。 我绝对需要对动态添加到我的CListCtrl的项目执行一些操作。
超基本上,我需要:
我想过这样做会覆盖DrawItem()方法。但OnDraw事件似乎不适用于我的CListCtrl。
永远不会生成事件。
重要提示:请注意,MyCustomCListCtrl将“ On Draw Fixed ”属性设置为 True ,但“查看“属性 NOT 设置为报告。
所以,我决定处理NW_CUSTOMDRAW事件,编写我的CustomDraw处理程序,如here和here所述:
Here您可以查看其他代码示例。
然后,我需要一种从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;
}
感谢任何帮助!
P.S。 请不要给我这样的提示:
我已经尝试了一切......: - )
感谢所有人!
IT
答案 0 :(得分:4)
首先,如果您需要检测单个项目的添加,为什么不处理LVN_INSERTITEM消息?我的意思是,这就是消息的用途。处理NM_CUSTOMDRAW是错误的方法,因为如果控件被隐藏,窗口最小化,你不一定会收到通知......
在OnCustomDraw()中,您始终会获得相同的ID:因为列表控件始终会绘制所有可见项,因此您将获得第一个可见项的ID。如果在那里设置断点,那么在下一次运行时,控件将刷新,并且图形将从第一个可见项开始。
注意:由于您正在处理NM_CUSTOMDRAW,因此您不会收到任何未插入控件可见部分的已添加项目的通知!正如我所提到的,你应该改为处理LVN_INSERTITEM。
答案 1 :(得分: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;
}
你能证实吗?
从我所看到的,它似乎工作。 :-)
再次感谢!
IT