zoukankan      html  css  js  c++  java
  • 用于对话框,窗体视图,对话框和属性类型的布局管理器

    作品简介: 如果你经常使用对话框,想调整他们你就会注意到没有 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

  • 相关阅读:
    49. 字母异位词分组
    73. 矩阵置零
    Razor语法问题(foreach里面嵌套if)
    多线程问题
    Get json formatted string from web by sending HttpWebRequest and then deserialize it to get needed data
    How to execute tons of tasks parallelly with TPL method?
    How to sort the dictionary by the value field
    How to customize the console applicaton
    What is the difference for delete/truncate/drop
    How to call C/C++ sytle function from C# solution?
  • 原文地址:https://www.cnblogs.com/Dincat/p/13462337.html
Copyright © 2011-2022 走看看