65.9K
CodeProject 正在变化。 阅读更多。
Home

WTL 中的对话框大小调整:Paolo Messina 的 MFC ResizableLib 移植。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.23/5 (11投票s)

2005年2月21日

CPOL

4分钟阅读

viewsIcon

63058

downloadIcon

2903

一篇关于如何使用 WTL 制作可调整大小的对话框的文章。

引言

首先,关于窗口大小调整的问题。例如,我们有一个对话框窗口,其中包含一些子控件(图 1)。

图 1

我们希望实现以下行为:当对话框大小改变时,一些子控件的大小也必须改变。在这个例子中,标有“Static”的 GroupBox 必须与窗口的左、上、右、下边缘保持相同的间距,而 ListBox 的行为应与 GroupBox 相同。“OK”按钮应保持在窗口的左下角,“About...”按钮应保持在右下角,而“Cancel”按钮应保持在窗口的中心。调整大小后的对话框显示在下一张图片中(图 2)。

图 2

要使子控件如上所述进行调整大小,并没有简单的方法。最简单的方法是处理 WM_SIZE 消息,并在消息处理程序中设置每个控件的位置。当控件数量不是很多时,这种方法是可行的。如果我们有更复杂的对话框,那么我们需要一些标准方法来描述控件的重新定位行为。

很久以前,我为 MFC 找到了一个出色的库,可以帮助设计可调整大小的对话框,该对话框没有闪烁,并且具有非常简单的调整大小行为描述。该库名为 ResizableLib。它由 Paolo Messina 创建,您可以在此处找到它。我决定将其移植到 WTL,这就是这项工作的结果。

WTL 也实现了大小调整:CDialogResize<> 模板,但 ResizableLib 具有更多功能。

  • 对大多数控件提供抗闪烁支持。
  • 支持任何窗口的 MinMaxInfo。
  • 支持保存/恢复窗口大小和位置。
  • 支持可调整大小的属性表和向导。
  • 可以将大小调整机制附加到任何窗口(不仅仅是对话框)。
  • 简单的控件行为描述。
  • 使对话框可调整大小所需的最小代码。

库内容

此库中包含的文件。
ResizableDialog.h

可调整大小的对话框实现。

ResizableGrip.h 可调整大小的抓手控件实现以及拥有抓手的窗口模板。
ResizableLayout.h 调整布局管理器实现。处理大小调整、子控件剪裁等。
ResizableMinMax.h 最小和最大窗口大小支持。
ResizablePage.h 可调整大小的属性页实现。
ResizableSheet.h 可调整大小的属性表实现。
ResizableState.h 支持大小和位置存储。
ResizableMsgSupport.h 对于自定义控件,我们可以使用消息来确定如何剪裁和刷新它。
ResizableVersion.h 支持文件,用于正确确定 Windows 和 shell 版本。
RegisteredMsg.h 用户注册消息的支持文件。
ResizableLib.h 此文件包含以上所有内容。

使用代码

如果您想使用 WTL ResizableLib,则必须完成以下步骤:

  • 将库提取到一个名为 ResizableLib 或任何其他名称的文件夹中。
  • 在您的项目中,将库路径添加到 include 搜索路径。
  • 在您的 stdafx.h 中插入 #include "ResizableLib.h"
  • 请参阅本文的下一个示例,以简化大小调整。

这里有一个使用 ResizableLib 和 WTL 对话框的小代码示例,如上文所述。

#pragma once
#include <ResizableLib.h>


// MainDlg class

class CMainDlg:
  public CResizableDialogImpl<CMainDlg>,
// Your inherited classes

  public CUpdateUI<CMainDlg>,
  public CMessageFilter, 
  public CIdleHandler
{
  typedef CResizableDialogImpl<CMainDlg> baseClass;
public:
  enum { IDD = IDD_MAINDLG };

  virtual BOOL PreTranslateMessage(MSG* pMsg);
  virtual BOOL OnIdle();

  BEGIN_UPDATE_UI_MAP(CMainDlg)
  END_UPDATE_UI_MAP()

  BEGIN_MSG_MAP(CMainDlg)
    CHAIN_MSG_MAP(baseClass) // First hadle messages 

                             // in base class message map

    MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
    COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
    COMMAND_ID_HANDLER(IDOK, OnOK)
    COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
  END_MSG_MAP()

  LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, 
             LPARAM /*lParam*/, BOOL& /*bHandled*/);
  LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, 
              HWND /*hWndCtl*/, BOOL& /*bHandled*/);
  LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, 
              HWND /*hWndCtl*/, BOOL& /*bHandled*/);
  LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, 
             HWND /*hWndCtl*/, BOOL& /*bHandled*/);
  // Your methods here

};

OnInitDialog 的实现中,您必须添加以下行:

// GrouBox behavior

AddAnchor(IDC_S1, TOP_LEFT, BOTTOM_RIGHT);
// ListBox behavior

AddAnchor(IDC_LIST1, TOP_LEFT, BOTTOM_RIGHT);
// OK Button behavior

AddAnchor(IDOK, BOTTOM_LEFT);
// Cancel Button behavior

AddAnchor(IDCANCEL, BOTTOM_CENTER);
// About Button behavior

AddAnchor(ID_APP_ABOUT, BOTTOM_RIGHT);

最后一步:如果您想保存和恢复对话框的大小和位置,您必须添加以下行:

EnableSaveRestore(HKEY_CURRENT_USER, "Software\\AlexTheBoss\\Settings\\", 
                                             PLACEMENT_ENT, "MainDlg");
// HKEY_CURRENT_USER: registry root key
// Software\\AlexTheBoss\\Settings\\: your application registry key
// PLACEMENT_ENT: define for windowplacment subkey
// MainDlg: your dialog name for storing placement in registry

这就是让您的对话框可调整大小所需的一切!

限制和问题

  • 由于 WTL 的架构,您必须在对话框模板中手动设置 WS_THICKFRAME
  • Groupboxes 在带主题的 WinXP 对话框中仍然会闪烁。
  • 启用 XP 主题后,如果主题窗口框架不是矩形,您可能会在调整大小时看到无效的窗口框架。

下载次数

要构建演示项目,请创建一个新文件夹并将两个存档解压到该文件夹中,然后打开 ResizeTest.sln 并进行构建。简单的演示项目包含一个非常简单的对话框大小调整示例,您可以在上面的屏幕截图中看到。

在完整的演示中,您可以看到 ResizableLib 的最强大功能。

  • 具有比例缩放的可调整大小的对话框。
  • 可调整大小的属性表和向导。
  • 带对话框的分割窗口位于其右侧窗格中。
  • 主框架包含窗口位置的加载和保存。
  • 主框架处理 MinMaxInfo。

历史

  • 2005 年 2 月 18 日
    • 首次公开发布。
  • 2005 年 2 月 24 日
    • 修复了 CResizableLayout<T>WM_NCCALCSIZE 处理程序的错误。
    • 添加了新的大型示例。
    • 文章已更新。
© . All rights reserved.