开发者

Why are mouse events not raised by my custom user control?

I want to create a composite custom control with trackbar and others that will be used by some client forms. I need to expose some events like MouseDown and MouseUp to detect start of drag and end of drag. Weirdly, MouseDown is OK but not MouseUp. The code below demonstrates it. Is this a bug in the .NET Framework or of the trackbar? If not, how should I do it instead?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace MyTrackbar
{

    public partial class UserControl1 : UserControl
    {
        public delegate void StartDragHandler();
        public delegate void EndDragHandler();

        [Category("Action")]
        [Description("Fires when user starts to drag.")]
        public event StartDragHandler StartDrag;
        [Category("Action")]
        [Description("Fires when user ends to drag.")]
        public event EndDragHandler EndDrag;

        public UserControl1()
        {
            InitializeComponent();
        }

        private void trackBar1_MouseDown(object sender, MouseEventArgs e)
        {
            textBox1.BackColor = Color.Red;
            if (StartDrag != null) {
                StartDrag();
            }

        }

        private void trackBar1_MouseUp(object sender, MouseEventArgs e)
        {
            textBox1.BackColor = Color.White;
            if (EndDrag != null) {
                EndDrag();
            }
        }
    }
}



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace TestMyTrackBar
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void userControl11_StartDrag()
        {
            // Work
            textBox1.BackColor = Color.Red;
        }

        private void userControl11_MouseUp(object sender, MouseEventArgs e)
        {
            // Doesn't work !!!!!!!!!!!!
            textBox1.BackColor = Color.White;
        }
    }
}

Update: For people who want to check InitializeComponent even though I didn't modify it:

For custom control:

namespace MyTrackbar
{
    partial class UserControl1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.trackBar1 = new System.Windows.Forms.TrackBar();
            this.textBox1 = new System.Windows.Forms.TextBox();
            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
            this.SuspendLayout();
            // 
            // trackBar1
            // 
            this.trackBar1.Location = new System.Drawing.Point(21, 17);
            this.trackBar1.Name = "trackBar1";
            this.trackBar1.Size = new System.Drawing.Size(356, 45);
            this.trackBar1.TabIndex = 0;
            this.trackBar1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.trackBar1_MouseDown);
            this.trackBar1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.trackBar1_MouseUp);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(31, 68);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(338, 20);
            this.textBox1.TabIndex = 1;
            // 
            // UserControl1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.tex开发者_StackOverflow社区tBox1);
            this.Controls.Add(this.trackBar1);
            this.Name = "UserControl1";
            this.Size = new System.Drawing.Size(400, 150);
            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.TrackBar trackBar1;
        private System.Windows.Forms.TextBox textBox1;
    }
}

For WinForm client:

namespace TestMyTrackBar
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.userControl11 = new MyTrackbar.UserControl1();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            // 
            // userControl11
            // 
            this.userControl11.Location = new System.Drawing.Point(13, 39);
            this.userControl11.Name = "userControl11";
            this.userControl11.Size = new System.Drawing.Size(400, 114);
            this.userControl11.TabIndex = 0;
            this.userControl11.StartDrag += new MyTrackbar.UserControl1.StartDragHandler(this.userControl11_StartDrag);
            this.userControl11.MouseUp += new System.Windows.Forms.MouseEventHandler(this.userControl11_MouseUp);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(45, 160);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(336, 20);
            this.textBox1.TabIndex = 1;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(457, 231);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.userControl11);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private MyTrackbar.UserControl1 userControl11;
        private System.Windows.Forms.TextBox textBox1;
    }
}


Before beginning, I want to clarify that the answer provided by Hans Passant already explains exactly the same thing I am about to. So, if you find this helpful, you should upvote his answer.

However, it seems from the comment exchange that you aren't quite understanding what he's trying to say. Perhaps I can do a little better job explaining it, and maybe you'll have an easier time if understanding what's going on if you saw precisely what you had to change in your code.

Let's start out by assessing the current situation: Your textbox that is part of userControl11 changes color properly when the user starts dragging the trackbar. However, the second textbox that is part of Form1 does not turn back to white after you finish dragging the trackbar.

Your user control already raises two custom events StartDrag and EndDrag, with names that obviously indicate the current state. In Form1, you're handling the user control's StartDrag event and changing the color of the second textbox to red. But, instead of handling the EndDrag event to change the color back to white, you're handling the MouseUp event. This is why it's not working, and what Hans's answer was trying to tell you. Instead, your form's code should look like this:

public partial class Form1 : Form
{
   public Form1()
   {
      InitializeComponent();

      this.userControl11.EndDrag += new MyTrackbar.UserControl1.EndDragHandler(this.userControl11_EndDrag);
   }

   private void userControl11_StartDrag()
   {
      // Works
      textBox1.BackColor = Color.Red;
   }

   private void userControl11_EndDrag()
   {
      // Now also works!
      textBox1.BackColor = Color.White;
   }
}

You already understand that you need to handle the custom StartDrag event that you've raised, so it seems simple enough that you'd also need to handle the EndDrag event to achieve the desired effect.

But then, you might ask, "Why does the MouseUp event work inside of the user control, but not work inside of the form?!?" I assume this is what you're trying to argue is a bug in the .NET Framework. (Hint: It's far less likely that any of us will discover a true bug in the Framework than one of us is confused about why we're seeing the behavior that we are, or simply missing something obvious.)

The reason is because, inside the user control, you're handling the MouseUp event raised by the trackbar control (trackBar1). But that event does not propagate upwards. Just because the trackbar control raises the MouseUp event does not mean that the user control that contains it raises the same event. You seem to already know that with regards to the MouseDown event, and it's exactly the same thing with the MouseUp event.

No need to file a bug report with Microsoft, and no need for anyone to get their feelings hurt.


    private void userControl11_MouseUp(object sender, MouseEventArgs e)
    {
        // Doesn't work !!!!!!!!!!!!
        textBox1.BackColor = Color.White;
    }

You should have used the EndDrag event, not MouseUp.


It isn't clear the real problem, since the InitializeComponent implementation is completely missing from the example.

So, my answer is based on the following assertions:

  • UserControl1.trackBar1 is a TrackBar, *trackBar1_MouseDown* is subsciber of UserControl1.trackBar1.MouseDown, *trackBar1_MouseUp* is subsciber of UserControl1.trackBar1.MouseUp
  • Form1.userControl11 is a UserControl1, *userControl11_StartDrag()* is subscriber of Form1.userControl11.StartDrag event, *userControl11_MouseUp* is subscriber of Form1.userControl11.MouseUp event

It is correct that "doesn't work". Probably (and you should confirm it if it is) the event Form1.userControl11.MouseUp is never raised. Infact Form1.userControl11.MouseUp and UserControl1.trackBar1.MouseUp are not the same; infact UserControl1 class expose the EndDrag event when its embedded Control trackBar1 raises the MouseUp event.

So, the solution is to subscribe the UserControl1.EndDrag event, not the mouse up (as Hans Passant has stated), in order to reflect the correct behavior (supposed by me).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜