鱼C论坛

 找回密码
 立即注册
查看: 1646|回复: 0

[学习笔记] MFC-002Windows应用程序编程模型

[复制链接]
发表于 2018-8-18 20:12:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2018-11-12 23:01 编辑

Windows应用程序编程模型
        一个完整的Win32程序(#include<windows.h>),是创建窗口并在其中响应和实现消息,其实现步骤:
        ① WinMain 函数的定义;
        ②创建一个窗口;
        ③进行消息循环;
        ④编写窗口过程函数。

程序具体步骤:
                1、设计窗口
                2、注册窗口
                3、创建窗口
                4、显示和更新
                5、通过循环取消息
                6、处理消息(窗口过程)

实现代码(windows.c):
  1. #include <Windows.h>   // 底层实现窗口的头文件

  2. // CALLBACK  代表__stdcall 表示参数的传递顺序:从右到左,以此入栈,并在函数返回前清空栈
  3. //6、处理消息(窗口过程)
  4. LRESULT CALLBACK WindowProc(
  5.         HWND   hwnd,     // 消息所属的窗口句柄
  6.         UINT   uMsg,     // 具体消息名称  WM_XXXX  消息名
  7.         WPARAM wParam,   // 键盘附加消息
  8.         LPARAM lParam)   // 鼠标附加消息
  9. {
  10.         int xPos, yPos;
  11.         char buf[1024];

  12.         switch (uMsg)
  13.         {
  14.         case WM_CLOSE:   //关闭消息(点击X的消息)
  15.                 //所有以xxxWindow结尾的消息,直接进入窗口过程,不进入消息队列
  16.                 DestroyWindow(hwnd);   // DestroyWindow 发送另一个消息  WM_DESTROY  
  17.                 break;

  18.         case WM_DESTROY:
  19.                 PostQuitMessage(0);   //发送正常的退出,会使GetMessage(&msg, NULL, 0, 0)的值为FALSE,然后退出消息循环
  20.                 break;

  21.         case WM_LBUTTONDOWN:  //鼠标左键按下
  22.                 xPos = LOWORD(lParam);
  23.                 yPos = HIWORD(lParam);
  24.                
  25.                 wsprintf(buf, TEXT("x = %d, y = %d"), xPos, yPos);    //连接字符串
  26.                 MessageBox(hwnd, buf, TEXT("鼠标左键按下"), MB_OK);   //弹出消息框
  27.                 break;

  28.         case WM_KEYDOWN:   //键盘按下
  29.                 MessageBox(hwnd, TEXT("键盘按下"), TEXT("键盘按下"), MB_OK);
  30.                 break;
  31.        
  32.         case WM_PAINT:   //绘图事件
  33.                 PAINTSTRUCT ps;  //绘图结构体)

  34.                 HDC hdc = BeginPaint(hwnd, &ps);  // 开始绘图,画家
  35.                 TextOut(hdc, 100, 100, TEXT("HELLO, 你好"), strlen("HELLO, 你好"));
  36.                 EndPaint(hwnd, &ps);
  37.         }

  38.         //返回值用默认处理方式
  39.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  40. }


  41. //程序入口

  42. // WINAPI 代表__stdcall 表示参数的传递顺序:从右到左,以此入栈,并在函数返回前清空栈
  43. int WINAPI WinMain(
  44.         HINSTANCE hInstance,       // 应用程序实例句柄
  45.         HINSTANCE hPrevInstance,   // 上一个应用程序句柄,在Win32环境下,参数一般为NULL
  46.         LPWSTR lpCmdLine,         // char* argv[]  命令行参数
  47.         int nShowCmd)             // 显示窗口  最大化、最小化、正常
  48. {
  49.         //1、设计窗口
  50.         WNDCLASS wc;
  51.         wc.cbClsExtra = 0;    // 类的额外内存
  52.         wc.cbWndExtra = 0;    // 窗口的额外内存
  53.         wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);   // 设置背景
  54.         wc.hCursor = LoadCursor(NULL, IDC_HAND);   //设置光标 如果第一个参数为NULL, 代表使用系统提供的光标
  55.         wc.hIcon = LoadIcon(NULL, IDI_ERROR);  // 设置图标  如果第一个参数为NULL, 代表使用系统提供的图标
  56.         wc.hInstance = hInstance; // 应用程序实例句柄, 由操作系统提供,传入WinMain中形参即可
  57.         wc.lpfnWndProc = WindowProc;     // 回调函数, 窗口过程
  58.         wc.lpszClassName = TEXT("WIN");   // 指定窗口类名称
  59.         wc.lpszMenuName = NULL;     // 菜单名称 (不使用)
  60.         wc.style = 0;        // 显示风格 0代表默认窗口

  61.         //2、注册窗口
  62.         RegisterClass(&wc);

  63.         //3、创建窗口
  64.         /*
  65.                 LPCTSTR   lpClassName     类名
  66.                 LPCTSTR   lpWindowName    标题名
  67.                 DWORD     dwStyle         风格 WS_OVERLAPPEDWINDOW(混合风格)
  68.                 int       x               显示起点坐标x      CW_USEDEFAULT  默认值
  69.                 int       y               显示起点坐标y
  70.                 int       nWidth          窗口宽度
  71.                 int       nHeight         窗口高度
  72.                 HWND      hWndParent      父窗口  NULL
  73.                 HMENU     hMenu           菜单  NULL
  74.                 HINSTANCE hInstance       实例句柄  hInstance
  75.                 LPVOID    lpParam         附加值  NULL
  76.         */

  77.         HWND hwnd = CreateWindow(wc.lpszClassName, TEXT("WINDOWS"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

  78.         //4、显示和更新
  79.         ShowWindow(hwnd, SW_SHOWNORMAL);
  80.         UpdateWindow(hwnd);

  81.         //5、通过循环取消息
  82.         /* MSG 结构体
  83.         HWND      hwnd;     主窗口句柄
  84.         UINT      message;  具体消息名称
  85.         WPARAM    wParam;   附加消息  键盘消息
  86.         LPARAM    lParam;   附加消息  鼠标消息
  87.         DWORD     time;     消息产生时间  
  88.         POINT     pt;       附件消息 鼠标点击位置消息
  89.         */
  90.         MSG msg;

  91.         while (1)
  92.         {
  93.                 /*
  94.                 LPMSG lpMsg,          消息
  95.                 HWND  hWnd,          捕获窗口   填NULL表示捕获所有的窗口
  96.                 UINT  wMsgFilterMin, 最大最小的过滤消息  一般填0,表示不过滤消息
  97.                 UINT  wMsgFilterMax  填0代表捕获所有消息
  98.                 */

  99.                 if (GetMessage(&msg, NULL, 0, 0) == FALSE)   //==FALSE 表示点击X关闭窗口
  100.                 {
  101.                         break;
  102.                 }

  103.                 //不为FALSE则分发消息(可能需要翻译(比如组合键CTRL+C))
  104.                 TranslateMessage(&msg);
  105.                 DispatchMessage(&msg);
  106.         }
  107.         return 0;
  108. }
复制代码

消息处理机制
1.png

① 操作系统接收到应用程序的窗口消息,将消息投递到该应用程序的消息队列中。
② 应用程序在消息循环中调用GetMessage函数从消息队列中取出一条一条的消息。取出消息后,应用程序可以对消息进行一些预处理,例如,放弃对某些消息的响应,或者调用TranslateMessage产生新的消息。
③ 应用程序调用DispatchMessage,将消息回传给操作系统。消息是由 MSG结构体对象来表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函数总能进行正确的传递。
④ 系统利用WNDCLASS结构体的lpfnWndProc成员保存的窗口过程函数的指针调用窗口过程,对消息进行处理。

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 20:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表