Reputation: 684
I'm trying to read the label names of menu items in an active application and store them in a List<String>
.
Unfortunately, dwTypeData
ALWAYS returns null
. Why is this?
List<string> ls = new List<string>();
IntPtr hMenu = Win32.GetMenu(hWnd);
if (hMenu.ToInt32() != 0)
{
for (int i = Win32.GetMenuItemCount(hMenu); i >= 0; i--)
{
try
{
uint MIIM_STRING = 0x00000040;
uint MFT_STRING = 0x00000000;
uint MIIM_TYPE = 0x00000010;
Win32.MENUITEMINFO mif = new Win32.MENUITEMINFO();
mif.cbSize = (uint)Marshal.SizeOf(typeof(Win32.MENUITEMINFO));
mif.fMask = MIIM_TYPE;
mif.fType = MFT_STRING;
mif.cch = 256;
mif.dwTypeData = "";
Win32.GetMenuItemInfo(hMenu, (uint)i, true, ref mif); //To load cch into memory
Win32.GetMenuItemInfo(hMenu, (uint)i, true, ref mif); //To fill dwTypeData
ls.Add(mif.dwTypeData);
}
catch { }
}
}
return ls;
Upvotes: 0
Views: 1905
Reputation: 11
Try to replace
mif.fMask = MIIM_TYPE;
mif.fType = MFT_STRING;
with
mif.fMask = MIIM_FTYPE;
mif.fType = MIIM_STRING;
The Win32 API MENUITEMINFOA documentation states that
MFT_STRING is replaced by MIIM_STRING.
Upvotes: 1
Reputation: 612993
Your problem is that you are trying to perform this action in a different process. When you call GetMenuItemInfo
you pass the address of a MENUITEMINFO
struct. But that address is only valid in your process. Because each process has its own private virtual memory space, that pointer that you send has no meaning in the other process.
It's possible that you could use VirtualAllocEx
, WriteProcessMemory
and ReadProcessMemory
to allocate, write and read an instance of the MENUITEMINFO
struct in the address space of the other process. That's your only hope of making this mechanism work. There are lots of examples to be found using websearch that illustrate the technique.
However, I would not recommend that you do that. You should use one of the standard automation interfaces to solve your actual problem. For example UIAutomation.
Upvotes: 1
Reputation: 5132
a) the loop should be for (int i = Win32.GetMenuItemCount(hMenu) - 1; i >= 0; i--)
b) before the first call to GetMenuItemInfo()
, you need to set mif.dwTypeData
to NULL (zero)
c) before the second call to GetMenuItemInfo()
, mif.dwTypeData
should point to a buffer allocated with a size of mif.cch + 1
-- see MSDN documentation
Make sure you deallocate the memory afterwards!
Upvotes: 1