作品简介: 如果你经常使用对话框,想调整他们你就会注意到没有 MFC的特性,帮助您安排的对话框控件后自动调整。 你必须这样做。也许你已经看到了一些布局机制在其他语言 (如Java),那么这个你会熟悉。 我将主要指的是对话框,但是这段代码可用于任何CWnd布局。 目前这些类/支持功能: 对话框FormView PropertySheet /页面DialogBars (DialogBar支持你必须使用& lt; a href = " http://msnhomepages.talkcity.com/WindowsWay/stasl/index.html "祝辞BCGControlBar图书馆。 你需要一个版本高于4.52。支持CTabCtrl和CStatic (groupbox)上浆爪(framewindow中发现的)(可选)约束处理(自动最小/最大跟踪大小处理)几乎没有闪烁的windowsizes调整自动重新/存储注册表(可选) 一般用法: 本节将简要描述了如何在您的代码中加入布局管理。 布局管理器的一个完整的描述看以后 部分。 包括所有你需要的FilesFirst包括标头。这些都是 ETSLayout.h位于文件。最好是直接包含在您stdafx.h。 所有类中定义名称空间“ETSLayout”,因此建议 你下面添加以下行#包括: 隐藏,复制代码… # include“ETSLayout.h” 使用名称空间ETSLayout; … 您还需要包括文件ETSLayout.cpp到您的项目 使用的类。这样做直接从DevStudio下项目比;添加到项目 比;文件。 改变BaseclassLet CMyDialog是假设你想让你的对话框 可调整大小的。 然后你将不得不改变baseclass CMyDialog ETSLayoutDialog。例如如果CMyDialog来源于 CDialog你将只需要替换出现的所有CDialog 与ETSLayoutDialog 如果你想添加一个新的正常CDialog的大小可调整的对话框添加它 随后改变baseclass如上所述。 自动添加WS_THICKFRAME风格 ETSLayoutDialog:: OnInitDialog,以防你忘记给对话框 可调整大小的边界在资源编辑器中。 定义LayoutNow是非常重要的一步:你 必须定义实际布局。这将描述你所希望的方式对话框 项目调整和安排。 事实上有两个不同的接口来定义布局。这将是 后来在参考部分描述。我将向您展示流 接口。 你看到左边对话框和所有您想要定义的控件id 布局。右边你会发现该窗格。你会注意到 垂直的玻璃被标记成红色而所有水平窗格是蓝色的。 通常你定义的布局对话框的OnInitDialog()处理程序。的 第一步是创建根窗格。在这种情况下,我们需要一个垂直的 第一级的subpanes水平。注意,没有 分号结束时线作为我们将项目添加到根窗格流operator< & lt;()。 隐藏,复制CodeBOOL CMyDialog: OnInitDialog () { ETSLayoutDialog: OnInitDialog (); / /定义布局 CreateRoot(垂直) 我们想要添加的第一项是IDC_NEW_ITEM_STATIC,顶端的子项 的根窗格。这是一个简单的静态(文本)我们不需要调整这个项目。 因此它被NORESIZE调整模式。获取根窗格使用 CreateRoot()的返回值或autopointer m_RootPane: 隐藏,复制Code< & lt;项目(IDC_NEW_ITEM_STATIC NORESIZE) 接下来的两个项目(蓝色边框)形成一个subpane,因为我们希望他们一行 (记住:根窗格是垂直的,所以所有subpanes水平)。& lt; href = " #流”的在流接口布局定义,您需要添加一个开放的支撑 后跟一个窗格创造者函数(在本例中窗格())。 现在所有物品后,关闭括号放在这subpane。我们想要的 这subpane横向扩张,但身高应该总是保持不变(因此 ABSOLUTE_VERT调整模式)。 隐藏,复制Code< & lt;ABSOLUTE_VERT(窗格(水平) 这里的水平subpane刚刚两个项目没有subpanes本身。第一项 我们希望成长(按钮应保持在正确的边界)。一个贪婪的 物品使用尽可能多的空间,它(它将共享同样与其他贪婪 物品。所以如果没有相当大的下一项永远是在正确的边界 (如第一个贪婪的占据了所有剩余的空间)。 隐藏,复制Code< & lt;item(IDC_NEW_ITEM,贪婪)<item(IDC_ADD_ITEM, NORESIZE) 注意,IDC_NEW_ITEM不会垂直调整大小,因为它的父节点 窗格具有ABSOULUTE_VERT大小调整模式!现在, 第一个子面板是完整的,我们可以关闭大括号,从而结束这个定义 subpane。 隐藏,复制代码) 接下来,我们需要添加一个简单的静态(文本)项——您之前已经看到了…… 隐藏,复制Code< & lt;item (IDC_ITEM_LIST_STATIC, NORESIZE) 直到现在,只有项目不能调整大小或只有在 水平方向。如果一个对话框只有这种类型的项目,它将不会是相当大的 根本没有垂直方向!但是在这个例子中,下一个条目(列表框)可以调整大小 在水平和垂直方向。在这种情况下,没有限制父级 窗格(与前面的IDC_NEW_ITEM相反)可以展开此项 垂直: 隐藏,复制Code< & lt;item (IDC_ITEM_LIST,贪心) 最后一个子窗格与第一个子窗格类似。如果我们想把所有的按钮都放在右边 必须有一个项目消耗所有剩余的空间来“推” 按钮到右边边框。本例中没有这样的项,这就是itemGrowing() 发挥作用了。这样就添加了可以一直使用的伪黄烷(paneNull) 作为一个占位符。它不显示,也没有任何与之关联的控件。 这个子窗格的其余部分如上图所示: 隐藏,复制Code< & lt;(pane(HORIZONTAL, ABSOLUTE_VERT) <<itemGrowing(水平) & lt; & lt;item(IDOK, NORESIZE) <<项目(IDCANCEL, NORESIZE)); 布局的定义现在已经完成。要激活布局,你必须 调用UpdateLayout()(如果不调用它,对话框将不会被布局 直到你调整它的大小!) 隐藏,复制代码UpdateLayout (); 返回TRUE; } 准备好了!就是这样:您刚刚创建了一个完全自动布局的对话框! 很简单,不是吗?唯一要做的是正确定义布局,这是可以的 对于非常复杂的布局要有技巧。 方向: 子窗格有水平和垂直两个方向 告诉LayoutManger如何向该窗格添加新项/子窗格。的水平 窗格所有项目都是从左到右添加的。然而,这并不意味着,水平 窗格只有水平大小,它只是指的方向和方向 添加了哪些项/子窗格!窗格的方向也称为其主方向 方向 调整模式: 实际的布局参数分别为每个项/子面板设置。的 然后LayoutManager将所有这些约束组合到全局布局中。 有许多不同的大小调整模式(或布局代码)。其中一些可能会被使用 以及对齐模式。组合模式只需使用| 操作符,如NORESIZE | ALIGN_RIGHT。 大小调整模式的类型是layResizeMode。为了结合多重 模式与|-运算符我需要一个小技巧。通常你不能 如果X和Y是枚举类型,那么写X | Y 结果也要列举出来。我可以使用普通的DWORD值 相反(在内部它们是这样处理的),但是那样的话我就会丢失 参数的静态类型检查。因此我重载了Hide 复制Code
layResizeMode operator|(layResizeMode X, layResizeMode Y)
以组合字符值 用标准的|算子来表示X和Y,然后 将结果转换回layResizeCode。 如果你省略了调整模式贪婪是默认参数。这意味着 默认情况下,项目/子窗格可以同时扩展到两个方向(水平方向和 垂直)。 解释大多是关于物品的。这是为了简洁起见。的 当然,子窗格也是如此。事实上,LayoutManager并没有什么区别 在项和子窗格之间,因为它们都派生自相同的基类。 主方向上可用空间的分配顺序如下: 首先,从可用的空间中减去所有ABSOLUTE_XXX项的空间 空间。其中XXX为主方向,即时的HORZ 项目被放置在一个水平窗格和类似的VERT 和垂直。然后,所有RELATIVE_XXX项都在占用剩余的空间 (取决于百分比值)。请注意,不应该使用 累积百分比大于100:)最后,剩余的空间平均分配给所有贪婪的项目。(由于约束)可能会有剩余的空间。在一个 fixup-step LayoutManager尝试重新分配这个剩余的空间。 贪婪(默认) 正如前面提到的,贪心项在水平和垂直方向上都会增长。如果 其他e是窗格中唯一的贪婪项,它占用了其他项剩下的所有空间 物品。如果有多个贪婪项,所有剩余空间都是均匀分布的 在他们中间。 你也可以用贪婪的物品和paneNull组合来填满 留出空间(为了让其他项目保持在右边或底部)。 ABSOLUTE_HORZ 如果你想要一个项目不改变它的水平范围,你将不得不使用这段代码。 使用对话框模板中的当前水平大小。具有此模式的窗格是 根据项目计算初始水平扩展。 请注意,具有这种限制的窗格将不允许项目的大小为水平- 即使这些项目本身有贪婪的调整大小模式。另一方面 只有ABSOULTE_HORZ项目的贪婪窗格将不能 调整自身水平! RELATIVE_HORZ 您可能需要一些项目,以覆盖可用空间的一定百分比。这是 需要使用的调整大小模式。使用此调整大小模式时,必须 提供一个x大小的项目。然后x-size被解释为一个百分比值 (在1至100之间),例如,x-size为30表示该物品将占 水平方向上的可用空间。 要填充完整的空间,您可以使用大小互补的RELATIVE_HORZ 项目(例如,如果你有60%的项目,你必须增加一个40%的项目)或仅仅使用贪婪 自动填充剩余空间的项 请注意,带有RELATIVE_HORZ | RELATIVE_VERT的项没有 通常会消耗x%的水平可用空间和y%的垂直可用空间!这是因为 窗格只在主要方向上布置(水平方向为水平方向) 垂直表示垂直方向。但是如果你放置一个RELATIVE_HORZ 在RELATIVE_VERT窗格中的项可以实现这种类型的布局。 ABSOLUTE_VERT 这个和ABSOLUTE_HORZ是一样的只是在竖直方向上。 RELATIVE_VERT 这和垂直方向上的相对horz是一样的。 NORESIZE 还可以保持项目的初始大小。实际上NORESIZE 定义为ABSOLUTE_HORZ | ABSOLUTE_VERT。一个很好的例子是 “Ok”按钮,通常应保持其初始大小。 对齐方式 对齐模式与调整大小模式一起使用。当有一个以上的时候 窗格中的项,其中一个项不可调整大小,可能出现以下情况: 由于物品不能变大,所以有更多的空间可供物品使用(I 将此称为剩余空间)。问题是,这个项目应该在哪里 放在剩余的空间里? ALIGN_LEFT 项目在剩余空间的左边界对齐(如果有的话)。 ALIGN_RIGHT 项目在剩余空间的右边界对齐(如果有的话)。 ALIGN_TOP 项目在剩余空间的顶部边缘对齐(如果有的话)。 ALIGN_BOTTOM 项目在剩余空间的底部对齐(如果有的话)。 ALIGN_HCENTER 如果有多余的空间,该项目将水平居中。 ALIGN_VCENTER 项目垂直居中于剩余空间(如果有的话)。 ALIGN_CENTER 项目水平和垂直居中剩余空间(如果有的话)。 实际上ALIGN_CENTER = ALIGN_HCENTER | ALIGN_VCENTER。 ALIGN_FILL_HORZ 项目被水平拉伸以填充剩余的空间,不管它是什么 调整模式。 ALIGN_FILL_VERT 无论项目是什么,它都会被垂直地拉伸以填充剩余的空间 调整模式。 ALIGN_FILL 项目被水平和垂直地拉伸以填充剩余空间, 不管它的大小调整模式。实际上ALIGN_FILL = ALIGN_HFILL | ALIGN_VFILL。 原始接口: Raw界面是定义对话框布局的最基本方式。大部分的 这里使用的方法与Stream接口相同。的 不同之处在于您组成窗格和子窗格的方式。Raw接口使用C风格 方法使用成员函数调用,而流接口 使用c++流操作符。我建议使用Stream接口 在可能的情况下。 使用原始界面,您可以以自底向上的方式组装布局。也就是你 首先将对话框控件分组到窗格中,然后将这些窗格进一步分组到(父)窗格中 直到您将这些父窗格添加到惟一的根窗格为止。 窗格 要创建一个新的窗格,只需调用pane()成员函数(有 还支持包含项本身和的特殊控件 因此,它们被用作窗格。有一些争论,你可以改变的行为: 隐藏,复制Code
// ETSLayoutMgr CPane pane( layOrientation orientation, layResizeMode modeResize = GREEDY, int sizeBorder = nDefaultBorder, int sizeExtraBorder = 0, int sizeSecondary = 0);
你必须为每一个设置一个方向(主要方向) 窗格。设置窗格的大小调整模式。如果省略此值,则为默认值 第三个参数(也可以省略)设置所有项之间的边界 (见图)。的第四个参数(也可以省略)设置额外的边框 项目(见图)。如果你为二次添加模式方向(即ABSOLUTE_VERT水平 面板),那么sizeSecondary用作大小(二级)。如果你不 指定sizeSecondary和ABSOLUTE_VERT模式(水平 窗格)将计算所有SubPanes的最大高度(垂直也是如此 窗格和subpanes ABSOLUTE_HORZ) 通常你会写这样的代码创建一个窗格OnInitDialog()或任何其他 派生类的成员: 隐藏,复制Code
// in OnInitDialog() CPane newItemPane = pane( HORIZONTAL );
AutoPointer 如你所见,你不用担心如果你使用CPane和CPaneBase指针 autopointers。可以使用这些自动引用计数,如指针面板* 分别和PaneBase *。CPane和CPaneBase的使用 强烈建议! 使用CPane如果你是处理一个窗格中,PaneTab 或PaneCtrl,因为CPaneBase PaneBase封装 指针。PaneBase是所有的通用基类的物品,也没有 支持添加项目。所以你不能用它来subpanes。 你永远不应该做的一件事:不要使用面板* 用GetPane()或GetPaneBase()构造一个新的CPane 或CPaneBase ! 项目 一个空面板就是——什么都没有。你必须添加项以做任何使用 他们。将条目添加到面板使用面板的成员函数(这就是 大影响流接口: 隐藏,复制Code
// members of Pane bool addItem( UINT nID, layResizeMode modeResize = GREEDY, int sizeX = 0, int sizeY = 0, int sizeXMin = 0, int sizeYMin = 0); bool addItem( CWnd* pWnd, layResizeMode modeResize = GREEDY, int sizeX = 0, int sizeY = 0, int sizeXMin = 0, int sizeYMin = 0); bool addPane( CPane pSubpane );
前两个成员将控件添加到面板中。 指定的控件的对话框或派生子类的成员ID国家免疫日 控制通过pWnd组调整模式的控制如果您添加模式(即二级方向。ABSOLUTE_VERT水平 面板),那么sizeSecondary用作大小(二级)。如果你不 指定sizeSecondary和ABSOLUTE_VERT模式(水平 窗格)将计算所有SubPanes的最大高度(垂直也是如此 窗格和subpanes ABSOLUTE_HORZ)设置的初始大小控制通过sizeX和sizeY。你 可能会忽略这些值(或一组他们0)。在这种情况下,初始大小是什么 基于对话框的大小控制模板。设置的最小尺寸控制通过sizeXMin和sizeYMin。 如果您省略这些值(或将它们设置为1)的当前大小控制 在对话框中定义模板将控制的最小尺寸。的 LayoutManager将确保控制是从来没有比这个小。的对话框 项目(因此对话框本身)将无法收缩小于在对话框中 模板(如果你只是使用默认参数)。如果你设置sizeXMin 和/或sizeYMin 0项能够缩小(几乎) 完全。 支持特殊控制 有一些特殊情况需要考虑。通常没有物品 布局可以重叠。但如果你想使用一个CTabCtrl或CStatic Groupbox 会有项目你想在这些控件。幸运的是有 一些特殊的类来支持这个。相应的构造函数: 隐藏,复制Code
// members of ETSLayoutMgr CPane paneTab( CTabCtrl* pTab, layOrientation orientation, layResizeMode modeResize = GREEDY, int sizeBorder = nDefaultBorder, int sizeExtraBorder = 0, int sizeSecondary = 0); CPane paneCtrl( CWnd* pCtrl, layOrientation orientation, layResizeMode modeResize = GREEDY, int sizeBorder = nDefaultBorder, int sizeExtraBorder = 0, int sizeTopExtra = 0, int sizeSecondary = 0); CPane paneCtrl( UINT nID, layOrientation orientation, layResizeMode modeResize = GREEDY, int sizeBorder = nDefaultBorder, int sizeExtraBorder = 0, int sizeTopExtra = 0, int sizeSecondary = 0);
正如你可能已经猜到paneTab TabCtrl的照顾。与paneCtrl 你得到一个面板和一个项目。它也像一个窗格但调整 一个对话框控制根据自己的大小。您希望使用CStatic groupboxes。 特殊的措施来减少这些控件内闪烁。 根窗格 直到现在我们知道如何创建这些窗格窗格和如何添加项目。唯一的 缺少的是如何“连接”这些窗格本身的对话框。正如已经 上面提到的存在一个叫做根窗格。 这种特殊的窗格是所有窗格的“母亲”。如果窗口的大小, 此窗格是自动调整到新的客户区,因此所有兄弟姐妹更新 他们的布局。 此外,如果兄弟姐妹构成约束最小或最大大小的窗口 这也是考虑到(注:你必须添加修改CMainFrame 如果你想让ETSLayoutFormView这样做。看到样品和/或标题)。 根窗格中也有一个方向。通过调用创建它 : 隐藏,复制Code
// member of ETSLayoutMgr CPane CreateRoot(layOrientation orientation, int sizeBorder = nDefaultBorder, int sizeExtraBorder = 0 );
参数是一样& lt; a href = " #窗格”祝辞Pane< / a>。然而,sizeBorder 设置窗口的边界和边界控制。如果你想要一些物品 棒靠近窗口的边界用0。你最终会需要一些 填料如果你不想坚持所有项目,。 通过成员m_RootPane根窗格访问,例如: 隐藏,复制Code
m_RootPane->addItem ( IDC_ITEM );
样本 这就是你要写定义等价的l向a致敬 href = " #样品”的在上面示例: 隐藏,复制Code
CPane newItemPane=new Pane ( this, HORIZONTAL ); newItemPane->addItem ( IDC_NEW_ITEM, GREEDY ); newItemPane->addItem ( IDC_ADD_ITEM, NORESIZE ); CPane bottomPane=new Pane ( this, HORIZONTAL ); bottomPane->addItem ( paneNull, GREEDY ); bottomPane->addItem ( IDOK, NORESIZE ); bottomPane->addItem ( IDCANCEL, NORESIZE ); CreateRoot( VERTICAL ); m_RootPane->addItem ( IDC_NEW_ITEM_STATIC, NORESIZE ); m_RootPane->addPane ( newItemPane, ABSOLUTE_VERT ); m_RootPane->addItem ( IDC_ITEM_LIST_STATIC, NORESIZE ); m_RootPane->addItem ( IDC_ITEM_LIST, GREEDY ); m_RootPane->addPane ( bottomPane, ABSOLUTE_VERT ); UpdateLayout();
流接口: Stream接口为布局定义添加了简单而自然的访问。 项目/子窗格通过流操作符<<()添加到其他窗格中。 与原始接口相比,该定义是某种自顶向下的: 根 起点总是根窗格。它的创建方式与<a完全相同 href = " #根”在原始接口: 隐藏,复制Code
// members of ETSLayoutMgr CPane CreateRoot(layOrientation orientation, int sizeBorder = nDefaultBorder, int sizeExtraBorder = 0 );
然后你可以使用m_RootPane作为流操作的目的地 这样的: 隐藏,复制Code
m_RootPane << item( IDC_SOMETHING) << item( IDC_WHATEVER);
也可以在CreateRoot()调用之后直接添加项目: 隐藏,复制Code
CreateRoot(VERTICAL) << item( IDC_SOMETHING) << item( IDC_WHATEVER);
或者,如果使用的是 UpdateLayout()调用的特殊版本。调用中提供的窗格 然后作为根窗格使用 隐藏,复制Code
// members of ETSLayoutMgr virtual void UpdateLayout(CPane p);
你可以像这样使用它来定义完整的布局在一行代码: 隐藏,复制Code
// in OnInitDialog() UpdateLayout( pane(VERTICAL) << item( IDC_SOMETHING) << item( IDC_WHATEVER) );
项目 您已经看到项目是如何创建和添加到窗格与流接口: 隐藏,复制Code
// members of ETSLayoutMgr CPaneBase item(UINT nID, layResizeMode modeResize = GREEDY, int sizeX = 0, int sizeY = 0, int sizeXMin = -1, int sizeYMin = -1); CPaneBase item(CWnd* pWnd, layResizeMode modeResize = GREEDY, int sizeX = 0, int sizeY = 0, int sizeXMin = -1, int sizeYMin = -1);
参数与原始接口相同。 窗格 当然,也有对子窗格的支持。它的工作原理和a一样 href = " #窗格”在原始接口。窗格的创建类似于项,但当您将项添加到 你应该确保在面板和它的项目周围使用大括号,像这样: 隐藏,复制Code
m_RootPane << ( paneHorz (ABSOLUTE_VERT ) << item( paneNull, GREEDY ) << item( IDOK, NORESIZE ) << item( IDCANCEL, NORESIZE ) );
上面的代码向根窗格中添加了一个包含3个项目的水平窗格。如果 你忘记了这样的牙套… 隐藏,复制Code
m_RootPane << paneHorz (ABSOLUTE_VERT ) << item( paneNull, GREEDY ) << item( IDOK, NORESIZE ) << item( IDCANCEL, NORESIZE );
…属性中添加一个空的水平窗格和3个项目 根窗格。 我们已经在上面的示例中使用了流接口,因此 我们真的不需要另一个在这里:)为了更多的例子,看看演示 源代码里。 附加功能: 还有一些有用的附加功能。我不会在这里全部描述,但是 您应该看一下头文件。这里有一些函数 看: 隐藏,收缩,复制Code
// members of Pane /** * Add a whitespace Item (paneNull) of variable size with * a minimum size of 0 */ bool addGrowing(); /** * Add a whitespace Item (paneNull) of fixed size based on the * current layout (as in the dialog template). Based on the layout * of the pane vertical or horizontal spacing is considered * * First argument is the left (top) item for a HORIZONTAL * (VERTICAL) pane */ bool addItemSpaceBetween( CWnd* pWndFirst, CWnd* pWndSecond ); bool addItemSpaceBetween( UINT nIDFirst, UINT nIDSecond ); /** * Add a whitespace Item (paneNull) of fixed size based on the * size of another item */ bool addItemSpaceLike( CWnd* pWnd ); bool addItemSpaceLike( UINT nID );
对于流接口,有等价的功能: 隐藏,收缩,复制Code
// members of ETSLayoutMgr /** * Add a whitespace Item (paneNull) of variable size with * a minimum size of 0 */ CPaneBase itemGrowing(layOrientation orientation); /** * Add a whitespace Item (paneNull) with fixed size */ CPaneBase itemFixed(int sizePrimary); /** * Add a whitespace Item (paneNull) of fixed size based on the * current layout (as in the dialog template). Based on the layout * of the pane vertical or horizontal spacing is considered * * First argument is the left (top) item for a HORIZONTAL * (VERTICAL) pane */ CPaneBase itemSpaceBetween( layOrientation orientation, CWnd* pWndFirst, CWnd* pWndSecond ); CPaneBase itemSpaceBetween( layOrientation orientation, UINT nIDFirst, UINT nIDSecond ); /** * Add a whitespace Item (paneNull) of fixed size based on the * size of another item */ CPaneBase itemSpaceLike( layOrientation orientation, CWnd* pWnd ); CPaneBase itemSpaceLike( layOrientation orientation, UINT nID );
PropertySheet 通常,您可以直接使用ETSLayoutPropertySheet,如下所示: 隐藏,复制Code
ETSLayoutPropertySheet sheet(_T("PropertySheet Test")); CPropPage1 page1; CPropPage2 page2; sheet.AddPage(&page1); sheet.AddPage(&page2); sheet.DoModal();
但是,如果你想在工作表上添加额外的控件(例如,不是在PropertyPages上),你可以 将需要重新定义ETSLayoutPropertySheet本身的布局。这个框架 为您提供了两个钩子: 虚拟空AddMainArea(CPane paneRoot, CPaneBase itemTab) 定义PropertySheet主区域的布局。通常,主要区域由 只有TabControl,因此默认为: 隐藏,复制Code
void ETSLayoutPropertySheet::AddMainArea(CPane paneRoot, CPaneBase itemTab) { // the default is: Whole main Area is covered by the TabCtrl paneRoot << itemTab; }
虚拟空白添加按钮(CPane paneBottom) 要更改底部按钮的显示方式,您可以重写此方法。如果你 想把按钮放在完全不同的地方,就重写这个,这里什么都不做。 但是请考虑,尽管如此,WizardMode中的水平线还是会被添加到主区域的下面。 它是如何工作的: 你真的不需要知道所有这些是如何工作的。如果你跳过这个部分,你就会 不会错过任何东西。但如果你对布局算法感兴趣,我会尝试 简要描述它。如果你想知道更多,看看来源,它很好 记录。 其思想是将对话框分割为窗格。每个窗格都有一个方向(水平或 垂直的),可能包含项目和/或其他(子)窗格。这是必要的 子窗格的方向相反(垂直窗格可能只包含水平的子窗格 反之亦然)。 当窗格要调整大小时,它将获得一定的空间来使用。假设是[1](as 在上面的图片中)得到一个指定的位置(这可能是因为[1] 是根窗格,或者因为它从父窗格获取新位置)。[1] 水平窗格,并有两个项:项[2]和子窗格[3]。 如果[1]有一个关联的窗口(这是唯一的情况,如果它是CTabCtrl或CStatic 它被移动到指定的位置。次要大小[2]和[3](高度)是由[1]的高度决定的。& lt; img src = " / / layoutmgr / layoutmgr8 KB /对话框。gif”alt = "主要/次要"比; 必须计算[2]和[3]的主要大小。因此[1]“询问”its 项目[2]和[3]它们需要多少可用空间。由于[2]是一个简单的项目,它在主方向所需的大小可以很容易地计算出来。 如果[2]的大小是固定的,那么它就是项目的宽度。如果项目可以增长,它只是 告诉[1]。稍后[1]可以将所有剩余空间分配给[2]。[3]本身是一个窗格,因此必须计算所需的主大小。因此[3] 查询其项的辅助大小。如果他们都已经修好了中等规模(在 这种情况下,宽度)然后[3]至少和它的最大宽度一样宽 物品。如果其中一个宽度增加而[3]自身水平增加,那么a 计算新宽度(基于当前可用空间)。顺便说一句:这就是 [1]的高度来自于如果[1]不是根窗格。现在可以根据前面步骤的结果重新定位项目[2]和[3]。 对于[3],这个过程从点1开始(递归地)。 现在,调整对话框的大小就像请求根窗格适应当前窗格一样简单 客户区!实际上这是在OnSize处理器中自动完成的,所以你有 来定义布局本身。 历史 隐藏,收缩,复制Code
// Version: 1.0 [1999/12/04] Initial Article on CodeProject // // 1999/12/10 Erase Backgroung within TabCtrl was 'fixed' badly. Reverted to // old working code // 2000/02/02 When the Dialog is child of a View the class works correctly // now [Didier BULTIAUW] // 2000/02/15 Combo-Boxes were not working correctly (in all modes!) // 2000/02/17 aligned SpinButton Controls (with buddy) now handled // automatically // !! do not add such a control to the layout !! it is always // reattached to its buddy. // 2000/02/17 changed some cotrol class names to the defined constants // // Version: 1.1 [2000/02/17] // // 2000/02/25 fixed auto alignment of SpinButton Controls to only affect // visible ones // 2000/03/07 Fixed growing Dialog after minimizing and restoring // 2000/05/22 Whole Statusbar (Gripper) is not excluded anymore in EraseBkgnd() // instead only the triangular Gripper is excluded // 2000/05/31 Fix for PropertySheets with PSH_WIZARDHASFINISH [Thömmi] // 2000/05/31 Fix for UpDown-Controls with EditCtrl Buddy in PropertyPages. // These were not repositioned every time the page is being show // until the first resize // 2000/07/28 Problems with resizing ActiveX Controls fixed [Micheal Chapman] // 2000/07/28 Some strings were not properly wrapped with _T() // 2000/08/03 Check for BS_GROUPBOX was not correct as BS_GROUPBOX is more // than one Bit // 2000/08/03 New override AddMainArea added to ETSLayoutPropertySheet in order // to have a hook for additional controls in a PropertySheet // (besides the Tab) // 2000/08/03 New override AddButtons added to ETSLayoutPropertySheet in order to // have a hook for additional controls in the bottem pane of a // PropertySheet // // Version: 1.2 [2000/08/05]
版权 本文及所有随附材料均为Erwin Tratar的版权所有。所有权利 保留。 源代码可以以您希望的任何方式(包括在 (商业应用程序),只要你的应用程序添加了必要的代码 不仅仅是一个包装器)到这里找到的功能 源代码本身的再分发,以任何媒体的形式发布或包含在 图书馆要求作者明确书面同意。您不能出售此代码 利润。 隐藏,本软件是“按原样”提供的,没有明示或隐含的保证。使用它 风险自负!作者不承担任何损害/损失的责任 这个产品可能引起的生意。 本文转载于:http://www.diyabc.com/frontweb/news5127.html