2015-07-29 2 views
0

Я пытаюсь добавить новый MenuItem, используя DLL Fucntions, импортированные из user32.dll, используя DLLImort для стороннего приложения из моего приложения WPF.Захват события клика после AppendMenu стороннего приложения

Нет. Мне бы хотелось получить событие щелчка вновь созданного MenuItem. Есть идеи? Вот код до сих пор. Я знаю, что есть функции SetWindowHookEx или что-то еще, но я застрял.

Это какой-то тестовый код и не bulletproofed ..

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; 
    } 

} 

Спасибо за любые идеи или предложения заранее.

ответ

1

Ваш первый шаг - положить C# и понять, как работает API-интерфейс родного меню. Начните здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/ms647553.aspx

Я настоятельно рекомендую вам создать новый проект на C++ и написать простую программу для добавления меню и ответа на клики.

Ключевая информация содержится в документации, которую я связан, с моим акцентом:

Когда пользователь выбирает элемент команды, системы отправляет сообщение команды к окну, которое владеет меню. Если элемент команды находится в меню окна, система отправляет сообщение WM_SYSCOMMAND. В противном случае он отправляет сообщение WM_COMMAND.

Вам необходимо перехватить это сообщение. Я подозреваю, что вам нужно использовать глобальный крючок WH_CALLWNDPROC. Это потребует неуправляемой DLL для реализации крючка.

+0

Спасибо за ответ. Но не было бы возможным создать проект dll C++ для создания меню и реализовать крючок? И слушать событие в проекте C#? – addy

+0

Разве это не то, что я сказал? –

+0

: D хорошо. Танки. Мысль о внедрении приложения wohle с использованием C++ – addy