s函数再调用 EndDeferWindowPos()函数,这一来,除了那个id为nIDLeftOver的子窗口外,所有的子窗口都一次性排好了位置了。
至于该结构的sizeTotal成员的意义,它累计每个子窗口所占据掉的可用区域的长宽尺寸和。每个子窗口在响应WM_SIZEPARENT消息时一般都要把自己所占据的区域的高和宽分别累加到sizeTotal结构的cy和cx成员里。这有什么意义呢?当每个子窗口所占据的区域都是挨在一起的时候,这个 sizeTotal结构就有意义了,主框架窗口可以使nFlag等于reposQuery,使bStretch等于FALSE来调用RepositionBars函数,RepositionBars函数会把 sizeTotal结构的两个成员值拷贝到lpRectParam参数里返回给主框架类(前面也提到过),这样主框架类就知道它的客户区内的子窗口占去了客户区内多大的一块空间。如果你的主框架窗口没有利用这个信息,那么响应WM_SIZEPARENT消息的子窗口就可以不理睬sizeTotal成员。
ID的分配
可以看到,每个子窗口都有个id,同一个父窗口的子窗口的id不能重复。mfc的一些现成的控件子窗口都有预定义的id:
id名 id值 意义
AFX_IDW_TOOLBAR 0xE800 // 主窗口的工具栏的id
AFX_IDW_STATUS_BAR 0xE801 // 状态栏的id
AFX_IDW_PREVIEW_BAR 0xE802 // PrintPreview Dialog Bar
AFX_IDW_RESIZE_BAR 0xE803 // OLE in-place resize bar
AFX_IDW_REBAR 0xE804 // COMCTL32 "rebar" Bar
AFX_IDW_DIALOGBAR 0xE805 // CDialogBar
还有象单文档程序的视图窗口,多文档
程序的那个MDIClient窗口,分隔条窗口,他们的id值介于下面两个id值之间:
AFX_IDW_PANE_FIRST 0xE900 //
AFX_IDW_PANE_LAST 0xE9FF
你要给你自己的子窗口分配id的话,别和上面的重复了。一般如果用IDE的菜单view/resource symbols项来加入自己的id的话,是不会重复的。有关id,还可以看看msdn里的TN020文章,那是专讲id的。
实例分析
1。CFrameWnd类是如何调用RepositionBars函数的
前面介绍了RepositionBars的各个参数和意义,现在看看CFrameWnd类是如何调用这个函数的,从中可以
学习RepositionBars函数的使用方法。
CFrameWnd类及其派生类生成的窗口的客户区内可以有工具栏,状态条和视图窗口等子窗口。当父窗口的尺寸发生变化时,这些子窗口的各自的位置和大小比例关系保持不变,这就需要父窗口一旦在它自己的尺寸发生变化时就调用RepositionBars函数。CFrameWnd类是集中在函数 RecalcLayout里调用RepositionBars函数的。该类保证了在窗口尺寸发生变化时函数RecalcLayout都被调用,从而RepositionBars函数也能被及时调用,确保了各个子窗口都能及时调整自己的位置和大小。
RecalcLayout是个虚函数。该函数的功能就是在主框架的客户区内提供一个初始的可用区域,并把这个区域放在一个CRect类型的变量里。该函数大致是这样的:
void CFrameWnd::RecalcLayout(BOOL bNotify)
{
if (m_bInRecalcLayout)
return;//这大概是在防止该函数重入
m_bInRecalcLayout = TRUE;
.
.
.
.
if (GetStyle() & FWS_SNAPTOBARS)
{
CRect rect(0, 0, 32767, 32767);
RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,
&rect, &rect, FALSE);
RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra,
&m_rectBorder, &rect, TRUE);
CalcWindowRect(&rect);
SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
}
else
RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra, &m_rectBorder);
m_bInRecalcLayout = FALSE;
} 可以看出,mfc认为这个函数是不能重入的。在编制自己的RecalcLayout()函数时也得用同样的方法来防止重入。
后面的if语句检查框架窗口是否具有风格FWS_SNAPTOBARS,这个风格用在什