收藏 分销(赏)

windows消息循环原理---一个简单的MFC实例.docx

上传人:仙人****88 文档编号:12024208 上传时间:2025-08-29 格式:DOCX 页数:11 大小:65.91KB 下载积分:10 金币
下载 相关 举报
windows消息循环原理---一个简单的MFC实例.docx_第1页
第1页 / 共11页
windows消息循环原理---一个简单的MFC实例.docx_第2页
第2页 / 共11页


点击查看更多>>
资源描述
#include <windows.h> /* 导入包含文件WINDOWS.H,此文件包含了其它的Windows头文件                */  /* WINDEF.H   基本类型定义                                              */  /* WINNT.H    支持Unicode的类型定义                                     */  /* WINBASE.H  内核函数                                                  */  /* WINUSER.H  用户接口函数                                              */  /* WINGDI.H   图形设备接口函数 */ /************************************************************************/  /* 窗口对象的过程处理函数                                               */  /* LRESULT: 简单定义为LONG(long)                                       */  /* CALLBACK:__stdcall,指在Windows本身和用户的应用程序之间发生的函数调 */  /*           用的特殊调用序列。                                         */  /* HWND:    窗口句柄,32位数字,该参数为接受消息的窗口的句柄,          */  /*           CreateWindow函数的返回值。                                 */  /* UINT:    unsigned int 无符号整型32位,                              */  /*           该参数为MSG结构中的message域相同,表示该消息的数字         */  /* WPARAM:  UINT,32位消息参数                                         */  /* LPARAM:  LONG,32位消息参数                                         */  /************************************************************************/  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR lpszCmdLine, int iCmdShow)  {  /* 定义窗口类                                                           */   /* TCHAR:char                                                          */   /* _T和TEXT宏,功能一致,通常没用,在Unicode系统中,                    */   /* 自动把后面的字符串转换为宽字符串                                     */   /************************************************************************/   TCHAR tcClassName[] = TEXT("My Window");  //窗口类名字符串   /************************************************************************/   /* WNDCLASS:窗口类结构,定义了窗口的一般特性,可以创建不同的窗口       */   /* typedef struct                                                       */   /* {                                                                    */   /*      UINT        style ;                                             */   /*      WNDPROC     lpfnWndProc ;                                       */   /*      int         cbClsExtra ;                                        */   /*      int         cbWndExtra ;                                        */   /*      HINSTANCE   hInstance ;                                         */   /*      HICON       hIcon ;                                             */   /*      HCURSOR     hCursor ;                                           */   /*      HBRUSH      hbrBackground ;                                     */   /*      LPCTSTR     lpszMenuName ;                                      */   /*      LPCTSTR     lpszClassName ;                                     */   /* }                                                                    */   /* WNDCLASS, * PWNDCLASS ;                                              */   /************************************************************************/      HWND hWnd;     MSG msg;     WNDCLASS wc;                      //窗口类属性描述结构      wc.lpszClassName = tcClassName;   //窗口类名      wc.lpszMenuName  = NULL;          //窗口类菜单资源名      wc.lpfnWndProc   = WndProc;       //窗口对象的过程处理函数,指向函数的指针      wc.hInstance     = hInstance;     //当前进程对象句柄,接收于WinMain参数      wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //窗口背景刷子对象      wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);     //图标对象      wc.hCursor       = LoadCursor(NULL, IDC_ARROW);         //光标对象      wc.cbClsExtra    = 0;             //同类窗口对象公共数据区大小      wc.cbWndExtra    = 0;             //当前窗口对象私有数据区大小      wc.style         = CS_HREDRAW | CS_VREDRAW; //窗口类风格,水平或垂直尺寸改变后刷新      if (!RegisterClass(&wc))          //注册窗口类,参数为指向WNDCLASS结构的指针      {         /************************************************************************/          /* 窗口类注册不成功的错误信息                                           */          /* MessageBox 消息框                                                    */          /* 参数一:窗口句柄,如果没有则为NULL                                   */          /* 参数二:消息框主体显示的字符串                                       */          /* 参数三:消息框标题栏上的字符串                                       */          /* 参数四:winuser.h中定义的MB_开始的常数组合,消息框风格:按钮,图标    */          /*      为0,则只有ok按钮                                            */          /* 返回值:返回IDOK(1)。                                                */          /* 还可以返回IDYES、IDNO、IDCANCEL、IDABORT、IDRETRY、IDIGNORE等        */          /************************************************************************/          MessageBox(NULL, TEXT("RegisterClassError!"), TEXT("Error"), MB_ICONERROR);          return 0;                        //如果注册失败,返回并终止程序      }     /************************************************************************/   /* 定义窗口对象属性,指定有关窗口的更详细信息                           */   /************************************************************************/   TCHAR tcWindowCaptionName[] = TEXT("Win32 API"); //窗口对象标题名称   CREATESTRUCT cs;                  //窗口对象属性描述结构,定义在WINUSER.H   cs.lpszClass      = tcClassName;  //窗口类名   cs.lpszName       = tcWindowCaptionName; //窗口对象标题名称,显示在标题栏   cs.style          = WS_OVERLAPPEDWINDOW; //窗口对象风格   cs.x              = 100;          //窗口对象在屏幕上的x坐标   cs.y              = 100;          //窗口对象在屏幕上的y坐标   cs.cx             = 400;          //窗口对象的宽度   cs.cy             = 300;          //窗口对象的高度   cs.hwndParent     = NULL;         //窗口对象的父窗口句柄   cs.hMenu          = NULL;         //窗口对象的菜单句柄或子窗口编号   cs.hInstance      = hInstance;    //当前进程的实例句柄,WinMain参数   cs.lpCreateParams = NULL;         //创建参数指针,可以访问以后想要引用的程序中的数据   /************************************************************************/   /* 创建窗口对象                                                         */   /* 定义窗口句柄hWnd,值为CreateWindows函数的返回值。                    */   /* 即创建成功返回窗口的句柄,否则返回NULL                               */   /************************************************************************/   hWnd = CreateWindow(cs.lpszClass,        cs.lpszName,        cs.style,        cs.x,        cs.y,        cs.cx,       cs.cy,        cs.hwndParent,        cs.hMenu,        cs.hInstance,        cs.lpCreateParams);   if (hWnd == NULL)    //判断创建是否成功   {    /************************************************************************/    /* 窗口对象创建不成功的错误提示                                         */    /************************************************************************/    MessageBox(NULL, TEXT("CreateWindowError!"), TEXT("Error!"),MB_ICONERROR);    return 0;   }   /************************************************************************/   /* 显示窗口对象                                                         */   /* 此时Windows内部已经创建了这个窗口。已经分配内存。                    */   /* 但是要显示在显示器上还需要调用两个函数。                             */   /* ShowWindows(hwnd,iCmdShow)                                           */   /* 第一个参数是刚刚用CreateWindow创建的窗口的句柄。                     */   /* 第二个参数是传给WinMain的iCmdShow。用来确定最初如何在屏幕上显示窗口。*/   /* 也可以自定义选择以选项:                                             */   /* SW_SHOWNORMAL      //常规                                            */   /* SW_SHOWMAXIMIZED   //最大化                                          */   /* SW_SHOWMINNOACTIVE //只显示在任务栏                                  */   /* UpdateWindow(hWnd)                                                   */   /* 导致客户区域被绘制。通过给窗口过程(Wndproc)发送一个WM_PAINT消息实现  */   /************************************************************************/   ShowWindow(hWnd, iCmdShow);   UpdateWindow(hWnd);//立即刷新窗口对象  /************************************************************************/   /* 消息检索,消息循环                                                   */   /* MSG:消息结构,被定义在WINUSER.H                                     */   /* 消息循环以GetMessage调用开始,它从消息队列中取出一个消息             */   /* 这一调用传递给Windows一个指向msg的MSG结构指针。                      */   /* 第二、三、四个参数为NULL或者0表示程序接收自己创建的所有窗口的所有消息*/   /* Windows用从消息队列中取出的下一个消息填充msg结构的各个域             */   /* MSG:消息结构:                                                      */   /* typedef struct tagMSG                                                */   /* {                                                                    */   /*   HWND   hwnd ;    //消息发向的窗口的句柄。                          */   /*   UINT   message ; //消息标识符,一个数值,定义在Window头文件中      */   /*   WPARAM wParam ;  //一个32位的消息参数,含义根据消息不同而不同      */   /*   LPARAM lParam ;  //同上                                            */  /*   DWORD  time ;    //消息放入消息队列时的时间                        */   /*   POINT  pt ;      //消息放入消息队列时的鼠标坐标                    */   /* }                                                                    */   /* MSG, * PMSG ;      //结构名                                          */   /************************************************************************/   while (GetMessage(&msg, NULL, 0, 0))   {    /************************************************************************/    /* 检索消息;当检索到WM_QUIT(其值为0x0012)消息时,从消息循环中退出      */    /************************************************************************/    TranslateMessage(&msg);//将msg结构传递给Windows,进行虚拟键盘消息的转换    DispatchMessage(&msg); //发送消息,由此操作系统调用相应的窗口过程处理消息   }   /************************************************************************/   /* 主窗口返回                                                           */   /************************************************************************/   return msg.wParam;  } /************************************************************************/  /* 窗口对象的过程处理函数                                               */  /* 四个参数与MSG结构中的前四个参数相同。                                */  /* 程序通常不直接调用窗口过程,由Windows本身调用。                      */  /* 程序可以通过SendMessage函数调用自己的窗口过程                        */  /************************************************************************/  LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)  {   /************************************************************************/   /* 对消息进行分类处理                                                   */   /* WINUSER.H为每个消息定义以WM为前缀的标识符                            */   /*一般Windows程序元用switch和case结构来处理,此时必须返回0。            */   /*窗口过程不处理的其它消息必须传递给DefWindowProc函数,                 */   /*窗口过程返回该函数返回值                                              */   /************************************************************************/   switch (iMsg)   {    /************************************************************************/    /* 客户区的绘制消息,窗口客户区域无效时刷新                             */    /************************************************************************/    case WM_PAINT:    {     /************************************************************************/     /* PAINTSTRUCT:绘图结构,定义在WINUSER.H中                             */     /* RECT:矩形结构                                                       */     /* HDC:设备描述表句柄                                                  */     /************************************************************************/     PAINTSTRUCT ps;     HDC hDC;     RECT rect;     /* 对于WM_PAINT的处理几乎总是从一个BeginPaint函数开始的:               */     /* hDC = BeginPaint(hWnd, &ps)                                          */     /* 而已一个EndPaint函数结束                                             */     /* EndPaint(hWnd, &ps)                                                  */     /* 两个调用中第一个参数是程序的窗口句柄,                               */     /* 第二个参数是指向类型为PAINTSTRUCT的结构指针                          */     /************************************************************************/     hDC = BeginPaint(hWnd, &ps);       //获取显示设备对象及绘制描述属性     GetClientRect(hWnd, &rect);        //获取当前窗口对象客户区矩形     SetBkMode(hDC,TRANSPARENT);        //设置背景方式     SetTextColor(hDC, RGB(255, 0, 0)); //设置文本颜色     /************************************************************************/     /* 绘制文本                                                             */     /* DrawText函数,第一个参数是从BeginPaint返回的设备描述表句柄           */     /* 第二个参数是要输出的文本                                             */     /* 第三个参数是-1,表示文本串是以字节0终结的。                          */     /* 第四个参数要绘制的矩形区域                                           */     /* 最后一个参数是系列标志位,定义在WINDUSER.H中,水平、垂直中央,单行   */     /************************************************************************/     DrawText(hDC, TEXT("Hello, Win32!"), -1, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);     EndPaint(hWnd, &ps);               //客户区绘制结束,归还显示设备对象     return 0;    }    case WM_DESTROY:                    //接收到WM_DEFTROY消息    {     /************************************************************************/     /* 发送WM_QUIT消息,通知线程消息检索循环,清除窗口主程序可以退出        */     /* PostQuitMessage(0)函数在消息队列里插入一个WM_QUIT消息                */     /************************************************************************/     PostQuitMessage(0);     return 0;    }   }   /************************************************************************/   /* 程序末处理的消息交给window系统的缺省窗口对象的过程处理函数处理       */   /************************************************************************/   return DefWindowProc(hWnd, iMsg, wParam,lParam);  } 我们看上面的流程,可以总结出创建一个窗口的流程: (1).注册窗口类(RegisterClass)。在注册之前,要先填写RegisterClass的参数WNDCLASSEX结构。 (2)建立窗口(CreateWindow)。 (3)显示窗口(ShowWindows)。 (4)刷新窗口客户区(UpdateWindow)。 (5)进入无限的消息获取和处理的循环。首先获取消息(GetMessage),如果有消息到达,则将消息分派到回调函数处理(DispatchMessage),如果消息是WM_QUIT,则退出循环。 二.那么为什么要按照这样的顺序做呢?我们来用下图阐述一下原理: (1).当我们按了键盘和shu标后,此时会产生一个消息(包含消息的类型,发生的时间,位置等),并放入到系统消息队列中。此时windows会检查消息发生的位置,如果发现这个消息刚好位于某个应用程序的窗口内的时候,就将这个消息放于应用程序的消息队列中。如图c所示。 (2).当应用程序还没有来取消息的时候,消息就暂时保留在消息队列里,当程序中的消息循环执行到GetMessage的时候,控制权转移到GetMessage所在的USER32.DLL中(箭头1),USER32.DLL从程序消息队列中取出一条消息(箭头2),然后把这条消息返回应用程序(箭头3)。 (3).然后应用程序将处理这条消息,但方法不是自己直接调用窗口过程来完成,而是通过DispatchMessage间接调用窗口过程,Dispatch的英文含义是“分派”,之所以是“分派”,是因为一个程序可能建有不止一个窗口,不同的窗口消息必须分派给相应的窗口过程。当控制权转移到USER32.DLL中的DispatchMessage时,DispatchMessage找出消息对应窗口的窗口过程,然后把消息的具体信息当做参数来调用它(箭头5),窗口过程根据消息找到对应的分支去处理,然后返回(箭头6),这时控制权回到DispatchMessage,最后DispatchMessage函数返回应用程序(箭头7)。这样,一个循环就结束了,程序又开始新一轮的GetMessage。 (4). 应用程序之间也可以互发消息,PostMessage是把一个消息放到其他程序的消息队列中,如图4.4中箭头d所示,目标程序收到了这条消息就把它放入该程序的消息队列去处理;而SendMessage则越过消息队列直接调用目标程序的窗口过程(如图4.4中箭头I所示),窗口过程返回以后才从SendMessage返回(如图4.4中箭头II所示)。 窗口过程是由Windows回调的,Windows又是怎么知道往哪里回调呢?答案是我们在调用RegisterClassEx函数的时候告诉了Windows。 三.理解了原理之后,我们来仔细分析上面创建一个窗口的程序。 (1).为什么要使用注册窗口类? 例如:在一个窗口中,可能有不同的按钮,它们的工作原理都是一样的。但是各个按钮可能都有不同的表现形式,比如大小,颜色等。所以在这种情况下,我们需要将创建窗口的共性提取出来,然后再设置每个具体的窗口。这样就更加符合面向对象的原理。 (2).当应用程序取得消息后,DispatchMessage是如何知道要发给谁去处理呢? 这是因为在注册窗口类时,已经指定了。否则windows不可能知道。 (3).注册窗口类后,就要创建窗口了,建立窗口以后,传回来的是窗口句柄,要把它先保存起来,这时候,窗口虽已建立,但还没有在屏幕上显示出来,要用ShowWindow把它显示出来,ShowWindow也可以用在别的地方,主要用来控制窗口的显示状态(显示或隐藏),大小控制(最大化、最小化或原始大小)和是否激活(当前窗口还是背后的窗口),它用窗口句柄做第一个参数,第二个参数则是显示的方式  (4).窗口建立后,我们需要在窗口的客户区显示内容,这就要用到UpdateWindow,
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服