I'm trying to gather the text of a menu item using GetMenuItemInfo API.
This is the code I'm using:
[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
Unfortunately after those lines dwTypeData results a string with only 1 character instead of mif.cch characters. Note: this character is the first one of the menu item!
It seems that there's some misalignment in the marshaling of data when returning MENUITEMINFO structure, isn.t it?
Please let me know how to solve such issue!
Best
cghersi
Your header translation is pretty good, but you've not got dwTypeData
quite right. That cannot be marshalled from caller to callee using string
. You need to do that with manual marshalling like this.
[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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With