HINSTANCE+hPreInstance

本文回顾了在Windows98时代,为了节省内存,一个应用程序的多个实例如何共享一个WNDCLASS的方法,并解释了为什么在32位Windows系统中这种方法不再适用。

在Windows98时,为了节省内存,需要一个应用程序的多个实例共享一个WNDCLASS。当程序启动时,hPreInstance指向前一个实例,如果当前实例为第一个实例,那么其值为NULL。所以,早期的WINDOWS程序,总会有如下代码:

if (!hPreInstance)
{
  wndclass.cbStyle = ***
 ***
 ***
 RegisterClass(&wndclass);
}

到了32位的Windows系统出现时,内存已经比较便宜,因此也没有必要再为了节省一个WNDCLASS大小的空间而浪费程序员的精力写出以上代码。在新的32位系统中hPreInstance永远为NULL。

那你把这段代码最关键的几个步骤给我单独列举出来,然后告诉我他们涉及到的知识点以及这样设计的目的:/* The codes below are generated by 'Element Studio'. */ #include <windows.h> #include "resource.h" #include <thread> #include <chrono> #include <functional> // declarations LRESULT __stdcall WndProcdure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR __stdcall DlgProcedure(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); void do_something(std::function<void(void)>); // function defines int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, wchar_t* lpCmdLine, int iCmdShow)//ui线程 注册窗口类 { wchar_t szAppName[] = L"WinApp"; WNDCLASSEX wcex = { 0 }; wcex.cbSize = sizeof(wcex); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = &WndProcdure; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); wcex.lpszMenuName = NULL; wcex.lpszClassName = szAppName; wcex.hIconSm = wcex.hIcon; if (!RegisterClassEx(&wcex)) { return -1; } HWND hWnd = NULL; hWnd = CreateWindowEx(//创建主窗口 WS_EX_OVERLAPPEDWINDOW, szAppName, L"App", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, NULL, hInstance, NULL); ShowWindow(hWnd, iCmdShow);//显示窗口 UpdateWindow(hWnd); //创建对话框 HWND hDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProcedure); ShowWindow(hDlg, iCmdShow); UpdateWindow(hDlg); //消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0))//不断获取消息 { TranslateMessage(&msg);//转换键盘消息 DispatchMessage(&msg);//分发消息对应处理函数 } return msg.wParam; } LRESULT __stdcall WndProcdure(//主窗口消息处理 HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC = NULL; PAINTSTRUCT ps; switch (message) { case WM_CREATE: { return 0; } case WM_PAINT: { hDC = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); return 0; } case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hWnd, message, wParam, lParam); } constinit static HWND hStaticText{ nullptr }; void ui_call_back(void)//回调函数 通知ui更新状态(显示finish) { // switch to ui thread. ::SetWindowText(hStaticText, L"finish!");//更新静态文本显示“finish" } INT_PTR __stdcall//对话框消息处理 DlgProcedure(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: { hStaticText = ::GetDlgItem(hDlg, IDC_STATIC1);//获取静态文本控件 return false; } case WM_CLOSE: { EndDialog(hDlg, 0); return true; } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: { ::PostQuitMessage(0); return true; } case IDOK: { // UI call do... do_something(ui_call_back);//调用后台任务函数 return true; } } return false; } } return false; } using namespace std::chrono_literals; void do_something(std::function<void(void)> cb)//后台线程 { std::jthread th([cb]() -> void//使用多线程来处理 创建一个新的后台线程 分离耗时任务和ui交互 { //模拟了一个耗时操作,如果不使用多线程会导致UI线程被卡住,窗口无法响应鼠标点击,无法刷新。 std::this_thread::sleep_for(5s); cb();//等价于调用 ui_call_back(); }); //通过接收一个std::function类型的cb(回调函数),do_something只需要在任务完成后调用cb()即可 //具体的 UI 更新逻辑(比如显示 “finish!”)由cb决定。 th.detach(); }
最新发布
08-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值