一、程序执行机制
1、过程驱动 - 程序的执行过程是按照预定好的顺序执行。
2、事件驱动 - 程序的执行是无序,用户可以根据需要随机触发相应的事件。
3、Win32窗口程序就是采用 事件驱动 方式执行,也就是 消息机制。
4、当系统通知窗口工作时,就采用消息的方式派发给窗口。
二、消息组成(windows平台下)
窗口句柄
消息ID 0-1023
消息的两个参数(两个附带信息)
消息产生的时间
消息产生时的鼠标位置
三、窗口处理函数和消息
1、每个窗口都必须具有窗口处理函数。
LRESULT CALLBACK WindowProc( HWND hwnd, //窗口句柄 UINT uMsg, //消息ID WPARAM wParam, //消息参数 LPARAM lParam //消息参数 );
2、当系统通知窗口时,会调用窗口处理函数同时,将消息ID和消息参数传递给窗口处理函数。
3、在窗口处理函数中,不处理的消息,使用默认窗口处理函数,例如DefWindowProc。
四、消息相关函数
1、GetMessage - 获取消息
BOOL GetMessage( LPMSG lpMsg, //存放获取到的消息BUFF HWND hWnd, //接收窗口句柄,如果是空,所有消息都管 UINT wMsgFilterMin,//获取消息的最小ID 0,如果是0,所有消息id都管 UINT wMsgFilterMax //获取消息的最大ID 0 );
lpMsg - 当获取到消息后,将消息的参数存放到MSG结构中。
hWnd - 获取到hWnd所指定窗口的消息。
wMsgFilterMin和wMsgFilterMax -只能获取到由它们指定的消息范围内的消息,如果都为0,表示没有范围。
2、TranslateMessage - 翻译消息。将按键消息,翻译成字符消息。
BOOL TranslateMessage( CONST MSG* lpMsg //要翻译的消息地址 )
检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行。
3、DispatchMessage - 派发消息。将消息派发到该消息所属窗口的窗口处理函数上
LRESULT DispatchMessage( CONST MSG* lpmsg //要派发的消息 );
五、windows常用消息
1、WM_DESTROY:窗口被销毁时的消息,无消息参数。常用于在窗口被销毁之前,做相应的善后处理,例如资源、内存等。
2、WM_SYSCOMMAND:系统命令消息,当点击窗口的最大化、最小化、关闭等命令时,收到这个消息。常用在窗口关闭时,提示用户处理。
wParam:具体点击的位置,例如关闭SC_CLOSE等.
lParam:鼠标位置
LOWORD:低字,水平位置
HIWORD:高字,垂直位置
3、WM_CREATE:在窗口创建成功还未显示之前,收到这个消息。常用于初始化窗口的参数、资源等等,包括创建子窗口等。
WPARAM:不使用,LPARAM:是CREATESTRUCT结构的指针,保存了CreatWindowEx中的12个参数。
4、WM_SIZE:在窗口的大小发生变化后,会收到WM_SIZE。常用于窗口大小变化后,调整窗口内各个部分的布局。
WPARAM:窗口大小变化的原因。
LPARAM:变化窗口客户区的大小
LOWORD:变化后的宽度
HIWORD:变化后的高度
5、WM_QUIT:用于结束消息循环处理。
wParam:PostQuitMessage 函数传递的参数。
lParam:不使用,当GetMessage收到这个消息后,会返回FALSE, 结束while处理,退出消息循环。
6、WM_PAINT:绘图消息 键盘消息 鼠标消息 定时器消息
7、相关代码
HINSTANCE g_hInstance = 0;//接收当前程序实例句柄 HANDLE g_接受句柄 = 0;//接收标准输出句柄 HWND g_编辑框句柄 = 0; //窗口创建前所做的事情 void 创建前(HWND hWnd, LPARAM lParam) { CREATESTRUCT* pcs = (CREATESTRUCT*)lParam; char* str = (char*)pcs->lpCreateParams; MessageBox(hWnd,(LPCWSTR)str , L"哎呦", MB_OK); } //DOS窗口 void DOS窗口(HWND hWnd, LPARAM lParam) { int DOS高 = LOWORD(lParam); int DOS宽 = HIWORD(lParam); MoveWindow(g_编辑框句柄, 0, 0, DOS宽, DOS高, TRUE);//移动窗口,控件随窗口变化 wchar_t szText[256] = {}; swprintf_s(szText, L"宽:%d,高:%d\n", DOS宽, DOS高); WriteConsole(g_接受句柄,szText, wcslen(szText) ,NULL,NULL); } //窗口上摆放编辑框 void 摆放控件(HWND hWnd) { g_编辑框句柄= CreateWindowEx(0,L"EDIT",L"",WS_CHILD|WS_VISIBLE|WS_BORDER, 0,0,500,500,hWnd,NULL,g_hInstance,NULL); } //2、消息处理函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { //7、处理消息 switch (msgID) { case WM_SIZE: DOS窗口(hWnd,lParam); break; case WM_CREATE: 创建前(hWnd,lParam); 摆放控件(hWnd); break; case WM_SYSCOMMAND: //MessageBox(hWnd,L"哎呦",L"不错哦",MB_OK); if (wParam==SC_CLOSE) { BOOL res= MessageBox(hWnd, L"要关闭么?", L"不错哦", MB_YESNO); if (res==IDYES) { //不用写,自动处理 } else { return 0; } } break; case WM_DESTROY: PostQuitMessage(0);//销毁窗口 break; } return DefWindowProc(hWnd, msgID, wParam, lParam); } //3、注册函数,第一个参数,窗口类名称,第二个参数,指向窗口处理函数的函数指针 void Register(LPSTR lpClassName, WNDPROC winProc) { WNDCLASSEX wc = { 0 }; wc.cbSize = sizeof(wc);//结构体大小 wc.cbClsExtra = 0;//窗口类的申请缓存区,0表示不开启缓存 wc.cbWndExtra = 0;//窗口的申请缓存区,0表示不开启缓存 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//背景颜色,一般白色 wc.hCursor = NULL;//设置光标。null表示默认 wc.hIcon = NULL;//默认左上角的图标 wc.hInstance = g_hInstance;//第一个参数实例句柄,可以找到进程在那块内存 wc.lpfnWndProc = winProc; //lp 一般都是指针,处理函数名或指针 wc.lpszClassName = (LPCWSTR)lpClassName;//窗口类名称,比如公司名字 wc.lpszMenuName = NULL;//没有菜单用null wc.style = CS_HREDRAW | CS_VREDRAW;//窗口变化,会重绘,窗口类的一般风格 RegisterClassEx(&wc); } //4、创建窗口,(窗口类名称,窗口标题栏名称) HWND CreateMain(LPCWSTR lpClassName, LPCWSTR lpWindowName) { HWND hWnd = CreateWindowExW(0, lpClassName, lpWindowName, WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, g_hInstance, (LPVOID)L"附加数据"); return hWnd; } //5、显示窗口(窗口句柄) void Display(HWND hWnd) { ShowWindow(hWnd, SW_SHOW);//句柄,显示方式 UpdateWindow(hWnd);//调用一次刷新窗口 } //6、消息循环 void Message() { MSG nMsg = { 0 }; while (GetMessage(&nMsg, nullptr, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } //1、入口函数 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevIns, LPSTR lpCmdLine, int nCmdShow) { g_hInstance = hInstance; AllocConsole();//增加一个dos窗口 g_接受句柄 = GetStdHandle(STD_OUTPUT_HANDLE); Register(LPSTR(L"主"), WndProc); HWND hWnd = CreateMain(LPCWSTR(L"主"), LPCWSTR(L"主窗口")); Display(hWnd); Message(); return 0; }
8、运行结果