Идеи о том, как отобразить немодальное окно сообщения в виде всплывающей подсказки - PullRequest
4 голосов
/ 19 июня 2009

Мне нужно отображать немодальное окно сообщения всякий раз, когда пользователь наводит курсор мыши на элемент меню. Я не могу использовать messagebox.show (...), потому что это модально. Поэтому я создал отдельную форму для окон и отобразил ее, используя событие hover в пункте меню. У меня 2 проблемы:

1) При отображении формы окна меню теряет видимость.
2) Окно формы не отображается рядом с пунктом меню, как подсказка.

Какие-нибудь идеи о том, как я могу настроить подсказку компонента, которая будет выглядеть и работать как форма окна?

Ответы [ 2 ]

5 голосов
/ 21 июня 2009

Поскольку класс Form является просто оболочкой для собственного окна, вы можете использовать следующий фрагмент для создания собственной всплывающей формы, которая выглядит почти как окно всплывающей подсказки:

public class PopupForm : Form
{
    private const int SWP_NOSIZE = 0x0001;
    private const int SWP_NOMOVE = 0x0002;
    private const int SWP_NOACTIVATE = 0x0010;

    private const int WS_POPUP = unchecked((int)0x80000000);
    private const int WS_BORDER = 0x00800000;

    private const int WS_EX_TOPMOST = 0x00000008;
    private const int WS_EX_NOACTIVATE = 0x08000000;

    private const int CS_DROPSHADOW = 0x00020000;

    private static readonly IntPtr HWND_TOPMOST = (IntPtr)(-1);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    public PopupForm()
    {
        InitializeComponent();
        SetStyle(ControlStyles.Selectable, false);
        Visible = false;
    }

    protected virtual void InitializeComponent()
    {
        FormBorderStyle = FormBorderStyle.None;
        StartPosition = FormStartPosition.Manual;
        ShowInTaskbar = false;
        BackColor = SystemColors.Info;

        // ...
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.Style |= WS_POPUP;
            cp.Style |= WS_BORDER;
            cp.ExStyle |= WS_EX_TOPMOST | WS_EX_NOACTIVATE;
            //if (Microsoft.OS.IsWinXP && SystemInformation.IsDropShadowEnabled)
            //    cp.ClassStyle |= CS_DROPSHADOW;
            return cp;
        }
    }

    protected override bool ShowWithoutActivation
    {
        get { return true; }
    }

    public new void Show()
    {
        SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);    
        base.Show();
    }

    public void Show(Point p)
    {
        Location = p;
        Show();
    }
}

Управляйте этой формой с помощью методов Show () и Hide () из внешнего кода.

5 голосов
/ 19 июня 2009

Чтобы ответить на вашу вторую проблему:

Если вы установите для свойства form.StartPosition значение FormStartPosition.Manual, тогда вы можете расположить форму на курсоре (например):

form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(Cursor.Position.X - 1, Cursor.Position.Y - 1);

Это может помочь и с вашей первой проблемой.

Если вы хотите, чтобы форма работала как всплывающая подсказка, то, если вы добавите следующий код обработчика событий, он может дать вам желаемое:

    private void Form_MouseLeave(object sender, EventArgs e)
    {
        // Only close if cursor actually outside the popup and not over a label
        if (Cursor.Position.X < Location.X || Cursor.Position.Y < Location.Y ||
            Cursor.Position.X > Location.X + Width - 1 || Cursor.Position.Y > Location.Y + Height - 1)
        {
            Close();
        }
    }

Это объясняет -1 в настройке положения формы. Это гарантирует, что курсор находится на форме при первом отображении.

...