MFC绘图2-客户区大小和DC

心已入冬 提交于 2019-11-30 14:11:29
MFC绘图2-客户区大小和DC

 客户区大小和DC
在绘图前,必须先得到客户区大小和设备上下文DC。
1.获得客户区
绘图一般都是在视图窗口的客户区进行,而客户区的大小在运行时可由用户改变,为了使绘制的图形能随窗口大小自动改变,必须先得到当前客户区大小的数据(宽w和高h)。
获取客户区大小的方法有如下两种:
1)在消息响应函数OnSize中获得
利用属性窗口的信息页,在视图类中添加WM_SIZE消息的响应函数OnSize。该函数在窗口第一次显示或窗口大小被改变时会被Windows系统调用。其输入参数中的cx和cy就是客户区大小的宽和高,可将它们赋值给类变量(如m_iW和m_iH)供绘图时使用。例如
void CDrawView::OnSize(UINT nType, int cx, int cy) {
      CView::OnSize(nType, cx, cy);

      // TODO: 在此处添加消息处理程序代码
      m_iW = cx; m_iH = cy;
}
其中,nType的值为:
<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXIMIZED(窗口已被最大化)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MINIMIZED(窗口已被最小化)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_RESTORED(窗口已被改变大小)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXHIDE(其他窗口被最大化)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXSHOW(其他窗口从最大化还原)

2)调用成员函数GetClientRect得到
可在绘图前,定义一个矩形变量rect,然后再调用CWnd类的成员函数GetClientRect:
void GetClientRect( LPRECT lpRect ) const;

得到当前客户区矩形的数据,其中的右(right)与底(bottom)就是客户区的宽与高(其左left与顶top都为0)。例如:
       RECT rect;
       GetClientRect(&rect);
       int w = rect.right, h = rect.bottom;
2.DC
在Windows中,绘图使用的是MFC的DC(Device-Context, 设备上下文)类CDC中各种绘图函数。

0)CDC类
CDC是CObject的直接派生类,CDC类自己也有若干派生类,其中包括窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响应函数的输入参数中使用的CPaintDC类、图元文件对应的 CMetaFileDC类和整个窗口所对应的CWindowDC类。
CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等,将在后面陆续加以介绍。
1)获得DC
可以从OnDraw函数的输入参数pDC或调用CWnd的成员函数GetDC:
CDC* GetDC( );

来获得DC的指针。
2)释放DC
因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源。因此,对每次获得的DC,在使用完成后必须立即释放。
从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。但由GetDC所获得的DC,必须自己来释放,这可以通过调用CWnd的成员函数ReleaseDC来完成:
int ReleaseDC( CDC* pDC ); // 成功返回非0

例如:
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{
       ReleaseCapture();
       if (m_bLButtonDown) {
              CDC* pDC = GetDC();
              pDC->SelectObject(new CPen(PS_SOLID, 0, RGB(255, 0, 0)));

              pDC->SelectStockObject(NULL_BRUSH);
              pDC-> Ellipse (rect);
              ReleaseDC(pDC);
              m_bLButtonDown = FALSE;
       }
       CView::OnLButtonUp(nFlags, point);
}
3)类DC
每次从OnDraw函数的输入参数或调用GetDC所获得的DC,都是一个全新的临时缺省DC。它不能用类变量来长期保存,而且原来选入的各种GDI对象全都被作废,必须从头再来。
为了使选入的各种GDI对象一直有效,必须在视图类的PreCreateWindow函数中调用CWnd类的成员函数AfxRegisterWndClass:
LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0,
HBRUSH hbrBackground = 0, HICON hIcon = 0 );

来修改窗口类的风格属性中的DC为类DC:CS_CLASSDC。如
BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs) {
    cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW |

CS_VREDRAW | CS_CLASSDC, 0,

::CreateSolidBrush(RGB(255, 255, 255)));
       return CView::PreCreateWindow(cs);

}
4)安全DC句柄
也可以用CDC类的成员函数:
HDC GetSafeHdc();

来获取CD所对应窗口(如客户区)的安全DC句柄,该句柄在窗口存在期间一直是有效的。例如,可先定义类变量HDC m_hDC;,再在适当的地方给它赋值m_hDC = GetDC()->GetSafeHdc();,然后就可以放心地使用了。例如,可以使用CDC类的成员函数

BOOL Attach(HDC hDC); // 成功返回非0

来将CDC对象与DC句柄连接在一起。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!