.NET/C#中如何在右键菜单上方绘制?

How to draw on top of the right-click menu in .NET/C#?

我正在开发一个辅助技术应用程序(在 C# 中),它将信息叠加在当前打开的 window 之上。它检测可点击的元素,并标记它们。

为此,我目前正在创建一个无边界、透明的 window,并将 TopMost 设置为 "true",并在其上绘制标签。这意味着总是有一个 window 悬停在当前应用程序的前面,我可以在上面绘制标签。

问题是,这个 window 不包括右键单击菜单 - 只有其他 windows。当用户单击鼠标右键时,上下文菜单绘制在叠加层上方。

我需要能够在右键单击菜单中标记元素,但我无法使用当前实现在其上绘制。有人知道解决方案吗?

编辑:这是绘制叠加层的相关代码。我在表单设计器中设置了表单选项,而不是在代码中明确设置,所以我不确定它会有多大帮助。我删除了与绘图无关的代码,或表单本身:

public partial class OverlayForm : Form
{
    public OverlayForm()
    {

    }

    protected override void OnPaint(PaintEventArgs eventArgs)
    {
        base.OnPaint(eventArgs);
        Graphics graphics = eventArgs.Graphics;
        Brush brush = new SolidBrush(this.labelColor);
        foreach (ClickableElement element in this.elements)
        {
            Region currentRegion = element.region;
            graphics.FillRegion(brush, currentRegion);
        }
    }    
}

我找到了一些 hack 解决方案。

通过定期将叠加层 window 置于最前面,我可以将其置于 Z 顺序的顶部,覆盖右键单击菜单。它并不完美,但确实有效。这是核心概念,去掉了多线程:

public class OverlayManager
{
    OverlayForm overlay;

    public OverlayManager() 
    {
        this.overlay = new OverlayForm();
        this.overlay.Show();
        this.RepeatedlyBringToFront();
    }

    private void RepeatedlyBringToFront()
    {
        while (true)
        {
            this.overlay.BringToFront();
            Thread.Sleep(50);
        }
    }
}

(假设 "OverlayForm" 是一个在表单设计器中设置了相关标志的表单 - 即 "Always on Top," "Transparency Key," "Borderless," "Maximised," 等)

我只在 Windows 8.1 上测试过。我不知道 Z 顺序在其他版本上是否以这种方式表现。

向表单添加上下文菜单,然后在 ContextMenuStrip 下的控件属性中分配它。

ContextMenu cm = new ContextMenu();
cm.MenuItems.Add("Item 1");
cm.MenuItems.Add("Item 2");

pictureBox1.ContextMenu = cm;