VC 获取控件在对话框中的坐标

VC如何获取对话框中控件的坐标

GetWindowRect是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置。

    GetClientRect取得窗口客户区(不包括非客户区)在客户区坐标系下的RECT坐标,可以得到窗口的大小,而不能得到相对屏幕的位置,它的top和left都为0,right和botton是宽和高,因为这个矩阵是在客户区坐标系下(相对于窗口客户区的左上角)的。  

    ClientToScreen把客户区坐标系下的RECT坐标转换为屏幕坐标系下的RECT坐标.

    ScreenToClient把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标.     我们对同一个窗口先GetWindowRect取得一个RECT,再用ScreenToClient转换到客户坐标系。然后GetClientRect取得一个RECT,再用ClientToScreen转换到屏幕坐标系。显然,GetWindowRect取得的矩阵不小于GetClientRect取得的矩阵。因为前者包含了非客户区,而后包括了客户区。


所以要获得一个控件再对话框中的坐标的实现代码是:

CRect lpRec; 
GetDlgItem(IDC_SLIDER_output)->GetWindowRect(&lpRec); 
ScreenToClient(&lpRec);

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

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

初始化:

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);

     .......

MFC中,class CRect : public tagRECT类的一个成员函数,作用是判断参数中给出的点是否在矩形区域内。returns TRUE if point is within rectangle。

  [函数原型]
  BOOL PtInRect( POINT point ) const throw( );
  [声明]
  Declare Function PtInRect Lib "user32" (lpRect As RECT, pt As POINTAPI) As Long
  [说明]
  这个函数判断指定的点是否位于矩形lpRect内部
  [参数表]
  point ------------- POINTAPI,欲判断的点
  [返回值]
  Long,非零表示点在矩形内部,零表示点在矩形外部。会设置GetLastError
  [其它]
  如点位于矩形四边之内,或矩形的顶部或左侧边线上,则认为它在矩形内部。如位于矩形的右侧或底部边线,则不认为它在矩形内部


包括:

(1)动态设置控件的颜色

(2)获取鼠标位置

(3)CButtonST

程序的界面效果如下图:


可以方便地获取屏幕上任意点位置的颜色。RGB表示。

有额外需要(比如在窗口最下化情况下的读取颜色)的话可以自己改写代码。

关键点是设置一个定时器,然后在定时器函数中进行如下设置即可:

[cpp]  view plain copy print ?
  1. void CGetScreenPixelDlg::OnTimer(UINT_PTR nIDEvent)  
  2. {  
  3.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  4. //  DWORD   dwPos = GetMessagePos();   
  5. //  CPoint point( LOWORD(dwPos),   HIWORD(dwPos) );  
  6. //  HWND hwnd=::GetForegroundWindow();  
  7.     CPoint   point;   
  8.     GetCursorPos(&point);  
  9.     HDC hDC = ::GetDC(NULL);    
  10.   
  11.     // 再获取当前鼠标位置像素值  
  12.     COLORREF color = ::GetPixel(hDC, point.x, point.y);   
  13.     // 设置中间显示的文字处的背景色(非黑色地方)  
  14.     m_colorState.SetBkColor(color);  
  15.     // 下面的都是设置对应文本控件的数值  
  16.     posx = point.x;  
  17.     posy = point.y;  
  18.     red = GetRValue(color);  
  19.     green = GetGValue(color);  
  20.     blue = GetBValue(color);  
  21.     UpdateData(FALSE);      // 文本控件的数值显示  
  22.     CDialogEx::OnTimer(nIDEvent);  
  23. }  


你可能感兴趣的:(VC++)