2013-02-28 132 views
3

我試圖在我的WinForms UI中顯示來自不同進程的系統菜單(包含最小化,還原等)。我知道我需要像GetSystemMenu和TrackPopupMenuEx這樣的interop調用,但是我沒能使它工作。有人可以提供一個示例代碼如何做到這一點?從另一個進程顯示系統菜單(使用WinForms,c#)

我發現(對WPF)這個代碼片段: Open another application's System Menu

我把它修改成這樣的:

const uint TPM_LEFTBUTTON = 0x0000; 
    const uint TPM_RETURNCMD = 0x0100; 
    const uint WM_SYSCOMMAND = 0x0112; 

    [DllImport("user32.dll")] 
    static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); 

    [DllImport("user32.dll")] 
    static extern uint TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm); 

    [return: MarshalAs(UnmanagedType.Bool)] 
    [DllImport("user32.dll", SetLastError = true)] 
    static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

    public void ShowContextMenu() 
    { 
     IntPtr wMenu = GetSystemMenu(ExternalWindowHandle, false); 
     // Display the menu 
     uint command = TrackPopupMenuEx(wMenu, TPM_LEFTBUTTON | TPM_RETURNCMD, 10, 10, ExternalWindowHandle, IntPtr.Zero); 
     if (command == 0) 
      return; 
     PostMessage(ExternalWindowHandle, WM_SYSCOMMAND, new IntPtr(command), IntPtr.Zero); 
    } 

正如在問題的標題所說,我不希望儘量減少一個窗口到系統托盤,我想顯示一個系統菜單從另一個進程(窗口)在我選擇的位置。幾乎和Windows任務欄一樣。任務欄(資源管理器)似乎可以在任務欄上右鍵單擊時顯示系統菜單。

感謝, 斯特凡

+0

而你發佈的代碼是...? – Brian 2013-02-28 06:49:24

+0

對不起,我錯過了提及,它不起作用。 TrackPopupMenuEx返回0. – 2013-02-28 07:27:32

回答

5

我的代碼的工作版本還我檢查了MSDN庫,我發現,爲了使TrackPopupMenuEx方法來工作「ExternalWindowHandle」變量,您通過即窗口該句柄表示需要位於桌面的前臺。

MSDN庫說以下內容:

「要爲通知圖標顯示上下文菜單,應用程序調用TrackPopupMenu或TrackPopupMenuEx之前當前窗口必須是前景窗口,否則,菜單會。當用戶點擊菜單或創建菜單的窗口(如果它是可見的)時,不會消失。如果當前窗口是子窗口,則必須將(頂層)父窗口設置爲前景窗口。http://msdn.microsoft.com/en-us/library/windows/desktop/ms648003(v=vs.85).aspx

因此,這意味着,當你的窗口是活動之一,因爲窗口是不是一個在前臺它僅會工作,並在前臺,如果你是在Visual Studio將無法正常工作實例調試即視覺工作室不是你的應用程序。

請參閱附上的工作代碼示例,請記住,它只會在應用程序窗口是焦點/前景中的應用程序窗口時才起作用。即當您正在調試或使用其他窗口時,TrackPopupMenuEx將始終返回0。

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

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

     const uint TPM_LEFTBUTTON = 0x0000; 
     const uint TPM_RETURNCMD = 0x0100; 
     const uint WM_SYSCOMMAND = 0x0112; 

     [DllImport("user32.dll")] 
     static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); 

     [DllImport("user32.dll")] 
     static extern uint TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm); 

     [return: MarshalAs(UnmanagedType.Bool)] 
     [DllImport("user32.dll", SetLastError = true)] 
     static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

     public static void ShowContextMenu(IntPtr appWindow, IntPtr myWindow, Point point) 
     { 
      IntPtr wMenu = GetSystemMenu(appWindow, false); 
      // Display the menu 
      uint command = TrackPopupMenuEx(wMenu, 
       TPM_LEFTBUTTON | TPM_RETURNCMD, (int)point.X, (int)point.Y, myWindow, IntPtr.Zero); 
      if (command == 0) 
       return; 

      PostMessage(appWindow, WM_SYSCOMMAND, new IntPtr(command), IntPtr.Zero); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      ShowContextMenu(new IntPtr(<<put your target window handle here>>), this.Handle, new Point(0, 0)); 
     } 
    } 
} 
+1

感謝您的幫助! – 2013-03-06 10:14:44

相關問題