三. 简单绘图--Windows编程课程学习笔记
2016-06-20 15:20
537 查看
3.1 MFC消息映射机制
首先新建一个单文档类型的MFC APPWizard(exe)工程,取名MyMFCApp。试完成左键消息的捕捉。在3.1.1 ClassWizard(类向导)
项目->类向导。有命令、消息、虚函数、成员变量、方法五个选项卡,此外,还可以添加类。
3.1.2 消息映射机制
用ClassWizard添加一个LButtonDown的响应函数,在源文件会增加以下代码。1) 消息响应函数原型
在MyMFCAppView.h中
// 生成的消息映射函数 protected: DECLARE_MESSAGE_MAP() public: afx_msg voidOnLButtonDown(UINT nFlags, CPoint point);
2) ON_WM_LBUTTONDOWN消息映射宏
在MyMFCAppView.cpp中
BEGIN_MESSAGE_MAP(CMyMFCAppView, CView) // 标准打印命令 ON_COMMAND(ID_FILE_PRINT,&CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview) ON_WM_LBUTTONDOWN() END_MESSAGE_MAP()
在BEGAIN_MESSAGE_MAP到END_MESSAGE_MAP()两个宏之间定义了CMyMFCApp类的消息映射表。作用是把WM_LBUTTONDOWN与OnLButtonDown关联。
3) 消息响应函数的定义
void CMyMFCAppView::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 MessageBox("Left button down!"); CView::OnLButtonDown(nFlags, point); }
在windows应用程序中,消息被放到消息队列,应用程序GetMessage取消息,DispatchMessage交给操作系统,后者调用应用程序的窗口过程函数,WndProc进行处理。该函数用switch-case进行判别并分类处理。
而MFC程序中,只要定义了与消息有关的三处信息,就可以实现消息的响应。
当收到一个消息,消息的第一个参数指明了与哪个窗口句柄相关,通过对照表,可以找到与之相关的C++对象指针。把这个指针传递给应用程序框架类的基类,后者调用一个名为WindowProc的函数。该函数在WinCore.cpp中。该函数是一个虚函数。调用了OnWndMsg函数。
LRESULTCWnd::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)) lResult = DefWindowProc(message, wParam,lParam); return lResult; }
OnWndMsg函数的处理过程:(1)首先判断消息是否有消息响应函数。判断方法是在相应窗口类中查找所需的消息响应函数。因为传递给WindowProc函数的事窗口子类指针,所以,OnWndMsg函数回到相应的子类头文件中查找,看看DECLARE_MESSAGE_MAP()宏上是否有消息响应函数的声明;再到子类源文件看看是否有相应的消息映射宏;(2)有消息响应函数则响应,没有则交给基类处理。
3.2 绘制线条
在CMyMFCAppView类添加一个类型为CPoint的m_ptOrigin私有成员。在CMyMFCAppView.cpp初始化为0。
m_ptOrigin = 0;
在OnLButtonDown函数中保存鼠标按下点的信息。
m_ptOrigin = point;
WM_LBUTTONUP消息添加响应函数。
(1)利用Platform SKD函数
HDChdc; hdc = ::GetDC(m_hWnd); ::MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y, NULL); ::LineTo(hdc, point.x, point.y); ::ReleaseDC(m_hWnd, hdc);
(2)利用MFC CDC类
CDC*pDC = GetDC(); pDC->MoveTo(m_ptOrigin); pDC->LineTo(point); ReleaseDC(pDC);
(3)利用CClientDC类
CClientDC dc(this); dc.MoveTo(m_ptOrigin); dc.LineTo(point);
(4)利用CWindowDC类
CWindowDC dc(this); dc.MoveTo(m_ptOrigin); dc.LineTo(point);
(5)在桌面窗口划线
CWindowDCdc(GetDesktopWindow()); ClientToScreen(&m_ptOrigin); dc.MoveTo(m_ptOrigin); ClientToScreen(&point); dc.LineTo(point);
因为客户区与桌面坐标转换问题的存在,需调用ClientToScreen函数。
(6)绘彩色线条
CPenpen(PS_SOLID, 5, RGB(255, 0, 0)); CClientDC dc(this); CPen*pOldPen = dc.SelectObject(&pen); dc.MoveTo(m_ptOrigin); dc.LineTo(point); dc.SelectObject(pOldPen);
当构造一个GDI对象后,该对象并不会立即生效,必须通过SelectObject函数选入设备描述表,它才会在以后的绘制操作中生效。在完成绘图操作之后,都要利用SelectObject把先前的GDI对象选入设备描述表,以便使其恢复到先前的状态。
3.3使用画刷画图
(1)绘制矩形填充块
CBrush brush(RGB(255, 0, 0)); CClientDC dc(this); dc.FillRect(CRect(m_ptOrigin,point), &brush);
(2)绘制位图填充块
CBitmap bmp; bmp.LoadBitmap(IDB_BITMAP1); CBrush brush(&bmp); CClientDC dc(this); dc.FillRect(CRect(m_ptOrigin,point), &brush);
(3)透明画刷
CPen pen(PS_SOLID, 5, RGB(255, 0, 0)); CClientDC dc(this); //CBrush*pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); //CBrush*pOldBrush = (CBrush*)dc.SelectObject(pBrush); CBrush* pOldBrush =(CBrush*)dc.SelectStockObject(HOLLOW_BRUSH); CPen* pOldPen = dc.SelectObject(&pen); dc.Rectangle(CRect(m_ptOrigin, point)); dc.SelectObject(pOldPen);
3.4 连续线条等
(1)连续线条
添加WM_MOUSEMOVE响应函数到View类中。补充函数。CClientDC dc(this); if (nFlags == MK_LBUTTON) { dc.MoveTo(m_ptOrigin); dc.LineTo(point); m_ptOrigin = point; }
也可以添加私有成员BOOL m_bDraw到View类,View构造时赋值为FALSE,WM_LBUTTONDOWN为TRUE,
CClientDC dc(this); if (m_bDraw == TRUE) { dc.MoveTo(m_ptOrigin); dc.LineTo(point); <span style="white-space:pre"> </span>m_bDraw = FALSE; m_ptOrigin = point; }
(2)扇形效果线条
添加私有成员CPoint m_btEnd到View类,OnLButtonDown赋值point。if (nFlags == MK_LBUTTON) { dc.MoveTo(m_ptOrigin); /* 3.4.1 连续线条 //dc.LineTo(point); //m_ptOrigin = point; */ // 3.4.2扇形 dc.LineTo(m_ptEnd); m_ptEnd = point; }
(3)橡皮筋技术
<span style="white-space:pre"> </span>//通过取反异或的模式擦除旧线条 dc.SetROP2(R2_NOTXORPEN); dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd); //绘制新线条 m_ptEnd = point; dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd);
相关文章推荐
- Visual C++中MFC消息的分类
- MFC中Radio Button的用法详解
- MFC对话框中添加状态栏的方法
- MFC创建右键弹出菜单的方法
- MFC中动态创建控件以及事件响应实现方法
- C++ 关于MFC多线程编程的注意事项
- MFC程序对文件的处理方法
- MFC自定义消息的实现方法
- MFC实现在文件尾追加数据的方法
- MFC之ComboBox控件用法实例教程
- MFC绘制不规则窗体的方法
- IE8引发 VS2005/2008 MFC向导出错的解决方案
- MFC实现全屏功能代码实例
- 使用VS2010创建MFC ActiveX工程项目
- C++中MFC Tab Control控件的使用详解
- MFC程序设计常用技巧汇总
- MFC扩展DLL中导出类和对话框的实现方法
- VC中SDK与MFC的区别浅析
- 浅谈MFC 改变控件大小和位置
- VC MFC非模态对话框的实现方法