代码:
auto pMenuEdit = GetCongregationSubMenu(1);
if (pMenuEdit != nullptr)
{
const int iSize = pMenuEdit->GetMenuItemCount();
for (int i = 0; i < iSize; i++)
{
CString strMenuText;
MENUITEMINFO sInfo{};
sInfo.cbSize = sizeof(MENUITEMINFO);
sInfo.fMask = MIIM_STRING | MIIM_ID;
sInfo.dwTypeData = strMenuText.GetBuffer();
GetMenuItemInfo(pMenuEdit->GetSafeHmenu(), i, TRUE, &sInfo);
strMenuText.ReleaseBuffer();
if (strMenuText == strCongregation)
{
// Simulate pressing the Edit Congregation menu item
PostMessage(WM_COMMAND, sInfo.wID);
break;
}
pMenuEdit->GetMenuString(i, strMenuText, MF_BYPOSITION);
if (strMenuText == strCongregation)
{
// Simulate pressing the Edit Congregation menu item
PostMessage(WM_COMMAND, sInfo.wID);
break;
}
}
}
为什么
pMenuEdit->GetMenuString(i, strMenuText, MF_BYPOSITION);
方法可以正确工作,而 GetMenuItemInfo(pMenuEdit->GetSafeHmenu(), i, TRUE, &sInfo);
方法却不能?根据调试器,文本为空。
Microsoft 文档鼓励使用
GetMenuItemInfo
而不是 GetMenuString
。
我的错误?
C 中的文本缓冲区始终由两部分组成:指向缓冲区开头的指针和计数(以元素或字节为单位)。相关代码永远不会为
cch
结构的
MENUITEMINFO
字段提供值。
解决此问题仍然会导致代码无法检索菜单项文本,因为
strMenuText
缓冲区为空。您还必须分配足够的空间(例如,通过在调用中提供缓冲区大小CString::GetBuffer()
)。
标准模式是首先发现所需的长度:
MENUITEMINFO sInfo{};
sInfo.cbSize = sizeof(MENUITEMINFO);
sInfo.fMask = MIIM_STRING | MIIM_ID;
if (!GetMenuItemInfo(pMenuEdit->GetSafeHmenu(), i, TRUE, &sInfo)) {
// Handle error
}
UINT const required_length = sInfo.cch;
并使用该信息来分配足够大小的缓冲区:
CString strMenuText;
sInfo.dwTypeData = strMenuText.GetBuffer(required_length);
sInfo.cch = required_length + 1;
if (!GetMenuItemInfo(pMenuEdit->GetSafeHmenu(), i, TRUE, &sInfo)) {
// Handle error
}
strMenuText.ReleaseBufferSetLength(sInfo.cch);