Вот пример того, как сделать смоделированную кнопку. Это происходит в самой форме, но работает так же и в пользовательском элементе управления.
Также показано, как получить «причудливый» стиль кнопки, используя 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).
Нажмите кнопку «Отмена» или «Обзор ...» и удерживайте ее нажатой.
Переместите мышь к окну браузера и обратите внимание, что оно больше не регистрирует движение мыши.
Вот так все кнопки работают по дизайну. Хотя вряд ли кто-то заметит это, потому что вы обычно щелкаете и отпускаете без движения мыши (сильно).
Перемещение мыши от кнопки и отпускание - это механизм, предоставленный пользователю, который позволяет им передумать, а не «нажимать» кнопку. Вот почему вы тестируете снова в событии при нажатии кнопки, чтобы убедиться, что они все еще находятся на кнопке, прежде чем вы определите, что пользователь выполнил щелчок.
Итак, есть три причины захватить мышь:
Во-первых, вы не хотите, чтобы другие окна выполняли такие вещи, как выделение, потому что пользователь занят взаимодействием с вашим окном, а выполнение другими окнами каких-либо действий во время операции отвлекает и потенциально сбивает с толку.
Во-вторых, вы не хотите, чтобы нажатие пользователем кнопки мыши отправлялось в другое окно, если они не могли полностью переместить мышь в другое окно. Ложное освобождение мыши без сопутствующей печати может запутать плохо написанные приложения.
В-третьих, для некоторых расширенных операций, таких как рисование или «спор», вы хотите знать координаты мыши, даже если они находятся за пределами вашего окна. Вы можете увидеть пример споров, нажав и удерживая на рабочем столе и перемещая мышь вокруг. Обратите внимание, как изменяется прямоугольник даже при наведении мыши на другие окна.