visual-c++ - 使用 CMFCMenuButton::SizeToContent 似乎并不像我想要的那样工作。为什么?

标签 visual-c++ mfc

我对 CMFCMenuButton 控件的 SizeToContent 方法感到困惑。

这是我在 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

我注意到帮助文档指出:

The new size of the button is calculated to fit the button text, image, and arrow. The framework also adds in predefined margins of 10 pixels for the horizontal edge and 5 pixels for the vertical edge.

我看了看我的按钮:

  • 默认大小:48 x 23(GeWindowRect 结果)。
  • 计算出的尺寸:57 x 23(SizeToContent 结果)。

如果我像这样调整我的代码:

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

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

最佳答案

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

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,这意味着它也会调整大小控件正好适合文本(没有下拉箭头)。这小于文本加箭头所需的大小,当然原始大小会丢失。

一种解决方法是在 SizeToContent() 调用之前获取(原始)宽度,并使用它而不是新的宽度:

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 的类,重写 SizeToContent() - 在实现中使用 调用基 CMFCButton::SizeToContent() >bCalcOnly 参数由调用者传递,不带 FALSE。将控件映射到此类而不是 CMFCMenuButton。那就是使用一个类来修复它。不过,对于一个解决方法来说,这太过分了。

关于visual-c++ - 使用 CMFCMenuButton::SizeToContent 似乎并不像我想要的那样工作。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74674331/

相关文章:

visual-c++ - 从哪里可以获得适用于 Windows SDK 8 的单独 Visual C++ 编译器?

c++ - 各种形式的 getline()

c++ - 从文本文件加载字符串后,字符串未相应格式化

c++ - 如何找到目录下的所有文件夹

c++ - 为什么 “delete *this” 会编译?

c++ - Visual C++无法写入exe

c++ - 在 Windows 10 TP 上使用 VS-2015 CTP 5 和 Python 3.5a 编译 boost-python 教程

c# - C++ 中的 XAML 桌面应用程序(Visual Studio Ultimate 2012 RC)

c++ - CTreeCtrl - 仅对某些行/子项使用复选框

c++ - const 函数中的 MessageBox