|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 moc 于 2018-11-12 23:01 编辑
Windows应用程序编程模型
一个完整的Win32程序(#include<windows.h>),是创建窗口并在其中响应和实现消息,其实现步骤:
① WinMain 函数的定义;
②创建一个窗口;
③进行消息循环;
④编写窗口过程函数。
程序具体步骤:
1、设计窗口
2、注册窗口
3、创建窗口
4、显示和更新
5、通过循环取消息
6、处理消息(窗口过程)
实现代码(windows.c):
- #include <Windows.h> // 底层实现窗口的头文件
- // CALLBACK 代表__stdcall 表示参数的传递顺序:从右到左,以此入栈,并在函数返回前清空栈
- //6、处理消息(窗口过程)
- LRESULT CALLBACK WindowProc(
- HWND hwnd, // 消息所属的窗口句柄
- UINT uMsg, // 具体消息名称 WM_XXXX 消息名
- WPARAM wParam, // 键盘附加消息
- LPARAM lParam) // 鼠标附加消息
- {
- int xPos, yPos;
- char buf[1024];
- switch (uMsg)
- {
- case WM_CLOSE: //关闭消息(点击X的消息)
- //所有以xxxWindow结尾的消息,直接进入窗口过程,不进入消息队列
- DestroyWindow(hwnd); // DestroyWindow 发送另一个消息 WM_DESTROY
- break;
- case WM_DESTROY:
- PostQuitMessage(0); //发送正常的退出,会使GetMessage(&msg, NULL, 0, 0)的值为FALSE,然后退出消息循环
- break;
- case WM_LBUTTONDOWN: //鼠标左键按下
- xPos = LOWORD(lParam);
- yPos = HIWORD(lParam);
-
- wsprintf(buf, TEXT("x = %d, y = %d"), xPos, yPos); //连接字符串
- MessageBox(hwnd, buf, TEXT("鼠标左键按下"), MB_OK); //弹出消息框
- break;
- case WM_KEYDOWN: //键盘按下
- MessageBox(hwnd, TEXT("键盘按下"), TEXT("键盘按下"), MB_OK);
- break;
-
- case WM_PAINT: //绘图事件
- PAINTSTRUCT ps; //绘图结构体)
- HDC hdc = BeginPaint(hwnd, &ps); // 开始绘图,画家
- TextOut(hdc, 100, 100, TEXT("HELLO, 你好"), strlen("HELLO, 你好"));
- EndPaint(hwnd, &ps);
- }
- //返回值用默认处理方式
- return DefWindowProc(hwnd, uMsg, wParam, lParam);
- }
- //程序入口
- // WINAPI 代表__stdcall 表示参数的传递顺序:从右到左,以此入栈,并在函数返回前清空栈
- int WINAPI WinMain(
- HINSTANCE hInstance, // 应用程序实例句柄
- HINSTANCE hPrevInstance, // 上一个应用程序句柄,在Win32环境下,参数一般为NULL
- LPWSTR lpCmdLine, // char* argv[] 命令行参数
- int nShowCmd) // 显示窗口 最大化、最小化、正常
- {
- //1、设计窗口
- WNDCLASS wc;
- wc.cbClsExtra = 0; // 类的额外内存
- wc.cbWndExtra = 0; // 窗口的额外内存
- wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); // 设置背景
- wc.hCursor = LoadCursor(NULL, IDC_HAND); //设置光标 如果第一个参数为NULL, 代表使用系统提供的光标
- wc.hIcon = LoadIcon(NULL, IDI_ERROR); // 设置图标 如果第一个参数为NULL, 代表使用系统提供的图标
- wc.hInstance = hInstance; // 应用程序实例句柄, 由操作系统提供,传入WinMain中形参即可
- wc.lpfnWndProc = WindowProc; // 回调函数, 窗口过程
- wc.lpszClassName = TEXT("WIN"); // 指定窗口类名称
- wc.lpszMenuName = NULL; // 菜单名称 (不使用)
- wc.style = 0; // 显示风格 0代表默认窗口
- //2、注册窗口
- RegisterClass(&wc);
- //3、创建窗口
- /*
- LPCTSTR lpClassName 类名
- LPCTSTR lpWindowName 标题名
- DWORD dwStyle 风格 WS_OVERLAPPEDWINDOW(混合风格)
- int x 显示起点坐标x CW_USEDEFAULT 默认值
- int y 显示起点坐标y
- int nWidth 窗口宽度
- int nHeight 窗口高度
- HWND hWndParent 父窗口 NULL
- HMENU hMenu 菜单 NULL
- HINSTANCE hInstance 实例句柄 hInstance
- LPVOID lpParam 附加值 NULL
- */
- HWND hwnd = CreateWindow(wc.lpszClassName, TEXT("WINDOWS"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
- //4、显示和更新
- ShowWindow(hwnd, SW_SHOWNORMAL);
- UpdateWindow(hwnd);
- //5、通过循环取消息
- /* MSG 结构体
- HWND hwnd; 主窗口句柄
- UINT message; 具体消息名称
- WPARAM wParam; 附加消息 键盘消息
- LPARAM lParam; 附加消息 鼠标消息
- DWORD time; 消息产生时间
- POINT pt; 附件消息 鼠标点击位置消息
- */
- MSG msg;
- while (1)
- {
- /*
- LPMSG lpMsg, 消息
- HWND hWnd, 捕获窗口 填NULL表示捕获所有的窗口
- UINT wMsgFilterMin, 最大最小的过滤消息 一般填0,表示不过滤消息
- UINT wMsgFilterMax 填0代表捕获所有消息
- */
- if (GetMessage(&msg, NULL, 0, 0) == FALSE) //==FALSE 表示点击X关闭窗口
- {
- break;
- }
- //不为FALSE则分发消息(可能需要翻译(比如组合键CTRL+C))
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
复制代码
消息处理机制
① 操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
② 应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。
③ 应用程序调用DispatchMessage,将消息回传给操作系统。消息是由 MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。
④ 系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理。
|
|