窗口的创建
编写窗口生成器
- 注册某个
窗口类
(用字符串作为类名注册) - 利用
窗口类
创建某个窗口 - 注意:每个自定义窗口类只能存在一个窗口实例
- 注册某个
- 编写消息处理器(响应窗口操作)
循环处理窗口的操作
GetMessage
获取消息DispatchMessage
派发消息(回调消息处理器)
主体结构
- 在程序中通过
while
配合GetMessage
获取窗口的操作 - 如果有需要调用
DispatchMessage
处理该消息(回调消息处理器) - 再合适的时机 消息处理器 调用
PostQuitMessage(0)
,不再处理任何窗口操作
消息处理器
- 消息处理器接收窗口的操作并且调用相应的函数
- 统一接受用户对窗口的操作参数
- 所有窗口的所有 操作/消息 都会调用这个函数
作为一个窗口必须有以下操作
- 显示
- 刷新
- 关闭
- ...
LRESULT CALLBACK MainWndProc(HWND hwnd, // handle to window
UINT uMsg, // message identifier 消息码
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter;
{
switch (uMsg)
{
//case WM_NCCREATE:{
// return 0;
//}
// break;
case WM_COMMAND:
{
if (HIWORD(wParam) == 0) {
//表示是菜单消息
if (LOWORD(wParam) == ID_OPEN) {
//表示打开按钮被点击
//MessageBox(hwnd, NULL, NULL, NULL);
//n_windows
create_window(m_HINSTANCE, 100+ n_windows*10, 200+ n_windows*10, str_cat("test", n_windows));
}
}
}
break;
case WM_CREATE:
// Initialize the window.
return 0;
case WM_PAINT:
// Paint the window's client area.
return 0;
case WM_SIZE:
// Set the size and position of the window.
return 0;
case WM_DESTROY:
// Clean up window-specific data objects.
//手动投递WM_QUIT
//PostMessage(hwnd,
// WM_QUIT,
// 0,
// 0);
n_windows--;
if (n_windows == 0) {
PostQuitMessage(0);
}
return 0;
//
// Process other messages.
//
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
窗口生成器
为了简化窗口生成的代码我们通过封装函数来实现窗口的显示
/*
创建窗口
*/
int create_window(HINSTANCE hinstance,int x,int y,char * str_name) {
//<<----注册窗口类
WNDCLASSEX wcx;
memset(&wcx, 0, sizeof(WNDCLASSEX));
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_HREDRAW |
CS_VREDRAW; // redraw if size changes
wcx.lpfnWndProc = MainWndProc; // points to window procedure
wcx.cbClsExtra = 0; // no extra class memory
wcx.cbWndExtra = 0; // no extra window memory
wcx.hInstance = hinstance; // handle to instance
wcx.hIcon = LoadIcon(NULL,
IDI_APPLICATION); // predefined app. icon
wcx.hCursor = LoadCursor(NULL,
IDC_ARROW); // predefined arrow
wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // white background brush
wcx.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU); // name of menu resource
//wcx.lpszClassName = _T("MainWClass"); // name of window class
wcx.lpszClassName = (LPCWSTR)str_name; // name of window class
ATOM atom = RegisterClassEx(&wcx);
if (atom == 0) {
return 0;
}
//注册窗口类---->>
//创建窗口
HWND hWnd = CreateWindowA((LPCSTR)atom,
str_name,
WS_OVERLAPPEDWINDOW,//窗口具有的属性,我们这里设置为常规窗口 其他属性参考 https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-createwindowa
x,
y,
800,
600,
NULL,
NULL,
hinstance,
NULL);
if (hWnd == NULL)
{
return 0;
}
//显示窗口
ShowWindow(hWnd, SW_SHOW);
//更新
UpdateWindow(hWnd);
n_windows++;
return 1;
}
监听操作
主要是通过while配合消息队列来处理
/*
gui的main
*/
int WINAPI _tWinMain(HINSTANCE hinstance, //应用程序实例句柄,模块基址
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
m_HINSTANCE = hinstance;
create_window(hinstance,100,200,"windows0");
//create_window(hinstance,200,300,"windows1");
//消息循环
//线程拥有消息队列
MSG msg;
while (GetMessage(&msg,
NULL,
0,
0) > 0)
{
//派发消息
DispatchMessage(&msg);
}
return 0;
}