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

ResizableLib - 一组用于简化 MFC 可调整大小窗口开发的类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (76投票s)

2001 年 6 月 11 日

CPOL

22分钟阅读

viewsIcon

1853506

downloadIcon

31007

类库,使 MFC 开发人员的可调整大小窗口开发更轻松,用户体验更愉快

注意:新版本将在 GitHub 上发布。

A resizable dialog! A resizable property sheet!

A resizable Wizard 97 style dialog A resizable form view

新闻和发布说明

我早在 2000 年(正如你从上面的旧截图所见)就开始了这一切,当时我还是个学生,纯粹是出于兴趣。但我一直想与其他的开发人员分享它,听取他们的评论,并从中学习经验。

现在我不再有太多时间用于我的业余项目,但我很高兴这段代码仍然对许多人有用。

经过多年的准休眠状态,大约在 2015 年,我决定将这个项目放到 GitHub 上,在那里我也开始为一些开源项目(主要是与工作相关的)做出贡献。

我希望这能为 ResizableLib 带来一股新鲜空气,并帮助这个旧库跟上最新的软件开发和操作系统版本,也许还能收到更多来自开发人员社区的贡献。

请查看 https://github.com/ppescher/resizablelib[^]。

我已经迁移了托管在 SourceForge 上的旧 CVS 仓库,因此自上次正式发布以来的所有小改进以及所有先前的开发历史现在都在那里。

请注意,以下文章和文档不完整,仍指旧版本的库,但我保留它是出于历史原因。也许我将来会找到时间来更新它。

ResizableLib - 它是什么以及为什么?

这个类库旨在使 MFC 开发人员的可调整大小窗口开发更容易一些,并为用户提供更愉快的体验。在此上下文中,可调整大小的窗口是指一个窗口,不一定是顶级窗口,一旦由用户或开发人员调整大小,就能够自动适当地调整其子控件的大小和位置。

要创建一个可调整大小的窗口,你可以使用这组“低级”类

CResizableGrip 实现用于顶级可调整大小窗口的尺寸手柄
CResizableMinMax 实现尺寸约束和最大化窗口位置
CResizableLayout 实现布局管理器以处理子窗口的调整大小和重新定位
CResizableState CResizableWndState CResizableSheetState 为通用窗口、属性表或向导对话框提供基本的保存/恢复方法和实现

对于最常见的 MFC 类,你可以简单地用其“可调整大小”的对应类替换标准 MFC 类

CResizableDialog 使用 CResizableGripCResizableMinMaxCResizableLayoutCResizableState
CResizablePage 使用 CResizableLayout
CResizableSheet 使用 CResizableLayoutCResizableGripCResizableMinMaxCResizableState
CResizablePageEx 使用 CResizableLayout
CResizableSheetEx 使用 CResizableLayoutCResizableGripCResizableMinMaxCResizableState
CResizableFormView 使用 CResizableLayoutCResizableGripCResizableMinMaxCResizableState
CResizableFrame 使用 CResizableMinMaxCResizableState
CResizableMDIFrame 使用 CResizableMinMaxCResizableState
CResizableMDIChild 使用 CResizableMinMaxCResizableState

这种选择的主要原因是为了简化和加快新型可调整大小窗口的开发,可能会扩展我的小集合,并避免重复早期版本的代码。

我还将所有类统一到一个库项目中,你可以轻松地将其添加到你的工作区,以便使用可调整大小的窗口。显然,你仍然可以将所需的文件添加到你的项目中,但使用库时,当新版本发布时,你只需在一个地方更新。

使用库

如果你已经有 1.1 或更高版本,你只需用新文件替换旧文件并重新编译。由于实现更改,可能会出现一些轻微的不兼容性,请参阅更新的文档和源代码中的注释。

作为独立项目

要使用类库,请执行以下步骤

  • 解压库源代码,并将 ResizableLib 目录放在你选择的位置。我建议使用你创建项目(例如,C:\MyProjects)或第三方库的公共路径的同一目录
  • 转到文件视图窗格并右键单击根元素,或选择项目菜单,然后选择将项目插入工作区...

The ResizableLib project in the workspace

  • 导航到你放置库的位置,选择库项目文件并勾选依赖项,指定哪个项目将使用该库

Insert ResizableLib into the workspace as a dependency of your project

  • 文件视图中重新激活你的项目,并打开设置对话框(也可从项目菜单打开)。
  • 确保在树视图中选择了你的项目,并在组合框中选择了所有配置,然后单击C/C++选项卡。
  • 类别组合框中,选择预处理器,并将库路径添加到附加包含目录编辑框。

Include directories in the project settings

现在你已准备好开始使用该库,或者如果从以前的版本更新,则重新构建你的项目。

请注意,此描述可能会在后续版本中更改,因为我希望将库作为独立可编译项目分发,而不是包含在工作区中。

作为你的项目的一部分的单个文件

你只需将必要的文件添加到你的项目中,注意类的依赖关系。例如,如果你想使用可调整大小的对话框类,你还需要包含低级类。

库的 stdafx.h include 文件中包含一些预处理器指令,以应对各种 Platform SDK 版本的头文件和 MFC (6.0)。你可能需要将这些行复制到你的项目的 stdafx.h 文件中,以使事情正常工作。

构建演示项目的注意事项

每个存档都包含一个带有 VC++ 项目和工作区的目录。由于每个演示的工作区都引用了 ResizableLib 项目,因此你应该将所有解压后的目录放在同一父目录中,这样 IDE 才不会抱怨缺少文件。

创建可调整大小的窗口 [已过时]

“低级”类的一个很好的使用示例是 CResizableDialog 类。但是,对于懒惰的程序员,这里有一个小指南。

添加布局管理

  • 首先,你的类应派生自 CResizableLayout
    class CMyResizableWindow : public CBaseWnd, public CResizableLayout
  • 这样实现 GetResizableWndvirtual 函数
    virtual CWnd* GetResizableWnd() { return this; };
  • 重写 OnSize 消息处理程序以重新排列子窗口
    void CMyResizableWindow::OnSize(UINT nType, int cx, int cy) 
    {
      CBaseWnd::OnSize(nType, cx, cy);
      
      // ...
        
      ArrangeLayout();
    }
  • 重写 OnEraseBkgnd 消息处理程序以减少调整大小操作期间的闪烁
    BOOL CMyResizableWindow::OnEraseBkgnd(CDC* pDC) 
    {
      EraseBackground(pDC);
    
      return TRUE;
    }
  • 如果你想使用 MFC 对象多次创建关联窗口(因为布局在对象销毁之前仍然有效),你可能还需要重写 OnDestroy 消息处理程序来清理布局。
    void CMyResizableWindow::OnDestroy() 
    {
      RemoveAllAnchors();
    
      CBaseWnd::OnDestroy();
    }
  • 现在你可以在初始化函数(例如 OnInitDialogOnInitialUpdate)中调用 AddAnchorAddAnchorCallback 来设置子窗口的布局。

添加最小/最大尺寸处理

  • 你的类应派生自 CResizableMinMax
    class CMyResizableWindow : public CBaseWnd, public CResizableMinMax
  • 重写 OnGetMinMaxInfo 消息处理程序以提供最小/最大信息
    void CMyResizableWindow::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
    {
      MinMaxInfo(lpMMI);
    }

添加尺寸手柄支持

  • 你的类应派生自 CResizableGrip
    class CMyResizableWindow : public CBaseWnd, public CResizableGrip
  • 这样实现 GetResizableWnd 纯虚拟函数
    virtual CWnd* GetResizableWnd() { return this; };
  • 重写 OnCreate 消息处理程序以创建手柄
    int CMyResizableWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
      if (CBaseWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
      
      // ...
    
      if (!CreateSizeGrip())
        return -1;
    
      return 0;
    }
  • 重写 OnSize 消息处理程序以更新手柄位置
    void CMyResizableWindow::OnSize(UINT nType, int cx, int cy) 
    {
      CBaseWnd::OnSize(nType, cx, cy);
      
      // ...
      
      UpdateSizeGrip();
    }

添加保存/恢复支持

  • 你的类应派生自 CResizableState
    class CMyResizableWindow : public CBaseWnd, public CResizableState
  • 这样实现 GetResizableWndvirtual 函数
    virtual CWnd* GetResizableWnd() { return this; };
  • 提供你自己的包装函数来保存/恢复窗口状态,特别是当你需要添加自定义设置时,或者让用户调用 LoadWindowRectSaveWindowRect

类参考 [已过时]

CResizableLayout

CResizableLayout::AddAnchor

void AddAnchor(HWND hWnd, CSize sizeTypeTL, CSize sizeTypeBR = NOANCHOR)
void AddAnchor(UINT nID, CSize sizeTypeTL, CSize sizeTypeBR = NOANCHOR)

将子窗口添加到布局列表,并为控件的左上角和右下角设置锚点类型。在调整大小操作期间,控件的角与你指定的对话框点保持固定距离:参数的 cx 成员是水平位置,而 cy 是垂直位置,以百分比表示。

如果有重叠的控件,你应该按照从外部控件到内部控件的顺序调用此函数,以使剪裁例程正确工作。

定义了一组有用的常量值,也用于兼容性

const CSize
  NOANCHOR(-1,-1),
  TOP_LEFT(0,0), TOP_CENTER(50,0), TOP_RIGHT(100,0),
  MIDDLE_LEFT(0,50), MIDDLE_CENTER(50,50), MIDDLE_RIGHT(100,50),
  BOTTOM_LEFT(0,100), BOTTOM_CENTER(50,100), BOTTOM_RIGHT(100,100);
我认为它们的含义不言自明。不允许在左上角使用 NOANCHOR,因此在调试版本中会生成“断言失败”。

CResizableLayout::AddAnchorCallback

void AddAnchorCallback(UINT nCallbackID)

使用给定的回调 ID 向布局添加一个占位符。当你要添加的控件或其“锚点”可以在运行时更改时,这很有用。

你必须重写 ArrangeLayoutCallback 以提供布局信息。

CResizableLayout::RemoveAnchor

BOOL RemoveAnchor(HWND hWnd)
BOOL RemoveAnchor(UIND nID)
根据其句柄或控件 ID,从布局中移除一个窗口。

对于回调项,没有相应的函数。

CResizableLayout::RemoveAllAnchors

void RemoveAllAnchors()
从布局中移除所有窗口。通常在 OnDestroy 中调用。

CResizableLayout::GetAnchorPosition

BOOL GetAnchorPosition(HWND hWnd, const CRect &rectParent, 
   CRect &rectChild, UINT* lpFlags = NULL)
BOOL GetAnchorPosition(UINT nID, const CRect &rectParent, 
   CRect &rectChild, UINT* lpFlags = NULL)
根据给定的父窗口大小计算锚定控件的大小和位置。返回的标志应用于调用 SetWindowPos。如果第一个参数标识了一个锚定控件,则返回值为 TRUE,否则为 FALSE

CResizableLayout::ArrangeLayout

void ArrangeLayout()

根据父窗口的大小,调整你使用 AddAnchor 添加到布局列表的子窗口的大小和位置。通常在你的 OnSize 处理程序中调用。

CResizableLayout::ArrangeLayoutCallback

virtual BOOL ArrangeLayoutCallback(LayoutInfo& layout)

重写此函数以提供给定回调 ID 的布局信息。当调用此函数时,layout 结构包含请求布局信息的回调 ID。你必须填充结构的其余部分。如果结构包含有效信息,则返回值为 TRUE,否则为 FALSE

你应该测试 nCallbackID 结构成员的值,如果你没有添加该 ID,则将控制权传递给基本实现。如果你不提供布局信息,默认实现返回 FALSE 并且不采取任何操作。

当调用此函数时,非回调项在调整大小后处于新位置,但你不能假设以前的回调项也如此。

CResizableLayout::GetTotalClientRect

virtual void GetTotalClientRect(LPRECT lpRect)

重写此函数以提供类用于执行布局计算的客户端区域,包括添加控件和重新排列布局时。

此函数由类使用,派生类也应使用它,而不是标准的 GetClientRect。对于带有滚动条或可扩展窗口的窗口,它可以用于提供总客户端区域,甚至包括那些不可见的部分。

CResizableLayout::ClipChildren

void ClipChildren(CDC *pDC)

需要与 WinXP 主题兼容时,不建议使用。

请参阅 EraseBackgroundGetClippingRegion

将子窗口从给定 DC 的剪裁区域中排除。通常在你的 OnEraseBkgnd 中调用,以实现无闪烁的调整大小。

CResizableLayout::GetClippingRegion

void GetClippingRegion(CRgn* pRegion)

获取当前布局的剪裁区域。需要父窗口绘制背景的窗口,例如某些类型的静态控件或透明窗口,属于该区域,而其他窗口则被剪裁掉。

你可以使用此区域,例如,在调用 PaintRgnFillRgn 时绘制父窗口的背景。

CResizableLayout::EraseBackground

void EraseBackground(CDC* pDC)

使用父窗口的默认画刷绘制布局的剪裁区域。通常在你的 OnEraseBkgnd 中调用,以实现无闪烁的调整大小。

CResizableLayout::InitResizeProperties

virtual void InitResizeProperties(CResizableLayout::LayoutInfo& layout)

用于设置锚定控件的初始调整大小属性,这些属性存储在 LayoutInfo 结构的 properties 成员中。

// wether to ask for resizing properties every time
BOOL bAskClipping;
BOOL bAskRefresh;
// otherwise, use the cached properties
BOOL bCachedLikesClipping;
BOOL bCachedNeedsRefresh;
各种标志用于指定调整大小属性(剪裁、刷新)是否可以在运行时更改,并且在每次布局调整时是否需要重新调用属性查询函数,或者它们是 static 属性,并且在需要时使用缓存值。

默认实现将“剪裁”设置为 static,只调用 LikesClipping 一次,将“刷新”设置为动态,导致每次都调用 NeedsRefresh。这对于大多数情况应该是正确的,但如果需要,你可以重写此函数。

注意:此函数和以下可重写函数的默认实现还会向锚定控件发送注册消息,使其有机会指定其调整大小属性,如果支持,这些属性将优先。有关详细信息,请参阅文件 ResizableMsgSupport.*

CResizableLayout::LikesClipping

virtual BOOL LikesClipping(const LayoutInfo &layout)

用于确定锚定控件是否可以安全地剪裁,即它是否能够重新绘制其背景。如果此窗口可以发生剪裁,则返回值为 TRUE,否则为 FALSE

默认实现尝试通过类名和窗口样式识别“可剪裁”窗口。如果你需要更多地控制剪裁,请重写此函数。请注意,未剪裁的窗口通常容易闪烁。

CResizableLayout::NeedsRefresh

virtual BOOL NeedsRefresh(const LayoutInfo &layout, 
   const CRect &rectOld, const CRect &rectNew)

用于确定子窗口在移动/调整大小时是否需要重新绘制。如果此窗口必须重新绘制,则返回值为 TRUE,否则为 FALSE

默认实现尝试通过类名和窗口样式识别需要刷新的窗口。如果你需要不同的行为或者你有自定义子窗口,请重写此函数。

CResizableGrip

CResizableGrip::CreateSizeGrip

BOOL CreateSizeGrip(BOOL bVisible = TRUE, BOOL bTriangular = TRUE, 
   BOOL bTransparent = FALSE)
你调用此函数来创建尺寸手柄,通常在你的 OnCreate 消息处理程序中。你可以指定初始可见性,以及是使用三角形形状还是透明背景。如果成功创建手柄,则返回非零值,否则返回零。

CResizableGrip::SetSizeGripShape

void SetSizeGripShape(BOOL bTriangular)
将手柄的形状更改为三角形或矩形。

CResizableGrip::SetSizeGripBkMode

BOOL SetSizeGripBkMode(int nBkMode)
设置尺寸手柄的背景模式。接受与 SetBkMode 函数相同的值:OPAQUETRANSPARENT。如果发生错误,则返回零,否则返回非零值。

CResizableGrip::SetSizeGripVisibility

void SetSizeGripVisibility(BOOL bVisible)

设置手柄的默认可见性。实际状态取决于当前的显示计数,该计数通过调用 ShowSizeGripHideSizeGrip 进行修改。

CResizableGrip::ShowSizeGrip

void ShowSizeGrip(DWORD* pStatus, DWORD dwMask = 1)

如果可见性状态尚未开启,则增加当前显示计数。对实际手柄可见性的更改仅在调用 UpdateSizeGrip 后生效。

pStatus 指向的 DWORD 变量,由 dwMask 掩码,保存了相对于特定条件(仅对调用者有意义)的可见性状态。此可见性状态的初始值必须为零(关闭)才能允许临时显示手柄,非零(开启)才能允许临时隐藏手柄。

注意:一个 DWORD 变量可以通过更改关联的掩码来保存多达 32 个条件。

CResizableGrip::HideSizeGrip

void HideSizeGrip(DWORD* pStatus, DWORD dwMask = 1)

如果可见性状态尚未关闭,则减少当前显示计数。对实际手柄可见性的更改仅在调用 UpdateSizeGrip 后生效。

每次调用 ShowSizeGrip 都应该与一次 HideSizeGrip 调用相匹配,这取决于可见性状态所代表的条件。

CResizableGrip::IsSizeGripVisible

BOOL IsSizeGripVisible()
用于根据当前显示计数判断尺寸手柄是否应该实际可见。

CResizableGrip::UpdateSizeGrip

void UpdateSizeGrip()
当包含窗口调整大小时重新计算手柄的位置,并根据需要显示或隐藏手柄。你通常在你的 OnSize 处理程序中或在调用 ShowSizeGripHideSizeGrip 之后调用此函数。

CResizableMinMax

CResizableMinMax::MinMaxInfo

void MinMaxInfo(LPMINMAXINFO lpMMI)
根据当前的最小/最大设置更新 MINMAXINFO 结构。

CResizableMinMax::SetMaximizedRect

void SetMaximizedRect(const CRect& rc)

设置窗口最大化时将占据的矩形区域。默认值是系统设置的标准大小和位置(屏幕的工作区)。

CResizableMinMax::ResetMaximizedRect

void ResetMaximizedRect()

恢复先前调用 SetMaximizedRect 的效果,即最大化窗口将产生标准行为。

CResizableMinMax::SetMinTrackSize

void SetMinTrackSize(const CSize& size)

设置窗口调整大小时的最小尺寸。此设置不影响最小化操作的行为,最小化操作始终产生预期结果。

CResizableMinMax::ResetMinTrackSize

void ResetMinTrackSize()

恢复先前调用 SetMinTrackSize 的效果,即由系统设置标准最小尺寸。

CResizableMinMax::SetMaxTrackSize

void SetMaxTrackSize(const CSize& size)

设置对话框调整大小时的最大尺寸。默认值是系统设置的标准尺寸(屏幕的工作区)。请注意,此设置会影响最大化操作的行为,最大化尺寸将被系统裁剪到此值。

CResizableMinMax::ResetMaxTrackSize

void ResetMaxTrackSize()

恢复先前调用 SetMaxTrackSize 的效果,即由系统设置标准最大尺寸。

CResizableState

CResizableState::LoadWindowRect

BOOL LoadWindowRect(LPCTSTR pszSection, BOOL bRectOnly)

从应用程序配置文件设置(注册表或 INI 文件)中的给定节加载窗口的大小、位置和状态。如果 bRectOnlyTRUE,则不恢复窗口的最小化/最大化状态。

CResizableState::SaveWindowRect

BOOL SaveWindowRect(LPCTSTR pszSection, BOOL bRectOnly)

将窗口的大小、位置和状态保存到应用程序配置文件设置(注册表或 INI 文件)中的给定节。对于 bRectOnly 参数,你应该使用与 LoadWindowRect 函数中相同的值。

当前和未来 - Alpha 版本 1.4a

我已经在 1.4 版本上工作了几个月,但仍然无法发布任何东西。这非常令人失望!我必须做些什么...这就是我发布这个不完整的 alpha 版本的原因。库中有很多改进,我甚至不记得了——感谢上帝我使用了 CVS——我相信发布一些东西比再等六个月甚至更糟要好。

我花了几周时间开始使用 Doxygen 记录代码,但仍然有很多事情要做

  • 完成 Doxygen 文档
  • 更新文章并讨论技术细节,因为类参考将在 Doxygen 生成的文件中占有一席之地
  • 测试一些问题最多的新功能(在 1.4a 中禁用)以备完整发布
  • 制作更好的演示项目以展示功能并帮助测试它们

所有这些工作由我一个人完成需要太长时间。我将非常感谢这个库最有经验的用户提供的任何一点帮助。否则,你将不得不等待更长时间...

已知问题

我尽力修复 bug 和/或为新问题找到解决方案,但肯定有一些我忘记或没有时间查看的东西。

  • Wizard97 风格的可调整大小对话框仍然有一些细微的绘图问题,尤其是在启用 WinXP 主题时,但我认为我已经让它们运行得相当好。
  • 闪烁已大大减少,但仍然存在。

    一些控件,例如某些类型的 StaticGroupBox 和透明窗口,依赖于父窗口绘制背景。这导致控件在重新绘制自己之前被背景颜色过度绘制。这正是闪烁的原因。

    版本 1.4a 的改进包括一项新功能,可在窗口左侧或顶部边缘发生调整大小时减少闪烁。这可能会导致使用 1.3 版本的项目出现问题,因为本来会停留在左上角的控件可能会未被锚定。现在你必须为所有子窗口调用 AddAnchor

  • 独立文档尚未准备好。

    自 1.1 版及更早版本以来,我将 Docs 目录添加到项目中,其中包含一个基本的 Doxygen 配置文件。但是源代码需要符合 Doxygen 的注释才能实际生成除类层次结构之外的更多内容。

    在 1.4a 版本中,我开始使用 VC++ 6 的 Doxbar 插件,现在一些核心类已经文档化。只需在库项目目录中运行 Doxygen。

待办事项

  • 尝试使用双缓冲技术以完全消除闪烁。

    Oz Solomonovich 帮助我解决了 WinXP 主题和剪切区域的问题。他还让我了解到一种技巧,你可以用它来强制窗口在特定的 DC 上绘制,从而可能启用双缓冲重绘(硬核方式)。

    在 1.4a 版本中,我尝试使用 XP 原生双缓冲,但这导致了许多问题,需要测试和时间来解决。此功能默认通过预处理器宏禁用,以便代码仍可安全使用。

  • 使用旧 Windows 平台测试新功能。

    我尽力保持与所有 Win32 平台的向后兼容性,但我不再安装旧 Windows 版本,所以不能确定一切都正常。

    在 1.4a 版本中,我还引入了额外的代码和预处理器指令,以帮助根据特定平台调整代码。原则是,当你使用通常的“WINVER 和朋友”宏选择目标 Windows 平台时,库会生成代码,该代码启用该平台特有的功能,但在旧平台上运行时会优雅地降级。

  • 更新演示项目以使用 XP 视觉样式,并可能使它们更美观。

    1.4a 版本包括用于 XP 视觉样式的清单文件。

  • 用 Unicode 测试库,并将 Unicode 构建配置添加到项目中。

    1.4a 版本包括 Unicode 构建配置。但仍需要测试。

  • 开始使用 Doxygen 风格注释并转换现有注释,同时使用此页面中的文档。

    嗯,这项工作已在 1.4a 版本中开始,官方 1.4 版本在完成之前不会发布。

  • 使库项目实际生成一个独立的编译库或可能的 DLL,就像任何好的类库一样,为调试和发布版本使用不同的输出名称。

    我不确定这一点,但我猜在某些项目中直接使用库会更容易。也欢迎在这方面的帮助。

计划

  • 一个 WTL 版本,以及可能的 SDK 版本的库

    Alexander D. Alexeev 贡献了一个旧版本(我想是 1.1)的 WTL 移植,这给了我一些关于这个库的想法。我想将他的移植更新到新版本,并可能避免重复代码。这让我想到了一个 SDK 移植,作为 MFC 和 WTL 版本的底层实现。

    我尝试了库的模板版本,并证明了上述想法是可行的,但这无疑是一项长期任务。肯定在官方 1.4 版本发布之后。

  • 库的独立参考指南(使用 Doxygen)。

    这正在为下一个官方版本进行中。

结论

这个类库致力于为可调整大小的窗口问题提供一个更可重用的解决方案。随着开发继续,这项工作变得越来越艰巨。我仍然有改进这个库的想法,但肯定缺乏时间去做。我讨厌看到那些固定大小的对话框,或者更糟糕的是那些严重闪烁的可调整大小的窗口,所以我真的希望看到更多外观漂亮的,可调整大小的窗口!

我不想说“使用我的库”,因为同样的事情肯定可以用更好的方式完成,但至少要使用像 ResizableLib 一样好用的东西。

感谢所有快乐的用户,特别是所有发送修复或错误报告的人。正如你所看到的,总是有很多事情要做...所以非常欢迎贡献!

此库现根据 Artistic License 的条款分发,允许用于商业应用程序。你不能将此作品作为库的一部分出售并声称它是你的。这也意味着不需要注明出处,但注明出处会很好!:)

CVS 树现托管在 Source Forge 上。

更新

2001 年 6 月 11 日

  • 首次公开发布

2001 年 7 月 15 日

  • 修改了手柄实现,现在使用滚动条子窗口
  • 不再需要重写 OnNcHitTestOnPaint
  • 手柄现在是三角形的,允许背景不同于简单的灰色
  • 为布局类添加了“回调锚点”,用于属性表集成
  • 回调允许向布局添加可变窗口和锚点类型
  • 添加了 Wizard97FormView 和完整的 PropertySheet 支持
  • 更新了新功能的文档

2001 年 8 月 18 日

  • 改进了剪切能力:如果 AddAnchors 调用顺序正确,则可以正确处理重叠的控件
  • 删除了 ArrangeLayout 中的第二个循环,现在使用 SWP_NOCOPYBITS
  • 修复了初始样式更改以启用调整大小时的错误,现在客户端矩形得以保留
  • 修复了透明工具栏的错误
  • 许可证更改为“Artistic License”,CVS 仓库现在位于 SourceForge

2001 年 10 月 29 日

版本 1.1 (CVS 标签: SF_1_1)
  • 修复了导航向导对话框时 CTRL+Tab 的错误
  • 为所有项目添加了静态构建配置
  • 一些界面美化

2002 年 7 月 13 日

版本 1.2 (CVS 标签: SF_1_2)
  • 更改了布局实现,现在使用 2 个列表和一个映射。
  • 更改了 LayoutInfo 结构:添加了类名,删除了刷新标志
  • 现在 NeedsRefresh 函数在布局每次更新时调用,而不是在 AddAnchor 期间只调用一次
  • 改进了 Static 控件的抗闪烁功能(需要测试)
  • 添加了支持动态窗口和检索布局中控件位置和大小的函数
  • 更改了手柄实现,现在使用 MFC 派生类
  • 修复了 WinXP 主题的背景问题(需要测试)
  • 更新了文档(此页面)

2002 年 10 月 27 日

版本 1.3 (CVS 标签: SF_1_3)
  • 更改了 ArrangeLayout 以一次性更新所有控件,包括回调
  • 更改了 LayoutInfo 结构:添加了调整大小属性支持
  • 更改了手柄功能,允许更多自定义,添加了透明背景
  • 添加了手柄、窗口状态保存/恢复和最小/最大尺寸处理
  • 为框架窗口(SDI、MDI)添加了类以处理最小/最大尺寸约束(尚不适用于拆分器)
  • 通过注册消息添加了对自定义窗口的初步支持
  • 修复了重叠的组框,错误地剪切了兄弟控件(旧代码未删除)
  • 修复了手柄,现在处理系统参数更改
  • 修复了滚动窗口(FormView)的问题
  • 更新了文档(此页面),为此版本添加了 ChangeLog

2004 年 6 月 9 日

版本 1.4 Alpha (CVS 标签: CP_1_4_alpha - Git 标签: v1.4a)
  • Alpha 版本,不完整
  • 最新版本可在 SourceForge 和 CodeProject 上获得

仓库和开发已迁移至 Github

2018 年 1 月 4 日

版本 1.5.1 (Git 标签: v1.5.1)
这个迟来的版本包含了自上次公开发布以来的许多修复和改进,并得到了 CodeProject 和 GitHub 用户的贡献。这段时间也意味着我部分忘记了单个提交旨在解决的问题,但这里有一个粗略的更改列表
  • 将仓库从 CVS 迁移到 Git,并将开发从 SourceForge 迁移到 GitHub
  • 将所有项目和解决方案迁移到 VS2015,支持 XP 构建
  • 添加了方便的函数来锚定剩余的控件
  • 为所有演示项目添加了清单以启用视觉样式
  • 修复了菜单重绘和非客户端区域计算的错误
  • 修复了剪切区域的资源泄漏
  • 修复了带拆分器窗口的最大跟踪尺寸计算
  • 修复了可调整大小组合框的编译
  • 修复了可调整大小组合列表框的外观
  • 修复了最小化后恢复的框架的错误
  • 修复了子(无模式)属性表的布局预设
  • 修复了 ANSI 构建的项目设置
  • 修复了 wizard97 头部重绘(在 CommCtrls >= 6.00 中缺失)
  • 修复了当窗口边框不可调整大小时,最大化尺寸不受跟踪尺寸限制的问题
  • 贡献了修复和其他次要更改(请参阅 GitHub 发布说明)

2019 年 4 月 28 日

版本 1.5.2 (Git 标签: v1.5.2)
带有少量贡献的小型 bug 修复版本
  • 修复 AddAllOtherAnchors() 错误地移动 SizeGrip
  • 贡献了其他修复和次要更改

2020 年 6 月 30 日

版本 1.5.3 (Git 标签: v1.5.3)
主要是源代码的界面更改和项目文件的更新,以及一些修复
  • 修复了对话框调整大小可能导致某些静态文本被剪裁或消失的问题
  • 修复了新旧“97 风格向导对话框”的重绘问题
© . All rights reserved.