mfc中绘图要用设备上下文才可以完成。
绘图基础
1。api
HDC hdc = ::GetDC(m_hWnd);
用api函数可以获得设备上下文句柄。m_hWnd是CWnd类对象的句柄。使用完后要调用ReleaseDC(m_hWnd, hdc)来释放。
2。MFC
CDC
CDC *pdc = GetDC();
CDC类封装了绘图相关的所有操作。在哪个CWnd子类中调用,就获得哪个类的设备上下文。同样要调用ReleaseDC来释放
CClientDC
CClientDC dc(this); //获取当前所在CWnd子类的设备上下文
CClientDC继承自CDC,它可以指定获得哪个CWnd对象的设备上下文,但只能得到程序的客户区。例如:
CButton cBtn;
CClientDC dc(&cBtn); //获得按钮的设备上下文,会在按钮上作图。
CClientDC dc(GetParent());
//GetParent()函数可以获得父类的句柄,(CWnd的成员函数)如果此句语在CView子类中,那么将得到对应CFrame子类的设备上下文
注意:
1。要知道是获得的哪个窗口对象的设备上下文,即在谁上面绘图
2。使用CClientDC时有客户区域的概念,CView子类的客户区域只在中间的白色view区。CFrame子类的客户区可以包括工具栏,但不包括菜单和标题栏。
CWindowDC
CWindowDC wdc(GetDesktopWindow());
//与CClientDC不同,它可以获得整个桌面的设备上下文。
//GetDesktopWindow() 也是CWnd的成员函数,获得整个桌面的设备上下文句柄
当然在构造时,要取得整个桌面的句柄才可以,如果CWindowDC wdc(this); 和CClientDC的效果是一样的。
绘图修饰
上图是设备修饰相关的几个对象,都从CGDIObject类继承。设备选用时都可以用dc.SelectObject(cp);这个函数进行选择,它返回旧的修饰对象。比如调用SelectObject装载CPen对象, 就会返回一个原来的CPen对象。
CPen
CPen cp(PS_DOT, 1, RGB(255, 200, 80));
。CPen只修饰线条,比如画线,但对dc.TextOut(...)不没有作用。
CClientDC dc(this);
CPen cp(PS_DOT, 10, RGB(255, 200, 80));
CPen *poldPen = dc.SelectObject(cb);
dc.MoveTo(20, 0);
dc.LineTo(20, 20);
dc.SelectObject(poldPen);
注意在dc选择CPen以后,会返回旧的CPen对象。在使用完后,要重新赋给DC
CBrush
CBrush cb(RGB(255, 200, 80));
。CBrush只修饰填充,比如画一个矩形,CPen负责边框,CBrush负责填充 。
CClientDC dc(this);
CPen cp(PS_DOT, 10, RGB(2, 100, 30));
CBrush cb(RGB(255, 200, 80));
dc.SelectObject(cp);
dc.SelectObject(cb);
dc.Rectangle(0, 0, 80, 80);
创建空画刷
可以利用GetStockObject来取得一些已经定义样式的Brush, Pen, Font的句柄
再利用CBrush对象的函数FromHandle根据一个brush句柄,返回一个brush对象
CClientDC dc(this);
CBrush *br;
br = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
dc.SelectObject(br);
dc.Rectangle(0, 0, 80, 80);
dc.Rectangle( 20, 40, 120, 200);
CBitMap
CBitmap bm;
bm.LoadBitmap(IDB_BITMAP1);
。可以根据资源ID获取位图
。可以用CBitmap修饰CBrush, 再用CBrush去绘图,而不是直接用CBitMap去修饰CDC
CClientDC dc(this);
CBitmap bm;
bm.LoadBitmap(IDB_BITMAP1);
CBrush cb(&bm);
dc.SelectObject(cb);
dc.Rectangle(0, 0, 80, 80);