1.GetWindowRect()和GetClientRect()
GetWindowRect()是取得窗口在屏幕坐标系下的RECT坐标(包括客户区和非客户区),这样可以得到窗口的大小和相对屏幕左上角(0,0)的位置。
GetClientRect()取得窗口客户区(不包括非客户区)在客户区坐标系下的RECT坐标,可以得到窗口的大小,而不能得到相对屏幕的位置,因为这个矩阵是在客户区坐标系下(相对于窗口客户区的左上角)的。
ClientToScreen()把客户区坐标系下的RECT坐标转换为屏幕坐标系下的RECT坐标.
ScreenToClient()把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标.
我们对同一个窗口先GetWindowRect取得一个RECT,再用ScreenToClient转换到客户坐标系。然后 GetClientRect取得一个RECT,再用ClientToScreen转换到屏幕坐标系。显然,GetWindowRect取得的矩阵不小于 GetClientRect取得的矩阵。因为前者包含了非客户区,而后仅包括了客户区。
对GetWindowRect取得的矩阵ScreenToClient后,矩阵的大小没有变小,(-3,-29)是窗口的左上角的坐标,相对窗口客户区左上角。对GetClientRect取得的矩阵ClientToScreen后,矩阵也没有变大,新得到的矩阵是窗口客户区在屏幕坐标系上的RECT。
2.OnPaint()和OnDraw()
当窗口改变后,会产生无效区域,这个无效的区域需要重画。一般Windows会发送两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)。非客户区的重画系统自己搞定了,而客户区的重画需要我们自己来完成,这就需要OnDraw()或OnPaint()来重画窗口。
OnDraw()和OnPaint()有什么区别呢?首先:我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CView类的一个纯虚函数,没有响应消息的功能,要使用必须重载它。
其次,要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备(不单指你17寸的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。
当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的 OnPaint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函数。可见在OnPaint()里调用了OnDraw()。通常我们不必编写重写的OnPaint处理成员函数,而由于OnDraw是虚拟函数,可以自己改写,所以就实现了不同的绘图目的。
///CView默认的标准OnPaint()
void CView::OnPaint()
{
CPaintDC dc(this);
OnPreparDC(&dc);
OnDraw(&dc); //调用了OnDraw
}
//自己写的OnDraw()
///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。
void CMyView::OnDraw( CDC* pDC )
{
CMyDoc* pDoc = GetDocument();
CString s = pDoc->GetData(); // Returns a Cstring
CRect rect;
GetClientRect( &rect );
pDC->SetTextAlign( TA_BASELINE | TA_CENTER );
pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );
}
因此我们一般用OnPaint维护窗口的客户区(例如在窗口客户区加一个背景图片),用OnDraw维护视图的客户区(例如通过鼠标在视图中画图)。
补充:我们还可以利用Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口。
3. Invalidate()和UpdateAllViews()
Invalidate()是让程序重画窗口,使系统向其发WM_PAINT消息,使的程序的OnPaint被调用重画客户区。
UpdateAllViews()是在DOC/VIEW结构中,当一个视图的数据改变后,通知所有视图作相应的改变。UpdateAllViews()是文档与视之间的联系,调用从它会使程序与此文档相关的所有视的UpdateView被调用,至于是否重画以及怎么画是由各视的UpdateView来决定的。
Invalidate()是Cwnd的成员函数,与DOC-VIEW无关;
UpdateAllViews()是CDocument的成员函数,具体体现DOC-VIEW的精神。
Invalidate()函数产生一条WM_PAINT消息,并送入windows消息队列中,是窗口产生重画。而UpdateAllViews 并不进入windows消息队列中,直接产生重画。
如果仅重画当前窗口用 this->Invalidate();如果通知所有和当前文档相关的窗口重画用GetDocument()->UpdateAllViews()(在View中)或this->UpdateAllViews()(在Doc中)。
还有一个函数:ONERASEBKGND()画背景用的,先于OnPaint()运行。
4. UpdateData(true)和UpdateData(false)
如果你为控件分配了变量:
UpdateData(true): 是使用户输入的数据能够反映到变量上,在函数调用之后变量才被赋值。
UpdateData(false): 是当你给控件对应的变量赋过值之后,在控件上体现出来,在函数调用之前,控件的值是不会随变量变化的。