创建一个视窗的具体步骤如下:
(1)注册窗口类RegisterClassEx
(2)创建窗口CreateWindowEx
(3)在桌面上显示窗口ShowWindow
(4)更新窗口客户区UpdateWindow
(5)进入无限的消息获取和循环处理。首先获取消息GetMessage,若有消息到达,则将消息分派回调函数DispatchMessage处理,如果返回的是WM_QUIT,则GetMessage函数返回FALSE,整个消息循环结束 。消息处理的具体过程在WndProc函数中进行
#include
#include
//窗口回调函数
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPreveInstance,
LPSTR szCmdLine, int nCmdShow) {
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;//窗口句柄
MSG msg;//消息类型
WNDCLASSEX wndclass; //用描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); //结构的大小(必须定义结构大小)
wndclass.style = CS_HREDRAW | CS_VREDRAW; //样式
wndclass.lpfnWndProc = WndProc; //指向窗口过程函数指针
wndclass.cbClsExtra = 0; //没有额外的类内存
wndclass.cbWndExtra = 0; //没有额外的窗体内存
wndclass.hInstance = hInstance; //包含类的窗口过程的实例的句柄
wndclass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);//使用预定义的图标
wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW); //使用预定义光标
wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);//使用白色背景画刷
wndclass.lpszMenuName = NULL; //不指定菜单
wndclass.lpszClassName = szAppName; //窗口类的名称
wndclass.hIconSm = NULL; //没有类的小图标
::RegisterClassEx(&wndclass);//注册这个窗口类
//创建主窗口
hwnd = ::CreateWindowEx(
0, //dwExStyle, 扩展样式
szAppName, //lpClassName,类名
"WindowsName", //lpWindowName
WS_OVERLAPPEDWINDOW, //dwStyle, 窗口风格
CW_USEDEFAULT, //X,初始X坐标
CW_USEDEFAULT, //Y,初始Y坐标
CW_USEDEFAULT, //nWight, 宽度
CW_USEDEFAULT, //nHight, 高度
NULL, //hWndParent, 父窗口句柄
NULL, //hMenu, 菜单句柄
hInstance, //hInstance, 程序实例句柄
NULL //ipParam,用户数据
);
//若窗口句柄为空,则创建失败
if (NULL == hwnd) {
::MessageBox(NULL, "创建窗口失败", "error", MB_OK);
return -1;
}
//显示窗口
::ShowWindow(hwnd, nCmdShow);
//更新窗口
::UpdateWindow(hwnd);
//从操作系统的消息队列中不断的捡取消息
while (::GetMessage(&msg, NULL, 0, 0)) {
::TranslateMessage(&msg); //软键盘转化消息
::DispatchMessage(&msg);//将消息发送到窗体中
}
return msg.wParam;//当GetMessage返回0时程序结束
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch (message) {
case WM_CREATE:
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("Hello windows32SDK"), -1, &rect,
DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY: //正在销毁窗口
//向消息序列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
在程序中WNDCLASSEX 类型是包含窗口信息,其结构是类似于WNDCLASS结构。有两个区别。WNDCLASSEX包括cbSize成员和hIconSm成员,该成员指定结构的大小,而hIconSm成员包含与窗口类关联的小图标的句柄。HWND类型定义窗口,MSG类型定义所传递的消息。通过展示窗口ShowWindow函数将注册的窗体展示在桌面上,通过UpdateWindow函数将消息回调函数中的操作更新,GetMessage函数则负责消息的接收和发送。
对于窗口回调函数WndProc函数的返回值类型为LRESULT,该类型为处理消息值指定的消息的窗口过程的返回值,在其中使用switch—case语句来进行相关消息的处理。进入WM_PAINT分支,意味着调整后的大小要重新画出BeginPaint函数开始绘制视窗,GetClientRect取得视窗区域显示大小,DrawText显示字符,EndPaint结束绘制视窗。
程序运行结果如下所示:
在程序中有很多大写的识别字,如CS_HREDRAW 等,一般是前两个或三个字母大写,后面接一个下划线后面再是字母,这些是简单的数值常数。字首指示的是该常数所属的类别,如下表所示:
字首 | 类别 |
---|---|
CS | 视窗类别样式 |
CW | 建立视窗 |
DT | 绘制文字 |
IDI | 图示ID |
IDC | 游标ID |
MB | 讯息方块 |
SND | 声音 |
WM | 视窗讯息 |
WS | 视窗样式 |
在代码中我们还用到了很多新的结构体来进行表示,如下表所示:
结构 | 含义 |
---|---|
MSG | 讯息结构 |
WNDCLASS | 视窗类别结构 |
PAINTSTRUCT | 绘图结构 |
RECT | 图示ID |
除此之外,在程序中我们还使用了很多代号,也可以称之为句柄,如下表所示:
识别字 | 含义 |
---|---|
HINSTANCE | 执行实体(程序本身)代号 |
HWND | 视窗代号 |
HDC | 装置内容代号 |
代号也被称之为句柄,它是一个整数(通常为32元),程序可以通过获得相关物件的代号来对该物件进行相关操作。
参考资料:
[1]《Windows程序设计(第五版)》
[2]windows程序设计应用开发 夏曹俊 丁宋涛
[3]https://docs.microsoft.com/zh-cn/welcome-to-docs