好久没搞MFC,复习下知识。

CPaintDC 、CWindowDC、 CClientDC、 CDC

关系图:

一句话概括:

CPaintDC            无效区dc,      相当于BeginPaint,   EndPaint
CClientDC          客户区dc,      相当于GetDC,   ReleaseDC
CWindowDC      整窗口dc,      相当于GetWindowDC,   ReleaseDC
CDC                     任何dc,          相当于CreateDC,   DeleteDC

一、CPaintDC

Mfc自动生成的OnPaint函数都会定义一个CPaintDC类型的变量。

如:

void CXXXXXX::OnPaint()
{CPaintDC dc(this); // device context for painting// TODO: Add your message handler code here// Do not call CView::OnPaint() for painting messages
}
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
void CXXXXDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // device context for paintingSendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// Center icon in client rectangleint 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 icondc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}
}

MSDN上的解释:

The CPaintDC class is a device-context class derived from CDC. It performs a CWnd::BeginPaint at construction time and CWnd::EndPaint at destruction time.

(翻译:CPaintDC继承自CDC,它在构造函数中执行CWnd::BeginPaint,在析构函数中调用CWnd::EndPaint)

CPaintDC object can only be used when responding to aWM_PAINT message, usually in yourOnPaint message-handler member function.

(翻译:CPaintDC对象通常当响应WM_PAINT消息时在OnPaint消息处理函数中被使用。)

题外话,这个英文按照中国人的逻辑来说应该这样表达:

when responding to a WM_PAINT message, a CPaintDC object can only be used usually in yourOnPaint message-handler member function.

二、CClientDC

MSDN上的解释:

The CClientDC class is derived from CDC and takes care of calling the Windows functionsGetDC at construction time andReleaseDC at destruction time. This means that the device context associated with aCClientDC object is the client area of a window.

(翻译:CClientDC继承自CDC,它在构造函数中调用GetDC,在析构函数中调用ReleaseDC.这意味着与CClientDC对象联系的DC是窗口的客户区。)

三、CWindowDC

The CWindowDC class is derived from CDC. It calls the Windows functionsGetWindowDC at construction time andReleaseDC at destruction time. This means that aCWindowDC object accesses the entire screen area of aCWnd (both client and nonclient areas).( 翻译:获取整个屏幕区域,包括客户区和非客户区。)

CSDN:

CPaintDC只能在OnPaint()中使用,CClientDC只和客户区有关,可以在任何地方使用。

CPaintDC代表整个窗口,而CClientDC代表窗口的客户区(不包括标题栏、边框),要选择合适的DC进行绘制。

CPaintDC一般是用在OnPaint()函数里的。CPaintDC对象一构造,消息队列中的WM_PAINT会被取走,而CClientDC是用在非OnPaint()函数里画图的。

用CClientDC时WM_PAINT消息没有从消息队列中清除,CPaintDC结束时会自动清除该消息。

CPaintDC是一个特殊的设备环境封闭类,它主要处理windows的wm_paint消息。CClientDC可以自动调用GetDC和ReleaseDC函数。CwindowDC是从CDC类继承,用于得到桌面窗口设备环境指针。

CclinetDC用于窗口客户区,CwindowDC用于整个窗口,包括非客户区。

在OnPaint中用CPaintDC仅仅对需要刷新的地方进行重绘。

> 往一个对话框上画图,在OnPaint()里是不是只能用   CPaintDC?
恰恰相反,CPaintDC是推荐只用在OnPaint中的。诚如   i_noname(晚九朝五)   所言:“它的范围是WM_PAINT消息所要重画的区域大小”,因为这个类的构造函数中调用了BeginPaint,析构函数中调用了EndPaint。这两个API是针对WM_PAINT消息使用的,所以不要把CPaintDC用在非对WM_PAINT消息响应的函数中。

https://blog.csdn.net/arcsinsin/article/details/9861003

鼠标响应关键就是对两个函数进行操作:OnLButtonDown和OnLButtonUp;

1、使用MFC AppWizard(exe)建立一个单文档MFC工程

2、首先要在CxxxView类的定义里加上后续必备的数据成员

class CDrawView : public CView
{
。。。。。。。。。。。。
private:
 CPoint m_ptOrigin;      //用来记录鼠标按下时的点          
 BOOL m_bDraw;           //鼠标按下的标志,用来判断鼠标弹起来了没有
 CPoint m_ptOld;         //用来记录鼠标的移动路劲
};

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) //鼠标按下
{
  MessageBox("Haibara Ai");            //鼠标一按下就会送出消息(以对话框形式)
  m_ptOrigin=m_ptOld=point;            //将当前鼠标按下的位置用m_ptOrigin记录
  m_bDraw=TRUE;                        //将鼠标按下标志置为TURE
  CView::OnLButtonDown(nFlags, point); //函数自调用,循环检测。nFlags 表示控制键状态

//(包括 ctrl,shift,鼠标左、中、右共5个键的状态)
                                        //point表示鼠标坐标。(相对于当前窗口而言的坐标)

}

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point) //鼠标弹起
{

//鼠标画直线方式一
 HDC hdc;                         //先定义一个HDC对象:Handler to a device context(DC),指向一个DC(设备描述表)的句柄
 hdc=::GetDC(m_hWnd);//“::”用全局的函数(即SDK中的函数)

MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);   //由原点(0,0)移动到起点(即鼠标按下点)
 LineTo(hdc,point.x,point.y);                                         //由当前位置移动到坐标点(x,y)(即鼠标弹起点);
 ::ReleaseDC(m_hWnd,hdc);                                       //释放DC

//鼠标画直线方式二

CWnd::GetDC

CDC* GetDC( );

Return Value

Identifies the device context for the CWnd client area if successful; otherwise, the return value is NULL. The pointer may be temporary and should not be stored for later use.

CDC *pDC=GetDC();                      //获取一个CDC类对象的指针
 pDC->MoveTo(m_ptOrigin);
 pDC->LineTo(point);
 ReleaseDC(pDC);

//鼠标画直线方式三
// CClientDC dc(this);                                  //在客户区画直线
 CClientDC dc(GetParent());                      //在框架窗口上画直线
 dc.MoveTo(m_ptOrigin);
 dc.LineTo(point);

//鼠标画直线方式四

// CWindowDC dc(this);                                 //在客户区画直线
// CWindowDC dc(GetParent());                   //在框架窗口上画直线
   CWindowDC dc(GetDesktopWindow());  //在整个桌面面板上画直线
   dc.MoveTo(m_ptOrigin);
   dc.LineTo(point);

//鼠标画直线方式五(画笔)

CPen pen(PS_SOLID,20,RGB(255,0,0));        //创建一个笔(CPen类封装了跟画笔相关的操作)

//(线型,线粗,线色)
 CClientDC dc(this);                                                //创建一个DC
 CPen *pOldPen=dc.SelectObject(&pen);           //将笔选到设备描述表中
 dc.MoveTo(m_ptOrigin);
 dc.LineTo(point);
 dc.SelectObject(pOldPen);

//鼠标响应画矩形(画刷)
 CBrush brush(RGB(255,0,0));                //创建画刷,红色
 CClientDC dc(this);                          //创建一个dc
 dc.FillRect(CRect(m_ptOrigin,point),&brush); //用一个指定画刷填充一个指定的区域,
                    //第一个参数用于设定这个区域,用画线时保存下来的起点和终点来设定这个区域

//运行结果是:我们的dc在用我们所创建的红色的画刷去填充了一块矩形的区域

//用位图对象填充鼠标画出的矩形框图
CBitmap  bitmap;              //首先定义一个位图
 bitmap.LoadBitmap(IDB_BITMAP1); //用资源的ID加载这个位图
 CBrush  brush(&bitmap);   //有了这个位图之后,就可以创建这个位图的画刷,形参为这个位图对象的指针
 CClientDC dc(this);                              //然后创建一个dc                            
 dc.FillRect(CRect(m_ptOrigin,point),&brush);     //用这个指定的画刷(位图画刷)去填充一块矩形区

///创建透明画刷,即空画刷    /

CClientDC dc(this);   
 CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
 //注意这里,GetStockObject函数返回的是一个HGDIOBJ
 //的一个句柄,需要用强制转换将其转换为画刷的句柄
 //(HBRUSH)GetStockObject(NULL_BRUSH)
 //FromHandle是CBrush类的静态成员函数(见MSDN),所以可以直接由类名调用
 CBrush *pOldBrush=dc.SelectObject(pBrush);     //将画刷选到我们的设备描述表中,

//用空画刷去替换我们先前的画刷(缺省画刷、默认画刷)
 dc.Rectangle(CRect(m_ptOrigin,point));         //DC当中用来画矩形矩形的一个函数
 dc.SelectObject(pOldBrush);                   //回到画刷替换前的默认画刷
  m_bDraw=FALSE;                  //鼠标弹起标志,将m_bDraw置为FALSE

CView::OnLButtonUp(nFlags, point);
}

//鼠标移动响应函数,应用在画曲线方面

void CDrawView::OnMouseMove(UINT nFlags, CPoint point)  //point为函数获取的当前鼠标所在位置的坐标

//它会鼠标的移动而不断改变值
{
    CClientDC dc(this);                   //创建一个DC,指向当前窗口(客户区)
    dc.SetROP2(R2_BLACK);                 //设置绘画模式
    CPen pen(PS_SOLID,1,RGB(255,0,0));    //设置画笔(线型、线宽、线颜色)
    CPen  *pOldPen=dc.SelectObject(&pen); //将画笔选到设备描述表中
 if(m_bDraw==TRUE)
 {

///
  ///画曲线
  dc.MoveTo(m_ptOrigin); //移动到起始点 
  dc.LineTo(point);       //画线到,注意这里的每一次画线都是很短的。很短的多次画线就得到了曲线
  m_ptOrigin=point;       //将终点设为下一次画线的起点。。。。这样不断循环,直到鼠标弹起,跳出循环结束画线。
  //

//
  ///画扇形线
  dc.MoveTo(m_ptOrigin); //定下起点不变 
  dc.LineTo(point);    
  //

//
  //画带边线的扇形线
  dc.MoveTo(m_ptOrigin);    //定下起点不变 
  dc.LineTo(point);          //开始画线
  dc.LineTo(m_ptOld);        //在线的终点处引线到另一条线的终点
  m_ptOld=point;             //将上一条线的终点寄存下,以待下一条线划下时,将终点与之相连。  
  //

}

dc.SelectObject(pOldPen);   //回到画刷替换前的默认画笔

CView::OnMouseMove(nFlags, point);//函数自调用,循环检测。nFlags 表示控制键状态

//(包括 ctrl,shift,鼠标左、中、右共5个键的状态)
                                   //point表示鼠标坐标。(相对于当前窗口而言的坐标)

Windows DC 画线相关推荐

  1. 用CFree写的Windows SDK 画线程序

    1 新建窗口程序 纯C语言: 2 添加代码 在文件头部加入四个变量, POINT startPoint; POINT endPoint; int m_LineWidth; //线宽 COLORREF ...

  2. windows应用(vc++2022)MFC基础到实战(4)-画线程序

    目录 CWnd 对象 画图程序 新建MFC项目 鼠标位置成员变量 类向导增加消息处理函数 扩展画线功能 LineTo 函数 (wingdi.h) 两种常用画线方式 移动鼠标擦除和绘制线 继续扩展 CW ...

  3. VC++ 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor

    目录 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor 接上:VC++ 绘制线条 OnLButtonDown函数 ...

  4. c c++ 画点 画线

    c++ 画点 画线 http://hi.baidu.com/xulei1143/item/73c7340dc9cf0231a3332a26 c http://zhidao.baidu.com/link ...

  5. 使用MFC画线(初学)

    使用MFC在单文档上划线(初学) MFC的画线 在Visual Studio 2019中新建MFC应用,选单个文档,去掉所有高级功能后创建 直接执行,则有 1.鼠标按下响应 (1)在类向导中 (2)代 ...

  6. VC/MFC动态画线(橡皮线),画圆,画椭圆,画矩形

    2012年12月7日 22:42:14 今天我在csdn网站上通过学习别人的博客学习到了动态画矩形,画线的方法,这使得我对Windows的消息循环机制有了更深刻的理解.首先来总结一下我今天的收获,呵呵 ...

  7. JAVA实现中点画线_实验1-中点画线和Bresenham画线算法的实现

    <实验1-中点画线和Bresenham画线算法的实现>由会员分享,可在线阅读,更多相关<实验1-中点画线和Bresenham画线算法的实现(9页珍藏版)>请在人人文库网上搜索. ...

  8. matlab画线不同颜色_怎样画线框图才有意义?

    本文由 Jonathan 译自 https://medium.muz.li/how-to-succeed-in-wireframe-design-2ab3cd5c4bc9 我们常轻忽身边习以为常的事物 ...

  9. matlab画线不同颜色_怎样画线框图才有意义

    我们常轻忽身边习以为常的事物,觉得没有必要为一些看似简单又可有可无的东西浪费时间--例如线框图.虽然没必要凡事都寻根问底,但当面对复杂问题时,脚踏实地回归基本面也许才是根本解法. 本文章深入介绍程序开 ...

最新文章

  1. opencv函数copyto的用法
  2. DOM-based XSS Test Cases
  3. python【蓝桥杯vip练习题库】ADV-103逆序排列
  4. FastReport使用
  5. python中dict的fromkeys用法
  6. 陕西活性炭需求分析_20212027年中国粉末活性炭行业市场发展现状调研与投资趋势前景分析报告...
  7. HDU 2757 Ocean Currents
  8. 流程图用计算机if怎么写,if语句流程图
  9. java 8 兼容_甲骨文限制 Java 9 到 Java 8 的向后兼容性
  10. django和scrapy创建项目命令
  11. Python游戏开发入门3 Pygame屏幕绘制机制
  12. Pycharm汉化使用教程
  13. Perl脚本常用操作
  14. 离散数学(第二版) 第一章、第二章习题
  15. 信息系统项目管理师 pdf_如何备考信息系统项目管理师?
  16. android int 字节数组,android 将int转byte,byte转int的两种方法
  17. cursor android,Android Cursor用法
  18. eclipse 中使用@slf4j报log找不到
  19. Halium 9 尝鲜 -- 在小米平板4上的移植 (六)
  20. 【Linux】文件查找、权限设置以及综合应用

热门文章

  1. Mac 查看本机ip
  2. [z]WPF中使用amCharts绘制股票K线图
  3. ubuntu安装无线网卡---tenda311mi
  4. 【七夕特别的礼物】都快2022了,你还只会用麒麟软件商店装软件?
  5. java算法思绪_疆场景算法(Java实现)
  6. DOM系列之自定义属性操作
  7. Hadoop3.3.0入门到架构篇之一
  8. 带自动收录批量验证简洁的福利网址导航源码
  9. Oracle:时间类型
  10. android系统方法裁剪图片部分手机显示为圆形