Как создать линии удаления при перетаскивании пункта меню в WinForm? - PullRequest
1 голос
/ 15 апреля 2010

Я хочу имитировать функциональность Google Chrome / FireFox, например, при перестановке ваших закладок, когда вы перетаскиваете элемент меню, он создает черную линию в предложенной точке отбрасывания, например:

альтернативный текст http://www.freeimagehosting.net/uploads/977900a13a.jpg

Я уже реализовал функцию перетаскивания для изменения меню, но я хотел бы добавить эти разделительные линии в качестве дополнительной функции.

Есть ли способ сделать это в .NET Framework (3.5) или мне придется прибегать к вызовам Win32 API? Просто хотел спросить, прежде чем я пошел по этому пути.

Ответы [ 2 ]

0 голосов
/ 15 апреля 2010

Я думаю, что самый простой способ сделать это - получить указатель на всплывающее меню, через которое вы перетаскиваете. Если у вас есть ручка, вы можете рисовать прямо на ней с помощью Graphics объекта.

Получение дескриптора, вероятно, требует некоторого API mojo. Я ищу это.

Обновление: совсем не моджо, хотя есть иронический улов (см. Ниже). Для этого добавьте

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 меню, оно должно работать нормально.

0 голосов
/ 15 апреля 2010

Обычный способ сделать это в чистом коде .NET - это создать форму без полей, которая окрашена и имеет размеры, похожие на линию точки отбрасывания. Также установите для свойства TopMost значение True в этой форме.

Затем используйте события MouseDown / MouseUp / MouseMove, чтобы определить, когда и где отображать линию удаления в ответ на действия пользователя.

Чтобы правильно расположить форму линии переноса, вам необходимо изучить методы Control.PointToScreen и / или Control.RectangleToScreen (и, возможно, Control.PointToClient).

...