windows消息循环原理---一个简单的MFC实例.docx_第1页
windows消息循环原理---一个简单的MFC实例.docx_第2页
windows消息循环原理---一个简单的MFC实例.docx_第3页
windows消息循环原理---一个简单的MFC实例.docx_第4页
windows消息循环原理---一个简单的MFC实例.docx_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

#include/*导入包含文件WINDOWS.H,此文件包含了其它的Windows头文件*/*WINDEF.H基本类型定义*/*WINNT.H支持Unicode的类型定义*/*WINBASE.H内核函数*/*WINUSER.H用户接口函数*/*WINGDI.H图形设备接口函数*/*/*窗口对象的过程处理函数*/*LRESULT:简单定义为LONG(long)*/*CALLBACK:_stdcall,指在Windows本身和用户的应用程序之间发生的函数调*/*用的特殊调用序列。*/*HWND:窗口句柄,32位数字,该参数为接受消息的窗口的句柄,*/*CreateWindow函数的返回值。*/*UINT:unsignedint无符号整型32位,*/*该参数为MSG结构中的message域相同,表示该消息的数字*/*WPARAM:UINT,32位消息参数*/*LPARAM:LONG,32位消息参数*/*/LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);intWINAPIWinMain(HINSTANCEhInstance,HINSTANCE,PSTRlpszCmdLine,intiCmdShow)/*定义窗口类*/*TCHAR:char*/*_T和TEXT宏,功能一致,通常没用,在Unicode系统中,*/*自动把后面的字符串转换为宽字符串*/*/TCHARtcClassName=TEXT(MyWindow);/窗口类名字符串/*/*WNDCLASS:窗口类结构,定义了窗口的一般特性,可以创建不同的窗口*/*typedefstruct*/*/*UINTstyle;*/*WNDPROClpfnWndProc;*/*intcbClsExtra;*/*intcbWndExtra;*/*HINSTANCEhInstance;*/*HICONhIcon;*/*HCURSORhCursor;*/*HBRUSHhbrBackground;*/*LPCTSTRlpszMenuName;*/*LPCTSTRlpszClassName;*/*/*WNDCLASS,*PWNDCLASS;*/*/HWNDhWnd;MSGmsg;WNDCLASSwc;/窗口类属性描述结构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);return0;/如果注册失败,返回并终止程序/*/*定义窗口对象属性,指定有关窗口的更详细信息*/*/TCHARtcWindowCaptionName=TEXT(Win32API);/窗口对象标题名称CREATESTRUCTcs;/窗口对象属性描述结构,定义在WINUSER.Hcs.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);return0;/*/*显示窗口对象*/*此时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:消息结构:*/*typedefstructtagMSG*/*/*HWNDhwnd;/消息发向的窗口的句柄。*/*UINTmessage;/消息标识符,一个数值,定义在Window头文件中*/*WPARAMwParam;/一个32位的消息参数,含义根据消息不同而不同*/*LPARAMlParam;/同上*/*DWORDtime;/消息放入消息队列时的时间*/*POINTpt;/消息放入消息队列时的鼠标坐标*/*/*MSG,*PMSG;/结构名*/*/while(GetMessage(&msg,NULL,0,0)/*/*检索消息;当检索到WM_QUIT(其值为0x0012)消息时,从消息循环中退出*/*/TranslateMessage(&msg);/将msg结构传递给Windows,进行虚拟键盘消息的转换DispatchMessage(&msg);/发送消息,由此操作系统调用相应的窗口过程处理消息/*/*主窗口返回*/*/returnmsg.wParam;/*/*窗口对象的过程处理函数*/*四个参数与MSG结构中的前四个参数相同。*/*程序通常不直接调用窗口过程,由Windows本身调用。*/*程序可以通过SendMessage函数调用自己的窗口过程*/*/LRESULTCALLBACKWndProc(HWNDhWnd,UINTiMsg,WPARAMwParam,LPARAMlParam)/*/*对消息进行分类处理*/*WINUSER.H为每个消息定义以WM为前缀的标识符*/*一般Windows程序元用switch和case结构来处理,此时必须返回0。*/*窗口过程不处理的其它消息必须传递给DefWindowProc函数,*/*窗口过程返回该函数返回值*/*/switch(iMsg)/*/*客户区的绘制消息,窗口客户区域无效时刷新*/*/caseWM_PAINT:/*/*PAINTSTRUCT:绘图结构,定义在WINUSER.H中*/*RECT:矩形结构*/*HDC:设备描述表句柄*/*/PAINTSTRUCTps;HDChDC;RECTrect;/*对于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);/客户区绘制结束,归还显示设备对象return0;caseWM_DESTROY:/接收到WM_DEFTROY消息/*/*发送WM_QUIT消息,通知线程消息检索循环,清除窗口主程序可以退出*/*PostQuitMessage(0)函数在消息队列里插入一个WM_QUIT消息*/*/PostQuitMessage(0);return0;/*/*程序末处理的消息交给window系统的缺省窗口对象的过程处理函数处理*/*/returnDefWindowProc(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, 它实际上就是向窗口发送了一条WM_PAINT消息 三消息循环函数会在这里返回取到的消息,hWnd参数指定要获取哪个窗口的消息,例子中指定为NULL,表示获取的是所有本程序所属窗口的消息,wMsgFilterMin和wMsgFilterMax为0表示获取所有编号的消息。GetMessage函数从消息队列里取得消息,填写好MSG结构并返回TranslateMessage将MSG结构传给Windows进行

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论