基于对话框的简单双缓冲绘图框架

简介: 基于文档视图结构程序的双缓冲绘图框架比较多,那么如何在对话框上绘图呢?以前通常的做法是拖一个静态文本控件或其它控件当作绘图区域或者在这个区域上创建一个视图出来。看了微软的一个示例程序DrawCli(一个绘图的单文档程序),产生了一些灵感,决心把它移植到对话框绘图上,摸索了一下,搞了一个基于对话框的简单双缓冲绘图框架。

   基于文档视图结构程序的双缓冲绘图框架比较多,那么如何在对话框上绘图呢?以前通常的做法是拖一个静态文本控件或其它控件当作绘图区域或者在这个区域上创建一个视图出来。看了微软的一个示例程序DrawCli(一个绘图的单文档程序),产生了一些灵感,决心把它移植到对话框绘图上,摸索了一下,搞了一个基于对话框的简单双缓冲绘图框架。


     具体代码如下,对话框头文件代码:


    

[cpp]   view plain copy
  1. #include <vector>  
  2. //@brief 直线结构体  
  3. struct stLine  
  4. {  
  5.     stLine(CPoint &Begin,CPoint &End)  
  6.     {  
  7.         m_Begin = Begin;  
  8.         m_End = End;  
  9.     }  
  10.     //@brief 起点  
  11.     CPoint m_Begin;  
  12.     //@brief 终点  
  13.     CPoint m_End;  
  14. };  
  15. class CDoubleBufDrawDlg : public CDialog  
  16. {  
  17.     DECLARE_DYNAMIC(CDoubleBufDrawDlg)  
  18. public:  
  19.     CDoubleBufDrawDlg(CWnd* pParent = NULL);   // 标准构造函数  
  20.     virtual ~CDoubleBufDrawDlg();  
  21. // 对话框数据  
  22.     enum { IDD = IDD_DIALOG_GDIPLUS };  
  23. protected:  
  24.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持  
  25.     DECLARE_MESSAGE_MAP()  
  26. public:  
  27.     virtual BOOL OnInitDialog();  
  28.     afx_msg void OnBnClickedDrawPoint();  
  29.     afx_msg void OnBnClickedDrawLine();  
  30.     afx_msg void OnSize(UINT nType, int cx, int cy);  
  31.     void AdjustControls();  
  32.     afx_msg void OnPaint();  
  33. protected:  
  34.     //   
  35.     void InitDrawPara();  
  36. protected:  
  37.     //@brief 上一个点  
  38.     CPoint m_PrePt;  
  39.     //@brief 鼠标按下点  
  40.     CPoint m_DownPt;  
  41.     //@brief 直线结构体数组  
  42.     std::vector<stLine> m_Lines;  
  43. public:  
  44.     afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
  45.     afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
  46.     afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
  47. };   

 



    Cpp文件源码(这里只列出主要函数):


   

[cpp]   view plain copy
  1. //@brief 初始化绘图参数  
  2. void CDoubleBufDrawDlg::InitDrawPara()  
  3. {  
  4.     m_PrePt = CPoint(-1,-1);  
  5.     m_DownPt = CPoint(-1,-1);  
  6. }  
  7. CDoubleBufDrawDlg::CDoubleBufDrawDlg(CWnd* pParent /*=NULL*/)  
  8. : CDialog(CDoubleBufDrawDlg::IDD, pParent)  
  9. {  
  10.     InitDrawPara();  
  11. }  
  12. void CDoubleBufDrawDlg::OnLButtonDown(UINT nFlags, CPoint point)  
  13. {  
  14.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  15.     // 记录鼠标按下点  
  16.     m_DownPt = point;  
  17.     CDialog::OnLButtonDown(nFlags, point);  
  18. }  
  19. void CDoubleBufDrawDlg::OnMouseMove(UINT nFlags, CPoint point)  
  20. {  
  21.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  22.     // 假如在移动鼠标的同时按下左键  
  23.     if (MK_LBUTTON&nFlags)  
  24.     {  
  25.         CDC *pDC = GetDC();  
  26.         pDC->SetROP2(R2_NOTXORPEN);  
  27.     // 将绘图区域限制在对话框的客户区上面的/4区域  
  28. CRect rtDraw(rtClient.top,rtClient.left,rtClient.Width(),3*(rtClient.Height()/4));  
  29.     CRgn DrawRgn;  
  30.     DrawRgn.CreateRectRgn(rtDraw.left,rtDraw.top,rtDraw.right,rtDraw.bottom);  
  31.     pDC->SelectClipRgn(&DrawRgn);  
  32.         if (m_PrePt.x!=-1)  
  33.         {  
  34.             // 擦除上一条线  
  35.             pDC->MoveTo(m_DownPt);  
  36.             pDC->LineTo(m_PrePt);  
  37.         }  
  38.         // 画线  
  39.         pDC->MoveTo(m_DownPt);  
  40.         pDC->LineTo(point);  
  41.         ReleaseDC(pDC);  
  42.         m_PrePt = point;  
  43.     }  
  44.     CDialog::OnMouseMove(nFlags, point);  
  45. }  
  46. void CDoubleBufDrawDlg::OnLButtonUp(UINT nFlags, CPoint point)  
  47. {  
  48.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  49.     // 将绘制的直线加入到直线数组  
  50.     m_Lines.push_back(stLine(m_DownPt,point));  
  51.     // 初始化绘图参数  
  52.     InitDrawPara();  
  53.     CDialog::OnLButtonUp(nFlags, point);  
  54. }  
  55. void CDoubleBufDrawDlg::OnPaint()  
  56. {  
  57.     // 最小时绘制菜单图标,因为我是在一个单文档程序中弹出该对话框的,故不需要绘制图标  
  58.     // 如果是基于对话框的程序则需要绘制图标  
  59.     if (IsIconic())  
  60.     {  
  61.         CPaintDC dc(this); // device context for painting  
  62.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);  
  63.         // Center icon in client rectangle  
  64.         //int cxIcon = GetSystemMetrics(SM_CXICON);  
  65.         //int cyIcon = GetSystemMetrics(SM_CYICON);  
  66.         //CRect rect;  
  67.         //GetClientRect(&rect);  
  68.         //int x = (rect.Width() - cxIcon + 1) / 2;  
  69.         //int y = (rect.Height() - cyIcon + 1) / 2;  
  70.         //// Draw the icon  
  71.         //dc.DrawIcon(x, y, m_hIcon);  
  72.     }  
  73.     else  
  74.     {  
  75.         CPaintDC dc(this);  
  76.         // 定义一个兼容DC  
  77.         CDC CompaDC;  
  78.         // 初始化绘图DC指针  
  79.         CDC* pDrawDC = &dc;  
  80.         CBitmap bitmap;  
  81.         CBitmap* pOldBitmap = 0;  
  82.         CRect rtClient;  
  83.         GetClientRect(&rtClient);  
  84.         // 将对话框的客户区上面的/4区域设为绘图区域  
  85.         CRect rtDraw(rtClient.top,rtClient.left,rtClient.Width(),3*(rtClient.Height()/4));  
  86.         // 假如不是打印机DC  
  87.         if (!dc.IsPrinting())  
  88.         {  
  89.             // 创建兼容DC,创建兼容位图,将兼容位图选进兼容DC  
  90.             if (CompaDC.CreateCompatibleDC(&dc))  
  91.             {  
  92.                 if (bitmap.CreateCompatibleBitmap(&dc,rtDraw.Width(),rtDraw.Height()))  
  93.                 {  
  94.                     pDrawDC = &CompaDC;  
  95.                     pOldBitmap = CompaDC.SelectObject(&bitmap);  
  96.                 }  
  97.             }  
  98.         }  
  99.         // 定义一个白色画刷,将背景色设为白色  
  100.         CBrush brush;  
  101.         if (!brush.CreateSolidBrush(RGB(255,255,255)))  
  102.             return;  
  103.         brush.UnrealizeObject();  
  104.         pDrawDC->FillRect(rtDraw,&brush);  
  105.         // 绘制直线  
  106.         for (size_t i = 0;i<m_Lines.size();i++)  
  107.         {  
  108.             pDrawDC->MoveTo(m_Lines[i].m_Begin);  
  109.             pDrawDC->LineTo(m_Lines[i].m_End);  
  110.         }  
  111.         // 使用GDI+绘制一个线性渐变画刷  
  112.         Gdiplus::Graphics graphics(pDrawDC->m_hDC);  
  113.         LinearGradientBrush linGrBrush(Point(100,0),Point(100,100),Color(255,255,0,0),Color(255,0,255,0));  
  114.         Color colors[] = {  
  115.             Color(255, 255, 0, 0),   // red  
  116.             Color(255, 255, 255, 0), //yellow  
  117.             Color(255, 0, 0, 255),   // blue  
  118.             Color(255, 0, 255, 0)};  // green  
  119.             REAL positions[] = {  
  120.                 0.0f,     
  121.                 0.33f,     
  122.                 0.66f,  
  123.                 1.0f};    
  124.                 linGrBrush.SetInterpolationColors(colors, positions,4);  
  125.                 // 填充指定区域矩形  
  126.                 graphics.FillRectangle(&linGrBrush,100,0,100,100);  
  127.                 graphics.ReleaseHDC(pDrawDC->m_hDC);  
  128.                 if (pDrawDC != &dc)  
  129.                 {  
  130.                     // 将绘图DC贴到真正的设备DC上  
  131.                     dc.BitBlt(rtDraw.left,rtDraw.top,rtDraw.Width(),rtDraw.Height(),&CompaDC, 0, 0, SRCCOPY);  
  132.                     CompaDC.SelectObject(pOldBitmap);  
  133.                 }  
  134.     }  
  135. }   

 


    效果图如下,其中上面的白色区域为绘图区域:


Dlg Double Buf



    现在你怎么改变对话框的大小绘图区域也不会产生非双缓冲绘图那种闪烁。

目录
相关文章
|
13天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
11455 124
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
2天前
|
人工智能 JSON 监控
Claude Code 源码泄露:一份价值亿元的 AI 工程公开课
我以为顶级 AI 产品的护城河是模型。读完这 51.2 万行泄露的源码,我发现自己错了。
3470 8
|
1天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
1333 2
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
12天前
|
人工智能 IDE API
2026年国内 Codex 安装教程和使用教程:GPT-5.4 完整指南
Codex已进化为AI编程智能体,不仅能补全代码,更能理解项目、自动重构、执行任务。本文详解国内安装、GPT-5.4接入、cc-switch中转配置及实战开发流程,助你从零掌握“描述需求→AI实现”的新一代工程范式。(239字)
7467 139
|
2天前
|
云安全 供应链 安全
Axios投毒事件:阿里云安全复盘分析与关键防护建议
阿里云云安全中心和云防火墙第一时间响应
1144 0
|
3天前
|
人工智能 自然语言处理 数据挖掘
零基础30分钟搞定 Claude Code,这一步90%的人直接跳过了
本文直击Claude Code使用痛点,提供零基础30分钟上手指南:强调必须配置“工作上下文”(about-me.md+anti-ai-style.md)、采用Cowork/Code模式、建立标准文件结构、用提问式提示词驱动AI理解→规划→执行。附可复制模板与真实项目启动法,助你将Claude从聊天工具升级为高效执行系统。
|
2天前
|
人工智能 定位技术
Claude Code源码泄露:8大隐藏功能曝光
2026年3月,Anthropic因配置失误致Claude Code超51万行源码泄露,意外促成“被动开源”。代码中藏有8大未发布功能,揭示其向“超级智能体”演进的完整蓝图,引发AI编程领域震动。(239字)
2152 9
|
11天前
|
人工智能 并行计算 Linux
本地私有化AI助手搭建指南:Ollama+Qwen3.5-27B+OpenClaw阿里云/本地部署流程
本文提供的全流程方案,从Ollama安装、Qwen3.5-27B部署,到OpenClaw全平台安装与模型对接,再到RTX 4090专属优化,覆盖了搭建过程的每一个关键环节,所有代码命令可直接复制执行。使用过程中,建议优先使用本地模型保障隐私,按需切换云端模型补充功能,同时注重显卡温度与显存占用监控,确保系统稳定运行。
2555 9