shaped button with _click event

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • JustRun
    New Member
    • Mar 2008
    • 127

    shaped button with _click event

    Hi,
    the below code drawing a custom Oval button, The problem is: I want after the click event to change its color many times but it stops at the red color and repaint again, so it always achieve just the first condition:

    Code:
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Drawing.Drawing2D;
    
    namespace ShappedButton
    {
        public partial class ctrlOvalBtn : Button
        {
            public ctrlOvalBtn()
            {
                InitializeComponent();
            }
            private bool _clicked = false;
            public bool Clicked
            {
                get { return _clicked; }
                set
                {
                    _clicked = value;
                    Invalidate();
                }
            }
    
            protected override void OnPaint(PaintEventArgs pevent)
            {
                Graphics g = pevent.Graphics;
                Rectangle innerRect = new Rectangle(new Point(0, 0), new Size(this.Width, this.Height));
                GraphicsPath innerPath = new GraphicsPath();
                SolidBrush brshFill = new SolidBrush(Color.WhiteSmoke);
                SolidBrush brshLine = new SolidBrush(Color.Black);
    
                innerPath.AddEllipse(innerRect);
    
                Region innerRegion = new Region(innerPath);
    
                this.Region = innerRegion;
    
                pevent.Graphics.FillEllipse(brshLine, 0, 0, this.Width, this.Height);
                pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
    
                if (_clicked == false)
                {
                    pevent.Graphics.FillEllipse(brshLine, 0, 0, this.Width, this.Height);
                    pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                }
                else
                {
                    if (brshFill.Color.Equals(Color.WhiteSmoke))
                    {
                        brshFill.Color = Color.Red;
                        pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                    }
                    else if (brshFill.Color.Equals(Color.Red))
                    {
                        brshFill.Color = Color.Blue;
                        pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                    }
                    else if (brshFill.Color.Equals(Color.Blue))
                    {
                        brshFill.Color = Color.Brown;
                        pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                    }
                    else
                    {
                        brshFill.Color = Color.WhiteSmoke;
                        pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                    }
                }
    
                // Dispose of painting objects
                brshFill.Dispose();
                brshLine.Dispose();
            }
    
            protected override void OnMouseEnter(EventArgs e)
            {
                this.Cursor = Cursors.Hand;
                base.OnMouseEnter(e);
            }
    
            protected override void OnMouseLeave(EventArgs e)
            {
                this.Cursor = Cursors.Arrow;
                base.OnMouseLeave(e);
            }
            protected override void OnMouseDown(MouseEventArgs mevent)
            {
                _clicked = true;
                base.OnMouseDown(mevent);
            }
    
            protected override void OnMouseUp(MouseEventArgs mevent)
            {
                _clicked = true;
                base.OnMouseUp(mevent);
            }
    
        }
    }
    what should i do !!
  • tlhintoq
    Recognized Expert Specialist
    • Mar 2008
    • 3532

    #2
    Personal opinion: If this is to become a button, presumably to be re-used later, then you shouldn't have so much specific purpose code in the the Draw method. In order to make this a re-usable item you will want to give it a true Click event that you can react to and assign event handlers to.

    If you give it a Click event, you could then change the color in the Click event handler just as you would with a standard button out of the toolbox.


    As for why this is only working the first time... You are assigning the brush color of SmokeWhite in line 31 every time the Draw method is run. Therefore the if condition in line 50 is the only one that can ever be true.

    Comment

    • JustRun
      New Member
      • Mar 2008
      • 127

      #3
      yeah I know the "Why" but actually I don't know the solution, and I tried your way, to set the event in the presentation form, but i didn't work, I tried many thing to pass the color, all of them were useless. it always repaint each time I click on !!!

      Comment

      • GaryTexmo
        Recognized Expert Top Contributor
        • Jul 2009
        • 1501

        #4
        Right now you're only painting from a set colour, then doing an if statement to see if that colour is any of a set of colours, at which point you change the colour and paint. Let me try to simplify that...

        You've got:
        A = 0
        if A == 0 then A = 0
        else if A == 1 then A = 1
        else if A == 2 then A = 2
        ...

        Which doesn't really make sense. You're starting from scratch every time you go through. Try making a private member called something like _lastPaintColou r and then running your code. When the click event fires, start it off at WhiteSmoke and let your code carry on.

        Also, this is only going to happen every paint cycle, which isn't really a predictable pace. I'm not 100% sure, but I think windows only paints when it needs to, so like when something moves over a window.

        I see you've got an Invalidate call there, but it's only on the click event. You might want to put it on the mouse down event to force a repaint constantly while the mouse is down. Of course, that'd be very, very slow.

        A better solution might be to put a timer in there and have it go off at some kind of set interval to give you a good frame rate. When the timer expires, shuffle the colours and force a repaint.

        Comment

        • JustRun
          New Member
          • Mar 2008
          • 127

          #5
          Till Now i can't stop it from Repainting, Please give me a more clear solution.

          Code:
          private bool _clicked = false;
                  private Color _brushColor;
                  public SolidBrush brshFill;
                  public SolidBrush brshLine;
          
                  public bool Clicked
                  {
                      get { return _clicked; }
                      set
                      {
                          _clicked = value;
                          Invalidate();
                      }
                  }
                  public Color brushColor
                  {
                      get { return _brushColor; }
                      set { _brushColor = value; }
          
                  }
          
                  public ctrlOvalBtn()
                  {
                      InitializeComponent();
                  }
                  public ctrlOvalBtn(Color _brushColor)
                  {
                      InitializeComponent();
                      brushColor = _brushColor;
                  }
          
                  protected override void OnPaint(PaintEventArgs pevent)
                  {
          
                      Graphics g = pevent.Graphics;
                      Rectangle innerRect = new Rectangle(new Point(0, 0), new Size(this.Width, this.Height));
                      GraphicsPath innerPath = new GraphicsPath();
                      brshFill = new SolidBrush(brushColor);
                      brshLine = new SolidBrush(Color.Black);
          
                      innerPath.AddEllipse(innerRect);
          
                      Region innerRegion = new Region(innerPath);
          
                      this.Region = innerRegion;
          
                      g.FillEllipse(brshLine, 0, 0, this.Width, this.Height);
          
                      //if (_clicked == false)
                      //{
                      //    this.brushColor = Color.WhiteSmoke;
                          //g.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                      //}
                      //else
                      //{
                          if (brushColor.Equals(Color.WhiteSmoke))
                              brushColor = Color.Red;
                          else if (brushColor.Equals(Color.Red))
                              brushColor = Color.Blue;
                          else if (brushColor.Equals(Color.Red))
                              brushColor = Color.Brown;
                          else
                              brushColor = Color.WhiteSmoke;
                      //}
          
                      g.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                      
                      brshFill.Dispose();
                      brshLine.Dispose();
                  }
          .

          Comment

          • JustRun
            New Member
            • Mar 2008
            • 127

            #6
            what i want to do, is to draw a shape and at every MouseDown, give it a different color (Red, Blue, Brown, White ...)

            Thats it.

            Hope you help me.

            Comment

            • JustRun
              New Member
              • Mar 2008
              • 127

              #7
              At Laaaast, I got it, as i said All i need is how to stop it from repaint, and its so simple, Invalidate() method

              Thanks for everyone :)

              Comment

              • JustRun
                New Member
                • Mar 2008
                • 127

                #8
                but one more question Gary, you said that with MouseDown, its very very slow, then offered a better solution which is the timer, would you please tell me what do u mean with enable a timer, regarding that I dont wanna let it rotate the color unless the Mouse is Down

                Thanks

                Comment

                • GaryTexmo
                  Recognized Expert Top Contributor
                  • Jul 2009
                  • 1501

                  #9
                  I really didn't know what you wanted. From the way your code was set up, it looked like you wanted the colours to cycle as a kind of animation when the mouse was down. It sounds like you were looking for something different. Either way, for your own knowledge (and fun), here's the code I made when buggering around with the code you posted. It has the timer stuff, so hopefully that explains it.

                  Code:
                  using System;
                  using System.ComponentModel;
                  using System.Drawing;
                  using System.Windows.Forms;
                  using System.Drawing.Drawing2D;
                  
                  namespace ShapedButton
                  {
                      public class OvalButton : Button
                      {
                          private bool _clicked = false;
                          private Color _fillColor = Color.WhiteSmoke;
                          private Color _lastColor = Color.WhiteSmoke;
                          private Timer _timer = new Timer();
                  
                          public bool Clicked
                          {
                              get { return _clicked; }
                              set
                              {
                                  _fillColor = Color.WhiteSmoke;
                                  _clicked = value;
                                  Invalidate();
                              }
                          }
                  
                          public OvalButton()
                          {
                              _timer.Interval = 100;
                              _timer.Tick += new EventHandler(_timer_Tick);
                          }
                  
                          void _timer_Tick(object sender, EventArgs e)
                          {
                              if (_clicked == false)
                              {
                                  _fillColor = Color.WhiteSmoke;
                              }
                              else
                              {
                                  if (_fillColor.Equals(Color.WhiteSmoke))
                                  {
                                      _fillColor = Color.Red;
                                  }
                                  else if (_fillColor.Equals(Color.Red))
                                  {
                                      _fillColor = Color.Green;
                                  }
                                  else if (_fillColor.Equals(Color.Green))
                                  {
                                      _fillColor = Color.Blue;
                                  }
                                  else
                                  {
                                      _fillColor = Color.Red;
                                  }
                              }
                  
                              if (_lastColor != _fillColor)
                              {
                                  this.Invalidate();
                                  _lastColor = _fillColor;
                              }
                          }
                  
                          protected override void OnPaint(PaintEventArgs pevent)
                          {
                              Graphics g = pevent.Graphics;
                              Rectangle innerRect = new Rectangle(new Point(0, 0), new Size(this.Width, this.Height));
                              GraphicsPath innerPath = new GraphicsPath();
                              SolidBrush brshFill = new SolidBrush(_fillColor);
                              SolidBrush brshLine = new SolidBrush(Color.Black);
                  
                              innerPath.AddEllipse(innerRect);
                  
                              Region innerRegion = new Region(innerPath);
                  
                              this.Region = innerRegion;
                  
                              pevent.Graphics.FillEllipse(brshLine, 0, 0, this.Width, this.Height);
                              pevent.Graphics.FillEllipse(brshFill, 1, 1, this.Width - 2, this.Height - 2);
                  
                              SizeF strSize = pevent.Graphics.MeasureString(this.Text, this.Font);
                              float posX = (float)(this.Width / 2.0 - strSize.Width / 2.0);
                              float posY = (float)(this.Height / 2.0 - strSize.Height / 2.0);
                              pevent.Graphics.DrawString(this.Text, this.Font, brshLine, new PointF(posX, posY));
                  
                              // Dispose of painting objects
                              brshFill.Dispose();
                              brshLine.Dispose();
                          }
                  
                          protected override void OnMouseEnter(EventArgs e)
                          {
                              this.Cursor = Cursors.Hand;
                              base.OnMouseEnter(e);
                          }
                  
                          protected override void OnMouseLeave(EventArgs e)
                          {
                              this.Cursor = Cursors.Arrow;
                              base.OnMouseLeave(e);
                          }
                          protected override void OnMouseDown(MouseEventArgs mevent)
                          {
                              if (_clicked == false)
                              {
                                  _clicked = true;
                                  //_timer.Stop();
                                  _timer_Tick(null, null);
                                  _timer.Start();
                                  base.OnMouseDown(mevent);
                              }
                          }
                  
                          protected override void OnMouseUp(MouseEventArgs mevent)
                          {
                              if (_clicked == true)
                              {
                                  _clicked = false;
                                  _timer.Stop();
                                  _timer_Tick(null, null);
                                  //_timer.Start();
                                  base.OnMouseUp(mevent);
                              }
                          }
                      }
                  }

                  Comment

                  • JustRun
                    New Member
                    • Mar 2008
                    • 127

                    #10
                    Well, Actually, I finished the project in exactly like I want, but with a bug:
                    the Scenario is: I have a shape was drawn by (override void OnPaint) and this control includes the events: (override void OnMouseEnter, override void OnMouseLeave, override void OnMouseDown and override void OnMouseUp).
                    The user will click on the button and the color will change, then by choosing "Save" the application save the button's color in the database.

                    The problem is happening after I execute a select statement that returns the button's colour to reload the correct colour again, it works fine, but the colour doesn't appear in the form unless i hover on the shape !!!!

                    Comment

                    • JustRun
                      New Member
                      • Mar 2008
                      • 127

                      #11
                      Isn't there anything can be helpful in this issue.

                      Thanks

                      Comment

                      • tlhintoq
                        Recognized Expert Specialist
                        • Mar 2008
                        • 3532

                        #12
                        You could try ordering it to .Refresh() or .Invalidate() which would force the OnPaint method to execute

                        Comment

                        • JustRun
                          New Member
                          • Mar 2008
                          • 127

                          #13
                          Yeah, I did the Refresh() after a lot of attempts.

                          Thanks all

                          Comment

                          • murathankocan
                            New Member
                            • Mar 2007
                            • 2

                            #14
                            look at:

                            Comment

                            Working...