繁体   English   中英

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

[英]Show system menu from another process (using WinForms, c#)

我试图在我的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);
    }

正如问题标题中所提到的,我不想最小化系统托盘的窗口,我想在我选择的位置显示来自另一个进程(窗口)的系统菜单。 几乎与Windows任务栏一样。 任务栏(资源管理器)似乎能够在任务栏上右键单击它时显示系统菜单。

谢谢,斯特凡

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

MSDN Library说明如下:

“要显示通知图标的上下文菜单, 当前窗口必须是应用程序调用TrackPopupMenu或TrackPopupMenuEx之前的前台窗口 。否则,当用户单击菜单外部或创建菜单的窗口时,菜单不会消失(如果可见的话。如果当前窗口是子窗口,则必须将(顶级)父窗口设置为前景窗口。“ http://msdn.microsoft.com/en-us/library/windows/desktop/ms648003(v = vs。85).aspx

所以这意味着它只会在你的窗口是活动窗口时才会工作,如果你在Visual Studio中进行调试它将无法工作,因为窗口不是前景窗口,即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));
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM