1. 程式人生 > 實用技巧 >用於對話方塊,窗體檢視,對話方塊和屬性型別的佈局管理器

用於對話方塊,窗體檢視,對話方塊和屬性型別的佈局管理器

作品簡介: 如果你經常使用對話方塊,想調整他們你就會注意到沒有 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