`
wo_deqing
  • 浏览: 60271 次
文章分类
社区版块
存档分类
最新评论

MFC消息映射机制和绘图DC的获取

 
阅读更多

基于消息的windows MFC程序设计是如何进行消息映射的呢?

对于一个MFC APPWizard运用程序,CMainFrame和View是窗口类,并且是父子关系,Doc一般用于数据的加载和存储,View用于图像的显示,App中是包括一些(窗口)初始化之类的东西。

一、消息映射机制

windows程序设计是种事件驱动方式的程序设计,主要基于消息的。当用户需要完成某种功能时,需要调用OS某种支持,然后OS将用户的需要包装成消息,并投入到消息队列中,最后应用程序从消息队列中取走消息并进行响应。

在左边View类处点右键,在出现的菜单里点击“Add Windows Message Handler”,在出现的对话框里选择“WM_LBUTTONDOWN”,添加消息映射函数。

回到原文件,我们将看到三处进行了修改:

1、在头文件(View.h)中声明消息响应函数原型。

//{{AFX_MSG(CDrawView) //注释宏

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

//}}AFX_MSG //注释宏

DECLARE_MESSAGE_MAP

afx_msg宏表示声明的是一个消息响应函数。

2、在源文件(View.cpp)中进行消息映射。

BEGIN_MESSAGE_MAP(CDrawView, CView)

//{{AFX_MSG_MAP(CDrawView)

ON_WM_LBUTTONDOWN()

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

在宏BEGIN_MESSAGE_MAP()与END_MESSAGE_MAP()之间进行消息映射。

宏ON_WM_LBUTTONDOWN()把消息WM_LBUTTONDOWN与它的响应函数OnLButtonDown()相关联。这样一旦有消息的产生,就会自动调用相关联的消息响应函数去处理。

宏ON_WM_LBUTTONDOWN()定义如下:

#define ON_WM_LBUTTONDOWN()

{ WM_LBUTTONDOWN, 0, 0, 0,

AfxSig_vwp, (AFX_PMSG)(AFX_PMSGW)(void

(AFX_MSG_CALL CWnd::*)(UINT, CPoint))&OnLButtonDown },

3、源文件中进行消息响应函数处理。

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)

{

// TODO: Add your message handler code here and/or call default

CView::OnLButtonDown(nFlags, point);

}

说明:

可见当增加一个消息响应处理,在以上三处进行了修改。可在消息响应函数里添加消息处理代码完成对消息的响应、处理。

消息响应的可能方式:(这个我也还没弄太清楚)

1)在基类中针对每种消息做一个虚函数,当子类对消息响应时候,只要在子类中重写这个虚函数即可。缺点:MFC类派生层次很多,如果在基类对每个消息进行虚函数处理,那么从基类派生的每个子类都将背负一个庞大的虚表,这样浪费内存,故MFC没有采取这中方式而采取消息映射方式。

2)消息映射方式:MFC在后台维护了一个句柄和C++对象指针对照表,当收到一个消息后,通过消息结构里资源句柄(查对照表)就可找到与它对应的一个C++对象指针,然后把这个指针传给基类,基类利用这个指针调用WindowProc()函数对消息进行处理,WindowProc()函数中调用OnWndMsg()函数,真正的消息路由及处理是由OnWndMsg()函数完成的。由于WindowProc()和OnWndMsg()都是虚函数,而且是用派生类对象指针调用的,由多态性知最总终调用子类的。在OnWndMsg()函数处理的时候,根据消息种类去查找消息映射,判断所发的消息有没有响应函数,具体方式是到相关的头文件和源文件中寻找消息响应函数声明(从注释宏//{{AFX_MSG(CDrawView)...//}}AFX_MSG之间寻找),消息映射(从宏BEGIN_MESSAGE_MAP(...)....END_MESSAGE_MAP()之间寻找),最终找到对应的消息处理函数。当然,如果子类中没有对消息进行处理,则消息交由基类处理。

说明:

virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);

二、绘图DC的获取

说明:在View类添加WM_LBUTTONDOWN和WM_LBUTTONUP的消息处理函数,用来演示各种DC的获取,以及显示效果。

View类添加全局变量CPoint m_ptOrigin用来存储左键按下点坐标。下面集中来关注OnLButtonUp中的绘图程序和效果。

以下语句添加于OnLButtonUp函数中,可以查看不同的效果。

1、使用SDK获取DC句柄:

HDC hdc;

hdc=::GetDc(m_hWnd);//获取DC句柄

MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);

LineTo(hdc,point.x,point.y);

::ReleaseDC(m_hWnd,hdc);//释放DC

2、利用CDC类指针和CWin类成员函数获取DC。

CDC *pDC=GetDC();

pDC->MoveTo(m_ptOrigin);

pDC->LineTo(point);

ReleaseDC(pDC);

3、利用CClientDC对象。(CClientDC类从CDC类派生来的)

CClientDC dc(this);

dc.MoveTo(m_ptOrigin);

dc.LineTo(point);

4、利用CWindowDC对象。(CWindowDC类从CDC类派生来的)

CWindowDC dc(this);//

dc.MoveTo(m_ptOrigin);

dc.LineTo(point);

5、父窗口(MainFrame框架)和屏幕指针。

将上面的dc(this)分别改成GetParent()和GetDesktopWindow(),就可以得到父窗口指针和屏幕窗口指针。

可以分别试验画线效果。

6、利用画笔改变线条颜色和类型:

CPen pen(PS_DOT,1,RGB(0,255,0));//构造画笔对象

CClientDC dc(this);CPen *pOldPen=dc.SelectObject(&pen);//将画笔选入DC

dc.MoveTo(m_ptOrigin);

dc.LineTo(point);

dc.SelectObject(pOldPen);//恢复先前的画笔

利用画笔或者画刷的方法:1、用CPen、CBrush构造画笔或画刷对象;2、利用CClientDC构建dc;3、将画笔或画刷选入DC,并保存老画笔或画刷;4、进行操作;5、恢复先前的画笔或画刷。

7、使用画刷(通常利用画刷去填充矩形区域):

使用单色画刷

CBrush brush(RGB(255,0,0));//构造画刷对象

CClientDC dc(this);

dc.FillRect(CRect(m_ptOrigin,point),&brush);//用指定的画刷去填充矩形区域

8、使用位图画刷

CBitmap bitmap;//构造位图对象(使用前需要初试化)

bitmap.LoadBitmap(IDB_BITMAP1);//初试化位图对象

CBrush brush(&bitmap);//构造位图画刷

CClientDC dc(this);

dc.FillRect(CRect(m_ptOrigin,point),&brush);//用指定的位图画刷去填充矩形区域

9、使用透明画刷

CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//获取透明画刷对象指针

CClientDC dc(this);

CBrush *pOldBrush=dc.SelectObject(pBrush);//将透明画刷选入DC

dc.Rectangle(CRect(m_ptOrigin,point));

dc.SelectObject(pOldBrush);//释放透明画刷

10、注意点:

1)静态方法不属于某一个具体对象,而属于类本身,在类加载的时候就已经为类静态方法分配了代码去,故可用CBrush::FromHandle()形式调用。

2)静态方法中,不能引用非静态的数据成员和方法。

3)静态数据成员需要在类外单独做初始化,形式如: 变量类型 类名::变量名=初始值;


BeginPaint()/GetDC()/GetDCEx()区别:

相同点:都是活的客户区域dc(Driver Context)

不同点:BeginPain:活的dc是,同时将客户区域设置为无效的。而其它两个函数无此功能。

所谓无效区域,就是说在被设置为有效区域之前,不允许此区域再更新。

调用完成后处理过程:

BeginPaint必须调用EndPaint函数将无效设置为有效。

GetDC()/GetDCEx()两个函数后必须调用ReleaseDc释放Dc资源


分享到:
评论

相关推荐

    MFC GDI绘图基础

    一.关于GDI的基本概念 什么是GDI? .../* Mapping Modes */定义了DC中的坐标映射方式,包括以下常用函数: SetMapMode、SetViewportExtEx、SetViewportOrgEx、 SetWindowExtEx 、SetWindowOrgEx。

    C++MFC教程

    MFC借助C++的优势为Windows开发开辟了一片新天地,同时也借助ApplicationWizzard使开发者摆脱离了那些每次都必写基本代码,借助ClassWizard和消息映射使开发者摆脱了定义消息处理时那种混乱和冗长的代码段。...

    c++面试题基础分享.doc

    33.MFC中的消息响应机制是如何实现的 34.WM_COMMAND命令消息处理顺序 35.MFC序列化的概念 36.PeekMessage和GetMessage的主要区别 37.WIN32创建窗口程序基本函数 38.Windows中的系统消息循环占用CPU的疑问 39....

    滚动窗口的实现兼容DC实现图形的保存和再现

    如何让CDC上输出的文字、图形具有保持功能,集合类CPtrArray的使用,CPaintDC与CClientDC的区别与应用,OnPaint与OnDraw在CView中的关系及实现内幕,...元文件设备描述表的使用,如何利用兼容DC实现图形的保存和再现。

    VC之美化界面篇本文专题讨论VC中的界面美化,适用于具有中等VC水平的读者。读者最好具有以下VC基础:

    2. 熟悉Windows消息机制,熟悉MFC的消息映射和反射机制; 3. 熟悉OOP理论和技术; 本文根据笔者多年的开发经验,并结合简单的例子一一展开,希望对读者有所帮助。 1 美化界面之开题篇 相信使用过《金山毒霸》、...

    SetMapMode绘制动态曲线

    vc6.0MFC dc的映射模式的运用 SetMapMode,SetWindowOrg,SetViewportOrg,SetWindowExt,SetViewportExt 曲线的缩放与移动 双缓冲绘图的运用

    OpenGL 系统开发的源代码

    1.1.6 MFC环境下OpenGL单文档应用程序框架 1.2 OpenGL图形的实现方式 1.2.1 设备上下文DC与渲染上下文RC 1.2.2 OpenGL像素格式设置 1.2.3 OpenGL图形处理流程 1.2.4 OpenGL图形绘制方式 1.2.5 OpenGL...

    类似画图板的小程序-windows

    一般视图缩放的实现是通过DC的两个函数来实现:SetViewportExt和SetWindowExt,但是这两个函数只在MM_ISOTROPIC和MM_ANISOTROPIC这两种映射模式下有效果,而常用的带滚动条的视图类CScrollView却不支持这两种模式...

    vc++ 应用源码包_1

    MFC+消息循环贴图---金山毒霸界面 自绘控件实现。 MFCDemo DirectUI移植到MFC中实现。 MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得...

    vc++ 应用源码包_2

    MFC+消息循环贴图---金山毒霸界面 自绘控件实现。 MFCDemo DirectUI移植到MFC中实现。 MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得...

    vc++ 开发实例源码包

    MFC+消息循环贴图---金山毒霸界面 自绘控件实现。 MFCDemo DirectUI移植到MFC中实现。 MFCHtml 调用脚本 如题。 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们...

    VC++几何绘图实例

    VC++几何绘图实例,如何让CDC上输出的文字、图形具有保持功能,集合类CPtrArray的使用,CPaintDC与CClientDC的区别与应用,OnPaint与OnDraw在CView中的关系及实现内幕,滚动窗口的实现,坐标空间,映射方式,设备...

    vc++ 应用源码包_6

    MFC+消息循环贴图---金山毒霸界面 自绘控件实现。 MFCDemo DirectUI移植到MFC中实现。 MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得...

    vc++ 应用源码包_5

    MFC+消息循环贴图---金山毒霸界面 自绘控件实现。 MFCDemo DirectUI移植到MFC中实现。 MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得...

    vc++ 应用源码包_3

    MFC+消息循环贴图---金山毒霸界面 自绘控件实现。 MFCDemo DirectUI移植到MFC中实现。 MFCHtml 调用脚本 MFC使用COM加载WMI服务,另类获取系统服务详细 大家都知道,现在流行的检测硬件软件视乎很神秘,我们要获得...

Global site tag (gtag.js) - Google Analytics