上一章节中我们讲解了Win32 API,Win32入口程序和宽字符,这一章节为大家介绍Win32中的事件,消息,消息处理函数,并且带领大家写出第一个图形界面程序。
一.事件,消息
Windows中的事件实际上是一个“动作”,这个动作可能是用户操作应用程序产生的,也可能是Windows自己产生的。而消息,就是用来描述这些动作的,比如这个动作何时产生,那个应用程序产生的,在哪个位置产生的。
Windows为了描述这些消息,提供了一个结构:
typedef struct{ HWND hwnd; //窗口句柄 UINI message; //消息类型 WPARM wParm; //附加消息 LPARM lParm; //附加消息 DWORD time; //时间 POINT pt; //坐标,表示动作的位置 }MSG,*PMSG;
其中,hwnd是窗口句柄,表示消息产生在哪个窗口,一个消息一般与一个窗口函数相关联,在Windows中一般HWND类型的变量用来标识窗口。
二.系统消息队列与应用消息队列
在这里给出一张图帮助大家理解:
我们来看看当某个动作触发消息,传送到应用程序的过程:
事件MSG→系统消息队列→应用程序消息队列→循环取出消息→处理消息
注意: 当应用程序处理消息的时候,与自己相关的消息会处理,与自己不相关的消息会交给windows处理。
- 1.用户触发某个动作
- 2.系统将这些信息存储到MSG结构体中
- 3.系统将这些消息存储到相关应用程序的队列中
- 4.应用程序循环取出消息
while(GetMessage(&MSG,NULL,0,0)){ Translatement(&MSG); //翻译消息 DispatchMessage(&MSG); //分发消息 }
- 5.DispachMessage将加工过的消息传递给操作系统
- 6.系统调用窗口过程函数
三.第一个图形界面程序
我们在写出第一个图形界面程序之前,我们要清楚步骤:
1.创建一个自己的窗口类
WNDCLASS wndclass;
我们来看看已经定义好的窗口类:
typedef struct tagWNDCLASSW { UINT style; WNDPROC lpfnWndProc; int cbClsExtra; int cbWndExtra; HINSTANCE hInstance; HICON hIcon; HCURSOR hCursor; HBRUSH hbrBackground; LPCWSTR lpszMenuName; LPCWSTR lpszClassName; } WNDCLASSW, *PWNDCLASSW, *NPWNDCLASSW, *LPWNDCLASSW;
2.将类的对象全部赋值,记得一定要全部赋值,注册窗口的时候必须要完整的窗口类
3.注册窗口类
RegistrClass(&wndclass); • 1
4.创建窗口
HWND hwnd = CreateWindow(); • 1
5.显示窗口
ShowWindow(hwnd,SW_SHOW); • 1
6.消息循环
MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd,NULL, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); }
7.回调函数
这个我们会在下一章节中介绍到
// Win32VS版本.cpp : 定义应用程序的入口点。 // #include "framework.h" #include "Win32VS版本.h" #define MAX_LOADSTRING 100 LRESULT CALLBACK WindowProc( IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ); int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { //窗口类名 TCHAR className[] = L"My First Windows."; //创建窗口对象 WNDCLASS wndclass = { 0 }; wndclass.hbrBackground = (HBRUSH)COLOR_MENU; //窗口背景颜色 wndclass.lpfnWndProc = WindowProc; //窗口的过程函数 wndclass.lpszClassName = className; //窗口的类名字 wndclass.hInstance = hInstance; //定义窗口类的应用程序的实例句柄 //注册窗口 RegisterClass(&wndclass); //创建窗口 HWND hwnd = CreateWindow( className, //lpname类名 TEXT("我的第一个窗口。"), //窗口标题 WS_OVERLAPPEDWINDOW, //dwStyle 10, 10, 600, 300, NULL, NULL, hInstance, NULL); //显示窗口 ShowWindow(hwnd, SW_SHOW); // 主消息循环: MSG msg; while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd,NULL, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } LRESULT CALLBACK WindowProc( IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { switch (uMsg) { //窗口消息 case WM_CREATE: { CREATESTRUCT* createst = (CREATESTRUCT*)lParam; return 0; } case WM_MOVE: { POINTS points = MAKEPOINTS(lParam); return 0; } case WM_SIZE: { int newWidth = (int)(short)LOWORD(lParam); int newHeight = (int)(short)HIWORD(lParam); return 0; } case WM_DESTROY: { PostQuitMessage(0); return 0; } //键盘消息 case WM_KEYUP: { return 0; } case WM_KEYDOWN: { return 0; } //鼠标消息 case WM_LBUTTONDOWN: { POINTS points = MAKEPOINTS(lParam); return 0; } } return DefWindowProc(hwnd, uMsg, wParam, lParam); }