当前位置:文档之家› 消息映射机制的剖析

消息映射机制的剖析

的机制。
完成画线的功能
方法一:用API函数
从CWnd派生出来的类中都有 一个数据成员m_hWnd保存了 跟C++类对象相关的窗口句柄
在MFC中如果要调用SDK的函数的话,要加::前缀
hdc=::GetDC(m_hWnd);
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
完成画线的功能
实现画笔中画线的功能,就是鼠标移动过程中画一系 列临时的直线,鼠标左键释放时画一条永久直线。 【作图模式及应用】 SetRop2可设置作图模式 作图模式R2_NOT下画的直线是通过反转屏幕当前颜色 作出的;在某一位置首次画一条直线时,它是可见的, 但是在相同的位置第二次画直线时,就变为不可见的。
完成画线的功能
实现画笔中画线的功能,就是鼠标移动过程中画一系 列临时的直线,鼠标左键释放时画一条永久直线。 在OnMouseMove中
if(m_bDraw==TRUE) { dc.SetROP2(R2_NOT); dc.MoveTo(m_ptOrigin); dc.LineTo(m_ptOld); dc.MoveTo(m_ptOrigin); dc.LineTo(point); m_ptOld=point; }
LineTo(hdc,point.x,point.y); ::ReleaseDC(m_hWnd,hdc);
完成画线的功能
方法二:用CDC类 有一个数据成员m_hDC,它保存设备描述表,也就是 与CDC这个类相关的句柄,就像m_hWnd保存窗口句柄 一样。
CDC *pDC=GetDC(); /* CWnd中的成员函数 */ pDC->MoveTo(m_ptOrigin); pDC->LineTo(point); ReleaseDC(pDC); /* CWnd类的成员函数 */
当我们用鼠标在窗口中点击一下,这时就有了一
个点,这个点就可以作为直线的起点。所以可以去
捕获一个鼠标左键按下的消息,在这个消息响应中 获取一个点。按住鼠标左键拖动然后释放左键,这 时也有一个点,这个点就是直线的终点。也就是说 我们要捕获2个消息,一个是鼠标左键按下的消息,
一个是鼠标左键释放的消息。有了这2个消息,对这
作图都是在客户区作图。
在框架窗口的客户区如何画图 将 ? 框架窗口是视图窗口的父窗口 CClientDC dc( this); 替换为 CClientDC dc( GetParent() );
完成画线的功能
方法四:用CWindowDC类
好处:可访问窗口的整个区域,包括客户区和非客户区。 (1)CWindowDC dc(this); (2)dc.MoveTo(m_ptOrigin); (3)dc.LineTo(point); 和CClientDC有没有区别? 换成CWindowDC dc ( GetParent( )); 编译运行,结果如何?
完成画线的功能
实现连续画线的功能
(2)在OnMouseMove中 CClientDC dc(this); if(m_bDraw==TRUE) { dc.MoveTo(m_ptOrigin); dc.LineTo(point); m_ptOrigin=point; }
完成画线的功能
画扇形 在鼠标移动事件中, CClientDC dc(this); if(m_bDraw==TRUE) { dc.MoveTo(m_ptOrigin); dc.LineTo(point); }
2个消息进行响应,在响应的过程中可以得到起点和 终点。
哪个窗口响应鼠标消息呢?
对于文档视图结构来说,有视图窗口和框架窗口,
视图窗口始终是覆盖在框架之上的,就好像说有一
面墙作为框架窗口,有一面墙它始终挡在框架窗口
这面墙前面,你对框架窗口这么墙的操作始终是对 它前面墙的操作,窗口也是一样,就是在框架窗口
MFC消息的路由
就是在类的头文件中看 DECLARE_MESSAGE_MAP()
这个宏前面是否有消息响应函数的原型声明, 然后在源文件中BEGIN_MESSAGE_MAP( )和 END_MESSAGE_MAP( )这2个宏之间是否有消息响应的 映射的宏。如果通过这2个步骤找到了消息响应函数,
那么就会对这个消息进行处理。这就是MFC消息映射
中捕获不到任何鼠标的消息。包括鼠标点击、鼠标
移动。
MFC消息的路由
在SDK中讲过:一旦消息产生,操作系统会把消息放 入消息队列中,应用程序通过GetMessage从消息队 列中取出一条消息,然后DispatchMessage交给操作 系统,操作系统会调用窗口过程函数去进行处理。 而在MFC中,好像不是走的这条路线。只要想捕获消 息,增加消息响应函数,遵照这个步骤,就可以完成 消息的响应。并不是象以前的switch~case对想捕获 的消息进行处理。
完成画线的功能
带边线的扇形 要增加一个新的变量,是点,是个旧的点,设为私有。 CPoint m_ptOld;在构造函数中设为0。当鼠标左键按 下时,把鼠标的点分别赋给这2个点。
if(m_bDraw==TRUE) { dc.MoveTo(m_ptOrigin); dc.LineTo(point); dc.MoveTo(m_ptOld); dc.LineTo(point); m_ptOld=point; }
画线可以访问整个框架窗口区域。包括客户区和非客户区。
所以用CWindowDC,就可以在非客户区作图。
完成画线的功能
能不能画到整个屏幕上面?
是可以的,关键是看DC是与哪个窗口相关联。 实际上我们的桌面本身就是一个窗口。所以如果我们 获取一个与桌面相关联的一个CDC的对象,就可在桌 面上画图。 要获取桌面,用GetDesktopWindow函数。 CWindowDC dc( GetDesktopWindow());
/* 作图是在与视图类相关的窗口上,如何传递视图类的指针? 每个类都有一个隐含的this,指向类对象本身。*/
dc.MoveTo(m_ptOrigin); dc.LineTo(point);
完成画线的功能
框架窗口的客户区是从工具栏开始,往下。 非客户区就是标题栏和菜单栏, 而视图(View)窗口是没有非客户区的。
完成画线的功能
方法三:用CClientDC类
在构造函数中会调用GetDC得到句柄,在析构函数中会调用 ReleaseDC释放句柄。所以不需要显示调用GetDC和 ReleaseDC,只需要构造CClientDC类的一个对象即可。当 这个对象的生命周期结束时,资源会释放掉。
CClientDC dc( this);
完成画线的功能
实现连续画线的功能
曲线是由许多连续的小线段组成,要把这些点都捕获 到,则需要捕获鼠标移动的消息。 (1)为视图捕获鼠标移动的消息,OnMouseMove。 只要鼠标移动就会进到这个消息处理函数来。这不是 我们所期望的,我们希望按下鼠标左键才作图。所以 我们要判读什么时候按下了鼠标左键。设置一个布尔 变量,按下了鼠标左键设置当真,当释放鼠标左键时 设置为假。在构造函数中初始化为假。
MFC消息映射机制的剖析
学会使用ClassWizard
理解发送给窗口的消息是如何被MFC框架
窗口类的函数进行响应的。
掌握设备描述表及其封装类CDC的使用,
CDC是如何与具体的设备发生关联的;
新建一个单文档应用程序,在窗口上实现画线
在窗口上画线,首先要有2个点,这2个点如何去
捕获?
Windows应用程序是基于消息的编程
typedef struct tagMSG {
MFC消息的路由
HWND hwnd;
UINT message; 在MFC中,采用的是消息映射的方式。 WPARAM wParam; 在我们的程序中。MFC在后台维护了一个句柄和 LPARAM lParam; c++对象的指针的对照表,也就是说,和视图类相关 DWORD time; POINT pt; 的有个窗口,窗口肯定有个窗口句柄,这个窗口句 } MSG; 柄就和我们的视图类的指针对照起来。当我们收到 消息的时候,消息的第一个参数就是窗口句柄,也 就是说这个消息和哪个窗口相关的。通过这个句柄 我们就可以找到与它相关联的c++对象的指针,然后 通过这个指针传递给基类,基类通过消息循环会去 调用函数WindowProc来对消息进行处理。
MFC消息的路由
而WindowProc是个虚函数。也就是说,当子类继 承CWnd时,它在后台都会有这样一个函数。在这 个函数内部,调用射 的处理。我们知道消息中的窗口句柄是和一个c++对 象的指针相关联的,通过这个指针传给基类,这样 的话它调用的都是子类的OnWndMsg。在这个函数 里,看看是否有消息响应函数
相关主题