MFC底层窗口实现
程序员文章站
2022-05-18 19:32:28
简要说明 MFC是微软的一个基础类库,如果在Windows平台上做GUI的开发,这是一个不错的选择。简单的记录MFC学习过程中的需要掌握或者后期需要查看的知识点。 Windows消息机制 1. 操作系统首先捕获到来自键盘或鼠标等输入系统的消息,并将获取到的消息存放到消息队列中。 2. 应用程序一直通 ......
简要说明
mfc是微软的一个基础类库,如果在windows平台上做gui的开发,这是一个不错的选择。简单的记录mfc学习过程中的需要掌握或者后期需要查看的知识点。
windows消息机制
- 操作系统首先捕获到来自键盘或鼠标等输入系统的消息,并将获取到的消息存放到消息队列中。
- 应用程序一直通过getmessage()从消息队列中获取消息。
- 应用程序再将获取到的消息通过dispatchmessage()分派到操作系统
- 操作系统再执行“窗口过程”
windows编程模型
- winmain函数的定义(winmain函数是windows程序的入口)
- 创建一个窗口
- 进行消息循环
- 编写窗口过程函数
整体框架结构
实现步骤
创建win32项目
- 新建win32项目,选择“空项目”并完成创建。
- 添加源文件,文件名以“.c”结尾。
- 添加头文件“windows.h”
- 添加程序入口函数“windowmain”
//winapi 代表__stdcall 参数的传递顺序:从右到左 以此入栈,并且在函数返回前 清空堆栈 int winapi winmain( hinstance hinstance, // 应用程序实例句柄 hinstance hprevinstance, // 上一个应用程序句柄,在win32环境下,参数一般为null,不起作用了 lpstr lpcmdline, // char * argv[] int nshowcmd) // 显示命令 最大化、最小化 正常 { ... return 0; }
应用程序过程
- 设计窗口
- 首先实例化一个窗口类,再依次设置其参数
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); wc.hinstance = hinstance; //应用程序实例句柄 传入winmain中的形参即可 wc.lpfnwndproc = windowproc;// 回调函数 窗口过程 wc.lpszclassname = text("win");//指定窗口类名称 wc.lpszmenuname = null; //null代表不使用菜单 wc.style = 0; //显示风格 0为默认
- 注册窗口
- 将上述实例化的窗口类进行注册
registerclass(&wc);
- 创建窗口
/* lpclassname, 类名 lpwindowname, 标题名 dwstyle, 风格 ws_overlappedwindow x, 显示坐标 cw_usedefault y, nwidth, 宽 nheight, 高 hwndparent, 父窗口 hmenu, 菜单 hinstance, 实例句柄 lpparam 附加值 lp一般为鼠标附加值 null */ hwnd hwnd = createwindow(wc.lpszclassname, text("windows"), ws_overlappedwindow, cw_usedefault, cw_usedefault, cw_usedefault, cw_usedefault, null, null, wc.hinstance, null);
- 显示和更新
showwindow(hwnd, sw_shownormal); updatewindow(hwnd);
- 通过循环取消息
/* hwnd hwnd; 主窗口句柄 uint message; 具体消息名称 wparam wparam; 附加消息 键盘消息 lparam lparam; 附加消息 鼠标消息 dword time; 消息产生时间 point pt; 附加消息 鼠标消息 x y */ msg msg; while (1) { /* lpmsg lpmsg, 消息 hwnd hwnd, 捕获窗口 填null代表捕获所有的窗口 uint wmsgfiltermin, 最小和最大的过滤的消息 一般填入0 uint wmsgfiltermax 填0代表捕获所有消息 */ if (getmessage(&msg, null, 0, 0) == false) { break; } // 翻译消息 translatemessage(&msg); // 分发消息 dispatchmessage(&msg); }
- 消息处理(窗口过程)
//callback 代表__stdcall 参数的传递顺序:从右到左 以此入栈,并且在函数返回前 清空堆栈 lresult callback windowproc( hwnd hwnd, // 消息所属的窗口句柄 uint umsg, // 具体消息名称 wm_xxxxxxxx 消息名 wparam wparam, // 键盘附加消息 lparam lparam // 鼠标附加消息 ) { switch (umsg) { case wm_close: //所有xxxwindow为结尾的方法,都不会进入到消息队列中,而是直接执行 destroywindow(hwnd); //destroywindow 发送另一个消息 wm_destroy break; case wm_destroy: postquitmessage(0); break; case wm_lbuttondown: { int xpos = loword(lparam); int ypos = hiword(lparam); char buf[1024]; 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); break; } default: break; }
大概流程如下
小结
- 首先要对整个创建流程有个整体的把握
- 学会查看msdn文档,不知道的参数及方法都可以从中获取
- 学习很重要,要好好学习