C++ Win32 ListView-LVM_INSERTITEM之后的句柄无效

C++ Win32 ListView-LVM_INSERTITEM之后的句柄无效,c++,windows,listview,winapi,sendmessage,C++,Windows,Listview,Winapi,Sendmessage,调用后,我遇到了一个窗口句柄(windowclass=WC\u LISTVIEW)问题 SendMessage(hListView_, LVM_INSERTITEM , 0, (LPARAM)&lvItem); 在哪里 是列表视图窗口的句柄,并且 lvItem 是一个LVITEM结构。下面的代码 std::cout << "Last error: " << GetLastError() << std::endl; SendMessage(hList

调用后,我遇到了一个窗口句柄(windowclass=WC\u LISTVIEW)问题

SendMessage(hListView_, LVM_INSERTITEM , 0, (LPARAM)&lvItem);
在哪里

是列表视图窗口的句柄,并且

lvItem
是一个LVITEM结构。下面的代码

std::cout << "Last error: " << GetLastError() << std::endl;
SendMessage(hListView_, LVM_INSERTITEM , 0, (LPARAM)&lvItem);
std::cout << "Last error: " << GetLastError() << std::endl;
根据代码6,表示错误处理无效

我创建LVITEM结构如下:

// define a char-buffer
char szBuffer[256];
szBuffer[0] = '\0';

// create new list view item
LVITEM lvItem;
lvItem.cchTextMax = 256;
lvItem.mask = LVIF_TEXT;
lvItem.iItem = 0;
lvItem.stateMask = 0;
lvItem.state = 0;
lvItem.iSubItem = 0;
snprintf(szBuffer, 256, "%s", myString.c_str());
lvItem.pszText = szBuffer;
此代码是从创建窗口(列表视图)的同一线程调用的。 还请注意,我有

lvItem.iSubItem = 0;
这是需要根据。在此调用之前,列表视图为空。此外,我实际上可以看到列表视图中插入的值(即,我可以在GUI的列表视图中看到该项)。 然而,当我尝试在此之后使用窗口句柄时,应用程序崩溃(没有例外,只是崩溃)

非常感谢任何关于可能导致这种情况的提示


谢谢。

您没有理由打电话给
GetLastError
LVM_INSERTITEM
的文档没有说明您应该这样做。它只说明
SendMessage
在成功时返回新项的索引,在失败时返回-1。因此,通过检查
SendMessage
返回的值来检查错误

另一个问题是没有初始化
LVITEM
的所有字段。那总是一个错误。您可以使用如下初始化声明:

LVITEM lvItem = { 0 };
LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT;
lvItem.cchTextMax = myString.length() + 1;
lvItem.pszText = myString.c_str();
int indexOfNewItem = SendMessage(hListView_, LVM_INSERTITEM, 0, (LPARAM)&lvItem);
if (indexOfNewItem == -1)
    // deal with failure
没有必要为文本设置单独的缓冲区。你可以这样做:

LVITEM lvItem = { 0 };
LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT;
lvItem.cchTextMax = myString.length() + 1;
lvItem.pszText = myString.c_str();
int indexOfNewItem = SendMessage(hListView_, LVM_INSERTITEM, 0, (LPARAM)&lvItem);
if (indexOfNewItem == -1)
    // deal with failure

事实上,你的错误很可能在别处。我看不出导致应用程序崩溃的
SendMessage
调用有什么特殊原因。至少现在您知道如何在发送
LVM\u INSERTITEM
时检查错误。如果这不会导致错误,那么证据将是崩溃是由其他代码引起的,并且您错误地识别了此代码,因为您错误地调用了
GetLastError
,而它的值没有意义。

感谢David Heffernan的帮助。我终于找到了问题所在,正如您所建议的,它位于代码中的另一个位置

我错过了下面一行(在我上面发布的代码之前调用的另一个函数中)

在哪里

当做下面的呼叫时

SendMessage(hListView_, LVM_GETITEMTEXT, (WPARAM) i, (LPARAM) &lvItem);
非常感谢你的帮助

编辑:如果我做了

lvItem.pszText = myString.c_str();

而不是字符缓冲区,这可能不会发生,所以感谢您的提示

您好,我尝试了您提出的更改,不幸的是,这没有帮助。我得到的indexOfNewItem等于0,即SendMessage调用不指示任何错误。也许我还应该提一下:这段代码是从父窗口的窗口过程调用到列表视图窗口的。那么你的问题就在别处了。然而,说我的答案没有帮助是错误的。现在,您将了解如何正确检查错误,以及如何初始化结构的所有成员。我并不是说您的回答没有帮助。从父窗口的窗口过程执行此代码时不应该有任何问题,对吗?没有。如果调用
SendMessage
返回
0
,则表示该项已成功插入。你现在需要找出真正的问题。好的,谢谢。可能是以下原因造成的吗?我有一个创建字符串向量的背景线程。然后将该向量(std::move)移动到全局变量(类变量,但在本例中等效于全局变量)中。然后,该后台线程通过PostMessage将用户定义的消息(WM_APP+2)发送到列表视图的父窗口。父窗口的wnd proc中的此消息处理程序随后调用更新listview的代码。您的错误检查代码已中断。只有当您调用的函数表示失败并且MSDN文档说明可以使用GetLastError()查找原因时,才可以调用GetLastError()。这是SendMessage()的问题,它没有。LVM_INSERTITEM消息没有做出任何承诺。你只能得到-1,只是一个“它没有工作”的指示。好的,谢谢。看来问题的根源可能在别处。应用程序崩溃(错误代码6)仅在调用SendMessage时出现,因此可能是其他原因造成的。@HansPassant:
SendMessage()
使用
GetLastError()
:“当UIPI阻止消息时,使用GetLastError检索的最后一个错误设置为5(拒绝访问)。”,您可以执行类似于
SetLastError(0)的操作;如果(SeNeMeTebug(HistListVIEWI,LVMIActudiTimes,0,(LPARAM)和LVITEM)=0){Err= GETLASTRORNORE();IF(Err!=0)…} /代码> @ HSPSPANTANT:否则,如果您想要更精确的错误检查,请考虑使用。它返回一个
BOOL
,指示
SendMessageCallback()
本身是成功还是失败,如果为FALSE,则使用
GetLastError()
报告错误代码。如果为TRUE,消息结果将传递给您提供的回调函数。
SendMessage(hListView_, LVM_GETITEMTEXT, (WPARAM) i, (LPARAM) &lvItem);
lvItem.pszText = myString.c_str();