在第三方应用程序的AppendMenu后连接点击事件

本文关键字:连接点 事件 AppendMenu 第三方 应用程序 | 更新日期: 2023-09-27 18:05:22

我正在尝试添加一个新的菜单项使用DLL函数导入的user32.dll使用DLLImort到第三方应用程序的WPF应用程序。

不,我想获得新生成的MenuItem的click事件。什么好主意吗?下面是目前为止的代码。我知道有SetWindowHookEx之类的函数,但我卡住了。

这是一些测试代码,没有防弹…

public partial class MainWindow : Window
{
    [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;
    const uint MF_POPUP = 0x00000010;
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern bool AppendMenu(IntPtr hMenu, MenuFlags uFlags, uint uIDNewItem, string lpNewItem);

    [DllImport("user32.dll")]
    static extern IntPtr CreatePopupMenu();
    [Flags]
    public enum MenuFlags : uint
    {
        MF_STRING = 0,
        MF_BYPOSITION = 0x400,
        MF_SEPARATOR = 0x800,
        MF_REMOVE = 0x1000,
        MF_POPUP = 0x00000010,
    }

    [StructLayout(LayoutKind.Sequential)]
    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)); }
        }
    }

    public MainWindow()
    {
        InitializeComponent();

        Loaded += OnLoaded;
    }
    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        createMenuEntry();
    }
    private void createMenuEntry()
    {
        Process[] proceses = Process.GetProcessesByName("spotify");
        Process process = proceses.Where(e => e.MainWindowTitle == "Spotify").First();
        IntPtr handle = process.MainWindowHandle;
        IntPtr mainMenu = GetMenu(handle);
        int mainMenuItemCount = GetMenuItemCount(mainMenu);
        AppendMenu(mainMenu, MenuFlags.MF_STRING, 555, "TestEntry");
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        //HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
        //source.AddHook(WndProc);
    }
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        // Handle messages...
        Debug.WriteLine((int)wParam);
        if (((int)wParam == 555))
        {
            MessageBox.Show("Click");
        }
        return IntPtr.Zero;
    }
}

在第三方应用程序的AppendMenu后连接点击事件

你的第一步是放下c#,了解本地菜单API是如何工作的。从这里开始:https://msdn.microsoft.com/en-us/library/windows/desktop/ms647553.aspx

我强烈建议您创建一个新的c++项目,并编写一个简单的程序来添加菜单并响应单击。

关键信息可以在我链接到的文档中找到,我的重点是:

当用户选择一个命令项时,系统向拥有该菜单的窗口发送一个命令消息。如果命令项在窗口菜单上,系统发送WM_SYSCOMMAND消息。否则,发送WM_COMMAND消息。

你需要拦截那个消息。我怀疑这意味着需要使用全局WH_CALLWNDPROC钩子。这将需要一个非托管DLL来实现钩子。