基于消息的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资源
分享到:
相关推荐
实验六的目的是让开发者熟悉Visual C++ 6.0的开发环境,并掌握MFC消息映射机制的基本原理和手动添加消息映射的方法。通过实现按下CTRL键绘制矩形、按下SHIFT键绘制椭圆的功能,可以深入了解消息处理的过程。 首先,...
总的来说,MFC菜单响应事件是通过消息映射机制将用户在菜单上的操作转化为代码执行的过程。在绘图应用程序中,这个过程使得我们可以根据用户的指令在窗口上绘制出各种图形,为用户提供直观的交互方式。通过理解并...
MFC提供了预定义的消息映射机制,允许开发者捕获和响应这些事件。例如,可以通过重写OnMouseMove()、OnLButtonDown()等函数来处理鼠标移动和点击事件,然后根据这些事件更新图形。同时,也可以使用CWnd类的OnChar()...
MFC中的GDI绘图涉及到Windows编程中的图形设备接口(GDI)和设备环境(DC)的概念,以及MFC框架中对这些概念的封装和支持。GDI是Windows操作系统提供的一种接口,允许开发者创建图形和文本,将其绘制在屏幕上或者...
在MFC中,还可以通过消息映射机制响应用户交互,如鼠标点击事件,以实现动态绘图。例如,可以添加一个成员变量记录鼠标位置,并在鼠标按下和移动时更新画布。 ```cpp // 在头文件中添加成员变量 CPoint m_lastPoint...
此外,MFC的绘图示例可能还会涉及消息映射(message mapping)、事件处理函数、视图类和文档类的交互等内容。通过分析和运行这个示例,你可以深入理解MFC框架的工作原理,以及如何在实际项目中利用它进行图形界面的...
2. **消息处理**:MFC应用程序基于消息驱动模型,因此我们需要重载或添加消息映射函数来处理各种用户交互,如鼠标点击、移动和释放,以及键盘输入。 3. **几何图形绘制**:使用CDC(Device Context)类,我们可以...
这涉及到消息映射、对象的创建和管理、以及在事件处理函数中更新图形的逻辑。 最后,标签中提到了"VC++",这是Visual C++的简称,它是微软的C++集成开发环境,包含了一个强大的IDE和调试工具,支持MFC和其他C++库,...
8. **内存DC和位图**:为了实现平滑的绘图,可能需要使用内存设备上下文和位图。在`OnMouseMove()`中,我们可以先在内存DC上绘图,然后将位图一次性复制到屏幕DC,避免频繁的屏幕刷新导致闪烁。 综上所述,创建一个...
MFC是基于事件驱动的,理解并熟练使用消息映射和消息处理函数是实现高效绘图控件的基础。 9. **自定义控件**: 如果标准的MFC控件不能满足需求,可以创建自定义的CWnd派生类,扩展其功能以适应高速绘图的要求。 ...
7. **内存DC和画刷**:为了提高绘图性能和避免闪烁,可以使用内存设备上下文(`CClientDC`)和临时画刷。首先在内存DC上绘制,然后一次性将内存DC的内容复制到屏幕上的对话框DC。 8. **测试和优化**:编译并运行...
MFC使用消息映射机制处理用户的交互事件。在CView或派生类中,通过ON_WM_LBUTTONDOWN、ON_WM_MOUSEMOVE、ON_WM_LBUTTONUP等宏定义处理鼠标点击、移动和释放事件,根据这些事件的参数进行相应的绘图操作。 7. **...
为了实现画图功能,我们需要重写消息映射函数,处理 WM_PAINT 和 WM_MOUSEMOVE 消息。WM_PAINT 用于首次显示画图板,而 WM_MOUSEMOVE 用于处理鼠标移动时的绘图操作。在消息映射中,添加如下代码: ```cpp ON_WM_...
这将涉及到对MFC控件的使用,以及处理消息映射和事件响应。 此外,对于更深入的MFC学习,可以探索以下主题: 1. **对话框(Dialog)**:MFC支持创建模态和非模态对话框,可以用来收集用户输入或展示信息。 2. **...
3. **注册消息映射**:确保在MFC的消息映射中包含了`ON_WM_PAINT()`,以便当控件需要重绘时,`OnPaint`消息能被正确处理。同时,由于我们自定义了`OnDraw`,还需要包含`ON_WM_ERASEBKGND()`来避免不必要的背景擦除。...
- **消息处理**:MFC中的消息映射机制允许我们响应用户的鼠标和键盘事件,如WM_LBUTTONDOWN、WM_MOUSEMOVE和WM_LBUTTONUP,实现选择、拖动等交互功能。 - **状态栏和菜单**:MFC提供了CStatusBar和CMenu类,方便...
MFC 中的绘图对象类包括 CBrush、CPen、CFont、CBitmap、CPalette 和 CRgn,它们分别封装了 GDI 中的刷子、画笔、字体、位图、调色板和区域对象。这些类使得程序员可以方便地创建、修改和使用这些绘图对象,进行复杂...
5. **事件处理**:MFC的CWinApp和CWnd类提供了处理用户输入的机制。例如,你可以重写OnMouseMove()来处理鼠标移动事件,更新模型视图矩阵以实现交互式旋转;OnKeyDown()和OnKeyUp()处理键盘输入,改变茶壶的大小或...
总之,通过结合`SETEVENT`定时器的精确计时、`OnTimer`的事件驱动机制以及内存DC的无闪烁绘图,MFC使得动态波形显示成为可能,同时还能提供直观的参数调整界面,增强了用户体验。这样的技术在许多科学和工程应用中都...
首先,我们要理解MFC中的绘图机制。在MFC应用程序中,通常通过重写`OnPaint()`函数来进行自定义绘图。`OnPaint()`函数是当窗口需要重绘时被调用的,我们可以在其中使用设备上下文对象(CDC)进行绘图操作。 颜色...