作者:朱金灿
来源:http://blog.csdn.net/clever101/
基于文档视图结构程序的双缓冲绘图框架比较多,那么如何在对话框上绘图呢?以前通常的做法是拖一个静态文本控件或其它控件当作绘图区域或者在这个区域上创建一个视图出来。看了微软的一个示例程序DrawCli(一个绘图的单文档程序),产生了一些灵感,决心把它移植到对话框绘图上,摸索了一下,搞了一个基于对话框的简单双缓冲绘图框架。
具体代码如下,对话框头文件代码:
#include
Cpp文件源码(这里只列出主要函数):
//@brief 初始化绘图参数 void CDoubleBufDrawDlg::InitDrawPara() { m_PrePt = CPoint(-1,-1); m_DownPt = CPoint(-1,-1); } CDoubleBufDrawDlg::CDoubleBufDrawDlg(CWnd* pParent /*=NULL*/) : CDialog(CDoubleBufDrawDlg::IDD, pParent) { InitDrawPara(); } void CDoubleBufDrawDlg::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 // 记录鼠标按下点 m_DownPt = point; CDialog::OnLButtonDown(nFlags, point); } void CDoubleBufDrawDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 // 假如在移动鼠标的同时按下左键 if (MK_LBUTTON&nFlags) { CDC *pDC = GetDC(); pDC->SetROP2(R2_NOTXORPEN); // 将绘图区域限制在对话框的客户区上面的/4区域 CRect rtDraw(rtClient.top,rtClient.left,rtClient.Width(),3*(rtClient.Height()/4)); CRgn DrawRgn; DrawRgn.CreateRectRgn(rtDraw.left,rtDraw.top,rtDraw.right,rtDraw.bottom); pDC->SelectClipRgn(&DrawRgn); if (m_PrePt.x!=-1) { // 擦除上一条线 pDC->MoveTo(m_DownPt); pDC->LineTo(m_PrePt); } // 画线 pDC->MoveTo(m_DownPt); pDC->LineTo(point); ReleaseDC(pDC); m_PrePt = point; } CDialog::OnMouseMove(nFlags, point); } void CDoubleBufDrawDlg::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 // 将绘制的直线加入到直线数组 m_Lines.push_back(stLine(m_DownPt,point)); // 初始化绘图参数 InitDrawPara(); CDialog::OnLButtonUp(nFlags, point); } void CDoubleBufDrawDlg::OnPaint() { // 最小时绘制菜单图标,因为我是在一个单文档程序中弹出该对话框的,故不需要绘制图标 // 如果是基于对话框的程序则需要绘制图标 if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle //int cxIcon = GetSystemMetrics(SM_CXICON); //int cyIcon = GetSystemMetrics(SM_CYICON); //CRect rect; //GetClientRect(&rect); //int x = (rect.Width() - cxIcon + 1) / 2; //int y = (rect.Height() - cyIcon + 1) / 2; //// Draw the icon //dc.DrawIcon(x, y, m_hIcon); } else { CPaintDC dc(this); // 定义一个兼容DC CDC CompaDC; // 初始化绘图DC指针 CDC* pDrawDC = &dc; CBitmap bitmap; CBitmap* pOldBitmap = 0; CRect rtClient; GetClientRect(&rtClient); // 将对话框的客户区上面的/4区域设为绘图区域 CRect rtDraw(rtClient.top,rtClient.left,rtClient.Width(),3*(rtClient.Height()/4)); // 假如不是打印机DC if (!dc.IsPrinting()) { // 创建兼容DC,创建兼容位图,将兼容位图选进兼容DC if (CompaDC.CreateCompatibleDC(&dc)) { if (bitmap.CreateCompatibleBitmap(&dc,rtDraw.Width(),rtDraw.Height())) { pDrawDC = &CompaDC; pOldBitmap = CompaDC.SelectObject(&bitmap); } } } // 定义一个白色画刷,将背景色设为白色 CBrush brush; if (!brush.CreateSolidBrush(RGB(255,255,255))) return; brush.UnrealizeObject(); pDrawDC->FillRect(rtDraw,&brush); // 绘制直线 for (size_t i = 0;i
效果图如下,其中上面的白色区域为绘图区域:
现在你怎么改变对话框的大小绘图区域也不会产生非双缓冲绘图那种闪烁。