`
javababy1
  • 浏览: 1169608 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

孙鑫MFC笔记教程(4)--MFC消息映射机制的剖析

 
阅读更多

1. 对应用程序(单文档程序)的窗口进行操作的时候,如点击鼠标,拖动鼠标等,所有的窗口消息应该在CView中捕获,而不能在MainFrame进行捕获,因为在文档-视图结构中,CView类总是覆盖在CMainFrm框架窗口之上的。

2. MFC的消息映射机制:

一般作为基类使用的CWnd类为Windows消息定义了大量窗口消息的缺省处理函数,这些函数大部分只是简单地调用了Windows的缺省过程,可以在派生类中对其进行重载。但是MFC应用程序框架却并没有象使用普通虚函数那样使用Windows消息处理函数,而是通过宏将指定的消息映射到派生类的成员函数。如果MFC仍象普通虚函数一样对消息响应函数进行处理,那么CWnd类就要为这上百个消息声明虚函数。而C++将为在程序中使用的每一个派生类都提供一个被称作vtable的虚拟函数分配表,这个分配表需要为每一个虚函数提供一个4字节的入口,而不管这些函数在派生类中是否真正被重载,这将不能有效利用存储空间。而且对于每一个不同类型的窗口或控件,应用程序都要为其提供一个超过400字节的虚拟函数分配表来实现对消息的响应。而采用 MFC的用宏将Windows消息映射到C++成员函数的方式则可避免产生庞大的虚拟函数分配表,其消耗的内存是同它所包含的消息入口数量成正比的

查看MFC的源代码:WINCORE.CPP

---------------------------------------------------------------------------------

LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

// OnWndMsg does most of the work, except for DefWindowProc call

LRESULT lResult = 0;

if (!OnWndMsg(message, wParam, lParam, &lResult))//真正的消息处理都是由OnWndMsg函数进行处理的

lResult = DefWindowProc(message, wParam, lParam);

return lResult;

}

---------------------------------------------------------------------------------

查看AFX_WIN.h

---------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------

MFC中维护了一张消息到窗口的对应表,当接收到一个消息后,通过消息的句柄,找到与其相关联的窗口对象的指针,然后传给CWnd::WindowProc函数,CWnd::WindowProc函数函数交由CWnd::OnWndMsg函数进行处理,判断子类是否有这个消息的响应函数,通过查看子类的头文件看有没有消息响应函数原型的声明,查看源文件,看有没有消息响应函数的定义.如果子类有,那么交由子类处理消息,如果子类没有,消息交由父类进行处理.

3. CDC相关类:

画线程序:

方法1Win32 GetDC实现

HDC hdc;

hdc=::GetDC(m_hWnd); //全局函数,所以需要::符号,SDK函数

MoveToEx(hdc,m_ptStart.x,m_ptStart.y,NULL); //设置操作起点

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

::ReleaseDC(m_hWnd,hdc);

方法2CDC实现,MFC封装了所有的绘图操作在CDC类中

//只能在CView区域画图

CDC *pDC=GetDC(); //注意此处的GetDC函数和上面的区别,此处为CWND成员

pDC->MoveTo(m_ptStart);

pDC->LineTo(point);

ReleaseDC(pDC);

方法3CClientDC实现,只能对客户区域操作

The CClientDC class is derived from CDC and takes care of calling the Windows functions "GetDC" at construction time and "ReleaseDC" at destruction time. This means that the device context associated with a CClientDC object is the client area of a window.

CClientDC dc(this); //参数为this表示访问的客户区域是CView

CClientDC dc(GetParent()); //参数是GetParent()表示CView的父窗口,即Frame窗口,框架类的客户区域为工具栏()以下

dc.MoveTo(m_ptStart);

dc.LineTo(point);

方法4CWindowDC实现,可对客户区和非客户区操作

CWindowDC dc(this); //CView区域操作

CWindowDC dc(GetParent()); //可对整个应用程序区域操作

CWindowDC dc(GetDesktopWindow()); //可对整个系统操作界面操作

dc.MoveTo(m_ptStart);

dc.LineTo(point);

注意:对CView之外的绘图区域操作,都是将CView区域模拟成客户区域,即画线动作只能在,CView区域只能,但画线结果可展现在期望区域中

附:MoveToLineToMSDN中的声明:

BOOL MoveToEx(
HDC hdc, // handle to device context
int X, // x-coordinate of new current position
int Y, // y-coordinate of new current position
LPPOINT lpPoint // old current position
);
BOOL LineTo(
HDC hdc, // device context handle
int nXEnd, // x-coordinate of ending point
int nYEnd // y-coordinate of ending point
);

4. CPen

CPen pen(PS_DASHDOT,1,RGB(255,0,0));

CClientDC dc(this);

CPen *pOldPen=dc.SelectObject(&pen); //将新的画笔选到设备描述表中;

dc.MoveTo(m_ptStart);

dc.LineTo(point);

dc.SelectObject(pOldPen); //将原先的画笔还原,以防止别地方使用错误的画笔

5. CBrush

一般用来填充某个封闭区域

a. 颜色画刷:
CBrush brush(RGB(255,0,0));
CClientDC dc(
this);
dc.FillRect(CRect(m_ptStart,point),&brush);
//因为是有参数可选(&brush),所以不需要选到设备描述表中(SelectStockObject

b. 位图画刷

CBitmap bmp;

bmp.LoadBitmap(IDB_BITMAP1); //参数为已有的位图的资源号,可以创建一张位图

CBrush brush(&bmp);

CClientDC dc(this);

dc.FillRect(CRect(m_ptStart,point),&brush);

c. 透明画刷

CClientDC dc(this);

//因为创建矩形时没有提供参数设置画刷类型,所以得考虑将默认的画刷替换掉

//FromHandle函数实现在句柄和指针之间的转化,像CPen也有该函数,另外FromHandle是一个静态方法,静态方法的调用采用::

CBrush *brush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

CBrush *pOldBrush=dc.SelectObject(brush);

dc.Rectangle(CRect(m_ptStart,point)); //发现如果两个矩形重叠,则后者会将前者部分区域覆盖,所以需要透明画刷

dc.SelectObject(pOldBrush); //还原

6. 设置绘图模式:

CDC::SetROP2Sets the current drawing mode.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics