一、MFC绘图
1.相关问题
WIN32 - HDC
MFC - CDC类对象
2.相关类
(1)CDC类 - 父类CObject,封装了关于绘图的各种API函数,还封装了成员变量m_hDC(保存绘图设备句柄)
(2)CDC类的子类
CClientDC - 封装了在客户区中绘图的绘图设备,::GetDC
CWindowDC - 封装了在整个窗口中绘图的绘图设备,::GetWindowDC
CPaintDC - 封装了在WM_PAINT消息中绘图的绘图设备,::BeginPaint
相关代码:在视图中处理菜单消息,绘图
void CT23_MFCCDCView::OnClient() { CClientDC dc(this); dc.TextOutW(0, 0, L"MFCCDCView::OnClient");//里面其实调的WIN32函数 //WIN32实现 //::TextOut(dc.m_hDC, 100, 100, L"MFCCDCView::OnClient", strlen("MFCCDCView::OnClient")); } void CT23_MFCCDCView::OnWindow() { CWindowDC dc(AfxGetApp()->m_pMainWnd); dc.TextOutW(10, 330, L"MFCCDCView::OnWindow");//里面其实调的WIN32函数 //WIN32实现 //::TextOut(dc.m_hDC, 0, 330, L"MFCCDCView::OnClient", strlen("MFCCDCView::OnClient")); } void CT23_MFCCDCView::OnPaint() { CPaintDC dc(this); dc.TextOutW(0, 0, L"MFCCDCView::OnPaint"); }
运行结果:
(3)CGDIObjecct - 父类CObject,封装了了成员变量m_hObject(保存了相应GDI绘图对象句柄)
(4)CGDIObject的子类
CPen - 封装了画笔的使用
CBrush - 封装画刷的使用
CFont - 封装了字体的使用
CBitmap - 封装了位图的使用
CRgn - 封装了关于复合(不规则)图形的绘制
a.将简单基本图像通过运算,构建一个复杂的集合运算
b.使用
利用一些列CRgn::CreateXXX,创建基本图形
利用CRgn::CombineRgn将基本图形通过指明的运算进行组合
填充复合图形
相关代码:在视图中处理菜单消息,绘图
void CT24_MFCGDIView::OnBmp() { CClientDC dc(this); CBitmap bmp; bmp.LoadBitmapW(IDB_BITMAP1); //CDC memdc; //memdc.CreateCompatibleDC(&dc); //CBitmap *oldBmp = memdc.SelectObject(&bmp); //dc.BitBlt(100, 100, 48, 48, &memdc, 0, 0, SRCCOPY); //memdc.SelectObject(oldBmp); //bmp.DeleteObject(); //memdc.DeleteDC(); //WIN32实现 HDC memdc = ::CreateCompatibleDC(dc.m_hDC); HGDIOBJ oldBmp = ::SelectObject(memdc, bmp.m_hObject); ::BitBlt(dc.m_hDC, 100, 100, 48, 48, memdc, 0, 0, SRCCOPY); ::SelectObject(memdc, oldBmp); ::DeleteObject(bmp.m_hObject); ::DeleteObject(memdc); } void CT24_MFCGDIView::OnBrush() { CClientDC dc(this); //CBrush brush( RGB(0, 255, 0) ); //实心画刷 CBrush brush(HS_CROSS, RGB(0, 255, 0)); //虚线画刷 CBrush *oldBrush = dc.SelectObject(&brush); dc.Rectangle(50, 50, 250, 250); dc.SelectObject(oldBrush); brush.DeleteObject(); //WIN32实现 //HGDIOBJ hOldBrush = ::SelectObject(dc.m_hDC, brush.m_hObject); //Rectangle(dc.m_hDC, 100, 100, 300, 300); //::SelectObject(dc.m_hDC, hOldBrush); //brush.DeleteObject(); } void CT24_MFCGDIView::OnFont() { CClientDC dc(this); CFont font; font.CreatePointFont(300, L"黑体"); CFont *oldFont = dc.SelectObject(&font); dc.TextOutW(100, 100, L"用黑体字体画"); dc.SelectObject(oldFont); font.DeleteObject(); } void CT24_MFCGDIView::OnPen() { CClientDC dc( this ); CPen pen( PS_SOLID, 10, RGB(255,0,0) ); CPen *oldPen = dc.SelectObject(&pen); dc.Rectangle(50, 50, 250, 250); dc.SelectObject(oldPen); pen.DeleteObject(); //WIN32实现 //HGDIOBJ hOldPen = ::SelectObject(dc.m_hDC, pen.m_hObject); //Rectangle(dc.m_hDC, 100, 100, 300, 300); //::SelectObject(dc.m_hDC, hOldPen); //::DeleteObject(pen.m_hObject); } void CT24_MFCGDIView::OnRgn() { CRgn rgn1; rgn1.CreateEllipticRgn(50, 50, 250, 250); CRgn rgn2; rgn2.CreateEllipticRgn(150, 150, 350, 350); //rgn1.CombineRgn(&rgn1, &rgn2, RGN_AND); //rgn1此时代表复合图形 //rgn1.CombineRgn(&rgn1, &rgn2, RGN_OR); rgn1.CombineRgn(&rgn1, &rgn2, RGN_XOR); CBrush brush(RGB(0,255,0)); CClientDC dc(this); dc.FillRgn(&rgn1, &brush); }
运行结果:
(1)画笔
(2)画刷
(3)字体
(4)位图
(5)复合图形
二、练习:实现简易的画图工具
::SetCapture - 捕获鼠标
::ReleaseCapture - 释放鼠标
int ::SetRop2( HDC hdc, //绘图设备句柄
int fnDrawMode ); //R2_NOT取反色
相关代码:
CPoint ptStart; //图形的起点 CPoint ptCur; //图形的当前点 int g_kind = 0; void CT25_MFCDrawView::OnPen() { g_kind = 1; } void CT25_MFCDrawView::OnLine() { g_kind = 2; } void CT25_MFCDrawView::OnRect() { g_kind = 3; } void CT25_MFCDrawView::OnEll() { g_kind = 4; } void CT25_MFCDrawView::OnLButtonDown(UINT nFlags, CPoint point) { ::SetCapture(this->m_hWnd); ptStart = point; ptCur = point; CView::OnLButtonDown(nFlags, point); } void CT25_MFCDrawView::OnLButtonUp(UINT nFlags, CPoint point) { ::ReleaseCapture(); CView::OnLButtonUp(nFlags, point); } void CT25_MFCDrawView::OnMouseMove(UINT nFlags, CPoint point) { CClientDC dc(this); if (nFlags & MK_LBUTTON) //鼠标左键按下 { if (1 == g_kind)//铅笔 { dc.MoveTo(ptStart); dc.LineTo(point); ptStart = point;//起点随时在变 } else if (2 == g_kind)//直线 { dc.SetROP2(R2_NOT); dc.MoveTo(ptStart);//覆盖前一次的线 dc.LineTo(ptCur); dc.MoveTo(ptStart); dc.LineTo(point); ptCur = point; } else if (3 == g_kind)//矩形 { dc.SetROP2(R2_NOT); HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH); HBRUSH hOldBrush = (HBRUSH)::SelectObject(dc.m_hDC, hBrush); dc.Rectangle(ptStart.x, ptStart.y, ptCur.x, ptCur.y); dc.Rectangle(ptStart.x, ptStart.y, point.x, point.y); ptCur = point; ::SelectObject(dc.m_hDC, hOldBrush); } else//圆形 { dc.SetROP2(R2_NOT); HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH); HBRUSH hOldBrush = (HBRUSH)::SelectObject(dc.m_hDC, hBrush); dc.Ellipse(ptStart.x, ptStart.y, ptCur.x, ptCur.y); dc.Ellipse(ptStart.x, ptStart.y, point.x, point.y); ptCur = point; ::SelectObject(dc.m_hDC, hOldBrush); } } CView::OnMouseMove(nFlags, point); }
运行结果: