Как различать щелчки и двойные щелчки (Windows Forms .NET)
Как правило, одинарный щелчок инициирует действие пользовательского интерфейса, а двойной щелчок расширяет действие. Например, один щелчок обычно выбирает элемент, а двойной щелчок редактирует выбранный элемент. Однако события Windows Forms не могут легко поддерживать сценарий, в котором одиночный щелчок и двойной щелчок выполняют разные действия, так как действие, связанное с событием Click или MouseClick, выполняется раньше действия, связанного с событием DoubleClick или MouseDoubleClick. В этом разделе демонстрируется два решения этой проблемы.
Одним из решений является обработка события двойного щелчка с целью отмены действий, выполненных при обработке события одиночного щелчка. В редких ситуациях может потребоваться имитировать поведение щелчка и двойного щелчка, обрабатывая событие MouseDown и используя свойства DoubleClickTime и DoubleClickSize класса SystemInformation. Вы измеряете время между щелчками и, если второй щелчок возникает до достижения значения DoubleClickTime, и щелчок находится в прямоугольнике, определенном DoubleClickSize, выполните действие двойного щелчка; в противном случае выполните действие щелчка.
Откат действия щелчка мыши
Убедитесь, что элемент управления, с которым вы работаете, имеет стандартное поведение двойного щелчка. Если нет, включите элемент управления с помощью метода SetStyle. Обработайте событие двойного щелчка и отмените действие одиночного щелчка, а также действие двойного щелчка. В следующем примере кода показано, как создать пользовательскую кнопку с поддержкой двойного щелчка, а также как откатить действие щелчка в коде обработки событий двойного щелчка.
В этом примере кода используется новый элемент управления кнопки, который позволяет дважды щелкать:
public partial class DoubleClickButton : Button
{
public DoubleClickButton()
{
// Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true);
}
}
Public Class DoubleClickButton : Inherits Button
Public Sub New()
SetStyle(ControlStyles.StandardClick Or ControlStyles.StandardDoubleClick, True)
End Sub
End Class
В следующем коде показано, как форма изменяет стиль границы на основе щелчка или двойного щелчка нового элемента управления кнопкой:
public partial class Form1 : Form
{
private FormBorderStyle _initialStyle;
private bool _isDoubleClicking;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_initialStyle = this.FormBorderStyle;
var button1 = new DoubleClickButton();
button1.Location = new Point(50, 50);
button1.Size = new Size(200, 23);
button1.Text = "Click or Double Click";
button1.Click += Button1_Click;
button1.DoubleClick += Button1_DoubleClick;
Controls.Add(button1);
}
private void Button1_DoubleClick(object sender, EventArgs e)
{
// This flag prevents the click handler logic from running
// A double click raises the click event twice.
_isDoubleClicking = true;
FormBorderStyle = _initialStyle;
}
private void Button1_Click(object sender, EventArgs e)
{
if (_isDoubleClicking)
_isDoubleClicking = false;
else
FormBorderStyle = FormBorderStyle.FixedToolWindow;
}
}
Partial Public Class Form1
Private _initialStyle As FormBorderStyle
Private _isDoubleClicking As Boolean
Public Sub New()
InitializeComponent()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim button1 As New DoubleClickButton
_initialStyle = FormBorderStyle
button1.Location = New Point(50, 50)
button1.Size = New Size(200, 23)
button1.Text = "Click or Double Click"
AddHandler button1.Click, AddressOf Button1_Click
AddHandler button1.DoubleClick, AddressOf Button1_DoubleClick
Controls.Add(button1)
End Sub
Private Sub Button1_DoubleClick(sender As Object, e As EventArgs)
' This flag prevents the click handler logic from running
' A double click raises the click event twice.
_isDoubleClicking = True
FormBorderStyle = _initialStyle
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs)
If _isDoubleClicking Then
_isDoubleClicking = False
Else
FormBorderStyle = FormBorderStyle.FixedToolWindow
End If
End Sub
End Class
Чтобы различать щелчки
Обработайте событие MouseDown и определите расположение и интервал времени между щелчками с помощью свойства SystemInformation и компонента Timer. Выполните соответствующее действие в зависимости от того, происходит ли щелчок или двойной щелчк. В следующем примере кода показано, как это можно сделать.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace project
{
public partial class Form2 : Form
{
private DateTime _lastClick;
private bool _inDoubleClick;
private Rectangle _doubleClickArea;
private TimeSpan _doubleClickMaxTime;
private Action _doubleClickAction;
private Action _singleClickAction;
private Timer _clickTimer;
public Form2()
{
InitializeComponent();
_doubleClickMaxTime = TimeSpan.FromMilliseconds(SystemInformation.DoubleClickTime);
_clickTimer = new Timer();
_clickTimer.Interval = SystemInformation.DoubleClickTime;
_clickTimer.Tick += ClickTimer_Tick;
_singleClickAction = () => MessageBox.Show("Single clicked");
_doubleClickAction = () => MessageBox.Show("Double clicked");
}
private void Form2_MouseDown(object sender, MouseEventArgs e)
{
if (_inDoubleClick)
{
_inDoubleClick = false;
TimeSpan length = DateTime.Now - _lastClick;
// If double click is valid, respond
if (_doubleClickArea.Contains(e.Location) && length < _doubleClickMaxTime)
{
_clickTimer.Stop();
_doubleClickAction();
}
return;
}
// Double click was invalid, restart
_clickTimer.Stop();
_clickTimer.Start();
_lastClick = DateTime.Now;
_inDoubleClick = true;
_doubleClickArea = new Rectangle(e.Location - (SystemInformation.DoubleClickSize / 2),
SystemInformation.DoubleClickSize);
}
private void ClickTimer_Tick(object sender, EventArgs e)
{
// Clear double click watcher and timer
_inDoubleClick = false;
_clickTimer.Stop();
_singleClickAction();
}
}
}
Imports System.Drawing
Imports System.Windows.Forms
Public Class Form2
Private _lastClick As Date
Private _inDoubleClick As Boolean
Private _doubleClickArea As Rectangle
Private _doubleClickMaxTime As TimeSpan
Private _singleClickAction As Action
Private _doubleClickAction As Action
Private WithEvents _clickTimer As Timer
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
_doubleClickMaxTime = TimeSpan.FromMilliseconds(SystemInformation.DoubleClickTime)
_clickTimer = New Timer()
_clickTimer.Interval = SystemInformation.DoubleClickTime
_singleClickAction = Sub()
MessageBox.Show("Single click")
End Sub
_doubleClickAction = Sub()
MessageBox.Show("Double click")
End Sub
End Sub
Private Sub Form2_MouseDown(sender As Object, e As MouseEventArgs) Handles MyBase.MouseDown
If _inDoubleClick Then
_inDoubleClick = False
Dim length As TimeSpan = Date.Now - _lastClick
' If double click is valid, respond
If _doubleClickArea.Contains(e.Location) And length < _doubleClickMaxTime Then
_clickTimer.Stop()
Call _doubleClickAction()
End If
Return
End If
' Double click was invalid, restart
_clickTimer.Stop()
_clickTimer.Start()
_lastClick = Date.Now
_inDoubleClick = True
_doubleClickArea = New Rectangle(e.Location - (SystemInformation.DoubleClickSize / 2),
SystemInformation.DoubleClickSize)
End Sub
Private Sub SingleClickTimer_Tick(sender As Object, e As EventArgs) Handles _clickTimer.Tick
' Clear double click watcher and timer
_inDoubleClick = False
_clickTimer.Stop()
Call _singleClickAction()
End Sub
End Class
См. также
.NET Desktop feedback