正文

令人费解的MFC客户区2008-11-11 14:39:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/miaowei/39345.html

分享到:

    估计很多人都会遇到这么一个问题,平时我们用单文档/视图结构时,很容易就在客户区画个图,画根线什么的,然而,要在对话框的某个控件中画这些东西,刚一上来,还真有点搞吧。

    下面,我就把在对话框中对某个控件画图的程序先列出来,然后再看看微软的一些搞的地方。

初始化:

m_IsDrawing=false;
 CWnd*pCanvas=GetDlgItem(IDC_CANVAS);
 pCanvas->GetWindowRect(&m_Canvas);
 ScreenToClient(&m_Canvas);

void CPaintORamaDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 /////////////////////////////////////////
 //Add code
 //---------------------------------------
 if(m_Canvas.PtInRect(point))
 {
  m_IsDrawing=true;
  m_LineStart=point;
  SetCapture();

 }


}

void CPaintORamaDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 //////////////////////////////////////////////
 //Add Code
 //------------------------------------------
 m_IsDrawing=false;
 ReleaseCapture();


}

void CPaintORamaDlg::OnMouseMove(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
 ////////////////////////////////////////
 //Add Code
 //-----------------------------------------------
 if(m_Canvas.PtInRect(point))
 {
 if(m_IsDrawing && (nFlags&MK_LBUTTON))
 {
  CClientDC dc(this);
  dc.MoveTo(m_LineStart);

  dc.LineTo(point);

  m_LineStart=point;
 }
 }
}

 

首先,说明一点的是,通过鼠标单击或者移动传进来的CPoint是一个客户坐标,在文档/视图程序中,也就是客户区,用GetClientRect可以获得该区域。而在对话框中,CPoint还是表示客户区,只不过这个时候这个客户区就是整个的对话框自己,整个对话框就是客户区。必须通过this->GetClientRect来获取,它的top和left都是0。right和botton分别是该对话框的宽与高。

这时,假如我们想在对话框中的某个控件画图,按照我们的想法,获取该控件的窗口以及它的DC,然后我们就可以画图了,实际不是这样的,中间还需要一次转换,请看下面代码:

1   CRect lpRect;

2   CStatic *m_static = (CStatic*)GetDlgItem(IDC_STATIC1);

3   m_static->GetClientRect(&lpRect);

4   CDC *pDC = m_static->GetDC();

5   pDC->MoveTo(CPoint point);

6   pDC->Ellipse(...);

等等

上面的这些操作有以下问题,

1. 第三句中,通过GetClientRect来获取客户区,我们知道该函数是获取窗体的客户区,那么上面第三句就是获得该控件的客户区,它的top和left都为0,right和botton是宽和高。然而,前面我们说过,通过鼠标传入的CPoint是一个以整个对话框为客户区的客户区坐标,即它是以整个对话框的左上顶角点作为坐标原点计算的。所以这两者根本无法联系在一起,所以也就不能在该控件上画出这个点了。

这时,我们想起了另一个函数, GetWindowRect(),可是,这个函数只可以用来获取控件的屏幕坐标。即使用它也还是不能在控件上画出该点。对了,转换呀,我们可以用ScreenToClient,用这个函数可以将控件的坐标lpRect转换成以对话框左上顶点为原点的控件客户区坐标。 这样,就和传入的CPoint的坐标一致了。

真是搞的,微软何不提供一个直接获取控件在对话框客户区中的位置坐标呢,非要这么绕干嘛呢!

2.  第四句和第五句的问题,获取该控件的DC,然后画图,这是人的正常思维,可是微软不这么干,如果像上面这么画,将什么也画不出来,按照微软的想法,只有客户区才能画图,所以,还是要先老老实实的得到客户区的DC,可是,对话框程序中的客户区就是对话框本身呀,唉,没办法,还是先得到这个客户区吧。

CClientDC dc(this); 这里应该明白前面的控件和传入点为什么都要用以对话框左上顶点为原点的客户区坐标了吧。这样就可以让对话框DC来画它们了。

上面这段代码可以修改为如下:

 

    CRect lpRect;

    CStatic *m_static = (CStatic*)GetDlgItem(IDC_STATIC1);

    m_static->GetWindowRect(&lpRect);

    ScreenToClient(&lpRect);  

     CClientDC dc(this);

     dc.MoveTo(CPoint point);

     dc.LineTo(CPoint point);

     .......

好了,就这些见识了,高手们有补充或者修正的地方,请不吝赐教。好好学习,天天向上。

阅读(10521) | 评论(4)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册