【问题标题】:Recalculate dynamic layout properties重新计算动态布局属性
【发布时间】:2018-06-23 18:36:04
【问题描述】:

这是一个可调整大小的窗口:

设置动态布局属性,以便顶部组框调整宽度,而下部组/框和树在两个维度上与 3 个按钮一起调整大小。

对于高级复选框,我添加了代码来隐藏额外的控件并调整相关框的高度。所以它看起来像这样:

用于切换控制值的代码是:

void CWishListDlg::ToggleAdvancedMode()
{
    CRect rtSortTalk, rtTalkSettings, rtTreeGroup, rtTree, rtTalkCombo;

    m_staticSortTalk.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_cbTalkSortField.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_cbTalkSortOrder.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_staticSortSpeaker.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_cbSpeakerSortField.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_cbSpeakerSortOrder.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_staticTalkHistory.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_checkIncludeTalkHistory.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_staticStyle.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);
    m_cbStyle.ShowWindow(m_bAdvancedMode ? SW_SHOW : SW_HIDE);

    m_staticSortTalk.GetWindowRect(&rtSortTalk);
    m_staticSettings.GetWindowRect(&rtTalkSettings);
    m_staticTreeDetails.GetWindowRect(&rtTreeGroup);
    m_Tree.GetWindowRect(&rtTree);

    if (m_bAdvancedMode)
    {
        rtTalkSettings.bottom += m_iOffsetY;
        rtTreeGroup.top += m_iOffsetY;
        rtTree.top += m_iOffsetY;
    }
    else
    {
        rtTalkSettings.bottom -= m_iOffsetY;
        rtTreeGroup.top -= m_iOffsetY;
        rtTree.top -= m_iOffsetY;
    }

    ScreenToClient(&rtTalkSettings);
    ScreenToClient(&rtTreeGroup);
    ScreenToClient(&rtTree);

    m_staticSettings.MoveWindow(&rtTalkSettings);
    m_staticTreeDetails.MoveWindow(&rtTreeGroup);
    m_Tree.MoveWindow(&rtTree);
}

它工作正常。我可以切换到我心中的内容。直到我尝试调整窗口大小:

我看不到任何基于活动显示重新计算动态布局属性的方法。

如果勾选“高级”,以便控件可见(从而匹配资源编辑器),则它可以很好地调整大小。只有当它被取消并且我修改了两个控件时,调整大小才会正常工作。

【问题讨论】:

    标签: mfc


    【解决方案1】:

    我发现了这个极好的资源:

    https://mariusbancila.ro/blog/2015/07/27/dynamic-dialog-layout-for-mfc-in-visual-c-2015/

    你要做的是删除动态布局并重新创建它:

    void CWishListDlg::SetupDynamicLayout()
    {
        // Disable dynamic layout (this will delete the pointer and set it to NULL)
        EnableDynamicLayout(FALSE);
    
        // Enable dynamic layout (this will create a new pointer with no elements)
        EnableDynamicLayout(TRUE);
    
        // Re-create the dynamic layout content
        auto pManager = GetDynamicLayout();
        if (pManager != nullptr)
        {
            pManager->Create(this); // Assign the window!
            auto moveNone = CMFCDynamicLayout::MoveNone();
            auto moveVertical100 = CMFCDynamicLayout::MoveVertical(100);
            auto moveBoth100 = CMFCDynamicLayout::MoveHorizontalAndVertical(100, 100);
            auto sizeBoth100 = CMFCDynamicLayout::SizeHorizontalAndVertical(100, 100);
            auto sizeHorizontal100 = CMFCDynamicLayout::SizeHorizontal(100);
            auto sizeNone = CMFCDynamicLayout::SizeNone();
    
            pManager->AddItem(m_staticSettings.GetSafeHwnd(), moveNone, sizeHorizontal100);
            pManager->AddItem(m_staticTreeDetails.GetSafeHwnd(), moveNone, sizeBoth100);
            pManager->AddItem(m_Tree.GetSafeHwnd(), moveNone, sizeBoth100);
            pManager->AddItem(IDC_BUTTON_HELP, moveVertical100, sizeNone);
            pManager->AddItem(IDC_BUTTON_REPORT, moveBoth100, sizeNone);
            pManager->AddItem(IDC_BUTTON_EXPAND_ALL, moveBoth100, sizeNone);
            pManager->AddItem(IDC_BUTTON_COLLAPSE_ALL, moveBoth100, sizeNone);
            pManager->AddItem(IDC_STATIC_RESIZE, moveBoth100, sizeNone);
        }
    }
    

    很遗憾,您不能只在布局中获取现有控件或告诉它根据活动内容重新初始化。但是这种方式效果很好。它现在可以正确调整大小:

    【讨论】:

      【解决方案2】:

      我遇到了完全相同的问题。但是,我找到了另一种解决方法。我没有手动编写布局,而是从“高级”按钮处理程序中的资源重新加载它。因此,布局会根据新控件的大小自行调整。

      // Find the layout resource and store it statically.
      // There is no need to unload it every time for optimization.
      static const HRSRC LAYOUT_RES = ::FindResource(NULL, MAKEINTRESOURCE(IDD_YOUR_DIALOG), RT_DIALOG_LAYOUT);
      static const LPVOID LAYOUT_RES_DATA = ::LockResource(::LoadResource(NULL, LAYOUT_RES));
      static const DWORD LAYOUT_RES_SIZE = ::SizeofResource(NULL, LAYOUT_RES);
      
      if(auto lo = GetDynamicLayout())
          lo->LoadResource(this, LAYOUT_RES_DATA, LAYOUT_RES_SIZE);
      

      就是这样。此代码 sn-p 从资源中获取动态对话框布局并将其应用于控件的当前状态(大小和位置)。

      编辑:

      不过,这里并没有错误的资源 ID 或其他错误情况处理...

      【讨论】:

      • 有趣。我还没有测试过这种方法。
      猜你喜欢
      • 2015-01-28
      • 1970-01-01
      • 2020-12-10
      • 1970-01-01
      • 2014-04-06
      • 2019-10-25
      • 1970-01-01
      • 2020-08-21
      • 2011-05-23
      相关资源
      最近更新 更多