AlonMln
AlonMln

Reputation: 257

Creating a custom button control

I am making a custom Tic Tac Toe game where there are three Tic Tac Toe frames in the form.

Instead of creating three times a 3x3 square of buttons, i thought it would be better to make a custom control that will contain nine buttons in the formation I want, and so I can put it three times in the form and also access each and every button in that formation.

I am pretty new to inheritance and custom controls so i would like your help with examples or instructions.

Upvotes: 1

Views: 15464

Answers (4)

Pritam Zope
Pritam Zope

Reputation: 69

using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Drawing;  
using System.Data;  
using System.Windows.Forms;  
namespace ButtonZ  
{  
    public class ButtonZ : System.Windows.Forms.Button  
    {  
        Color clr1, clr2;  
        private Color color1 = Color.LightGreen;  
        private Color color2 = Color.DarkBlue;  
        private Color m_hovercolor1 = Color.Yellow;  
        private Color m_hovercolor2 = Color.DarkOrange;  
        private int color1Transparent = 150;  
        private int color2Transparent = 150;  
        private Color clickcolor1 = Color.DarkOrange;  
        private Color clickcolor2 = Color.Red;  
        private int angle = 90;  
        private int textX = 100;  
        private int textY = 25;  
        private String text = "";  

        //Create Properties to read Button Text,Colors etc  
        public String DisplayText  
        {  
            get { return text; }  
            set { text = value; Invalidate(); }  
        }  

        public Color StartColor  
        {  
            get { return color1; }  
            set { color1 = value; Invalidate(); }  
        }  

        public Color EndColor  
        {  
            get { return color2; }  
            set { color2 = value; Invalidate(); }  
        }  

        public Color MouseHoverColor1  
        {  
            get { return m_hovercolor1; }  
            set { m_hovercolor1 = value; Invalidate(); }  
        }  

        public Color MouseHoverColor2  
        {  
            get { return m_hovercolor2; }  
            set { m_hovercolor2 = value; Invalidate(); }  
        }  

        public Color MouseClickColor1  
        {  
            get { return clickcolor1; }  
            set { clickcolor1 = value; Invalidate(); }  
        }  

        public Color MouseClickColor2  
        {  
            get { return clickcolor2; }  
            set { clickcolor2 = value; Invalidate(); }  
        }  

        public int Transparent1  
        {  
            get { return color1Transparent; }  
            set  
            {  
                color1Transparent = value;  
                if (color1Transparent > 255)  
                {  
                    color1Transparent = 255;  
                    Invalidate();  
                }  
                else  
                    Invalidate();  
            }  
        }  

        public int Transparent2  
        {  
            get { return color2Transparent; }  
            set  
            {  
                color2Transparent = value;  
                if (color2Transparent > 255)  
                {  
                    color2Transparent = 255;  
                    Invalidate();  
                }  
                else  
                    Invalidate();  
            }  
        }  

        public int GradientAngle  
        {  
            get { return angle; }  
            set { angle = value; Invalidate(); }  
        }  

        public int TextLocation_X  
        {  
            get { return textX; }  
            set { textX = value; Invalidate(); }  
        }  

        public int TextLocation_Y  
        {  
            get { return textY; }  
            set { textY = value; Invalidate(); }  
        }  

        public ButtonZ()  
        {  
            this.Size = new System.Drawing.Size(200, 50);  
            this.ForeColor = Color.White;  
            this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;  
            text = this.Text;  
        }  

        //method mouse enter  
        protected override void OnMouseEnter(EventArgs e)  
        {  
            base.OnMouseEnter(e);  
            clr1 = color1;  
            clr2 = color2;  
            color1 = m_hovercolor1;  
            color2 = m_hovercolor2;  
        }  

        //method mouse leave  
        protected override void OnMouseLeave(EventArgs e)  
        {  
            base.OnMouseLeave(e);  
            color1 = clr1;  
            color2 = clr2;  
        }  

        //method mouse click  
        protected override void OnMouseClick(MouseEventArgs e)  
        {  
            if (e.Clicks == 1)  
            {  
                base.OnMouseClick(e);  
                color1 = clickcolor1;  
                color2 = clickcolor2;  
            }  
        }  

        protected override void OnPaint(PaintEventArgs pe)  
        {  
            base.OnPaint(pe);  
            text = this.Text;  
            if (textX == 100 && textY == 25)  
            {  
                textX = ((this.Width) / 3) + 10;  
                textY = (this.Height / 2) - 1;  
            }  
            Color c1 = Color.FromArgb(color1Transparent, color1);  
            Color c2 = Color.FromArgb(color2Transparent, color2);  
            //drawing string & filling gradient rectangle   
            Brush b = new System.Drawing.Drawing2D.LinearGradientBrush(ClientRectangle, c1, c2, angle);  
            Point p = new Point(textX, textY);  
            SolidBrush frcolor = new SolidBrush(this.ForeColor);  
            Border3DStyle borderStyle = Border3DStyle.SunkenInner;  
            pe.Graphics.FillRectangle(b, ClientRectangle);  
            pe.Graphics.DrawString(text, this.Font, frcolor, p);  
            ControlPaint.DrawBorder3D(pe.Graphics, ClientRectangle, borderStyle);  
            b.Dispose();  
        }  

    }  
}  

Upvotes: 1

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112259

In this case, you can use a UserControl. This is easier than creating a custom control, which requires to derive a control from an existing control and to enhance it. In VS right click on your project and choose "Add" > "New Item...". In the Windows Forms section select "User Control". Give it the name "TicTacToeUserControl". You can design the user control much like designing a form. It will then automatically appear in to Toolbox of the current project and be ready to be dropped on a form.


UPDATE

Here some more explanations. Place a TableLayoutPanel on the UserControl. Change Dock to Fill. Add a row and a column in order to have three of both and change their size mode to Percent and change these values to 33.33. Add a button to each table field from left to right and then top down in order to have buttons names "button1", "button2" etc. in reading order. Save the user control (my VS had a glitch at this point and I had to start all over).

Create this class that we will use as event argument for our button click event

public class ButtonClickedEventArgs : EventArgs
{
    public ButtonClickedEventArgs(TicTacToeUserControl userControl, Button button,
                                  int buttonNumber, int row, int column)
    {
        UserControl = userControl;
        Button = button;
        ButtonNumber = buttonNumber;
        Row = row;
        Column = column;
    }

    public TicTacToeUserControl UserControl { get; private set; }
    public Button Button { get; private set; }
    public int ButtonNumber { get; private set; }
    public int Row { get; private set; }
    public int Column { get; private set; }
}

Change the code of the user control to make it look like this

[DefaultEvent("ButtonClicked")]
public partial class TicTacToeUserControl : UserControl
{
    public event EventHandler<ButtonClickedEventArgs> ButtonClicked;

    public TicTacToeUserControl()
    {
        InitializeComponent();
    }

    private void button_Click(object sender, EventArgs e)
    {
        OnButtonClicked((Button)sender);
    }

    private void OnButtonClicked(Button button)
    {
        var eh = ButtonClicked;
        if (eh != null) {
            int buttonNumber =
                Int32.Parse(button.Name.Substring(button.Name.Length - 1));
            int row = (buttonNumber - 1) / 3;
            int col = (buttonNumber - 1) % 3;
            eh(this, 
               new ButtonClickedEventArgs(this, button, buttonNumber, row, col));
        }
    }
}

Select the event handler "button_Click" for the click event of all your buttons in the properties window switched to Event (the flash symbol). Don't create a new one for each button. Hit F6 (compile)

Your control is ready and can be dropped onto a form from the tools window. Resize it as desired. Double click on it. Because of the DefaultEventAttribute that we specified for the form, VS will automatically create this event handler

private void ticTacToeUserControl1_ButtonClicked(object sender,
                                                 ButtonClickedEventArgs e)
{
}

Add this code line to it in order to test the user control

    MessageBox.Show(e.UserControl.Name + " " + e.Button.Name + " " + 
                    e.ButtonNumber + " " + e.Row + " " + e.Column);

NOTE: This does not actually create a new control, it just creates a template

Upvotes: 4

Parimal Raj
Parimal Raj

Reputation: 20565

Best way is to use a user control, but instead of creating buttons via designer, create button via code, that will help you to detect which button was clicked;

public partial class UserControl1 : UserControl
    {
        private List<Button> buttons = new List<Button>(9);
        public UserControl1()
        {
            InitializeComponent();
        }

        private void UserControl1_Load(object sender, EventArgs e)
        {
            int line = 0;
            int lastleft = 0;
            int lasttop = 0;
            for (int i = 1; i < 10; i++)
            {
                Button btn = new Button();
                btn.Text = string.Empty;
                btn.Parent = this;
                btn.Top = lasttop;
                btn.Left = lastleft;
                btn.Width = 30;
                btn.Height = 30;
                btn.Name = i.ToString(CultureInfo.InvariantCulture);

                if (i % 3 == 0)
                {
                    lastleft = 0;
                    lasttop += 35; // 30 for height and 5 for spacing
                }
                else
                {
                    lastleft += 35; // 30 for width and 5 for spacing
                }
                btn.Click += BtnOnClick;
                buttons.Add(btn);

            }
        }

        private void BtnOnClick(object sender, EventArgs eventArgs)
        {
            //ur logic to check game status
            // how to know button?
            Button btn = sender as Button;

            if (btn != null)
            {
                MessageBox.Show(String.Format("You clicked : {0}", btn.Name), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }

Upvotes: 2

Cole Tobin
Cole Tobin

Reputation: 9429

This isn't an answer, but its too long for a comment (so please don't vote down as not an answer)


I would not use a custom control in this case and instead just use an array of controls.

For example, just make 9 controls in a grid formation and just assign them to an array

Button[][] buttons = new Button[ROW_COUNT][];
for (int i = 0; i < ROW_COUNT; i++)
{
    buttons[i] = new Buttons[COLUMN_COUNT];
}
buttons[0][0] = btnTopLeft;
...

Upvotes: 0

Related Questions