MFC消息映射机制如何运用ClassWizard
- 格式:doc
- 大小:416.50 KB
- 文档页数:3
实验十一 MFC的简单消息映射与处理(4学时)[实验目的]1、基本掌握Windows环境下MFC程序的开发流程和方法;2、基本掌握MFC中的消息映射与处理方法;[实验内容]创建一个单文档的MFC工程,使用ClassWizard在视图类中添加WM_KEYDOWN、WM_KEYUP、WM_CHAR键盘消息映射和消息响应函数,添加WM_LBUTTON、WM_ RBUTTON鼠标消息映射和消息响应函数及。
界面如图所示,实现如下功能:程序运行界面图(1)用户按下/释放Shift键时,程序在视图窗口中显示有关的提示信息。
(2)用户按下Shift+B键时,程序在视图窗口中显示有关的提示信息。
(3)用户在视图窗口中按下鼠标左键,并拖动鼠标时,在窗口中绘制一个随鼠标位置变化的椭圆。
当用户释放鼠标键时,停止椭圆的绘制。
[实验步骤](1)创建一个单文档的MFC工程;(2)使用ClassWizard在其视图类中添加键盘消息WM_KEYDOWN、WM_KEYUP和WM_CHAR(分别对应键的按下、松开和按键动作)和消息响应函数;(3)在视图类的头文件中添加成员变量,以记录按键状态:protected:BOOL bShiftdown, bShiftup, bShiftB;并在视图类的构造函数中,对上述成员变量进行初始化:*View::*View(){// TODO: add construction code herebShiftdown=bShiftup=bShiftB=FALSE; //赋初值}其中,红色内容对应VC自动生成部分。
*View为视图类名。
(4)在键盘消息响应函数中,判断按键的状态,并设置上述成员变量的值。
代码如下:void *View::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: Add your message handler code here and/or call default//判断Shift键是否被按下if(nChar==VK_SHIFT){//AfxMessageBox("dd");bShiftdown=TRUE;bShiftup=FALSE;Invalidate(TRUE); //显示信息}CView::OnKeyDown(nChar, nRepCnt, nFlags);}void *View::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: Add your message handler code here and/or call default//判断Shift键是否被释放if(nChar==VK_SHIFT){//AfxMessageBox("dd");bShiftup=TRUE;//显示信息Invalidate(TRUE);bShiftdown=FALSE;}CView::OnKeyUp(nChar, nRepCnt, nFlags);}void *View::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: Add your message handler code here and/or call defaultif((nChar==98)||(nChar==66)) //判断是否敲击了字符键B键或b键{if(bShiftdown){bShiftB=TRUE;bShiftdown=FALSE;//显示信息Invalidate(TRUE);}}CView::OnChar(nChar, nRepCnt, nFlags);}(5)对视图类的OnDraw函数进行重载,根据成员变量的值(实际对应着按键的状态),显示相关信息。
1.打开对应对话框的类向导ClassWizard。
2.在消息映射MessageMaps中添加消息Message:WM_CTLCOLOR。
3.然后程序代码中会添加进函数:OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)4.在这个函数中添加if语句,其中的条件表达式改成想要设置的控件;比如改成: if (pWnd-> GetDlgCtrlID() == IDC_STATIC1 || pWnd-> GetDlgCtrlID() == IDC_STATIC2)注意,控件ID最好改过,如果多个控件使用同个默认ID,函数则不识别。
5.在if中添加以下语句:pDC->SetTextColor(RGB(255,255,255)); //设置字体为白色pDC->SetBkMode(TRANSPARENT); //设置背景为透明整个函数的代码如下:HBRUSH CHall::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);if (pWnd-> GetDlgCtrlID() == IDC_STATIC1 || pWnd-> GetDlgCtrlID() ==IDC_STATIC2 || pWnd-> GetDlgCtrlID() == IDC_STATIC3){pDC->SetBkMode(TRANSPARENT); //设置背景透明pDC->SetTextColor(RGB(255,255,255));return HBRUSH(GetStockObject(HOLLOW_BRUSH));}return hbr;}。
简述MFC消息映射机制
MFC采用消息映射来处理消息。
绝大多数消息都可由MFC的CLassWizard 来映射。
将ClassWizard对话框切换到MessaageMaps页面,选择相应的Class Name与Object IDs选项,在Messages列表中选定消息名。
双击消息在XXX 类中自动添加了该消息的处理函数。
ClassWizard消息映射包括三个方面的内容。
一是在头文件XXX.h中声明消息处理函数;其次在XXX.cpp源文件前面的消息映射入口处,添加了相应的映射宏。
最后在XXX.cpp文件中写入一个空消息处理函数的模板以便用户填入具体代码。
简述模式对话框编程的主要步骤
(1)用MFC AppWizard[exe]生成单文档
(2)在资源视图中右击Dialog文件夹插入对话框
(3)设计对话框
右击工具栏空白处打开控件工具栏
(4)测试对话框单击编排/Test或Ctrl+T
(5)创建对话框类
在对话框模板空白处双击鼠标为对话框创建新类(或Ctrl+W)
(6)创建对话框数据成员
添加与对话框控件相关联的数据成员。
目的是接收用户输入的数据。
Ctrl+W->Member Variables
(7)在程序中使用对话框
若新建的对话框类为CDlog,在程序中使用如下代码:
CDlog dlg; //对话框类对象;
dlg.DoModal();// DoModal() :模式对话框函数用于对话框的显示与终止
(8) 在XXXView.cpp中添加头文件
如: #include “Dlog.h”。
MFC消息映射摘要:控件通知消息有很多种,但是有一种是很常用,但是又不是很容易掌握的,那就是WM_NOTIFY,我试着对此做一下比较全面的论述,有不对的地方,还希望各路大虾批评指正。
控件通知消息在《深度解析VC中的消息(上)》中,我们提到了消息的分类有3种:窗口消息、命令消息和控件通知消息,我们这里要谈的是最后一种:控件通知消息。
控件通知消息,是指这样一种消息,一个窗口内的子控件发生了一些事情,需要通知父窗口。
通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。
例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。
她类似于命令消息,当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。
但是这种消息的存在并不是为了处理用户命令,而是为了让主窗口能够改变控件,例如加载、显示数据。
例如按下一个按钮,他向父窗口发送的消息也可以看作是一个控件通知消息;单击鼠标所产生的消息可以由主窗口直接处理,然后交给控件窗口处理。
控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。
控件通知格式控件通知经历了一个演变过程,因而SendMessage( )的变量Message、wParam和lParam有三种格式。
第一控件通知格式第一控件通知格式只是窗口消息的子集。
它的特征格式如下:WM_XXXX。
它主要来自下面的3种消息类型:(1)表示一个控件窗口要么已经被创建或销毁,要么已经被鼠标单击的消息:WM_PARENTNOTIFY;(2)发送到父窗口,用来绘制自身窗口的消息,例如:WM_CTLCOLOR、WM_DRAWITEM、WM_MEASUREITEM、WM_DELETEITEM、WM_CHARTOITEM、WM_VKTOITEM、WM_COMMAND 和WM_COMPAREITEM(3)有滚动调控件发送,通知父窗口滚动窗口的消息:WM_VSCROLL和WM_HSCROLL第二控件通知格式第二控件通知格式与命令消息共享,它的特征格式如下:WM_COMMAND。
下面几节将分析MFC的消息机制的实现原理和消息处理的过程。
为此,首先要分析ClassWizard实现消息映射的内幕,然后讨论MFC 的窗口过程,分析MFC窗口过程是如何实现消息处理的。
1.消息映射的定义和实现1.MFC处理的三类消息根据处理函数和处理过程的不同,MFC主要处理三类消息:∙Windows消息,前缀以“WM_”打头,WM_COMMAND例外。
Windows消息直接送给MFC窗口过程处理,窗口过程调用对应的消息处理函数。
一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC窗口类的成员函数。
∙控制通知消息,是控制子窗口送给父窗口的WM_COMMAND通知消息。
窗口过程调用对应的消息处理函数。
一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC 窗口类的成员函数。
需要指出的是,Win32使用新的WM_NOFITY来处理复杂的通知消息。
WM_COMMAND类型的通知消息仅仅能传递一个控制窗口句柄(lparam)、控制窗ID和通知代码(wparam)。
WM_NOTIFY能传递任意复杂的信息。
∙命令消息,这是来自菜单、工具条按钮、加速键等用户接口对象的WM_COMMAND通知消息,属于应用程序自己定义的消息。
通过消息映射机制,MFC框架把命令按一定的路径分发给多种类型的对象(具备消息处理能力)处理,如文档、窗口、应用程序、文档模板等对象。
能处理消息映射的类必须从CCmdTarget类派生。
在讨论了消息的分类之后,应该是讨论各类消息如何处理的时候了。
但是,要知道怎么处理消息,首先要知道如何映射消息。
1.MFC消息映射的实现方法MFC使用ClassWizard帮助实现消息映射,它在源码中添加一些消息映射的内容,并声明和实现消息处理函数。
现在来分析这些被添加的内容。
在类的定义(头文件)里,它增加了消息处理函数声明,并添加一行声明消息映射的宏DECLARE_MESSAGE_MAP。
MFC思想win32程序中创建一个窗口的过程:设计窗口阶段(由WNDCLASS结构描述部分)、窗口的注册及创建显示过程、消息循环部分。
win32用标准的C语言代码实现,是面向过程的。
在MFC中采用了面向对象的思想,即用面向对象的C++思想对以上代码进行了封装,也就是说将一些对窗口进行操作的API的函数封装到了一个类中,以下我将用简短的代码来演示一下这个过程:class CWnd{public:HWND m_hWnd;BOOL Create();BOOL ShowWindow();};BOOL CWnd::Create(){WNDCLASS wndClass;wndClass.style=CS_HREDRAW;wndClass.lpfnWndProc=(WNDPROC)DefWndProc;wndClass.cbClsExtra=0;wndClass.cbWndExtra=0;wndClass.hInstance=hInstance;wndClass.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));wndClass.hCursor=LoadCursor(hInstance,MAKEINTRESOURCE(IDC_CURSOR1));LOGBRUSH lgbr;lgbr.lbStyle=BS_SOLID;lgbr.lbColor=RGB(192,192,0);lgbr.lbHatch=0;wndClass.hbrBackground=CreateBrushIndirect(&lgbr);wndClass.lpszMenuName=NULL;wndClass.lpszClassName="mycls";RegisterClass(&wndClass);HWND hWnd;m_hWnd=CreateWindow("mycls","窗口标题",WS_OVERLAPPEDWINDOW,0,NULL,NULL,hInstance,NULL);if(m_hWnd!=NULL)return true;elsereturn false;}BOOL CWnd::ShowWindow(){return ShowWindow(hWnd,nCmdShow);}为了保证代码和以前的执行方式一样,Winmain()函数可以写成如下形式:int WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){CMyWnd m_wnd;m_wnd.Create();m_wnd.ShowWindow();MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return true;}此时,如果再写一个新的类来对剩下的代码进行封装,代码如下:class CWinApp{public:CWnd * m_pMainWnd;BOOL InitInstance();BOOL Run();CWinApp ();};CWinApp:: CWinApp (){if(InitInstance())Run();}BOOL CWinApp::InitInstance(){CWnd m_wnd;m_pMainWnd=&m_wnd;m_pMainWnd->Create();m_pMainWnd->ShowWindow();return true;}BOOL CWinApp::Run(){MSG msg;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg);DispatchMessage(&msg);}return true;}CWinApp theApp;int PASCAL WinMain() {}Windows消息的产生:1用户按键或者鼠标操作可以产生消息,如WM_KEYDOWN,WM_LBUTTONDOWN等;2系统可以自己产生消息,如,创建窗口的时候会产生WM_CREATE,WM_TIMER等;3应用程序间可以定义自己的消息,在应用程序间进行消息通讯;Windows消息的分类:1窗口消息(Windows Message):通常跟窗口的移动、创建,关闭等操作有关。
消息映射的实现Windows消息概述Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。
这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
消息的分类队列消息和非队列消息从消息的发送途径上看,消息分两种:队列消息和非队列消息。
队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
这里,对消息队列阐述如下:Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。
线程消息队列接收送给该线程所创建窗口的消息。
线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。
这些队列消息以外的绝大多数消息是非队列消息。
系统消息和应用程序消息从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER (0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。
消息结构和消息处理消息的结构为了从消息队列获取消息信息,需要使用MSG结构。
MFC消息映射及MFC入门一、MFC消息映射机制在前面Win32Class工程中,我们进行了Win32环境下的“消息映射”。
其实,通过前面的过程,我们已经不知不觉的接触到了MFC消息映射的核心。
MFC环境下的消息映射,其原理和我们讲解过的Win32下的消息映射是类似的。
简单地讲,就是让程序员指定要某个MFC类(有消息处理能力的类)处理某个消息。
MFC提供了工具ClassWizard来帮助实现消息映射,在处理消息的类中添加一些有关消息映射的内容和处理消息的成员函数。
程序员负责编写消息处理函数的代码,实现所希望的功能。
可以通过如下的3个重要的宏来实现MFC消息映射,这些宏功能强大,其实现相对也比较复杂。
这里只要求我们会用就可以。
稍后我们会用其实际代码替换这些宏,就能理解了。
●DECLARE_MESSAGE_MAP:初始化消息映射表,实际上是给所在类添加几个用于消息处理的静态成员变量和静态或虚拟函数。
●BEGIN_MESSAE_MAP:开始消息映射。
●END_MESSAE_MAP:结束消息映射。
其他常见的、用于实现MFC消息的宏还有:●前缀为“ON_WM_”的宏:用于Windows消息的宏(不带参数)如:ON_WM_PAINT()把消息WM_PAINT映射到OnPaint函数。
●ON_COMMAND宏:通过参数指定命令ID和消息处理函数。
如ON_COMMAND(ID_EDIT_PASTE, OnEditPaste),其中第二个参数OnEditPaste 的原型说明为:void CView::OnEditPaste()。
●ON_UPDA TE_COMMAND_UI宏:用于更新菜单的状态。
●前缀为”ON_”控件通知消息宏:这类宏可能带有三个参数,如ON_CONTROL,就需要指定控制窗口ID,通知码和消息处理函数;也可能带有两个参数,如具体处理特定通知消息的宏ON_BN_CLICKED、ON_LBN_DBLCLK、ON_CBN_EDITCHANGE等,需要指定控制窗口ID和消息处理函数。
M F C消息映射机制如何
运用C l a s s W i z a r d The Standardization Office was revised on the afternoon of December 13, 2020
画图的基本应用:
Point的应用,在mfc中的很多的位置都要用到。
只是当前点的信息,xy坐标,MoveToEx 移动位置函数The MoveToEx function updates the current position to the specified point and optionally returns the previous position.
LineTo 画直线的函数
CDC类,作图相关的操作
GetDC,cwnd::getdc 以及cdc的释放(区别hdc),两者的范围不同,调用方式不同
CClientDC 不需要显示地调用getdc和releasedc,只需要声明类的定义和类的调用。
Cliendc对象里利用view指针构造,但是调用的时候用的是对象的点调用方式。
Cwnd::getparent 获得父窗口的指针,view的父窗口是frame。
注意区别view 和framework的客户区域。
Cwindowdc类和clientdc一样自动调用getdc和releasedc。
了解他的访问客户区的范围。
Getdesktopwindow 获得桌面窗口。
创建画笔:
CPen 类,设置画笔的属性,包括一些类型宽度,颜色。
CDC::SelectObject 用的过程中要保存原来的画笔指针。
创建一个阴影线的笔只能是1或更小。
(其他的注意情况看msdn)。
创建画刷:
CBrush 类的方法
FillRect填充矩形的区域。
CRect类,几种不同的方法。
用位图填充画刷。
CBitmap 的构造函数,没有参数。
调用之前必需初始化。
透明画刷的创建:
(); 画出矩形。
空画刷:GetStockObject
CBrush::FromeHandle
空画刷的实现方法:
CBrush *brush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush *oldbrush=(brush);
(CRect(org,point));
(oldbrush);
理解
消息响应的知识:
MouseMove。