Windows 销毁窗口资源的正确方法
这是我基于win32 api的代码摘录:Windows 销毁窗口资源的正确方法,windows,winapi,resources,Windows,Winapi,Resources,这是我基于win32 api的代码摘录: LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, uMsg, wParam, lParam); } void __fastcall TMyThread::Execute(void) { WNDCLASSEX wc = {0}; wc.cbSize
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void __fastcall TMyThread::Execute(void)
{
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = class_name.c_str();
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
return;
}
hwnd = CreateWindowEx(0, class_name.c_str(), NULL, 0, 0, 0, 100, 100, HWND_MESSAGE, NULL, wc.hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, L"Window Creation Failed!", L"Error", MB_ICONEXCLAMATION | MB_OK);
return;
}
MSG msg;
BOOL ret;
while ((ret = GetMessage(&msg, 0, 0, 0)) != 0)
{
if (ret != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
我的问题是:
请记住,TMyThread不是应用程序的主线程。因此,它可以在一次应用程序运行中多次创建和销毁。请不要注意非常简化的窗口创建。此特定窗口不应在屏幕上可见。它的创建完全是为了从另一个应用程序接收消息。调用CreateWindowEx函数时,使用hWndParent参数的HWND_消息值来突出显示这一点。在Win32中使用资源时必须非常小心。确保您已经仔细阅读了文档,以确定Windows本身将为您卸载什么以及您必须自己卸载什么 例如,
HWND
s将被销毁,因为父级HWND
s将被销毁
最好的方法是尝试卸载您个人创建的所有内容。如果在卸载时从特定函数返回错误,则可能不应该卸载它,因为它已由Windows或某些相关资源卸载
重要的是不要在不必要的时候卸载物品,因为这可能会导致崩溃
因此,例如,使用直接来自资源的窗口创建的图标可能不应卸载。但是,您创建的绘制到其他窗口的HBITMAP
应该被卸载
您的部分问题可以通过使用断点的快速测试来确定。我一点也不知道。在Win32中使用资源时必须非常小心。确保您已经仔细阅读了文档,以确定Windows本身将为您卸载什么以及您必须自己卸载什么 例如,
HWND
s将被销毁,因为父级HWND
s将被销毁
最好的方法是尝试卸载您个人创建的所有内容。如果在卸载时从特定函数返回错误,则可能不应该卸载它,因为它已由Windows或某些相关资源卸载
重要的是不要在不必要的时候卸载物品,因为这可能会导致崩溃
因此,例如,使用直接来自资源的窗口创建的图标可能不应卸载。但是,您创建的绘制到其他窗口的HBITMAP
应该被卸载
您的部分问题可以通过使用断点的快速测试来确定。我不知道该怎么办。通过在上面的示例中一次又一次地创建、运行和销毁线程,我发现在退出消息循环后需要调用两个方法。第一个是DestroyWindow,第二个是UnregisterClass。在常规应用程序中,在用户确认确实要关闭应用程序后,WM_CLOSE handler中的Destroy Window函数将被销毁。DestroyWindow函数然后向window发送WM_DESTROY和WM_NCDESTROY消息。为了响应WM_销毁消息,应用程序应调用PostQuitMessage(0)函数,该函数将立即退出消息循环。因此,这部分代码在所有场景中都不是必需的。我需要显式调用DestroyWindow函数,因为我通过简单地发送WM_QUIT消息来退出消息循环。当不这样做时,有时我在尝试注销窗口类时收到错误1412(错误\u类\u有\u窗口)
if (hwnd != NULL)
{
ret = DestroyWindow(hwnd);
if (ret == 0)
{
str.printf(L"Window destroying failed (GetLastError = %d)!", GetLastError());
ShowError(str);
}
hwnd = NULL;
}
ret = UnregisterClass(class_name.c_str(), wc.hInstance);
if (ret == 0)
{
str.printf(L"Window class unregistration failed (GetLastError = %d)!", GetLastError());
ShowError(str);
}
通过在上述示例中一次又一次地创建、运行和销毁线程,我发现在退出消息循环后需要调用两个方法。第一个是DestroyWindow,第二个是UnregisterClass。在常规应用程序中,在用户确认确实要关闭应用程序后,WM_CLOSE handler中的Destroy Window函数将被销毁。DestroyWindow函数然后向window发送WM_DESTROY和WM_NCDESTROY消息。为了响应WM_销毁消息,应用程序应调用PostQuitMessage(0)函数,该函数将立即退出消息循环。因此,这部分代码在所有场景中都不是必需的。我需要显式调用DestroyWindow函数,因为我通过简单地发送WM_QUIT消息来退出消息循环。当不这样做时,有时我在尝试注销窗口类时收到错误1412(错误\u类\u有\u窗口)
if (hwnd != NULL)
{
ret = DestroyWindow(hwnd);
if (ret == 0)
{
str.printf(L"Window destroying failed (GetLastError = %d)!", GetLastError());
ShowError(str);
}
hwnd = NULL;
}
ret = UnregisterClass(class_name.c_str(), wc.hInstance);
if (ret == 0)
{
str.printf(L"Window class unregistration failed (GetLastError = %d)!", GetLastError());
ShowError(str);
}
由于您创建窗口的唯一目的似乎是在线程上接收消息,因此我应该指出,这并不是严格必要的。任何线程都可以使用(限制适用)接收发送到它的消息。@IInspectable:我考虑过这个选项。这很复杂,因为其他应用程序在向线程发布消息时必须知道线程ID。另一方面,在向窗口发布消息时,我可以通过FindWindow函数找到它,该函数方便且非常可靠(我使用窗口类名作为唯一ID)。由于您创建窗口的唯一目的似乎是在线程上接收消息,我应该指出,这并不是严格必要的。任何线程都可以使用(限制适用)接收发送到它的消息。@IInspectable:我考虑过这个选项。这很复杂,因为其他应用程序在向线程发布消息时必须知道线程ID。另一方面,在向窗口发布消息时,我可以通过FindWindow函数找到消息,该函数方便且非常可靠(我使用窗口类名作为唯一ID)。