【发布时间】:2020-10-17 15:17:48
【问题描述】:
我目前使用的是 Windows 10、MSVC v142(带有 VS2019)和 wxWidgets 3.1.3。我有一个旧的 Windows C++ 应用程序,它使用 WinAPI 作为其 GUI 功能,即 Windows 消息循环,使用“CreateWindow”,并且必须“手动”创建所有窗口过程和事件处理。
我想通过逐步使用 wxWidgets 替换 UI 来改进这个应用程序,这样我就不必从头开始。我会在 wxWidgets 中实现新的、独立的 UI 功能(例如特定对话框),然后返回并用 wxWidgets 实现替换所有旧的 UI 代码,而不必一路中断应用程序。
下面是我的应用程序当前设置的框架:
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// Handling window messages, e.g menus, buttons, etc.
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* lpCmdLine, int nCmdShow)
{
// Initialize resources, register main window class using MainWndProc, etc.
// ...
HWND mainwnd = CreateWindow(/* CreateWindow args... */);
do
{
MSG msg = {};
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Per-frame application logic
// ...
} while (msg.message != WM_QUIT);
// Clean up resources
// ...
return 0;
}
我需要如何修改它以使所有 WinAPI 对象继续运行,但我现在也可以使用 wxWidgets 创建窗口?我之前尝试通过从wxApp 派生的自定义类初始化 wxWidgets 来替换上面的消息循环,但我的应用程序在清理代码期间不断崩溃(有时甚至无法到达)。
编辑:我设法让它工作,更新的骨架可以在下面找到。
// Main WinAPI window procedure
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// Code to handle other messages
// ...
case WM_CLOSE:
// Closing this window should shut down the app
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
class MyApp : public wxApp
{
public:
virtual bool OnInit() override
{
if(!Old_Init())
{
// Perform cleanup in case something goes wrong
Old_Exit();
return false;
}
// Wrap the WinAPI window in a dummy wxWindow
m_dummyMainWindow = new wxWindow();
m_dummyMainWindow->SetHWND(m_mainWnd);
return true;
}
int OnExit() override
{
// Unset the dummy window HWND and delete it (is this necessary?)
m_dummyMainWindow->SetHWND(NULL);
delete m_dummyMainWindow;
// Clean up everything else
return Old_Exit();
}
private:
bool Old_Init()
{
// Perform the old initialization
// ...
m_mainWnd = CreateWindow(/* CreateWindow args... */);
if(m_mainWnd)
{
return true;
}
else
{
return false;
}
}
int Old_Exit()
{
// Perform the old cleanup (previously done after exiting the Windows message loop)
// ...
return 0;
}
HWND m_mainWnd;
wxWindow* m_dummyMainWindow;
};
wxIMPLEMENT_APP_NO_MAIN(MyApp);
// App entrypoint
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char* lpCmdLine, int nCmdShow)
{
if (wxEntry())
{
// Exit if something goes wrong (this might not be the correct way to do it?)
wxExit();
}
return 0;
}
这似乎确实有效,所有旧的 UI 元素都像以前一样工作,但我不能 100% 确定这是一个稳定的解决方案。我的调试器警告我内存泄漏,当我激活 UI 元素(例如打开和关闭对话框)时,内存泄漏的数量似乎增加了。我怀疑 WinAPI 资源可能没有被正确清理。我错过了什么吗?
EDIT2:我做了更多的调试,我的原始应用程序中的代码(即没有 wxWidgets)也会导致那些“内存泄漏”,我无法在最小的工作示例中复制它,所以我怀疑这个问题根本与 wxWidgets 无关。因此,我相信上述方法应该可以解决我的问题,但我不介意第二意见。
【问题讨论】:
-
计划是什么 - 多平台应用程序?如果不是,Win32 比 wxWidgets 好。
-
@i486 我想要一个对 OOP 更友好并且有不错的 RAD 工具的框架。 Qt 是我最初的选择,考虑到我的使用经验,但没有办法可靠地设置它,而无需基本上重写整个应用程序。
-
Win32 唯一的缺点是控件数量有限。 OOP 会使事情变得复杂而没有显着的好处。你可以试试
Ultimate++。 -
@i486 Win32 确实可以很强大,但它会占用我所有的时间来设置它足够灵活,而且缺乏 RAD 工具使情况变得更糟。我真的不想滥用 OOP,我的意思是我不想花时间重新发明轮子。如果有人实现了我需要的所有基本 UI 工具,并为它们提供了一个方便的 OOP 包装器,这样我就可以实例化对象,那就足够了。
标签: c++ user-interface winapi wxwidgets