Win32 API GetMenuItemInfo 仅返回项文本的第一个字符
本文关键字:文本 第一个 字符 返回 API GetMenuItemInfo Win32 | 更新日期: 2023-09-27 17:56:27
我正在尝试使用GetMenuItemInfo API收集菜单项的文本。
这是我正在使用的代码:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPosition, ref MENUITEMINFO lpmii);
[StructLayout(LayoutKind.Sequential)]
public struct MENUITEMINFO
{
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public uint wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public String dwTypeData;
public uint cch;
public IntPtr hbmpItem;
// Return the size of the structure
public static uint sizeOf
{
get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
}
}
MENUITEMINFO mif = new MENUITEMINFO();
mif.cbSize = MENUITEMINFO.sizeOf;
mif.fMask = MIIM_STRING;
mif.fType = MFT_STRING;
mif.dwTypeData = null;
bool res = Win32.GetMenuItemInfo(hMenu, (uint)0, true, ref mif); //To load cch into memory
mif.cch += 1;
mif.fMask = MIIM_STRING;
mif.fType = MFT_STRING;
mif.dwTypeData = new String(' ', (Int32)(mif.cch));
res = Win32.GetMenuItemInfo(hMenu, (uint)i, true, ref mif); //To fill dwTypeData
不幸的是,在这些行之后,dwTypeData 会生成一个只有 1 个字符而不是 mif.cch 字符的字符串。注意:此字符是菜单项的第一个!
返回 MENUITEMINFO 结构时,数据封送处理中似乎有一些错位,不是吗?
请让我知道如何解决此类问题!
最好
切尔西
你的标题翻译很好,但你还没有dwTypeData
完全正确。这不能使用 string
从呼叫者编接到被调用方。您需要使用这样的手动编组来执行此操作。
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool GetMenuItemInfo(IntPtr hMenu, int uItem, bool fByPosition, MENUITEMINFO lpmii);
[StructLayout(LayoutKind.Sequential)]
public class MENUITEMINFO
{
public int cbSize;
public uint fMask;
public uint fType;
public uint fState;
public uint wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public IntPtr dwTypeData;
public uint cch;
public IntPtr hbmpItem;
public MENUITEMINFO()
{
cbSize = Marshal.SizeOf(typeof(MENUITEMINFO));
}
}
....
MENUITEMINFO mif = new MENUITEMINFO();
mif.fMask = MIIM_STRING;
mif.fType = MFT_STRING;
mif.dwTypeData = IntPtr.Zero;
bool res = GetMenuItemInfo(hMenu, 0, true, mif);
if (!res)
throw new Win32Exception();
mif.cch++;
mif.dwTypeData = Marshal.AllocHGlobal((IntPtr)(mif.cch*2));
try
{
res = GetMenuItemInfo(hMenu, 0, true, mif);
if (!res)
throw new Win32Exception();
string caption = Marshal.PtrToStringUni(mif.dwTypeData);
}
finally
{
Marshal.FreeHGlobal(mif.dwTypeData);
}
更新 2
使用反射System.Windows.Forms.MenuItem
中找到的代码。似乎他们也使用字符串。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MENUITEMINFO_T
{
public int cbSize = Marshal.SizeOf(typeof(NativeMethods.MENUITEMINFO_T));
public int fMask;
public int fType;
public int fState;
public int wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public string dwTypeData;
public int cch;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool GetMenuItemInfo(HandleRef hMenu, int uItem, bool fByPosition, [In, Out] MENUITEMINFO_T lpmii);
................
MENUITEMINFO_T menuiteminfo_t;
menuiteminfo_t = new MENUITEMINFO_T();
menuiteminfo_t.fMask = MIIM_STRING;
menuiteminfo_t.dwTypeData = new string(''0', 256);
menuiteminfo_t.cch = menuiteminfo_t.dwTypeData.Length - 1;
bool result = GetMenuItemInfo(new HandleRef(null, hMenu), 0, true, menuiteminfo_t);
更新 1
正如 Lebeau @Remy所建议的那样,字符串封送处理与 char[] 封送之间存在差异。 在我将CharSet=CharSet.Auto
属性添加到结构后,使用您的代码一切正常。
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct MENUITEMINFO
{
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public uint wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public string dwTypeData;
public uint cch;
public IntPtr hbmpItem;
// return the size of the structure
public static uint sizeOf
{
get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
}
}
IntPtr hWnd = FindWindow(null, "untitled - notepad");
IntPtr hMenu = GetMenu(hWnd);
MENUITEMINFO mif = new MENUITEMINFO();
uint MIIM_STRING = 0x00000040;
uint MFT_STRING = 0x00000000;
mif.cbSize = MENUITEMINFO.sizeOf;//(uint)Marshal.SizeOf(typeof(MENUITEMINFO));
mif.fMask = MIIM_STRING;
mif.fType = MFT_STRING;
mif.dwTypeData = null;
//IntPtr hMenu = menuStrip1.Handle;
//1st call to get the text length into (cch)
bool res = GetMenuItemInfo(hMenu, (uint)0, true, ref mif); //To load cch into memory
if (res)
{
mif.cch += 1;
//Set the length of the buffer to cch + 1
mif.dwTypeData = new string(' ', (int)(mif.cch));
res = GetMenuItemInfo(hMenu, (uint)0, true, ref mif); //To fill dwTypeData
}
查看此链接,了解有关字符串的默认封送处理的更多详细信息
老:
您需要初始化 dwTypeData 和 cch 数据成员。
获取菜单项字符串示例(使用新的菜单项信息结构):
List<string> ls = new List<string>();
IntPtr hMenu = Win32.GetMenu(hWnd);
if (hMenu.ToInt32() != 0)
{
for (int i = Win32.GetMenuItemCount(hMenu); i >= 0; i--)
{
uint MIIM_STRING = 0x00000040;
uint MFT_STRING = 0x00000000;
Win32.MENUITEMINFO mif = new Win32.MENUITEMINFO();
mif.cbSize = (uint)Marshal.SizeOf(typeof(Win32.MENUITEMINFO));
mif.fMask = MIIM_STRING;
mif.fType = MFT_STRING;
mif.cch = 256;
mif.dwTypeData = new string(' ', (int)(mif.cch));
bool a = Win32.GetMenuItemInfo(hMenu, 0, true, ref mif);
ls.Add(mif.dwTypeData);
}
}