从另一个进程显示系统菜单(使用WinForms,c#)

从另一个进程显示系统菜单(使用WinForms,c#),c#,winforms,interop,C#,Winforms,Interop,我试图从WinForms UI中的不同进程显示系统菜单(包含最小化、还原等)。我知道我需要像GetSystemMenu和TrackPopupMenuEx这样的互操作调用,但我没能让它工作。有人能提供一个示例代码来说明如何做到这一点吗 我发现了以下代码片段(用于WPF): 我将其修改为如下内容: const uint TPM_LEFTBUTTON = 0x0000; const uint TPM_RETURNCMD = 0x0100; const uint WM_SYSC

我试图从WinForms UI中的不同进程显示系统菜单(包含最小化、还原等)。我知道我需要像GetSystemMenu和TrackPopupMenuEx这样的互操作调用,但我没能让它工作。有人能提供一个示例代码来说明如何做到这一点吗

我发现了以下代码片段(用于WPF):

我将其修改为如下内容:

    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);
    }
如问题标题所述,我不想最小化systray的窗口,我想在我选择的位置显示另一个进程(窗口)的系统菜单。与windows任务栏的方式几乎相同。当您在任务栏上右键单击任务栏(资源管理器)时,它似乎能够显示系统菜单

谢谢,
Stefan

我有一个工作版本的代码,我也检查了MSDN库,我发现为了让TrackPopupMenuEx方法工作,您传递的“ExternalWindowHandle”变量,即句柄表示的窗口需要位于桌面的前台

MSDN库说明如下:

“若要显示通知图标的上下文菜单,在应用程序调用TrackPopupMenu或TrackPopupMenuEx之前,当前窗口必须是前台窗口。否则,当用户在菜单或创建菜单的窗口(如果可见)外单击时,菜单不会消失。”。如果当前窗口是子窗口,则必须将(顶级)父窗口设置为前景窗口。“,

因此,这意味着只有当您的窗口是活动窗口时,它才会工作,并且如果您正在visual studio中调试,它将不会工作,因为该窗口不是前景中的窗口,即visual studio不是您的应用程序

请参阅随附的工作代码示例,请记住,只有当应用程序窗口处于焦点/前景时,它才会工作。i、 e.调试或使用其他窗口时,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));
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用System.Runtime.InteropServices;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Forms;
命名空间Windows窗体应用程序2
{
公共部分类Form1:Form
{
公共表格1()
{
初始化组件();
}
consuint TPM_LEFTBUTTON=0x0000;
常数TPM_RETURNCMD=0x0100;
const uint WM_SYSCOMMAND=0x0112;
[DllImport(“user32.dll”)]
静态外部IntPtr GetSystemMenu(IntPtr hWnd、bool bRevert);
[DllImport(“user32.dll”)]
静态外部跟踪弹出菜单(IntPtr HUNEU、int fuFlags、int x、int y、IntPtr hwnd、IntPtr lptpm);
[返回:Marshallas(UnmanagedType.Bool)]
[DllImport(“user32.dll”,SetLastError=true)]
静态外部bool PostMessage(IntPtr hWnd、uint Msg、IntPtr wParam、IntPtr lParam);
公共静态void ShowContextMenu(IntPtr appWindow、IntPtr myWindow、Point-Point)
{
IntPtr wMenu=GetSystemMenu(appWindow,false);
//显示菜单
uint命令=TrackPopupMenuEx(wMenu,
TPM_LEFTBUTTON | TPM_RETURNCMD,(int)point.X,(int)point.Y,myWindow,IntPtr.Zero);
如果(命令==0)
返回;
PostMessage(appWindow、WM_SYSCOMMAND、newintptr(command)、IntPtr.Zero);
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
ShowContextMenu(newintptr(),this.Handle,新点(0,0));
}
}
}

而您发布的代码是…?对不起,我没提到,它就是不起作用。TrackPopupMenuEx返回0。