子类化TListView:CNNotify中编辑取消时pszText值判断异常问题
解决TListView子类化中编辑取消时pszText判断无效的问题
问题背景
子类化TListView时,在CNNotify()事件中处理LVN_ENDLABELEDIT通知,预期编辑取消时plvdi->item.pszText应为NULL,但多次尝试判断均无效,其余功能正常。
代码问题分析
原代码存在以下关键错误:
- 未过滤通知类型:所有
WM_NOTIFY通知都被处理,错误访问非LVN_ENDLABELEDIT通知的结构数据。 - 父类调用顺序错误:先调用
TListView::Dispatch(&Message),导致父类提前修改了plvdi中的数据,无法正确获取取消编辑时的pszText值。 - Result值设置错误:将
Message.Result与LVN_ENDLABELEDIT(通知码)进行位或操作,不符合该通知的返回值规则。 - 有效性检查缺失:未验证列表项的有效性,可能导致空指针访问。
修复后的代码
.cpp文件中修改CNNotify函数
void __fastcall TCustomListView1::CNNotify(Winapi::Messages::TWMNotify &Message) { // 仅处理LVN_ENDLABELEDIT通知 if (Message.NMHdr->code == LVN_ENDLABELEDIT) { NMLVDISPINFO* plvdi = reinterpret_cast<NMLVDISPINFO*>(Message.NMHdr); // 编辑取消时pszText为NULL,同时确保操作的是有效列表项 if (plvdi->item.pszText == NULL && plvdi->item.iItem != -1) { TListItem* targetItem = Items->Item[plvdi->item.iItem]; if (FOnEditCancel && targetItem != nullptr) { cancel = true; FOnEditCancel(this, targetItem, cancel); cancel = false; } } } // 最后调用父类处理其他通知逻辑 TListView::Dispatch(&Message); }
修复说明
- 过滤通知类型:仅在收到
LVN_ENDLABELEDIT时处理编辑结束逻辑,避免无效结构访问。 - 调整父类调用顺序:先处理自定义逻辑,再调用父类
Dispatch,确保能获取原始的通知数据。 - 增加有效性验证:通过
plvdi->item.iItem != -1确认列表项有效,避免空指针错误。 - 移除错误的Result设置:原代码中
Message.Result |= LVN_ENDLABELEDIT是错误用法,若需阻止控件默认处理编辑结果,可设置Message.Result = TRUE(非0值),否则由父类处理即可。
内容的提问来源于stack exchange,提问作者user16458899
相关产品推荐
相关产品推荐

