代码之家  ›  专栏  ›  技术社区  ›  Andrew Truckle

USing CMFCMenuButton::SizeToContent似乎无法按我的意愿工作。为什么?

  •  0
  • Andrew Truckle  · 技术社区  · 2 年前

    我对 SizeToContent 方法 CMFCMenuButton 控制

    这是我在IDE中的对话框:

    enter image description here

    正如你所看到的,我特别把按钮做得比最右边的两个更宽。

    我将以下代码添加到 OnInitDialog :

    // Resize (if required)
    const auto sizNewButton = m_btnReset.SizeToContent(true);
    CRect rctButton;
    m_btnReset.GetWindowRect(&rctButton);
    if(sizNewButton.cx > rctButton.Width())
    {
        m_btnReset.SizeToContent();
    }
    

    然而,当我用英语运行我的应用程序时:

    enter image description here

    它使它变小了。我的应用程序通过使用卫星DLL支持50多种语言,我希望只有在需要时才能根据内容调整大小。但它似乎无论如何都要调整它的大小。我是不是错过了一步?

    我已经检查了IDE中控件的属性,但它没有设置为自动调整大小:

    enter image description here

    我注意到帮助文档中指出:

    按钮的新大小将根据按钮文本、图像和箭头进行计算。该框架还添加了 水平方向10像素的预定义边距 边缘和垂直边缘的5个像素。

    我看了一下我的纽扣:

    • 默认尺寸:48 x 23( GeWindowRect 结果)。
    • 计算尺寸:57 x 23( 大小到内容 结果)。

    如果我这样调整代码:

    if((sizNewButton.cx - 10) > rctButton.Width())
    

    这将使其降至47,因此不会调整大小。我假设代码工作不正常,因为填充了空白 GetWindowRect 对此一无所知。

    0 回复  |  直到 2 年前
        1
  •  2
  •   Andrew Truckle    2 年前

    搜索了一下,发现问题出在MFC的 CMFCMenuButton::SizeToContent() afxmenubutton.cpp中的实现:

    CSize CMFCMenuButton::SizeToContent(BOOL bCalcOnly)
    {
        CSize size = CMFCButton::SizeToContent(FALSE); // <==== The culprit!!!
        size.cx += CMenuImages::Size().cx;
    
        if (!bCalcOnly)
        {
            SetWindowPos(NULL, -1, -1, size.cx, size.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
        }
    
        return size;
    }
    

    也就是说,它将 SizeToContent() bCalcOnly 参数设置为 FALSE ,这意味着它还将调整控件的大小以刚好适合文本(没有下拉箭头)。这比文本加上箭头所需的要小,当然原始大小也会丢失。

    解决方法可以是在 大小到内容() 调用,并使用此项而不是新项:

    CRect rctButton;
    m_btnReset.GetWindowRect(&rctButton);
    const auto nOrigWidth = rctButton.Width(); // Store the original width
    const auto sizNewButton = m_btnReset.SizeToContent(true); // This resizes the control!!!
    if (sizNewButton.cx > nOrigWidth) // Compare to the original width rather than the new one
        m_btnReset.SizeToContent();
    else // Restore original width
        m_btnReset.SetWindowPos(NULL, -1, -1, nOrigWidth, sizNewButton.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
    

    替代解决方案:
    定义新的 CMFCMenuButton -基于类,重写 大小到内容() -在实现中调用基础 CMFCButton::SizeToContent() b仅计算 由调用方传递的参数,而不是 错误的 。将控件映射到此类,而不是 CMFC菜单按钮 。那就是使用一个修复它的类。不过,对于一个变通方法来说,这太过分了。