假如我们自己从 CWnd 类派生一个窗口类并生成一个窗口,在它的客户区里要生成若干个
子窗口,我们想使这些子窗口排列得规规矩矩,互不重叠,当父窗口的尺寸变了时各个子窗
口能适时调整自己的尺寸和位置,使各个子窗口之间的位置大小比例关系不变。当移动其中
一个或几个子窗口时,别的子窗口能及时为这个移动了的子窗口让位。当然我们可以利用
api 函数里管理窗口的函数来编写自己的管理子窗口的方法。可是如果在父窗口的客户区里
有了工具栏,状态条等等子窗口时,你自己加进来的子窗口还能和这些 mfc 提供的子窗口
融洽相处吗?你如何保证你的子窗口不会覆盖了能够四处停靠的工具栏?当工具栏和状态
条消失后你的子窗口如何才能知道,以便及时调整自己的大小从而覆盖工具栏和状态条腾出
的空间?基于文档视图构架的窗口的客户区内还有个视图,你自己硬加上的子窗口能不和视
图窗口争地盘吗?
所以必须了解 mfc 的窗口管理它的客户区的方法。其实,mfc 的窗口管理它的客户区的方法
是非常简单的:父窗口调用一个函数,子窗口响应一个消息,就这么多。
CWnd::RepositionBars 函数和 WM_SIZEPARENT 消息
先简述一下 mfc 的窗口为子窗口分配客户区空间的过程:这一过程是父窗口与子窗口共同
协调完成的。父窗口先提供它的客户区内的一块区域,叫做起始可用区域。然后调用一个函
数,在这个函数里,父窗口把这片区域通过一个消息提交给它的第一个子窗口,该子窗口决
定自己要占用多大一块,然后在可用区域里把它将占据的部分划出去,这样可用区域就被切
去了一块。父窗口再把这块剩下的可用区域通过同样的消息提交给第二个子窗口,第二个子
窗口再根据自己的需要切掉一块。如此这般,每个子窗口都切去自己所需的一块。最后剩下
的可用区域就给最后的子窗口使用。可以看出,除了最后一个子窗口外,其它子窗口都得在
消息响应函数里有自己的算法来决定自己将在可用区域里占据多大一块,最后一个子窗口由
于别无选择,所以不需要这样的算法。
当然,初始的可用区域是一个矩形,每次被切割后剩下的可用区域还是一个矩形,不可能是
别的形状的。
举例说来,在一个典型单文档程序中,父窗口就是从 CFrameWnd 派生的主框架窗口,最后
一个子窗口就是视图窗口,如果用了 CSplitterWnd 生成分隔条的话,最后一个子窗口就是
拥有分隔条的那个窗口。其它子窗口就是工具栏窗口和状态条窗口,以及可能有的别的控件
窗口。
在典型多文档界面程序中,父窗口就是主框架窗口,最后一个子窗口就是覆盖在主窗口客户
区,背景为黑灰色,拥有包含文档的子框架窗口的那个窗口,这是个预定义了窗口类的窗口,
它的窗口类名是“MDIClient”。如果用了 CSplitterWnd 生成分隔条的话,最后一个子窗口就
是拥有分隔条的那个窗口。其它窗口就是工具栏窗口,状态条窗口以及可能有的别的控件窗
口。
这个函数和消息是:函数 CWnd::RepositionBars()以及消息 WM_SIZEPARENT。这个消息是
mfc 自定义的,不是 windows 自有的。