代码解析
函数声明
#include <windows.h>
// 窗口过程函数原型 LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
LRESULT:Long Result,是一个长整型数据类型,表示函数返回的结果。在消息处理函数中,通常用于返回消息的处理结果。
CALLBACK:用来告诉编译器这个函数将作为一个回调函数被调用。回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数(callback)是什么?
WindowProcedure:窗口过程,就是一个回调函数,这个函数由操作系统在有消息送到窗口的时候调用,窗口过程里对不同的消息进行处理,从而实现响应消息,做出反应。比如按下按钮,打开菜单,点击鼠标等。
HWND:handle to a window,窗口的句柄。图解说明——究竟什么是Windows句柄
UINT:unsigned int,无符号整型,是windows message的编号。
Param:参数。
WPARAM和LPARAM:字(word)参数和长(long)参数。WPARAM和LPARAM的含义
// WinMain:应用程序入口点 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)
WinMain 函数接收 4 个参数,这些参数都是在系统调用 WinMain 函数时,传递给应用程序的。
WinMain:是窗口函数的语言声明,不可使用Main代替。
HINSTANCE hInst:实例句柄,指向当前正在运行的窗口。实例是指正在运行的窗口类程序。句柄是一种void型的无返回值的控制型指针。
HINSTANCE hPrevInst:表示上一个实例,在Win32中该参数始终为NULL。
LPSTR:Long Pointer string。Long Pointer是长指针,string是字符串类型。是一个以NULL终止的字符串,指定传递给应用程序的命令行参数。
例如:在 D 盘下有一个 sunxin.txt 文件,当我们用鼠标双击这个文件时将启动记事本程序( notepad.exe ),此时系统会将 D:/sunxin.txt 作为命令行参数传递给记事本程序的 WinMain 函数,记事本程序在得到这个文件的全路径名后,就在窗口中显示该文件的内容。
int ncmdshow:命令行指令,指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。这个参数的值由该程序的调用者所指定,在调用ShowWindow()时可以使用到该值。
创建窗口
{ WNDCLASSW wc = {0}; // 创建窗口类结构体实例,并初始化为0 wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // 窗口背景颜色 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口光标 wc.hInstance = hInst; // 应用程序实例句柄 wc.lpszClassName = L"MyWindowClass"; // 窗口类名 wc.lpfnWndProc = WindowProcedure; // 窗口过程函数
WNDCLASSW是一个结构体,与CReateWindowsW是模板与实例的关系。
// 注册窗口类 if (!RegisterClassW(&wc)) return -1;
类:类是C++中对于C语言中的结构体的延伸,class将结构相同的对象归统在类中,在类中定义这些对象相同的属性,行为,以及访问权限等。
RegisterClassW():注册窗口类函数。理解RegisterClass
参数:&wc表示对变量wc的地址进行引用。在C和C++中&运算符用于获取变量的地址。
检测函数:在if()中如果出现了!跟在非布尔型前面,表示这是一个检测函数,等价为
if(Fn()==0){ return -1; }
而一般来说,函数Fn()只有在运行失败时返回值才会是0,所以这可以作为一个检测函数来判断函数是否运行失败。
// 创建窗口 CreateWindowW(L"MyWindowClass", L"我的窗口", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 500, NULL, NULL, NULL, NULL);
L”MyWindowClass”:lpClassName, 如果 lpClassName 是字符串,则指定窗口类名称。
IpClassName :指向一个指定了类名的空字符串,或一个标识类名字符串的成员的指针。该参数实际是一个指针,用于创建一个类成员并定义类的属性,此处定义的是类名。
WS_OVERLAPPEDWINDOW | WS_VISIBLE:创建出的窗口样式,windows style。
WS_OVERLAPPED:产生一个层叠的窗口,一个层叠的窗口有一个标题栏和一个边框。
WS_VISIBLE:窗口初始时可见。
100,100,500,500:(100,100)定义的是窗口框左上角定位点的初始坐标位置,500,500分别是宽和高。
后四个参数:详看以下链接。
消息循环以及消息响应
// 消息循环 MSG msg = {0}; while( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
MSG:结构体名,创建一个名为msg的结构体,初始化为0。
GetMessage:获取消息编号和其他参数,其中&msg表示指向MWG结构的指针,该结构从线程的消息队列接收消息信息。NULL表示当前窗口类。0,0是过滤器参数,捕捉编号为int-int之间的信息,如果为(0,0)则不进行过滤全部捕捉。
当GetMessage接收到WM_QUIT消息时,GetMessage输出0,断开消息获取,退出while循环。WM_QUIT消息会在应用程序调用 PostQuitMessage函数时生成。
TranslateMessage:编译消息。
DispatchMessage:发送编译后的消息给WindowProcedure。
// 窗口过程函数:处理窗口消息 LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { switch(msg) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcW(hwnd, msg, wp, lp); } return 0; }
该函数为死循环函数,在窗口运行过程中不断执行。
switch对消息的编号进行遍历。
WM_DESTROY:按下窗口右上角关闭按钮时发出该消息。
PostQuitMessage:退出并关闭窗口进程。
完整代码
#include <windows.h> // 窗口过程函数原型 LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM); // WinMain:应用程序入口点 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow) { WNDCLASSW wc = {0}; // 创建窗口类结构体实例,并初始化为0 wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // 窗口背景颜色 wc.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口光标 wc.hInstance = hInst; // 应用程序实例句柄 wc.lpszClassName = L"MyWindowClass"; // 窗口类名 wc.lpfnWndProc = WindowProcedure; // 窗口过程函数 // 注册窗口类 if (!RegisterClassW(&wc)) return -1; // 创建窗口 CreateWindowW(L"MyWindowClass", L"我的窗口", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 500, NULL, NULL, NULL, NULL); // 消息循环 MSG msg = {0}; while( GetMessage(&msg, NULL, 0, 0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } // 窗口过程函数:处理窗口消息 LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { switch(msg) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcW(hwnd, msg, wp, lp); } return 0; }
评论