我认为最简单的方法是获取您正在拖动的弹出菜单的句柄。获得句柄后,您可以使用Graphics 对象直接在其上绘制。
获取句柄可能需要一些 API 魔力。我正在查。
更新:没有太多魔力,尽管有一个讽刺意味(见下文)。为此,请添加
using System.Runtime.InteropServices;
在您的表单或班级或其他任何内容的顶部。在某处添加此声明:
[DllImport("user32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindowA(string lpClassName,
string lpWindowName);
弹出式菜单窗口(即您通常看不到的部分)是类名为“#32768”的最顶层窗口。这段代码展示了如何获取菜单的窗口句柄并直接在上面绘制:
IntPtr hWnd = FindWindowA("#32768", null);
if (hWnd != IntPtr.Zero)
{
using (Graphics g = Graphics.FromHwnd(hWnd))
{
g.FillRectangle(Brushes.Red,
new Rectangle(0, 0, 20, 20));
}
}
此示例仅在菜单的左上角绘制了一个 20x20 的红色方块。要渲染下降线,你必须做更多的工作来确定它应该在哪里,然后在那里绘制你想要的任何东西。在我看来,它只是一条两像素高的黑线,两端各有小部分箭头,所以应该不难模仿。
你可能不得不担心清理你画的任何东西,但我对此表示怀疑。弹出菜单窗口是临时的,我认为当您将光标移到它们上方时它们会自动重新绘制。如果没有,您可能必须在每次下拉线更改位置时向弹出菜单窗口发送重绘消息。
即使您打开了多个嵌套菜单(它们都可能具有类名“#32768”),它似乎也可以工作 - FindWindow 似乎总是返回 z 顺序中最顶部的菜单。另一件好事 - 因为您是在菜单窗口本身上绘图,所以该行将位于半透明放置光标下方,这就是您想要的。
具有讽刺意味的是:我在一堆不同的程序和菜单上对此进行了测试。它适用于所有这些和所有菜单,除了 Internet Explorer 中的收藏夹菜单。我猜那个特定的菜单使用的不是内置的 Windows 菜单。如果您使用常规 .Net 菜单执行此操作,它应该可以正常工作。