.NET Framework 4 - Windows Forms How to: Distinguish Between Clicks and Double-Clicks Typically, a single click initiates a user interface (UI) action and a double-click extends the action. For example, one click usually selects an item, and a double-click edits the selected item. However, the Windows Forms click events do not easily accommodate a scenario where a click and a double-click perform incompatible actions, because an action tied to the Click or MouseClick event is performed before the action tied to the DoubleClick or MouseDoubleClick event. This topic demonstrates two solutions to this problem. One solution is to handle the double-click event and roll back the actions in the handling of the click event. In rare situations you may need to simulate click and double-click behavior by handling the MouseDown event and by using the DoubleClickTime and DoubleClickSize properties of the SystemInformation class. You measure the time between clicks and if a second click occurs before the value of DoubleClickTime is reached and the click is within a rectangle defined by DoubleClickSize, perform the double-click action; otherwise, perform the click action. To roll back a click actionEnsure that the control you are working with has standard double-click behavior. If not, enable the control with the SetStyle method. Handle the double-click event and roll back the click action as well as the double-click action. The following code example demonstrates a how to create a custom button with double-click enabled, as well as how to roll back the click action in the double-click event handling code.
Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Public Class Form1
Inherits Form
Private WithEvents button1 As DoubleClickButton
Private initialStyle As FormBorderStyle
Public Sub New()
Me.SuspendLayout()
initialStyle = Me.FormBorderStyle
Me.ClientSize = New System.Drawing.Size(292, 266)
button1 = New DoubleClickButton()
button1.Location = New Point(40, 40)
button1.AutoSize = True
button1.Text = "Click or Double Click"
Me.Controls.Add(button1)
Me.Name = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub 'New
' Handle the double click event.
Private Sub button1_DoubleClick(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.DoubleClick
' Change the border style back to the initial style.
Me.FormBorderStyle = initialStyle
MessageBox.Show("Rolled back single click change.")
End Sub
' Handle the click event.
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.Click
Me.FormBorderStyle = FormBorderStyle.FixedToolWindow
End Sub
<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
End Class
Public Class DoubleClickButton
Inherits Button
Public Sub New()
' Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick Or ControlStyles.StandardDoubleClick, True)
End Sub 'New
End Class 'DoubleClickButton
using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MouseRollBackSingleClick
{
public class Form1 : Form
{
private DoubleClickButton button1;
private FormBorderStyle initialStyle;
public Form1()
{
initialStyle = this.FormBorderStyle;
this.ClientSize = new System.Drawing.Size(292, 266);
button1 = new DoubleClickButton();
button1.Location = new Point (40,40);
button1.Click += new EventHandler(button1_Click);
button1.AutoSize = true;
this.AllowDrop = true;
button1.Text = "Click or Double Click";
button1.DoubleClick += new EventHandler(button1_DoubleClick);
this.Controls.Add(button1);
}
// Handle the double click event.
void button1_DoubleClick(object sender, EventArgs e)
{
// Change the border style back to the initial style.
this.FormBorderStyle = initialStyle;
MessageBox.Show("Rolled back single click change.");
}
// Handle the click event.
void button1_Click(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
public class DoubleClickButton : Button
{
public DoubleClickButton() : base()
{
// Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick |
ControlStyles.StandardDoubleClick, true);
}
}
}
To distinguish between clicks in the MouseDown event

Compiling the Code

See Also
|
.NET Framework 4 - Windows Forms Gewusst wie: Unterscheiden zwischen Klicks und Doppelklicks Normalerweise initiiert ein einzelner Klick eine Benutzeroberflächenaktion, und mit einem Doppelklick wird die Aktion erweitert. Beispielsweise wird mit einem Klick für gewöhnlich ein Element ausgewählt und dieses mit einem Doppelklick bearbeitet. Die Windows Forms-Klickereignisse lassen jedoch nur schwer ein Szenario zu, in dem ein Klick und ein Doppelklick inkompatible Aktionen ausführen, da eine mit dem Click-Ereignis oder dem MouseClick-Ereignis verknüpfte Aktion vor der mit dem DoubleClick-Ereignis oder dem MouseDoubleClick-Ereignis verknüpften Aktion ausgeführt wird. Dieses Thema zeigt zwei Lösungen für dieses Problem auf. Eine Lösung besteht darin, das Doppelklickereignis zu behandeln und die Aktionen bei der Behandlung des Klickereignisses per Rollback zurückzusetzen. In wenigen Situationen müssen Sie möglicherweise das Klick- und Doppelklickverhalten simulieren, indem Sie das MouseDown-Ereignis behandeln und die DoubleClickTime-Eigenschaft und die DoubleClickSize-Eigenschaft der SystemInformation-Klasse verwenden. Sie messen die Zeit zwischen den Klicks, und wenn ein zweiter Klick erfolgt, bevor der DoubleClickTime-Wert erreicht wird und der Klick innerhalb eines durch DoubleClickSize definierten Rechtecks stattfindet, führen Sie die Doppelklickaktion aus; andernfalls führen Sie die Klickaktion aus. So führen Sie für eine Klickaktion einen Rollback ausStellen Sie sicher, dass das Steuerelement, mit dem Sie arbeiten, standardmäßiges Doppelklickverhalten aufweist. Aktivieren Sie andernfalls das Steuerelement mit der SetStyle-Methode. Behandeln Sie das Doppelklickereignis, und führen Sie einen Rollback für die Klickaktion sowie für die Doppelklickaktion aus. Im folgenden Codebeispiel wird gezeigt, wie eine benutzerdefinierte Schaltfläche mit aktiviertem Doppelklick erstellt wird und wie für die Klickaktion ein Rollback im Behandlungscode für das Doppelklickereignis ausgeführt wird.
Imports System
Imports System.ComponentModel
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms
Public Class Form1
Inherits Form
Private WithEvents button1 As DoubleClickButton
Private initialStyle As FormBorderStyle
Public Sub New()
Me.SuspendLayout()
initialStyle = Me.FormBorderStyle
Me.ClientSize = New System.Drawing.Size(292, 266)
button1 = New DoubleClickButton()
button1.Location = New Point(40, 40)
button1.AutoSize = True
button1.Text = "Click or Double Click"
Me.Controls.Add(button1)
Me.Name = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub 'New
' Handle the double click event.
Private Sub button1_DoubleClick(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.DoubleClick
' Change the border style back to the initial style.
Me.FormBorderStyle = initialStyle
MessageBox.Show("Rolled back single click change.")
End Sub
' Handle the click event.
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles button1.Click
Me.FormBorderStyle = FormBorderStyle.FixedToolWindow
End Sub
<STAThread()> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
End Class
Public Class DoubleClickButton
Inherits Button
Public Sub New()
' Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick Or ControlStyles.StandardDoubleClick, True)
End Sub 'New
End Class 'DoubleClickButton
using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MouseRollBackSingleClick
{
public class Form1 : Form
{
private DoubleClickButton button1;
private FormBorderStyle initialStyle;
public Form1()
{
initialStyle = this.FormBorderStyle;
this.ClientSize = new System.Drawing.Size(292, 266);
button1 = new DoubleClickButton();
button1.Location = new Point (40,40);
button1.Click += new EventHandler(button1_Click);
button1.AutoSize = true;
this.AllowDrop = true;
button1.Text = "Click or Double Click";
button1.DoubleClick += new EventHandler(button1_DoubleClick);
this.Controls.Add(button1);
}
// Handle the double click event.
void button1_DoubleClick(object sender, EventArgs e)
{
// Change the border style back to the initial style.
this.FormBorderStyle = initialStyle;
MessageBox.Show("Rolled back single click change.");
}
// Handle the click event.
void button1_Click(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
}
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
public class DoubleClickButton : Button
{
public DoubleClickButton() : base()
{
// Set the style so a double click event occurs.
SetStyle(ControlStyles.StandardClick |
ControlStyles.StandardDoubleClick, true);
}
}
}
So unterscheiden Sie im MouseDown-Ereignis zwischen KlicksBehandeln Sie das MouseDown-Ereignis, und bestimmen Sie anhand der entsprechenden SystemInformation-Eigenschaften und einer Timer-Komponente die Position und die Zeitspanne zwischen Klicks. Führen Sie die entsprechende Aktion aus, je nachdem, ob ein Klick oder ein Doppelklick stattfindet. Im folgenden Codebeispiel wird gezeigt, wie dies durchgeführt werden kann.
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Namespace SingleVersusDoubleClick
Class Form1
Inherits Form
Private hitTestRectangle As New Rectangle()
Private doubleClickRectangle As New Rectangle()
Private textBox1 As New TextBox()
Private WithEvents doubleClickTimer As New Timer()
Private doubleClickBar As New ProgressBar()
Private label1 As New Label()
Private label2 As New Label()
Private isFirstClick As Boolean = True
Private isDoubleClick As Boolean = False
Private milliseconds As Integer = 0
<STAThread()> _
Public Shared Sub Main()
Application.EnableVisualStyles()
Application.Run(New Form1())
End Sub
Public Sub New()
label1.Location = New Point(30, 5)
label1.Size = New Size(100, 15)
label1.Text = "Hit test rectangle:"
label2.Location = New Point(30, 70)
label2.Size = New Size(100, 15)
label2.Text = "Double click timer:"
hitTestRectangle.Location = New Point(30, 20)
hitTestRectangle.Size = New Size(100, 40)
doubleClickTimer.Interval = 100
doubleClickBar.Location = New Point(30, 85)
doubleClickBar.Minimum = 0
doubleClickBar.Maximum = SystemInformation.DoubleClickTime
textBox1.Location = New Point(30, 120)
textBox1.Size = New Size(200, 100)
textBox1.AutoSize = False
textBox1.Multiline = True
Me.Controls.Add(doubleClickBar)
Me.Controls.Add(textBox1)
Me.Controls.Add(label1)
Me.Controls.Add(label2)
End Sub
' Detect a valid single click or double click.
Sub Form1_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles Me.MouseDown
' Verify that the mouse click is in the main hit
' test rectangle.
If Not hitTestRectangle.Contains(e.Location) Then
Return
End If
' This is the first mouse click.
If isFirstClick = True Then
isFirstClick = False
' Determine the location and size of the double click
' rectangle to draw around the cursor point.
doubleClickRectangle = New Rectangle( _
e.X - (SystemInformation.DoubleClickSize.Width / 2), _
e.Y - (SystemInformation.DoubleClickSize.Height / 2), _
SystemInformation.DoubleClickSize.Width, _
SystemInformation.DoubleClickSize.Height)
Invalidate()
' Start the double click timer.
doubleClickTimer.Start()
' This is the second mouse click.
Else
' Verify that the mouse click is within the double click
' rectangle and is within the system-defined double
' click period.
If doubleClickRectangle.Contains(e.Location) And _
milliseconds < SystemInformation.DoubleClickTime Then
isDoubleClick = True
End If
End If
End Sub
Sub doubleClickTimer_Tick(ByVal sender As Object, _
ByVal e As EventArgs) Handles doubleClickTimer.Tick
milliseconds += 100
doubleClickBar.Increment(100)
' The timer has reached the double click time limit.
If milliseconds >= SystemInformation.DoubleClickTime Then
doubleClickTimer.Stop()
If isDoubleClick Then
textBox1.AppendText("Perform double click action")
textBox1.AppendText(Environment.NewLine)
Else
textBox1.AppendText("Perform single click action")
textBox1.AppendText(Environment.NewLine)
End If
' Allow the MouseDown event handler to process clicks again.
isFirstClick = True
isDoubleClick = False
milliseconds = 0
doubleClickBar.Value = 0
End If
End Sub
' Paint the hit test and double click rectangles.
Sub Form1_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles Me.Paint
' Draw the border of the main hit test rectangle.
e.Graphics.DrawRectangle(Pens.Black, hitTestRectangle)
' Fill in the double click rectangle.
e.Graphics.FillRectangle(Brushes.Blue, doubleClickRectangle)
End Sub
End Class
End Namespace
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SingleVersusDoubleClick
{
class Form1 : Form
{
private Rectangle hitTestRectangle = new Rectangle();
private Rectangle doubleClickRectangle = new Rectangle();
private TextBox textBox1 = new TextBox();
private Timer doubleClickTimer = new Timer();
private ProgressBar doubleClickBar = new ProgressBar();
private Label label1 = new Label();
private Label label2 = new Label();
private bool isFirstClick = true;
private bool isDoubleClick = false;
private int milliseconds = 0;
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
public Form1()
{
label1.Location = new Point(30, 5);
label1.Size = new Size(100, 15);
label1.Text = "Hit test rectangle:";
label2.Location = new Point(30, 70);
label2.Size = new Size(100, 15);
label2.Text = "Double click timer:";
hitTestRectangle.Location = new Point(30, 20);
hitTestRectangle.Size = new Size(100, 40);
doubleClickTimer.Interval = 100;
doubleClickTimer.Tick +=
new EventHandler(doubleClickTimer_Tick);
doubleClickBar.Location = new Point(30, 85);
doubleClickBar.Minimum = 0;
doubleClickBar.Maximum = SystemInformation.DoubleClickTime;
textBox1.Location = new Point(30, 120);
textBox1.Size = new Size(200, 100);
textBox1.AutoSize = false;
textBox1.Multiline = true;
this.Paint += new PaintEventHandler(Form1_Paint);
this.MouseDown += new MouseEventHandler(Form1_MouseDown);
this.Controls.AddRange(new Control[] { doubleClickBar, textBox1,
label1, label2 });
}
// Detect a valid single click or double click.
void Form1_MouseDown(object sender, MouseEventArgs e)
{
// Verify that the mouse click is in the main hit
// test rectangle.
if (!hitTestRectangle.Contains(e.Location))
{
return;
}
// This is the first mouse click.
if (isFirstClick)
{
isFirstClick = false;
// Determine the location and size of the double click
// rectangle area to draw around the cursor point.
doubleClickRectangle = new Rectangle(
e.X - (SystemInformation.DoubleClickSize.Width / 2),
e.Y - (SystemInformation.DoubleClickSize.Height / 2),
SystemInformation.DoubleClickSize.Width,
SystemInformation.DoubleClickSize.Height);
Invalidate();
// Start the double click timer.
doubleClickTimer.Start();
}
// This is the second mouse click.
else
{
// Verify that the mouse click is within the double click
// rectangle and is within the system-defined double
// click period.
if (doubleClickRectangle.Contains(e.Location) &&
milliseconds < SystemInformation.DoubleClickTime)
{
isDoubleClick = true;
}
}
}
void doubleClickTimer_Tick(object sender, EventArgs e)
{
milliseconds += 100;
doubleClickBar.Increment(100);
// The timer has reached the double click time limit.
if (milliseconds >= SystemInformation.DoubleClickTime)
{
doubleClickTimer.Stop();
if (isDoubleClick)
{
textBox1.AppendText("Perform double click action");
textBox1.AppendText(Environment.NewLine);
}
else
{
textBox1.AppendText("Perform single click action");
textBox1.AppendText(Environment.NewLine);
}
// Allow the MouseDown event handler to process clicks again.
isFirstClick = true;
isDoubleClick = false;
milliseconds = 0;
doubleClickBar.Value = 0;
}
}
// Paint the hit test and double click rectangles.
void Form1_Paint(object sender, PaintEventArgs e)
{
// Draw the border of the main hit test rectangle.
e.Graphics.DrawRectangle(Pens.Black, hitTestRectangle);
// Fill in the double click rectangle.
e.Graphics.FillRectangle(Brushes.Blue, doubleClickRectangle);
}
}
}
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>
using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
namespace SingleVersusDoubleClick
{
public ref class Form1 : public Form
{
private:
Rectangle hitTestRectangle;
private:
Rectangle doubleClickRectangle;
private:
TextBox^ outputBox;
private:
Timer^ doubleClickTimer;
private:
ProgressBar^ doubleClickBar;
private:
Label^ hitTestLabel;
private:
Label^ timerLabel;
private:
bool isFirstClick;
private:
bool isDoubleClick;
private:
int milliseconds;
public:
Form1()
{
hitTestRectangle = Rectangle();
hitTestRectangle.Location = Point(30, 20);
hitTestRectangle.Size = System::Drawing::Size(100, 40);
doubleClickRectangle = Rectangle();
outputBox = gcnew TextBox();
outputBox->Location = Point(30, 120);
outputBox->Size = System::Drawing::Size(200, 100);
outputBox->AutoSize = false;
outputBox->Multiline = true;
doubleClickTimer = gcnew Timer();
doubleClickTimer->Interval = 100;
doubleClickTimer->Tick +=
gcnew EventHandler(this, &Form1::doubleClickTimer_Tick);
doubleClickBar = gcnew ProgressBar();
doubleClickBar->Location = Point(30, 85);
doubleClickBar->Minimum = 0;
doubleClickBar->Maximum = SystemInformation::DoubleClickTime;
hitTestLabel = gcnew Label();
hitTestLabel->Location = Point(30, 5);
hitTestLabel->Size = System::Drawing::Size(100, 15);
hitTestLabel->Text = "Hit test rectangle:";
timerLabel = gcnew Label();
timerLabel->Location = Point(30, 70);
timerLabel->Size = System::Drawing::Size(100, 15);
timerLabel->Text = "Double click timer:";
isFirstClick = true;
this->Paint += gcnew PaintEventHandler(this, &Form1::Form1_Paint);
this->MouseDown +=
gcnew MouseEventHandler(this, &Form1::Form1_MouseDown);
this->Controls->
AddRange(gcnew array<Control^> { doubleClickBar, outputBox,
hitTestLabel, timerLabel });
}
// Detect a valid single click or double click.
private:
void Form1_MouseDown(Object^ sender, MouseEventArgs^ e)
{
// Verify that the mouse click is in the main hit
// test rectangle.
if (!hitTestRectangle.Contains(e->Location))
{
return;
}
// This is the first mouse click.
if (isFirstClick)
{
isFirstClick = false;
// Determine the location and size of the double click
// rectangle area to draw around the cursor point.
doubleClickRectangle = Rectangle(
e->X - (SystemInformation::DoubleClickSize.Width / 2),
e->Y - (SystemInformation::DoubleClickSize.Height / 2),
SystemInformation::DoubleClickSize.Width,
SystemInformation::DoubleClickSize.Height);
Invalidate();
// Start the double click timer.
doubleClickTimer->Start();
}
// This is the second mouse click.
else
{
// Verify that the mouse click is within the double click
// rectangle and is within the system-defined double
// click period.
if (doubleClickRectangle.Contains(e->Location) &&
milliseconds < SystemInformation::DoubleClickTime)
{
isDoubleClick = true;
}
}
}
private:
void doubleClickTimer_Tick(Object^ sender, EventArgs^ e)
{
milliseconds += 100;
doubleClickBar->Increment(100);
// The timer has reached the double click time limit.
if (milliseconds >= SystemInformation::DoubleClickTime)
{
doubleClickTimer->Stop();
if (isDoubleClick)
{
outputBox->AppendText("Perform double click action");
outputBox->AppendText(Environment::NewLine);
}
else
{
outputBox->AppendText("Perform single click action");
outputBox->AppendText(Environment::NewLine);
}
// Allow the MouseDown event handler to process clicks again.
isFirstClick = true;
isDoubleClick = false;
milliseconds = 0;
doubleClickBar->Value = 0;
}
}
// Paint the hit test and double click rectangles.
private:
void Form1_Paint(Object^ sender, PaintEventArgs^ e)
{
// Draw the border of the main hit test rectangle.
e->Graphics->DrawRectangle(Pens::Black, hitTestRectangle);
// Fill in the double click rectangle.
e->Graphics->FillRectangle(Brushes::Blue, doubleClickRectangle);
}
};
}
[STAThread]
int main()
{
Application::EnableVisualStyles();
Application::Run(gcnew SingleVersusDoubleClick::Form1);
}

Kompilieren des Codes

Siehe auch
|