클릭과 두 번 클릭을 구분하는 방법(Windows Forms .NET)
일반적으로 한 번 ‘클릭’은 사용자 인터페이스 작업을 시작하고 ‘두 번 클릭’은 작업을 확장합니다. 예를 들어 한 번 클릭은 대개 항목을 선택하고 두 번 클릭은 선택된 항목을 편집합니다. 그러나 Windows Forms 클릭 이벤트는 한 번 클릭과 두 번 클릭이 호환되지 않는 동작을 수행하는 시나리오에는 쉽게 적용되지 않습니다. Click 또는 MouseClick 이벤트에 연결된 동작이 DoubleClick 또는 MouseDoubleClick 이벤트에 연결된 동작 앞에 수행되기 때문입니다. 이 항목에서는 이 문제에 대한 두 가지 솔루션을 보여 줍니다.
한 솔루션은 두 번 클릭 이벤트를 처리하고 클릭 이벤트 처리 시 작업을 롤백하는 것입니다. 드물지만 MouseDown 이벤트를 처리하고 SystemInformation 클래스의 DoubleClickTime 및 DoubleClickSize 속성을 사용하여 클릭 및 두 번 클릭 동작을 시뮬레이션해야 할 수 있습니다. 클릭 사이의 시간을 측정하고, 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