MFC
控制条窗口布局原理
——by Koote Bi@fudan cse
一、框架窗口
框架窗口在其大小被改变的时候会收到
WM_SIZE
消息,这个消息的处理函数是
CFrameWnd::OnSize
,此函数接着调用
RecalcLayout
来重新安置各子窗口,它的主体代码如下:
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);
}
这里有两个小的地方要注意,第一是
FWS_SNAPTOBARS
风格。一般来说,都是框架窗口主动改变大小,子窗口随之要修改自己来适应框架窗口的改变,但是这个
FWS_SNAPTOBARS
风格却相反,是让框架窗口改变大小来适应它的子窗口,但我一路跟踪下来没有发现有哪个框架窗口有这个风格,都是走
else
分支的(事实上这个风格是为
CMiniDockFrameWnd
准备的,这个框架窗口的大小是根据它内部的控制条来定的);第二是要注意
RecalcLayout
是不可重入的,
MFC
防止重入的方法虽然非常的简单有效,但是它的方法要不能防止多线程的重入
——
话说回来
MFC
本身就不是一个线程安全的库
J
好了现在我们进入了整个重布局动作的主体函数
RepositionBars
,让我们仔细分析一下它都干了些啥见不得人的
“
勾当
”
(这个函数在
MSDN
里有文档记载,关于它的几个参数的含义就不在这里赘述了):
首先,它创建一个
AFX_SIZE