I have programming a new program where I can get shell context menu of the file(s).
But I have a problem when I call win32 api function GetMenuItemInfo. This method returns me false as result and when I immediately call Marshall.GetLastWin32Error then I got the error code 87.
This is my code:
int count = Win32APICaller.GetMenuItemCount(pMenu);
MENUITEMINFO mif = new MENUITEMINFO();
uint MIIM_STRING = 0x00000040;
uint MFT_STRING = 0x00000000;
mif.fMask = MIIM_STRING;
mif.fType = MFT_STRING;
mif.dwTypeData = null;
mif.cbSize = Marshal.SizeOf(mif);
bool result = Win32APICaller.GetMenuItemInfo(pMenu, 1, true, ref mif);
int errorCode = Marshal.GetLastWin32Error();
And this is my MENUITEMINFO structure:
public long cbSize;
public long fMask;
public long 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;
I don't know where I am an error.
As the comment pointed out, according to the MENUITEMINFO
, the struct in c++ is:
typedef struct tagMENUITEMINFOA {
UINT cbSize;
UINT fMask;
UINT fType;
UINT fState;
UINT wID;
HMENU hSubMenu;
HBITMAP hbmpChecked;
HBITMAP hbmpUnchecked;
ULONG_PTR dwItemData;
LPSTR dwTypeData;
UINT cch;
HBITMAP hbmpItem;
} MENUITEMINFOA, *LPMENUITEMINFOA;
in C#, the size of uint
is not equal to long
:
So you will need to replace the long
with the uint
.
Then the size of MENUITEMINFO
is 48 in 32-bit and 80 in 64-bit.
In addition, you will need to first obtain mif.cch
to get the string length, and then assign mif.cch+1
size (add terminator size) to mif.dwTypeData
bool result = GetMenuItemInfo(pMenu, 1, true, ref mif);
if (result)
{
mif.cch += 1;
//Set the length of the buffer to cch + 1
mif.dwTypeData = new string(' ', (int)(mif.cch));
result = GetMenuItemInfo(pMenu, 1, true, ref mif); //To fill dwTypeData
}
To ensure uniform character, use auto charset:
[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;
}
Finally, MFT_STRING
is replaced by MIIM_STRING
. You only need to specify MIIM_STRING
.
Sample:
ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("Item 1");
cm.MenuItems.Add("Item 2");
IntPtr pMenu = cm.Handle;
int count = GetMenuItemCount(pMenu);
MENUITEMINFO mif = new MENUITEMINFO();
uint MIIM_STRING = 0x00000040;
//uint MFT_STRING = 0x00000000;
mif.fMask = MIIM_STRING;
//mif.fType = MFT_STRING;
mif.dwTypeData = null;
mif.cbSize = (uint)Marshal.SizeOf(mif);
bool result = GetMenuItemInfo(pMenu, 1, true, ref mif);
if (result)
{
mif.cch += 1;
mif.dwTypeData = new string(' ', (int)(mif.cch));
result = GetMenuItemInfo(pMenu, 1, true, ref mif);
}
User contributions licensed under CC BY-SA 3.0