1. 程式人生 > 實用技巧 >用於調整視窗大小的助手類

用於調整視窗大小的助手類

介紹 在MFC中,調整或重新定位控制元件可能是相當麻煩的。如果您熟悉。net平臺,那麼通過使用控制元件類的錨和停靠屬性,以及在設計時支援向容器控制元件新增子控制元件,事情會簡化得多。我試著模仿。net的一些特性,但是用c++的方式。 背景 為此,還有其他線上解決方案(也可以在CodeProject.com上)。我認為我的解決方案在設計、簡單和豐富的特性上脫穎而出。 這個解決方案允許你做以下事情: 錨對話方塊控制元件建立面板包含其他面板或UI控制元件限制對話方塊控制元件的大小或面板通過使用最小大小和最大大小屬性對話方塊大小的限制,使用最小大小和最大大小屬性建立水平或垂直分離容器冷凍分離容器,這樣使用者不能使用滑鼠調整面板設定面板的分裂容器被固定,當對話方塊尺寸,固定面板將保持不變集對話方塊控制元件的父或面板(與Win32 SetParent API)顯示調整控制對話方塊的右下角用視覺風格(如果應用程式支援它)顯示調整控制分配器的分裂集裝箱碼頭在其母面板對話方塊控制元件建立流佈局面板 讓我們來看看。net是如何調整子控制元件的大小的: 它允許子控制元件被錨定到左、上、右、下邊緣,或者這四個選項的任意組合。停靠——它允許子控制元件停靠在左、上、右和下邊緣。Visual Studio設計器支援——如果您將一個框架控制元件放置在一個Windows窗體上,然後將一個按鈕控制元件拖動到該框架的頂部,該按鈕將成為框架的實際子控制元件和Windows窗體的孫子控制元件。但在MFC的資源編輯器中,如果您將框架放在對話方塊模板上,然後在框架控制元件的頂部拖動一個按鈕,該按鈕實際上是對話方塊模板的直接子元素,而不是框架。這意味著如果你移動框架,按鈕將不會移動。SplitContainer——自從這個控制元件發明以來,建立拆分器視窗從來沒有這麼簡單過。它有兩個面板,可以容納其他控制元件。表示水平或垂直地動態佈局其內容的面板。 在。net中,所有控制元件都是窗體的子控制元件或子控制元件;這就建立了控制元件的層次結構。當父節點被調整大小或重新定位時,它的所有子節點將根據其錨定或停靠屬性設定調整大小或重新定位。 在我的解決方案中,我建立了一個矩形的層次結構(CRect)。我已經實現了錨、面板、SplitContainer、Dock和FlowLayout概念。 這個解決方案中有幾個類,但是CWndResizer是開發人員將使用的唯一類。 通常,你會在Visual Studio資源編輯器中設計你的對話方塊模板,然後在對話方塊類實現中,你會有一個這樣的成員變數: 隱藏,複製Code

private:
    CWndResizer m_resizer;

本文附帶的示例使用CDialog類演示該類的許多特性。但是這個類可以與任何從CWnd派生的類一起使用(CDialog, CPropertyPage, CPropertySheet, CFrmWnd, CFormView,等等)。 在這個類做任何事情之前,你必須像這樣呼叫鉤子方法: 隱藏,複製Code

BOOL CExample1Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  BOOL bOk = m_resizer.Hook(this);
  ASSERT(bOk == TRUE);
}

在本文中,我將把這個視窗(傳遞給Hook方法)稱為“掛鉤視窗”。 通過呼叫這個方法,它在WndProc鏈中放置了一個視窗過程鉤子。 當您呼叫鉤子方法時,它將鉤子視窗的客戶區儲存在一個名為CPanel的結構中。面板主要是用鉤窗的客戶端座標表示的矩形區域。一個面板可以有零個或多個面板作為子面板。在建立面板期間,您將為面板分配一個惟一的名稱。該名稱用於引用面板或查詢面板。掛鉤視窗的客戶區域是層次結構的根,它被命名為_root。 每個面板都有錨、MinSize和MaxSize屬性(以及其他一些屬性)。但不能直接設定或獲取面板的屬性;相反,您將使用member metCWndResizer類的hods。 其思想是,當CPanel被調整大小或重新定位時,它的所有子元素也會相對地調整大小和重新定位。 現在,讓我們看一些程式碼片段。 下面的程式碼將把對話方塊的OK和Cancel按鈕錨定到右下角: 隱藏,複製Code

BOOL CExample1Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  BOOL bOk = m_resizer.Hook(this);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDOK, ANCHOR_RIGHT | ANCHOR_BOTTOM);
  ASSERT(bOk == TRUE);

  bOk = m_resizer.SetAnchor(IDCANCEL, ANCHOR_RIGHT | ANCHOR_BOTTOM);
  ASSERT(bOk == TRUE);
}

如果你想建立一個面板並將其錨定屬性設定為anchor_horizontal,你可以這樣做: 隱藏,複製Code

BOOL CExample1Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  BOOL bOk = m_resizer.Hook(this);
  ASSERT(bOk == TRUE);
  CRect rc(40, 40, 240, 240);
  bOk = m_resizer.CreatePanel(_T("MyNewPanel"), &rc);

  bOk = m_resizer.SetAnchor(_T("MyNewPanel"), ANCHOR_HORIZONTALLY);
  ASSERT(bOk == TRUE);

  ASSERT(bOk == TRUE);
}

關於剪下(重要) 此解決方案不能剪下對話方塊控制元件的任何部分或面板的任何部分。通常,CPanel物件沒有任何與之關聯的視窗(HWND)。如果一個子面板比它的父面板大,子面板在父面板外面的區域將是可見的,因為父面板和子面板實際上都不是視窗。為了避免這個問題,我們應該通過呼叫SetMinimumSize方法為父面板設定一個合理的最小大小,以便父面板永遠不會小於子面板的最小大小。您還應該考慮設定掛鉤視窗的最小大小,以便它能夠包含其客戶區域內的所有面板。 使用的程式碼 在VS2008中建立的示例應用程式演示了這個類的許多特性。 CWndResizer類有以下成員: CreateFlowLayoutPanel CreatePanel CreateSplitContainer GetAnchor GetAutoHandlePaint GetDock GetFixedPanel GetFlowDirection GetFlowItemSpacingX GetFlowItemSpacingYgettissplitterfixed GetMaximumSize GetMinimumSize GetParent GetShowResizeGrip GetShowSplitterGrip Hook invokeonresize SetAnchor SetAutoHandlePaint SetDock SetFixedPanel SetFlowDirection SetFlowItemSpacingX SetFlowItemSpacingY SetIsSplitterFixed SetMaximumSizeSetMinimumSize SetShowResizeGrip SetShowSplitterGrip Unhook 具體內容如下: 方法BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const CRect * prcPanel); BOOL CreateFlowLayoutPanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE); Description在掛鉤視窗的客戶區建立一個流佈局面板。淨類比)。此面板的唯一名稱。稍後將使用此名稱引用此面板。在掛鉤視窗的客戶端座標中給出的矩形。刪除對話方塊控制元件id陣列。此方法使用此陣列中指定的對話方塊控制元件的組合區域建立面板。如果這是真的,那麼這個方法將為在parrID中指定的每個對話方塊控制元件建立面板,並使它們成為自己的子控制元件。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, panelName不是唯一的或者是空的。 或者, parrID包含一個無效的ID。 FlowLayout面板將其內容按水平或垂直流向排列。它的內容可以從一行包裝到下一行,或者從一列包裝到下一列。 您可以通過呼叫SetFlowDirection方法的值來指定流方向。 其他面板可以是FlowLayout面板的子面板。有了這個功能,您就可以在執行時構建適合對話方塊尺寸的複雜佈局。 方法BOOL CreatePanel(LPCTSTR panelName, const CRect * prcPanel); BOOL CreatePanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE); BOOL CreatePanel(使用UINT panelID); Description在掛鉤視窗的客戶區建立一個面板。此面板的唯一名稱。稍後將使用此名稱引用此面板。在掛鉤視窗的客戶端座標中給出的矩形。刪除對話方塊控制元件id陣列。此方法使用此陣列中指定的對話方塊控制元件的組合區域建立面板。如果為真,那麼該方法將為parrID中指定的每個對話方塊控制元件建立面板,並將它們作為自己的子控制元件。對話方塊控制元件的ID。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, panelName不是唯一的或者是空的。 或者, parrID包含一個無效的ID。 或者, panelID是無效的。 面板建立後,預設情況下會有以下初始設定: 父名:_T("_root") Anchor: ANCHOR_LEFT | ANCHOR_TOP Dock: DOCK_NONE MinimumSize: cx = 10, cy = 10 MaximumSize: cx = 100000, cy = 100000 關於BOOL CreatePanel(UINT panelID): 通常可以對ActiveX或OLE控制元件使用此過載方法。通過這個過載方法建立的面板將使用MoveWindow API重新調整大小/定位。對於其他面板,CWndResizer使用BeginDeferWindowPos、DeferWindowPos和EndDeferWindowPos來調整UI控制元件的大小/位置。 注意:當對話方塊控制元件第一次被引用時,CWndResizer會在內部為對話方塊控制元件建立面板。 關於BOOL CreatePanel(LPCTSTR panelName, const CUIntArray * parrID, BOOL setAsChildren = FALSE): 這種方法可以作為一些技術的捷徑。假設您有一個非常簡單的對話方塊,只有OK和Cancel按鈕,並且您想在底部錨定這兩個按鈕-右下角的對話方塊,然後你可以做以下三種技術中的任何一種來實現這個: 技巧1: 隱藏,Codem_resizer副本。SetAnchor(IDOK, ANCHOR_RIGHT | ANCHOR_BOTTOM); m_resizer。SetAnchor(IDCANCEL, ANCHOR_RIGHT | ANCHOR_BOTTOM) 技巧2: 隱藏,複製CodeCRect rcArea;//兩個按鈕的組合區域 繪圖用的矩形類rcBtn;//區域的單個按鈕 GetDlgItem (IDOK)→GetWindowRect(及rcBtn); rcArea.UnionRect(及rcArea, rcBtn); GetDlgItem (IDCANCEL)→GetWindowRect(及rcBtn); rcArea.UnionRect(及rcArea, rcBtn); ScreenToClient(及rcArea); //建立面板 m_resizer.CreatePanel (_T(“My_OK_Cancel_Panel”),rcArea); //將按鈕設定為新建立面板的子元素 m_resizer。SetParent (IDOK _T (My_OK_Cancel_Panel ")); m_resizer。SetParent (IDCANCEL _T (My_OK_Cancel_Panel ")); //設定新建立的面板的錨 m_resizer.SetAnchor (_T(“My_OK_Cancel_Panel”), ANCHOR_RIGHT | ANCHOR_BOTTOM); 技巧3: 隱藏,CodeCUIntArray arrID影印件; arrID.Add (IDOK); arrID.Add (IDCANCEL); m_resizer.CreatePanel (_T(“My_OK_Cancel_Panel”), , arrID,真正的); m_resizer.SetAnchor (_T(“My_OK_Cancel_Panel”), ANCHOR_RIGHT | ANCHOR_BOTTOM); 技術2和技術3產生了完全相同的面板層級。但是技巧3比技巧2短得多。 方法BOOL CreateSplitContainer(LPCTSTR splitContainerName, LPCTSTR panelNameA, LPCTSTR panelNameB); BOOL CreateSplitContainer(LPCTSTR splitContainerName, LPCTSTR panelNameA, UINT panelIDB); BOOL CreateSplitContainer(LPCTSTR splitContainerName, UINT panelIDA, UINT panelIDB); BOOL CreateSplitContainer(LPCTSTR splitContainerName, UINT panelIDA, LPCTSTR panelNameB); 描述建立一個分割容器(。淨類比)。引數splitContainerName這個分割容器的唯一名稱。稍後將使用此名稱引用此面板。panelnama面板的名稱,該面板是由之前呼叫CWndResizer::CreatePanel或CWndResizer::CreateSplitContainer建立的。 如果結果面板是水平拆分容器,則這指的是拆分容器的左側面板。否則,它就是分割容器的頂部面板。 巢狀視窗的子控制元件(視窗)的ID。 如果結果面板是水平拆分容器,則這指的是拆分容器的左側面板。否則,它就是分割容器的頂部面板。 之前呼叫CWndResizer::CreatePanel或CWndResizer::CreateSplitContainer建立的面板的名稱。 如果結果面板是水平拆分容器,則這指的是拆分容器的右面板。否則,它是拆分容器的底部面板。 巢狀視窗的子控制元件(視窗)的ID。 如果結果面板是水平拆分容器,則這指的是拆分容器的右面板。否則,它是拆分容器的底部面板 返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, splitContainerName, panelNameA, panelIDA, panelNameB或panelIDB不是唯一的或為空。 或者, 指定的面板(矩形)重疊。 或者, 一個或所有指定的面板已經用於建立分割容器。 CWndResizer決定了分割容器應該是水平的還是垂直的。 如果第一個矩形的右成員(第二個引數)小於第二個矩形的左成員(第三個引數),此方法將建立一個水平分割容器。否則,如果第一個矩形的底部成員(第二個引數)小於第二個矩形的頂部成員(第三個引數),此方法將建立一個垂直分割容器。 CSplitContainer的定義 CSplitContainer由兩個csplitpanel和一個CSplitterPanel組成。CSplitterPanel包含CSplitterGripperPanel。 如果您將滑鼠移動到CSplitContainer的兩個面板(CSplitPanel)之間的空間(CSpitterPanel)上,滑鼠指標將會改變。然後您可以按下滑鼠左鍵並拖動來調整面板的大小。如果面板的父面板調整了大小,則拆分器面板的兩個面板將按比例調整大小。 方法BOOL GetAnchor(LPCTSTR panelName, UINT &錨); UINT panelID, UINT &錨); Description獲取指定面板的錨(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。錨接收錨值。返回值為真。錨包含一個有效值。錯誤的失敗。錨值應該被忽略。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 備註檢索麵板的錨定值。詳情請參閱SetAnchor。BOOL GetAutoHandlePaint()方法; 描述獲取CWndResizer是否應該自動處理油漆。返回值為真。錨包含一個有效值。錯誤的失敗。錨值應該被忽略。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 備註詳情請參閱SetAutoHandlePaint。方法GetDock(LPCTSTR panelName, UINT &uDock); UINT panelID, UINT &uDock); Description獲取指定面板的錨(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。uDock接收dock值。返回值為真。錨包含一個有效值。錯誤的失敗。錨值應該被忽略。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 備註檢索麵板的停靠值。詳細資訊請參見SetDock。方法BOOL GetFixedPanel(LPCTSTR splitContainer, short &面板);Description獲取固定面板的名稱(如果有的話)。淨類比)。引數splitContainerName分割容器的名稱,該分割容器是由之前呼叫CWndResizer建立的::CreateSplitContainer。面板接收固定面板的ID。如果它包含1,那麼左側面板(如果splitContainer是一個垂直分隔容器,則頂部面板)是固定的;如果它是2,則右側面板(如果splitContainer是一個垂直分隔容器,則底部面板)是固定的。否則,splitContainer沒有固定面板。返回值為真。面板包含一個有效值。錯誤的失敗。面板值應該被忽略。 鉤子方法沒有被呼叫。 或者, splitContainerName無效。 備註檢索一個分割容器的固定面板ID。有關詳細資訊,請參見SetSetFixedPanel。方法BOOL GetFlowDirection(LPCTSTR flowPanelName, short &方向);說明獲取流面板的流方向(。淨類比)。引數flowPanelName分割容器的名稱,它是由之前呼叫CWndResizer建立的::CreateFlowLayoutPanel。方向接收流板的流向。返回值為真。方向包含一個有效值。錯誤的失敗。方向值應該被忽略。 鉤子方法沒有被呼叫。 或者, flowPanelName無效。 詳細資訊請參見SetFlowDirection。方法BOOL GetFlowItemSpacingX(LPCTSTR flowPanelName, int &nSpace);說明獲取流面板中x方向項之間的間距。引數flowPanelName分割容器的名稱,它是由之前呼叫CWndResizer建立的::CreateFlowLayoutPanel。nSpace接收以畫素為單位的空間。返回值為真。面板包含一個有效值。錯誤的失敗。nSpace值應該被忽略。 鉤子方法沒有被呼叫。 或者, flowPanelName無效。 詳情請參見SetFlowItemSpacingX。方法BOOL GetFlowItemSpacingY(LPCTSTR flowPanelName, int &nSpace);說明獲取流面板中y方向項之間的間距。引數flowPanelName分割容器的名稱,它是由之前呼叫CWndResizer建立的::CreateFlowLayoutPanel。nSpace接收以畫素為單位的空間。返回值為真。面板包含一個有效值。錯誤的失敗。nSpace值應該被忽略。 鉤子方法沒有被呼叫。 或者, flowPanelName無效。 詳情請參見SetFlowItemSpacingY。方法BOOL GetIsSplitterFixed(LPCTSTR splitContainerName, BOOL &fixed);描述獲取拆分容器的拆分器是否被設定為固定(。淨類比)。引數splitContainerName分割容器的名稱,該分割容器是由之前呼叫CWndResizer建立的::CreateSplitContainer。固定接收布林值。如果這是真的,那麼分割器是固定的;否則,拆分器可以由滑鼠自由移動。返回值為真。固定包含一個有效的值。錯誤的失敗。固定值應該被忽略。 鉤子方法沒有被呼叫。 或者, splitContainerName無效。 備註檢索一個標誌,該標誌指示拆分容器的拆分器是否可以由滑鼠自由移動。有關詳細資訊,請參見SetIsSplitterFixed。方法BOOL GetMaximumSize(LPCTSTR panelName, CSize &大小); (UINT panelID, CSize &大小); Description獲取指定面板的最大大小(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。返回值為真。size包含有效值。錯誤的失敗。大小值應該被忽略。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 如果panelName或panelID引用的面板是水平分割容器的一部分,則CSize::cy成員應被忽略。如果panelName或panelID指的是panel是垂直分割容器的一部分,那麼CSize::cx成員應該被忽略。方法BOOL GetMinimumSize(LPCTSTR panelName, CSize &大小); (UINT panelID, CSize &大小); Description獲取指定面板的最小大小(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。返回值為真。size包含有效值。錯誤的失敗。大小值應該被忽略。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 如果panelName或panelID引用的面板是水平分割容器的一部分,則CSize::cy成員應被忽略。如果panelName或panelID引用的面板是一個垂直分離容器的一部分,那麼CSize::cx成員應被忽略。方法BOOL GetParent(LPCTSTR panelName, CString &parentName); UINT panelID, CString &parentName); Description獲取指定面板的父面板的名稱。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。parentName接收父節點的名稱。返回值為真。parentName包含一個有效值。錯誤的失敗。大小值應該被忽略。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 如果parentName是_root,則說明該面板是掛鉤視窗的直接子視窗。BOOL GetShowResizeGrip()方法;如果在掛鉤視窗的右下角繪製了一個調整大小的手柄,說明將顯示一個標誌指示。無引數。它將在對話方塊/視窗的右下角繪製一個調整大小的手柄。FALSE它不會在對話方塊/視窗的右下角繪製一個調整大小的手柄。這個方法永遠不會失敗。方法BOOL GetShowSplitterGrip(LPCTSTR splitContainerName, BOOL &bShow);描述獲取拆分容器的拆分柄是否可見。引數splitContainerName分割容器的名稱,該分割容器是由之前呼叫CWndResizer建立的::CreateSplitContainer。bShow接收一個布林值。如果這是真的,那麼splitter抓地力是可見的,否則splitter抓地力是隱藏的。返回值為真。錯誤的失敗。bShow值應該被忽略。 鉤子方法沒有被呼叫。 或者, splitContainerName無效。 N/A方法BOOL Hook(CWnd * pWnd);描述在WndProc鏈中放置了一個鉤子。引數pWnd一個指向要調整大小的CWnd及其子控制元件的指標。返回值為真。錯誤的失敗。 pWnd無效。 或者, 此方法已經被呼叫過一次。 您必須在呼叫任何其他方法之前呼叫此方法。 pWnd指向的視窗稱為“掛鉤視窗”。 BOOL InvokeOnResized()方法;描述模擬掛鉤視窗的大小調整。無引數。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 這個方法傳送一個WM_SIZE訊息到掛鉤視窗。 在建立了必要的面板和設定錨點之後,您可能希望呼叫它來初始應用設定。 方法BOOL SetAnchor(LPCTSTR panelName, UINT &錨); UINT panelID, UINT &錨); Description設定指定面板的錨(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。錨錨值。看到評論。返回值為真。錨包含有效值。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 講話錨可以下列一個或多個: 錨值描述ANCHOR_LEFT錨其母面板的左邊緣。這是預設的面板。ANCHOR_TOP錨其母面板的頂部邊緣。這是預設的面板。ANCHOR_RIGHT錨板的右邊緣其母。ANCHOR_BOTTOM錨板的底部邊緣。ANCHOR_CENTER_HORIZONTALLY父矩形內的面板水平居中。它有更高的優先順序比ANCHOR_ALL。net沒有類似的支援。ANCHOR_CENTER_VERTICALLY父矩形內的面板垂直居中。它有更高的優先順序比ANCHOR_ALL。net沒有類似的支援。如果使用ANCHOR_HORIZONTALLY ANCHOR_PRIORITY_RIGHT這僅僅是有用的。如果面板的寬度大於允許的最大寬度,預設情況下,面板的左邊緣將錨定並右邊緣將釋放適應的最大大小。如果這是指定的,那麼右邊緣將錨定並左邊緣將釋放適應的最大大小。net沒有類似的支援。如果使用ANCHOR_VERTICALLY ANCHOR_PRIORITY_BOTTOM這僅僅是有用的。如果面板的高度增長大於允許的最大高度,預設情況下,面板的上邊緣固定和底部邊緣會被釋放到適應的最大大小。如果這是指定的,那麼底部邊緣將錨定並頂部邊緣將釋放適應的最大大小。net沒有類似的支援。ANCHOR_VERTICALLY (ANCHOR_TOP | ANCHOR_BOTTOM) ANCHOR_HORIZONTALLY (ANCHOR_LEFT | ANCHOR_RIGHT) ANCHOR_ALL (ANCHOR_VERTICALLY | ANCHOR_HORIZONTALLY) 注意:一個面板永遠長不到其允許的最小大小,超過允許的最大尺寸。 方法BOOL SetAutoHandlePaint (BOOL bHandle); 描述集塗料是否應該被CWndResizer自動處理。引數bHandle真實如果CWndResizer自動處理WM_PAINT訊息。否則錯誤。返回值真總是返回TRUE假永遠不會返回FALSE。她的講話e就是一個例子: 隱藏,收縮,複製CodeBOOL CTestDlg: OnInitDialog () { CDialog: OnInitDialog (); BOOL bOk = FALSE; 博克= m_resizer.Hook(這個); 斷言(博克); //關閉自動油漆手柄 m_resizer.SetAutoHandlePaint(假); m_resizer.SetShowResizeGrip(真正的); 博克= m_resizer.InvokeOnResized (); 斷言(博克); 返回TRUE; } 空白CTestDlg: OnPaint () { CPaintDC直流(這個);//繪製的裝置上下文 //你的自定義圖 rect(10, 20, 60, 60); CBrush刷(RGB (0, 0, 0)); 直流。FillRect(矩形和刷); //呼叫CWndResizer::Draw方法,使它可以繪製 //任何從CVisualPanel派生的類 m_resizer.Draw(及直流);// <=呼叫繪製方法 } 方法SetDock(LPCTSTR panelName, UINT &uDock); UINT panelID, UINT &uDock); 描述設定指定面板的停靠(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。uDock碼頭的價值。看到評論。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 uDock可以是下列之一: DOCK_NONE面板將不會被停靠。這是預設的面板。DOCK_LEFT面板將停靠在其父面板的左邊緣。DOCK_TOP面板將停靠在其父面板的上邊緣。DOCK_RIGHT面板將停靠在其父面板的右邊緣。DOCK_BOTTOM面板將停靠在其父面板的下邊緣。 方法BOOL SetFixedPanel(LPCTSTR splitContainerName, short panel);說明將拆分容器的一個面板設定為固定(。淨類比)。引數splitContainerName:先前呼叫CWndResizer建立的面板的名稱::CreateSplitContainer。固定面板的面板ID。如果它包含1,那麼左側面板(如果splitContainer是一個垂直分隔容器,則頂部面板)是固定的;如果它是2,則右側面板(如果splitContainer是一個垂直分隔容器,則底部面板)是固定的。否則,splitContainer沒有固定面板。返回值正確成功了。錯誤的失敗。 鉤子方法沒有被呼叫。 當掛鉤視窗調整大小時,固定面板保持不變,而其他面板調整大小。 注意:一個面板永遠長不到其允許的最小大小,超過允許的最大尺寸。 方法BOOL SetFlowDirection(LPCTSTR flowPanelName, short direction);描述設定流面板的流向(。淨類比)。引數flowPanelName分割容器的名稱,它是由之前呼叫CWndResizer建立的::CreateFlowLayoutPanel。流板的流向。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, flowPanelName無效。 將方向設定為1表示從左到右的方向,其他任何值將表示從上到下的方向。方法BOOL SetFlowItemSpacingX(LPCTSTR flowPanelName, int nSpace);說明設定流面板中x方向項之間的間距。引數flowPanelName分割容器的名稱,它是由之前呼叫CWndResizer建立的::CreateFlowLayoutPanel。nSpace,空間單位是畫素。返回值為真。錯誤的失敗。nSpace值應該被忽略。 鉤子方法沒有被呼叫。 或者, flowPanelName無效。 如果流的方向是從左到右,nSpace表示x方向上兩個專案之間的空格,否則表示專案的兩列之間的空格。方法BOOL SetFlowItemSpacingY(LPCTSTR flowPanelName, int &nSpace);說明獲取流面板中y方向項之間的間距。引數flowPanelName分割容器的名稱,它是由之前呼叫CWndResizer建立的::CreateFlowLayoutPanel。nSpace,空間單位是畫素。返回值為真。錯誤的失敗。nSpace值應該被忽略。 鉤子方法沒有被呼叫。 或者, flowPanelName無效。 如果流的方向是從左到右,nSpace表示y方向上兩個專案之間的空格,否則表示兩行專案之間的空格。方法BOOL SetIsSplitterFixed(LPCTSTR splitContainerName, BOOL fixed);描述設定拆分容器的拆分器是否被設定為固定(。淨類比)。引數splitContainerName分割容器的名稱,該分割容器是由之前呼叫CWndResizer建立的::CreateSplitContainer。固定一個布林值。如果這是真的,那麼拆分器是固定的,否則拆分器是自由移動的滑鼠。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 如果拆分器被設定為固定,使用者不能使用滑鼠移動拆分器。方法BOOL SetMaximumSize(LPCTSTR panelName, CSize &大小); (UINT panelID, CSize &大小); 描述設定指定面板的最大尺寸(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。面板的最小尺寸。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, size小於CWndResizer::GetMinimumSize。 如果panelName或panelID引用的面板是水平分割容器的一部分,則應忽略cy成員的大小。如果panelName或panelID指的是一個面板,該面板是一個垂直分離容器的一部分,那麼cx成員的大小應該被忽略。方法SetMinimumSize(LPCTSTR panelName, CSize &大小); (UINT panelID, CSize &大小); 描述設定指定面板的最小尺寸(。淨類比)。引數panelName先前呼叫CWndResizer::CreatePanel建立的面板的名稱。鉤窗的子控制元件(視窗)的ID。返回值為真。錯誤的失敗。 鉤子方法沒有被呼叫。 或者, panelName或panelID無效。 如果panelName或panelID引用的面板是水平分割容器的一部分,則應忽略cy成員的大小。如果panelName或panelID指的是一個面板,該面板是一個垂直分離容器的一部分,那麼cx成員的大小應該被忽略。方法BOOL SetParent (LPCTSTR panelName, LPCTSTR parentName); BOOL SetParent(使用UINT panelID LPCTSTR parentName); BOOL SetParent (LPCTSTR panelName,使用UINT parentID); BOOL SetParent(使用UINT panelID使用UINT parentID); 描述集的母公司的名稱指定的面板。引數panelName名稱的前面板是由一個叫CWndResizer:: CreatePanel。panelID子控制元件的ID hooked-window(視窗)。parentID母公司的名稱。parentName母公司的名稱。返回值真的成功了。parentName包含一個有效值。錯誤的失敗。大小值應該被忽略。 CWndResizer::鉤方法沒有被呼叫。 或者, panelName、panelID parentName或parentName無效。 評論這個不應該被認為是Win32 SetParent API。 設定parentName _root表明,面板是立即hooked-window的孩子。 方法空白SetShowResizeGrip (BOOL顯示= TRUE);描述設定一個標誌指示如果調整控制將hooked-window的右下角。引數顯示正確,如果調整控制應該吸引,否則錯誤的。返回值N /無返回值。評論這個方法從未失敗。方法BOOL SetShowSplitterGrip (LPCTSTR splitContainerName BOOL bShow);描述設定一個標誌指示是否顯示或隱藏爪分離器的分離容器。引數splitContainerName分離容器的名稱之前,是由一個叫CWndResizer:: CreateSplitContainer。bShow真實如果調整控制應該吸引,否則隱藏。返回值真的成功了。錯誤的失敗。 CWndResizer::鉤方法沒有被呼叫。 或者, splitContainerName是無效的。 評論這個方法從未失敗。BOOL解開()方法;引數N /一個沒有引數。返回值真的成功了。錯誤的失敗。 CWndResizer::鉤方法沒有被呼叫。 的話你不需要呼叫這個方法。 當掛鉤視窗收到WM_DESTROY訊息時,會自動呼叫這個方法。 的興趣點 這個解不需要你計算任何數字。此解決方案封裝了CWndResizer中的所有功能。 可以重新設計它,使它暴露其他物件(CPanel、CSplitContainer等)。我這樣設計它的原因是我不想讓使用者知道太多的物件,並簡化記憶體分配和釋放。 另一件事是它依賴於MFC類(CWnd等);同樣,您可以刪除所有對MFC類的引用,並使用純Win32 api。 歷史 2011年1月13日:文章更新,包括新特性,對接和FlowLayoutPanel 2011年2月25日:CWndResizer:解開方法改變按成員2272507的評論2011年3月16日:更新演示和原始碼2011年5月23日:更新演示和原始碼1 2011年8月:演示和原始碼2011年8月17日更新:更新演示和原始碼,現在支援滾動CFormView 7 2011年12月:演示和原始碼2013年1月25日更新:新的例子新增(11例)和一個bug修正2013年6月28日:2013年11月9日更新的原始碼:使用者報告錯誤9例子是固定在2014年10月20日:新增三個新方法:畫(CPaintDC * pDC), GetAutoHandlePaint()和SetAutoHandlePaint (BOOL bHandle)。當你有了自定義的繪畫時,這些會很有幫助。有關詳細資訊,請參閱上面的文件。2014年10月20日:修復報告的bug 本文轉載於:http://www.diyabc.com/frontweb/news5209.html