Hi all,
I have made (just to learn C#) a calculator program, which is working OK. I made a Round button class for it, but the edges of the buttons still look "crispy". I set SmoothingMode and PixelOffsetMode to HighQuality but it seems to have no effect. Is this once again a problem of Vista? MonthCalendar has a problem whit it, as Ramy once pointed out to me.
Or is it something else here?
Any advice is more than welcome.
This is the code of my Roundbutton class:

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace CalculatorApp
{
    // Class for "3D" oval or circle button
    // just using a color trick to simulate a 3D effect
    //
    class RoundButton : Button
    {
        private Color _startcolor = Color.White;
        private Color _endcolor = Color.Black;
        private Color _textcolor = Color.Black;
        private bool _swap = false;

        //default constructor
        public RoundButton(){}

        public RoundButton(Color startcolor, Color endcolor) 
        {
            _startcolor = startcolor;
            _endcolor = endcolor;
        }

        public Color Startcolor 
        { 
            get { return _startcolor;}            
            set { _startcolor = value;} 
        }

        public Color Endcolor
        {
            get { return _endcolor; }
            set { _endcolor = value; }
        }

        public Color Textcolor
        {
            get { return _textcolor; }
            set { _textcolor = value; }
        }

        private void DoDraw(Graphics G, bool sw) //sw does the color swap, quicker than a swap routine!
        {
            Brush textBr = new SolidBrush(_textcolor);
            Rectangle R = new Rectangle(0, 0, this.Width, this.Height);
            StringFormat strFormat = new StringFormat();
            strFormat.Alignment = StringAlignment.Center;
            strFormat.LineAlignment = StringAlignment.Center;

            G.SmoothingMode = SmoothingMode.HighQuality;    // change??????
            G.PixelOffsetMode = PixelOffsetMode.HighQuality;// change?????? 

            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(R);
            this.Region = new Region(path);

            R.Inflate(1, 1);
            LinearGradientBrush linBr;
            if (sw)
                linBr = new LinearGradientBrush
                    (new Point(R.Left, R.Top), new Point(R.Right, R.Bottom), _endcolor, _startcolor);
            else
                linBr = new LinearGradientBrush
                   (new Point(R.Left, R.Top), new Point(R.Right, R.Bottom), _startcolor, _endcolor);
            G.FillEllipse(linBr, R);

            R.Inflate(-5, -5);
            LinearGradientBrush linBrBack;
            if (sw)
                linBrBack = new LinearGradientBrush
                    (new Point(R.Left, R.Top), new Point(R.Right, R.Bottom), _startcolor, _endcolor);
            else
                 linBrBack = new LinearGradientBrush
                    (new Point(R.Left, R.Top), new Point(R.Right, R.Bottom), _endcolor, _startcolor);
            G.FillEllipse(linBrBack, R);

            G.DrawString(this.Text, this.Font, textBr, R, strFormat);
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);
            DoDraw(pevent.Graphics, _swap);    
        }

        protected override void OnMouseHover(EventArgs e) // not needed really, but nice to have
        {
            Graphics g = this.CreateGraphics();
            _swap = true;
            DoDraw(g, _swap);
            _swap = false;
            g.Dispose();
            base.OnMouseHover(e);
        }
    }
}

And this is how I use it in my main form:

private const int cTotalOperBtns = 5;
        private string[] OperBtnStr = new string[cTotalOperBtns] { "/", "*", "-", "+", "=" };

private void MakeOperatorBtns()
        {
            for (int i = 0; i < cTotalOperBtns; i++)
            {
                _OperatorBtn[i] = new RoundButton(Color.Blue, Color.White);
                _OperatorBtn[i].Name = OperBtnStr[i];
                _OperatorBtn[i].Text = OperBtnStr[i];
                _OperatorBtn[i].Size = new Size(60, 30); //make oval button
                _OperatorBtn[i].Font = new Font("Microsoft Sans Serif", 12F,
                                           System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                this.OperatorBtnLayoutPanel.Controls.Add(_OperatorBtn[i]);
                _OperatorBtn[i].Click += new EventHandler(OperatorBtn_Click);
                _OperatorBtn[i].Textcolor = Color.White; //set text to white
            }
        } //END MakeOperatorBtns

Recommended Answers

All 11 Replies

why dont you attach the solution so we test it on our local PCs.
i use vista home premium. let me see your buttons :)

Hi Serkan,
I have Vista Basic on a MacBook Pro.
This is in fact my first "big" working project after a year study of C#!
It is sort of a simulation of a hand calculator I have at home.
It even has an ON button!
It really serves no other purpose than my own learning, I very much like to hear your comments about it:)

in my screen it looks ok, i attach the screen shot. compare it to how it looks on yours then we will understand if it is a Os or Machine issue or has to do with your coding..

Hey Danny, Serkan...
As I have no experience about GDI+ but I just replace this line R.Inflate(1,1); with R.Inflate(R.Size); I feel the shape changes but I don't know that's you need Danny or not.
Wish for you the best of luck in it and solve it ASAP..

Thanks for the effort and help guys!
I thouht I would see some antialiasing at the edges when using Highquality, but the jpg you send me Serkan has the same outlook as I see it : no antialiasing. It also depends a bit on the color the blue buttons being the worst.

R.Inflate(R.Size); does not solve it Ramy. In fact I use R.Inflate(1,1); to make it a little better. You see what I mean if you use R.Inflate(-1,-1);

Hi danny,

I have some suggestions: Use AntiAlias for both text & drawing objects.

G.SmoothingMode = SmoothingMode.AntiAlias;
G.InterpolationMode = InterpolationMode.NearestNeighbor;
G.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;

and also outline the outermost ellipse.

....
             R.Inflate(-1, -1);
             Pen pen = new Pen(linBr);
             pen.Width = 1f;
             G.DrawEllipse(pen, R);
          
             R.Inflate(1, 1);
             G.FillEllipse(linBr, R);
             ...

Thanks all you guys for your help and support. Did some testing and the fact that I could draw an oval with a brush and antialiasing, made me believe that it MUST be possible.
So I figured out that I must not call the base class paint event as I do and that I have to adjust my region. Still working on it but I have good hopes.
Thanks again.

Best wishes, Danny

Hello,

What a nice calculator maan! Great

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.