Manipulating win32 app menus from c# using pinvoke...

G

Guy Mahieu

Hi,

I am trying to dynamically add menu items to external win32 applications
from c# code. I have found some VB6 examples on the net that do just that,
but when I rewrite them into c# they will either do nothing, add a separator
or add an empty menu item which does not trigger commands when clicked.

The difference between a separator or an empty item getting inserted lies in
supplying the fMask of the MENUITEMINFO with the MF_OWNERDRAW constant from
winuser.h

Does anyone have experience with this kind of thing?

Thanks in advance!

Here is the code to reproduce the situation, it starts up notepad and adds
an extra menu item at the bottom of the file menu:
(I only included win api constants which I thought are relevant to the issue
at hand so this message would not be unnecessarily long.)


----8<---------------------------------------

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Example
{
[StructLayout(LayoutKind.Sequential)]
internal 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 string dwTypeData;
public IntPtr dwItemData;
public uint cch;
public IntPtr hbmpItem;
}

/// <summary>
/// Summary description for Example.
/// </summary>
public class Example
{

const string PATH_TO_NOTEPAD = @"C:\WINNT\system32\notepad.exe";

[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);

[DllImport("user32.dll")]
private static extern int GetMenuItemCount(IntPtr hMenu);

[DllImport("user32.dll")]
private static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool
fByPosition, [In] ref MENUITEMINFO lpmii);

[DllImport("user32.dll")]
private static extern bool DrawMenuBar(IntPtr hWnd);

internal const UInt32 MIIM_FTYPE = 0x00000100;

internal const UInt32 MF_STRING = 0x00000000;
internal const UInt32 MF_OWNERDRAW = 0x00000100;

public static void Main(string[] args)
{
Process process = Process.Start(PATH_TO_NOTEPAD);
IntPtr handle = process.MainWindowHandle;

IntPtr mainMenu = GetMenu(handle);
IntPtr fileMenu = GetSubMenu(mainMenu, 0);

MENUITEMINFO myMenuItem = new MENUITEMINFO();
myMenuItem.cbSize = (uint) Marshal.SizeOf(myMenuItem);
myMenuItem.fMask = MIIM_FTYPE;
myMenuItem.fType = MF_STRING;
myMenuItem.dwTypeData = "myName";
myMenuItem.cch = (uint) myMenuItem.dwTypeData.Length;

uint itemIndex = (uint) GetMenuItemCount(fileMenu) + 1;
InsertMenuItem(fileMenu, itemIndex, true, ref myMenuItem);
DrawMenuBar(handle);
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top