1

我想模仿 Google Chrome/FireFox 的功能,例如,在重新排列书签时,当您拖动菜单项时,它会在建议的放置点创建一条黑线,如下所示:

替代文字 http://www.freeimagehosting.net/uploads/977900a13a.jpg

我已经实现了拖放功能来重新排列菜单,但我想添加这些分隔线作为附加功能。

有没有办法在 .NET Framework (3.5) 中做到这一点,还是我必须求助于 Win32 api 调用?只是想在我走那条路之前问一下。

4

2 回答 2

0

我认为最简单的方法是获取您正在拖动的弹出菜单的句柄。一旦你有了手柄,你就可以用一个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 菜单执行此操作,它应该可以正常工作。

于 2010-04-15T02:28:05.923 回答
0

在纯 .NET 代码中执行此操作的一种常见方法是创建一个无边框的窗体,该窗体的颜色和大小看起来像落点线。还要在此表单上将 TopMost 属性设置为 True。

然后使用 MouseDown/MouseUp/MouseMove 事件来确定何时何地显示下拉线以响应用户操作。

要正确定位放置线表单,您需要查看Control.PointToScreen和/或Control.RectangleToScreen(可能还有 Control.PointToClient)方法。

于 2010-04-15T02:07:03.810 回答