Click here to Skip to main content
15,886,110 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am trying to make an application that will edit the Menu item (with a submenu item) in the external application. I am currently carrying out tests on a notepad.

img[^]

What I have tried:

The commented part of the code is unfortunately not working...
C#
<pre>using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ChangeMenu
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

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

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

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

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

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

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);

        private const int WM_GETTEXT = 0x000D;
        private const int WM_SETTEXT = 0x000C;

        private void Button1_Click(object sender, EventArgs e)
        {
            foreach (Process proc in Process.GetProcesses())
            {
                if (proc.ProcessName.ToLower() == "notepad")
                {
                    var HMENU = GetMenu(proc.MainWindowHandle);
                    var count = GetMenuItemCount(HMENU);

                    //somehow change menu text
                    //var menu = FindWindowEx(HMENU, IntPtr.Zero, "File", null);
                    //SendMessage(menu, WM_SETTEXT, IntPtr.Zero, "New text1");

                    while (count > 0)
                    {
                        var HsubMENU = GetSubMenu(proc.MainWindowHandle, count);

                        //somehow change submenu text
                        //var submenu = FindWindowEx(HMENU, IntPtr.Zero, "Page Setup...", null);
                        //SendMessage(submenu, WM_SETTEXT, IntPtr.Zero, "New text2");

                        count--;
                    }

                    DrawMenuBar(proc.MainWindowHandle);
                    break;
                }
            }
        }
    }
}
Posted
Updated 9-Jan-20 4:46am
Comments
Maciej Los 12-Nov-19 4:19am    
Why? Is there any reason to change menu in an external application?
mateusz_lozo 12-Nov-19 7:32am    
yes, I am preparing a translation of the program into another language - because in current form it is not useful for many users (the author of the program allowed me to make such a modification).
mateusz_lozo 14-Nov-19 6:06am    
Hey Maciej Los, are you able to help me? I see that you are a very experienced programmer, please guide me how to achieve it ...
Maciej Los 14-Nov-19 6:23am    
Sorry, but i can't.

1 solution

Hi mateusz_lozo,

Your question is nearly two months old. I don't know if you are still interested in this, but I know how to do it.

You Need to use ModifyMenu and GetMenuItemID Windows-API Functions and call them per Interop.

Here you have an example that shows how to change notpads file menu:

C#
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace ConsoleApp6
{
    class Program
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetMenu(IntPtr hWnd);

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

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

        [DllImport("user32.dll")]
        static extern bool ModifyMenu(IntPtr hMnu, uint uPosition, uint uFlags,   IntPtr uIDNewItem, string lpNewItem);

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

        const uint MF_BYPOSITION = 0x00000400;

        static void ChangeText()
        {
            foreach (Process proc in Process.GetProcesses())
            {
                if (proc.ProcessName.ToLower() == "notepad")
                {
                    // Get the main menu handle of notepad
                    var hwndMenuMain = GetMenu(proc.MainWindowHandle);
                    // Get the file menu handle 
                    var hwndMenuFile = GetSubMenu(hwndMenuMain, 0);
                    uint menuItemIDFile = GetMenuItemID(hwndMenuFile, 0);

                    //change menu text
                    ModifyMenu(hwndMenuMain, 0, MF_BYPOSITION, (IntPtr)menuItemIDFile, "Test");

                    // Change sub-menus of file menu
                    var count = GetMenuItemCount(hwndMenuFile);
                    for (int i = 0; i < count; i++)
                    {
                        uint menuItemIDSub = GetMenuItemID(hwndMenuFile, i);

                        ModifyMenu(hwndMenuFile, (uint) i, MF_BYPOSITION, (IntPtr)menuItemIDSub, "SubMenu" + i);                        
                    }

                    break;
                }
            }
        }

        static void Main(string[] args)
        {
            ChangeText();
            Console.ReadKey();
        }
    }
}



Enjoy!

Johannes
 
Share this answer
 
Comments
mateusz_lozo 22-Apr-20 7:56am    
Thank you very much, it was very useful to me!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900