您的位置:首页 > 编程语言 > C语言/C++

孙鑫vc++ 第四课 笔记 MFC消息映射机制及CDC的使用

2007-05-23 22:36 288 查看
MFC消息映射机制的剖析,掌握设备描述表及其封装类CDC的使用

同样笔记也是没有整理过的,如果有错误,请你告诉我,谢谢^_^

1、mfc在后台维护了一个句柄,以及程序各个类的句柄映射表,当我门在某个窗口上操作产生消息,该消息携带一个该窗口的句柄,通过该句柄找到该对象的指针,由窗口类传至父类,再由父类通过消息循环调用一个CWnd::WindowProc()
WindowProc()是一个虚函数,每个从CWnd继承的子类都有这样一个虚函数
WindowProc()调用了一个OnWndMsg(),该函数完成了主要的消息映射的处理
OnWndMsg()会辨别消息的种类,随后根据传过来的隐含的this指针来到类.h消息宏(DECLARE_MESSAGE_MAP()之上)查找有无对应的消息处理函数原形的声明,然后到类.cpp中的消息映射表(BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP())中寻找有没有对应的处理函数,最终调用消息处理函数

2、每个继承于CWnd的窗口类中都维护着一个窗口句柄m_hWnd,要在该类中使用该类窗口的句柄,直接使用m_hWnd即可

3、用api画线
HDC hdc=::GetDC(m_hWnd); //GetDC()要传入窗口句柄,返回dc句柄
MoveToEx(hdc,oldpoint.x,oldpoint.y,NULL); //dc句柄,移至坐标,移动时上一坐标(不用就NULL)
LineTo(hdc,point.x,point.y); //dc句柄,终点坐标
::ReleaseDC(m_hWnd,hdc); //窗口句柄,dc句柄,每次画完后一定要释放dc

4、mfc把所有的窗口操作都封装到cwnd类中,把所有做图的操作封装到cdc类中
CDC : CObject

5、cdc类中也维护着一个与该dc相关的句柄m_hDc

6、用mfc 的cdc类画线,同样也是4句,简单了许多,没有了传递窗口句柄m_hDc的操作,因为类内有维护
CDC *pDC=GetDC();//CWnd::GetDC(),原CView没有这个函数,当然就用父类的了,其中也传递了m_hDc
pDC->MoveTo(oldpoint);//MoveTo()是cdc的成员函数
pDC->LineTo(point);
ReleaseDC(pDC); //这里当然也是父类cwnd的了

7、CClientDC : CDC : CObject
CClientDC 类在构造函数和析构函数中分别调用了GetDC()和ReleaseDC()

8、用CClientDC画线,更简单了
CClientDC dc(this); //传入窗口类指针,构造函数原形:CClientDC(CWnd* pwnd)
dc.MoveTo(oldpoint);
dc.LineTo(point);

注意不同的类的构造函数的参数,有的是窗口句柄HWND,有的是类对象指针CWnd*,你想到了什么?
this 换成 getparent()呢,当然就是在框架客户区内画图了

9、CWindowDC : CDC : CObject
CWindowDC 类在构造函数和析构函数中分别调用了GetWindowDC()和ReleaseDC()
CWindowDC 可以访问整个屏幕,包括客户区和非客户区,即标题栏等

10、用CWindowDC画线
CWindowDC dc(this); //传入窗口类指针,构造函数原形:CWindowDC(CWnd* pwnd)
dc.MoveTo(oldpoint);
dc.LineTo(point);

这样,参数换成getparent()时,就能画到标题栏去了
参数换成getdesktopwindow()时,就能画到窗口外面去了

sdk函数返回的一般是句柄,::Get****() ,使用api相应就配合使用sdk函数
mfc函数返回的一般是指针,Get****() ,使用mfc相应就配合使用mfc函数

11、设备描述表中缺省的画笔是黑色的
CPen 最常用的一个构造函数是CPen(类型,宽度,颜色);

CDC::SelectObject 构造函数,看了你是不是明白了很多东西
CPen* SelectObject(CPen* pPen); //返回的是先前的画笔,这样可以保存原画笔以用于还原
CBrush* SelectObject(CBrush* pBrush);
CBitmap* SelectObject(CBitmap* pBitmap);
virtual CFont* SelectObject(CFont* pFont);

用自己的颜色画线
CClineDC dc(this);
CPen pen(PS_SOLID,1,RGB(255,0,0)); //构造画笔
CPen *pOldPen = dc.SelectObject(&pen); //将新画笔选入dc,替换原画笔,用返回值保存原画笔
dc.MoveTo(oldpoint);
dc.LineTo(point);
dc.SelectObject(pOldPen); //还原原画笔

12、画刷用来填充一个矩形
CBrush::CBrush 构造函数
CBrush(COLORREF crColor);
CBrush(int nIndex, COLORREF crColor);
CBrush(CBitmap* pBitmap);

CBrush brush(RGB(255,0,0));
CClienDC dc(this);
dc.FillRect(CRect(oldpoint,point),&brush); //FillRect()用画刷填充矩形

因为是用指定的画刷填充指定的矩形区域,所以并不需要把画刷选入设备描述表dc当中?什么?

用位图画刷填充矩形
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bitmap);
CClienDC dc(this);
dc.FillRect(CRect(oldpoint,point),&brush); //FillRect()用画刷填充矩形
结果位图在指定范围内平铺填充,注意,这里用的都是画刷的“对象”及其“指针”

CBitmap::CBitmap
CBitmap(); //构造函数只有一个,没有任何参数,只能在初始化参数中对其初始化
LoadBitmap(....);等等,有的类构造函数可以初始化,有的要用初始化函数初始化,不同,注意

CRect::CRect
CRect();
CRect(int l,int t,int r,int b);
CRect(const RECT& srcRect);
CRect(LPCRECT lpSrcRect);
CRect(POINT point, SIZE size);
CRect(POINT topLeft, POINT bottomRight);

13、透明画刷
CBrush并没有提供透明画刷构造函数,所以要用其他办法
HGDIOBJ GetStockObject(int fnObject);//该sdk函数可以获取画刷,画笔,字体等等句柄,其中包括有黑、白、透明画刷的句柄,可是mfc绘图函数中用的是画刷对象或者指针,怎么办呢
另外,GetStockObject()获取的句柄类型是HGDIOBJ,如何将该句柄转化为cdc用的类型HBRUSH呢,强制转换

CBrush::FromHandle //画刷类中有一个成员函数可以做到这一点
static CBrush* PASCAL FromHandle(HBRUSH hBrush); //可以把一个画刷句柄返回为一个画刷指针

CClienDC dc(this);
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush *pOldBrush=dc.selectObject(pBrush); //将画刷选入dc,替换原画刷,保存原画刷指针
dc.Rectangle(oldpoint,point); //Rectangle()画矩形
dc.selectObject(pOldBrush);

在上上上面的例子中,我们并没有将画刷选入dc中,是因为调用的dc使用画刷的绘图函数中已经将画刷选入其中
dc.FillRect(CRect(oldpoint,point),&brush);
但这里或者上上上上上上面的例子需要用selectObject()选入画刷,是因为函数中没有指定画刷
dc.Rectangle(oldpoint,point);

我靠,看到这里,我终于明白了!!!

14、奇怪的调用方法
CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
以前用过的类成员调用方法,生成实例对象,用. ,生成对象指针并指向某一空间,用->
这个方法可以用于静态成员,但不能用于非静态成员,因为静态成员不属于任何一个实例对象,它只属于所属的类,当类被加载的时候,该静态成员就已经分配了代码区了,而类内非静态成员只属于某个对象,因此在对象没有建立起来,没有实例化的时候,静态成员是无法使用非静态成员的,所以,如果在静态成员函数中使用非静态成员对象,就会报错
反过来,非静态成员函数是可以调用静态成员的,静态成员变量可以被访问,但静态成员变量定义时必须初始化
但如果访问了非静态成员的静态成员函数没有在主程序中被调用,则不会报错
===》一个对象一段代码能用,必须在内存中存在了该对象或代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: