Share via


방법: 클릭과 두 번 클릭 간 구별

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

클릭 동작을 롤백하려면 다음을 수행합니다.

  • 작업하고 있는 컨트롤에 표준 두 번 클릭 동작이 있는지 확인합니다. 그러지 않으면 SetStyle 메서드로 컨트롤을 사용하도록 설정합니다. 두 번 클릭 이벤트를 처리하고 두 번 클릭 동작과 클릭 동작을 롤백합니다. 다음 코드 예제에서는 두 번 클릭이 사용되는 사용자 지정 단추를 만드는 방법과 두 번 클릭 이벤트 처리 코드에서 클릭 동작을 롤백하는 방법을 보여 줍니다.

    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);
            }
        }
    }
    
    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
        
        
        ' 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
    End Class
    

MouseDown 이벤트에서 클릭을 구분하려면 다음을 수행합니다.

  • MouseDown 이벤트를 처리하고 적절한 SystemInformation 속성 및 Timer 구성 요소를 사용하여 클릭 사이의 위치 및 시간 차이를 결정합니다. 클릭 또는 두 번 클릭이 수행되는지에 따라 적절한 동작을 수행합니다. 다음 코드 예제에서는 이 작업을 수행하는 방법을 보여 줍니다.

    #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);
    }
    
    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);
            }
        }
    }
    
    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
    

코드 컴파일

이러한 예제에는 다음이 필요합니다.

  • System, System.Drawing 및 System.Windows.Forms 어셈블리에 대한 참조

참고 항목