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

3. CDC相关类:

画线程序:

方法1:Win32 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);

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

//只能在CView区域画图

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

pDC->MoveTo(m_ptStart);

pDC->LineTo(point);

ReleaseDC(pDC);

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

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的父窗口,252即Frame窗口,框架类的客户区域为工具栏(含)以下

dc.MoveTo(m_ptStart);

dc.LineTo(point);

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

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

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

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

dc.MoveTo(m_ptStart);

dc.LineTo(point);

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

附:MoveTo和LineTo在MSDN中的声明:

BOOL M

异常的分类

oveToEx(
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::SetROP2,Sets the current drawing mode.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值