老惯例,先上一段代码。
 
  1. CWnd* pWnd; 
  2. pWnd=GetDlgItem(IDC_STATIC_PICFRAME); 
  3. CRect rect1; 
  4. pWnd->GetClientRect(&rect1); 
  5. CRect rect2; 
  6. m_staticPicFrame.GetClientRect(&rect2);
说明一下,m_staticPicFrame与IDC_STATIC_PICFRAME是关联的。IDC_STATIC_PICFRAME的位置在窗口的中间。因为如果在窗口的0, 0处的话,这种比较就没有意义了。
 
那么rect1与rect2是相同的吗?答案是相同。
原因是rect1是通过IDC_STATIC_PICFRAME的句柄得到的,所以rect1的左上角永远是0, 0。通过m_staticPicFrame得到的自然也是通过控件句柄得到的,所以rect2与rect1无异。
 
 
那么再来一段代码。
  1. CImage image; 
  2. image.Load(_T(“src.jpg”)); 
  3. image.Bitblt(pWnd->GetDC()->m_hDC, CPoint(rect1.left, rect1.top)); 
  4. CDC* pDC = GetDC(); 
  5. pDC->Rectangle(rect2.left, rect2.top, rect2.left + image.GetWidth(), rect2.top + image.GetHeight()); // 绘制一个与图片一样大小的矩形框 
问题来了,图片与矩形能重合吗?答案是不能。
 
可以看出画图片时与画矩形时使用的是不同的DC,画图片时使用的是IDC_STATIC_PICFRAME的DC,绘图的坐标原点是控件位置的左上角。
画矩形时使用的是新建的DC,绘图的坐标原点是整合窗口的左上角。
起初我认为一个用的是HDC,一个用的是CDC,大错特错 =。=
 
HDC与CDC究竟有什么区别呢?先说HDC和CDC都是什么。
HDC,设备环境句柄,是一种数据类型。
CDC是MFC封装的Windows设备相关的一个类,封装了所有对HDC的操作。原来搞了半天,CDC中有个成员变量m_hDC就是HDC类型的。
既然是成员变量,从CDC中获得HDC只需使用GetSafeHdc()就可以喽。
 
CDC有几个有用的子类。CPaintDC、CClientDC、CWindowDC和CMetaFileDC。
1. CPaintDC是个循规导矩的类,一般用来响应WM_PAINT消息。"For drawing in a window’s client area(OnPaint handles only)"。
2. CClientDC是个不循规导矩的类,它会在OnPaint的外面创建一个客户区域DC,什么时候需要画图,已经等不及下一个WM_PAINT消息了,就调用此类,马上就可以画个图出来给你看。"For drawing in a window’s client area(anywhere but OnPaint)"。
3. CWindowDC这个类是可以在非客户区域(标题栏啊菜单栏啊啥的)进行绘图的类。会向系统发出WM_NCPAINT消息。"For drawing anywhere in a window, including the noclient area."
4. CMetaFileDC这个类主要是集中了一些GDI指令,可以用来使用并做一些绘制命令。metafile图元文件。
 
题外话,还有一个容易引起人混乱的东西,就是GetClientRect()和GetWindowRect()。
GetClientRect: Copies the client coordinates of the CWnd client area into the structure pointed to by lpRect. 是将控件相对于客户区域的区域传给参数lpRect。
GetWindowRect: Copies the dimensions of the bounding rectangle of the CWnd object to the structure pointed to by lpRect. 获取的是控件相对整个屏幕(对,你是面前的这个)的区域。