MFC笔记——VC++深入详解(第3版)孙鑫
1、Windows下的程序都是基于消息的,窗口在创建时都会产生一个WM_CREATE消息。其他类可以响应这个消息,添加WM_CREATE消息的处理函数。
类视图——某个类处鼠标右键,属性——消息(找到WM_CREATE)。或者使用“类向导”。
2、文档/视类结构,视类窗口始终覆盖在框架类窗口之上,鼠标所有操作都只能由视类窗口捕获。如,CMainFrame中鼠标单击事件无反应,而在CDrawView中就有反应。
3、消息映射机制
消息映射表,由头文件的DECLARE_MESSAGE_MAP()、源文件的BEGIN_MESSAGE_MAP与END_MESSAGE_MAP构建而成。BEGIN_MESSAGE_MAP与END_MESSAGE_MAP之间,有消息映射宏,一旦有消息产生,程序就调用对应的消息响应函数来处理。
消息响应函数
4、画线,推荐方式三
/* 方式一:SDK // 首先获得窗口的设备描述表 HDC hdc; hdc = ::GetDC(m_hWnd); //当前窗口的设备描述表 //移动到线条的起点 MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y, NULL); //画线 LineTo(hdc, point.x, point.y); //释放设备描述表 ::ReleaseDC(m_hWnd, hdc); */ /* 方式二:MFC的CDC类,封装了所有与绘图相关的操作 CDC* pDC = GetDC(); pDC->MoveTo(m_ptOrigin); pDC->LineTo(point); ReleaseDC(pDC); */ 方式三:MFC的CClientDC类,CDC的进一步封装,省去GetDC与ReleaseDC CClientDC dc(this); //客户区范围 //CClientDC dc(GetParent()); //客户区+工具栏区 dc.MoveTo(m_ptOrigin); dc.LineTo(point); /* 方式四:MFC的CWindowDC类,也是派生自CDC,可画的范围更大 CWindowDC dc(this); //客户区范围 //CWindowDC dc(GetParent()); //客户区+工具栏区 //CWindowDC dc(GetDesktopWindow()); //所有窗口 dc.MoveTo(m_ptOrigin); dc.LineTo(point); */
5、画笔
CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); //PS_DASH、PS_DOT宽度≤1,虚线才有效 CClientDC dc(this); CPen* pOldPen = dc.SelectObject(&pen); //选择画笔 dc.MoveTo(m_ptOrigin); dc.LineTo(point); //推荐写上以下两行,不然可能造成GDI对象的增加,程序崩溃 dc.SelectObject(pOldPen); //重置画笔 pen.DeleteObject(); //释放画笔
6、画刷,一般用于填充
CBrush brush(RGB(255, 0, 0));//创建一个红色画刷 CClientDC dc(this); //创建并获得设备描述表 dc.FillRect(CRect(m_ptOrigin, point), &brush);//利用红色画刷填充鼠标拖曳过程中形成的矩形区域 brush.DeleteObject();
画刷画矩形,dc中有默认白色画刷。但是新的会覆盖旧的。透明矩形的实现。
/* 画矩形,dc中有默认白色画刷 CClientDC dc(this); dc.Rectangle(CRect(m_ptOrigin, point)); //绘制矩形,黑边白色填充 */ // 透明矩形,新的不遮蔽旧的 CClientDC dc(this);//创建并获得设备描述表 CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//创建一个空画刷 CBrush *pOldBrush = dc.SelectObject(pBrush);//将空画刷选入设备描述表 dc.Rectangle(CRect(m_ptOrigin, point));//绘制一个矩形 dc.SelectObject(pOldBrush);//恢复先前的画刷 pBrush->DeleteObject();
说明,CClientDC操作的都是对象而不是句柄。GetStockObject()获取画刷、画笔、字体的句柄。
将句柄转为对象,用画刷、画笔、字体类提供的FromHandle()函数。
7、绘制连续线条
鼠标移动消息WM_MOUSEMOVE,不断更新起始点,不断在起始点与最新点之间画非常短的线段。
void CDrawView::OnMouseMove(UINT nFlags, CPoint point) { CClientDC dc(this); CPen pen(PS_SOLID, 1, RGB(255, 0, 0));//创建一个红色的、宽度为1的实线画笔 CPen *pOldPen = dc.SelectObject(&pen);//把创建的画笔选入设备描述表 if (m_bDraw == TRUE) //鼠标按下开始,抬起结束 { dc.MoveTo(m_ptOrigin); dc.LineTo(point); m_ptOrigin = point;//修改线段的起点 } dc.SelectObject(pOldPen);//恢复设备描述表 pen.DeleteObject(); CView::OnMouseMove(nFlags, point); }
8、窗口重绘
当窗口创建时、尺寸发生变化时,都会调用OnDraw()。防止文字等内容在窗口重绘时消失,可以将代码写在OnDraw()中。