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

简单且功能更强大的可调整大小对话框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (29投票s)

2004年9月27日

4分钟阅读

viewsIcon

237655

downloadIcon

8572

一个简单的可调整大小对话框,可在 NONE、RESIZE、REPOS、RELATIVE、ZOOM、DELTA_ZOOM 模式下进行调整,并在不同方向(左、上、右、下)表现不同。

示例对话框

  1. 原始对话框
  2. 右下角调整大小后的对话框
  3. 左上角调整大小后的对话框

引言

此类可调整大小的对话框类可以自动调整控件的位置和/或大小,因为对话框被调整了大小。重新定位和调整大小是方向敏感的(可以分别处理左和右、上和下的情况),并表现为以下六种方式之一:NONE、RESIZE、REPOS、RELATIVE、ZOOM、DELTA_ZOOM(有关更多信息,请参见下文)。

背景

此类源自 Flicker-Free Resizing Dialog(感谢 Andy Brown)。Andy Brown 解决了闪烁问题(这曾经让我非常困扰),他的类支持 NONE、RESIZE、REPOS、RELATIVE 模式的调整大小。

但是,我需要更可控的重新定位和/或调整大小处理程序,我认为其他人也需要。因此,我增强了 Andy Brown 的类,并编写了此类,增加了以下功能:

  1. 重新定位和调整大小是方向敏感的。例如,Andy Brown 的类将对话框的左右拖动视为相同的调整(x 方向)。此类可以分别处理它们。
  2. 对话框缩放时进行控件缩放。
  3. 能够相应地调整一个以上控件的位置和/或大小,这些控件位于同一 X/Y 级别。例如,此类可以使同一水平线上的两个控件的大小调整为对话框更改宽度的 50%,换句话说,如果对话框的宽度增加了 10 像素,此类将每个控件的宽度增加 5 像素。

使用代码

  1. ResizeDlg.cppResizeDlg.h 添加到您的项目或 Makefile 中;
  2. stdafx.h 文件或您的对话框头文件中添加 "#Include ResizeDlg.h";
  3. 通过将对话框头文件和实现文件中的所有 "CDialog" 实例替换为 "CResizeDlg",使您的对话框派生类继承自 CResizeDlg 而不是 CDialog
  4. 如果尚未添加,请为您的对话框类中的 WM_INITDIALOG 添加一个处理程序,如下所述。

WM_INITDIALOG (OnInitDialog)

OnInitDialog 处理程序中,您应该调用基类的 OnInitDialog,并为需要随对话框大小调整而自动重新定位和/或调整大小的控件调用 AddControl。以下是一个示例。

//
// the minimal work you have to do in your OnInitDialog handler.
//
BOOL CMyDialog::OnInitDialog()
{
 CResizeDlg::OnInitDialog();

 AddControl(IDOK, CST_REPOS, CST_REPOS, CST_NONE, CST_NONE, 1);
 AddControl(IDCANCEL, CST_REPOS, CST_REPOS, CST_NONE, CST_NONE, 1);
 
 return TRUE;
}

控件如何重新定位和/或调整大小

此类允许控件在每个方向(左、上、右、下)上动态地重新定位和/或调整大小,方式如下。

CST_NONE 在此方向上不重新定位和调整大小;
CST_RESIZE 在此方向上按对话框更改的大小调整控件的大小。
    //
    // in x direction, where deltaX is 
    // dialog's changed-width.
    //
    ctrlRect.right += deltaX;
CST_REPOS 在此方向上按对话框更改的大小重新定位控件。
    //
    // in x direction, where deltaX is dialog's 
    // changed-width.
    //
    ctrlRect.left += deltaX;
    ctrlRect.right += deltaX;
CST_RELATIVE 按用户定义的比例重新定位控件(使控件始终在对话框中处于相同的比例位置)。
    //
    // in x direction, where m_xRatio is 
    // user-defined proportion
    // pnRect is dialog's new ClientRect
    //
    newCx = ctrlRect.Width();
    ctrlRect.left = (int)(m_xRatio * 
        pnRect->Width() - newCx / 2.0);
    ctrlRect.right = ctrlRect.left + newCx;
CST_ZOOM 自动重新定位和调整控件大小
    //
    // in x direction, where pnRect is 
    // dialog's new ClientRect.
    // pR0 is dialog's original ClientRect
    // (NOT previous width).
    //
    ctrlRect.left = (int)(1.0 * ctrlRect.left  
       * (double)pnRect->Width() / pR0->Width());
    ctrlRect.right = (int)(1.0 * ctrlRect.right 
       * (double)pnRect->Width() / pR0->Width());
CST_DELTA_ZOOM 按比例重新定位和调整控件大小,两种比例都可以分别设置。
    //
    // in x direction, where deltaX0 is 
    // the dialog's chenged-width
    // compared with its original width(NOT 
    // previous width, otherwise error 
    // will mess the result).
    // m_xRatio is user defined X-reposition 
    // proportion and
    // m_cxRatio is user defined X-size proportion.
    //
    newCx = ctrlRect.Width();
    ctrlRect.right = (int)(ctrlRect.left + 
      deltaX0 * m_xRatio + newCx + deltaX0 * m_cxRatio);
    ctrlRect.left += (int)(deltaX0 * m_xRatio);

AddControl 的用法

您应该在 OnInitDialog 中调用 AddControl 来设置控件在对话框调整大小时的行为。其原型如下:

void AddControl( UINT nID, int xl, int xr, int yt, 
              int yb, int bFlickerFree = 0, 
              double xRatio = -1.0, double cxRatio = -1.0,
              double yRatio = -1.0, double cyRatio = -1.0 );
其中
nID 控件的资源 ID
xl 对话框向左调整大小时控件如何重新定位和/或调整大小。设置为 CST_xx 之一。
xr 对话框向右调整大小时控件如何重新定位和/或调整大小。设置为 CST_xx 之一。
yt 对话框向上调整大小时控件如何重新定位和/或调整大小。设置为 CST_xx 之一。
yb 对话框向下调整大小时控件如何重新定位和/或调整大小。设置为 CST_xx 之一。
bFlickerFree 重新定位和/或调整此控件大小时是否尝试避免闪烁
xRatio 用户定义的 x 方向重新定位比例。仅在 xl 或 xr 为 CST_RELATIVE 或 CST_DELTA_ZOOM 时有效。设置为 0.0~1.0。
cxRatio 用户定义的 x 方向调整大小比例。仅在 xl 或 xr 为 CST_DELTA_ZOOM 时有效。设置为 0.0~1.0。
yRatio 用户定义的 y 方向重新定位比例。仅在 yt 或 yb 为 CST_RELATIVE 或 CST_DELTA_ZOOM 时有效。设置为 0.0~1.0。
cyRatio 用户定义的 y 方向调整大小比例。仅在 yt 或 yb 为 CST_DELTA_ZOOM 时有效。设置为 0.0~1.0。

AddControl 的典型用法

  1. 使编辑控件水平调整大小以适应对话框大小。
    AddControl(edit-ID, CST_RESIZE, CST_RESIZE,
     CST_NONE, CST_NONE, 1);
  2. 使右上角的按钮保持在相同的右上方位置。
    AddControl(button-ID, CST_REPOS, CST_REPOS,
     CST_NONE, CST_NONE, 1);
  3. 保持按钮与底部和水平中心固定距离。
    AddControl(button-ID, CST_RELATIVE, CST_RELATIVE,
     CST_REPOS, CST_REPOS, 1, 1.0);
  4. 两个编辑控件在同一水平线上,当对话框向左调整大小时,使左侧编辑控件调整大小,右侧编辑控件保持相同大小;或当对话框向右调整大小时,使左侧编辑控件保持相同大小,右侧编辑控件调整大小。
    AddControl(left-edit-ID, CST_RESIZE, 
     CST_NONE, CST_NONE, CST_NONE, CST_NONE, 1);
    AddControl(right-edit-ID, CST_REPOS,
     CST_RESIZE, CST_NONE, CST_NONE, 1);
  5. 以示例 4 的两个编辑控件为例。使它们的大小共享对话框更改宽度的相同比例。换句话说,如果对话框的宽度增加 10 像素,那么每个编辑控件的宽度分别增加 5 像素。
    AddControl(left-edit-ID, CST_DELTA_ZOOM, CST_DELTA_ZOOM,
     CST_NONE, CST_NONE, 1, 0.0, 0.5);
    AddControl(right-edit-ID, CST_DELTA_ZOOM, CST_DELTA_ZOOM,
     CST_NONE, CST_NONE, 1, 0.5, 0.5);
    其中 0.0, 0.5 表示左侧编辑控件在其位置和大小上不随对话框宽度更改而改变,而是按对话框更改宽度的 50% 进行调整大小。0.5, 0.5 表示右侧编辑控件按 50% 的比例重新定位,并且由于左侧控件调整了大小,因此它必须重新定位,并按对话框更改宽度的 50% 进行调整大小。

注意

  1. Resize-grip(对话框右下角的 )的资源 ID (IDC_DLGSIZEBOX) 在 ResizeDlg.h 中定义。如果您已在其他地方使用了该 ID,则应将其设置为另一个未使用的资源 ID。
  2. 请勿为对话框中的组合控件设置闪烁消除(在调用 AddControl 时将 bFlickerFree 设置为 0)。

历史

  1. 2004 年 9 月 26 日 - 初始公开发布。
© . All rights reserved.