Winforms: добавить кнопку закрытия "х" в UserControl - PullRequest
2 голосов
/ 16 мая 2011

Мне нужно добавить кнопку закрытия "x" в верхнем левом углу UserControl.Мне бы хотелось, чтобы у этой кнопки был такой же стиль, как у обычной кнопки закрытия Winforms (синий в стиле XP и т. Д.).

Возможно ли это сделать?

Ответы [ 3 ]

4 голосов
/ 16 мая 2011

Вот пример того, как сделать смоделированную кнопку. Это происходит в самой форме, но работает так же и в пользовательском элементе управления.

Также показано, как получить «причудливый» стиль кнопки, используя VisualStyleRenderer в случае, если стиль ControlPaint слишком «старый».

Обновлено После шести правок я думаю, что я доволен этим.

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;

class Form1 : Form
{
    [STAThread]
    static void Main()
    {
        //Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public Form1()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.Opaque | ControlStyles.AllPaintingInWmPaint, true);
    }

    Rectangle buttonRect = new Rectangle(10, 10, 50, 20);
    ButtonState buttonState = ButtonState.Normal;

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (buttonRect.Contains(e.Location))
            buttonState = Capture ? ButtonState.Pushed : ButtonState.Checked;
        else
            buttonState = ButtonState.Normal;
        Invalidate(buttonRect);

        base.OnMouseMove(e);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left && buttonRect.Contains(e.Location))
        {
            Capture = true;
            buttonState = ButtonState.Pushed;
            Invalidate(buttonRect);
        }

        base.OnMouseDown(e);
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        if (Capture)
        {
            Capture = false;
            Invalidate(buttonRect);
            if (buttonRect.Contains(e.Location))
            {
                // The button was clicked

                MessageBox.Show("You clicked the button.");
            }
        }

        base.OnMouseUp(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.FillRectangle(SystemBrushes.Window, e.ClipRectangle);

        VisualStyleRenderer renderer = null;
        if (Application.RenderWithVisualStyles)
        {
            switch (buttonState)
            {
                case ButtonState.Checked:
                    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Hot))
                        renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Hot);
                    break;
                case ButtonState.Pushed:
                    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Pressed))
                        renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Pressed);
                    break;
                default:
                    if (VisualStyleRenderer.IsElementDefined(VisualStyleElement.Window.CloseButton.Normal))
                        renderer = new VisualStyleRenderer(VisualStyleElement.Window.CloseButton.Normal);
                    break;
            }
        }

        if (renderer != null)
            renderer.DrawBackground(e.Graphics, buttonRect);
        else
            ControlPaint.DrawCaptionButton(e.Graphics, buttonRect, CaptionButton.Close, buttonState);

        base.OnPaint(e);
    }
}

Расширенный комментарий

Расширенная операция - это операция, которая начинается с того, что пользователь нажимает кнопку мыши, (необязательно) перемещает мышь, а затем отпускает эту кнопку. Нажатие на кнопку пользовательского интерфейса всегда является расширенной операцией. Цель захвата мыши - предотвратить взаимодействие с другими окнами во время этой операции.

Вы можете увидеть это продемонстрировано прямо сейчас:

Сначала обратите внимание, что при наведении указателя мыши на элементы на этой странице (например, комментарии) они меняют цвет фона.

Теперь откройте диалоговое окно запуска Windows (Win + R).

Нажмите кнопку «Отмена» или «Обзор ...» и удерживайте ее нажатой.

Переместите мышь к окну браузера и обратите внимание, что оно больше не регистрирует движение мыши.

Вот так все кнопки работают по дизайну. Хотя вряд ли кто-то заметит это, потому что вы обычно щелкаете и отпускаете без движения мыши (сильно).

Перемещение мыши от кнопки и отпускание - это механизм, предоставленный пользователю, который позволяет им передумать, а не «нажимать» кнопку. Вот почему вы тестируете снова в событии при нажатии кнопки, чтобы убедиться, что они все еще находятся на кнопке, прежде чем вы определите, что пользователь выполнил щелчок.

Итак, есть три причины захватить мышь:

Во-первых, вы не хотите, чтобы другие окна выполняли такие вещи, как выделение, потому что пользователь занят взаимодействием с вашим окном, а выполнение другими окнами каких-либо действий во время операции отвлекает и потенциально сбивает с толку.

Во-вторых, вы не хотите, чтобы нажатие пользователем кнопки мыши отправлялось в другое окно, если они не могли полностью переместить мышь в другое окно. Ложное освобождение мыши без сопутствующей печати может запутать плохо написанные приложения.

В-третьих, для некоторых расширенных операций, таких как рисование или «спор», вы хотите знать координаты мыши, даже если они находятся за пределами вашего окна. Вы можете увидеть пример споров, нажав и удерживая на рабочем столе и перемещая мышь вокруг. Обратите внимание, как изменяется прямоугольник даже при наведении мыши на другие окна.

3 голосов
/ 16 мая 2011

Обновленный ответ
Я только что обнаружил класс ControlPaint в .net, который делает то же самое, что и функция DrawFrameControl. Используйте это вместо этого!

Вы можете использовать класс ControlPaint для реализации элемента управления кнопки, который рисует себя, чтобы выглядеть как кнопка «Закрыть» Windows (переопределить OnPaint). В зависимости от требуемого уровня сложности, вы можете также реализовать события наведения мыши и события наведения мыши вниз, чтобы обеспечить визуальную обратную связь для текущего состояния. Если вы поместите этот элемент управления на UserControl, вы должны быть на правильном пути.

Оригинал, устаревший ответ
Возможно, вы захотите взглянуть на API-функцию DrawFrameControl в Windows.

Комбинация DFC_CAPTION и DFCS_CAPTIONCLOSE должна делать то, что вы хотите.

0 голосов
/ 16 мая 2011

не уверен, что это возможно, но это определенно запутает пользователей, если ваш основной элемент управления, в котором будет размещен этот UserContorl, будет иметь эти 3 кнопки (мин, макс / закрыть) и ваш пользовательский элемент управления.что за этим стоит?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...