Solved

Creating a Form With Mobile/Cell Phone Text Input Style Buttons

Posted on 2008-10-01
3
560 Views
Last Modified: 2013-12-17
I am just working on a small little idea and really need to make it more efficient, you will see why shortly.

Basically I am have 1 form, 3 textBoxes and 9 buttons.  Think of it as a mobile/cell phone when you text/send SMS.  You press the number a certain amount of times and you get a specific letter.

So any only 1 of the textboxes will be enabled at any one time, so there has to be a check to decide which to focus on to add the text - and I have no clue how to do that!.  Hopefully that gives an idea of what I'm trying to do.

My problem comes from the staggering, and mainly unnecessary amount of code what I have produces.  So I am hoping that somebody here can help me out.  You can see from the code below that for just 1 button it's a lot, so for 9 it would be far too big.  Especially as the code is only for 1 of the 3 textboxes.

private void btnKeyPad1_Click(object sender, EventArgs e)
        {
          
            if (txtFirstName.Enabled == true || txtSurName.Enabled == true || txtPIN.Enabled == true)
            {
                // some form of code to select whichever textbox and Focus() on it.   
                // I need to find out how to do this
             
                number1Count++;
                if (number1Count >= 4)
                {
                    number1Count = 1;
                }
                else if (number1Count == 1)
                {
                    textBox1.Text = textBox1.Text + "a";
                }
                else if (number1Count == 2)
                {
                    textBox1.Text = textBox1.Text + "b";
                }
                else if (number1Count == 3)
                {
                    textBox1.Text = textBox1.Text + "c";
                }
 
            }
        }

Open in new window

0
Comment
Question by:angus_young_acdc
  • 2
3 Comments
 
LVL 29

Accepted Solution

by:
anarki_jimbel earned 500 total points
ID: 22620400
The task you are talking about is a bit more tricky. At least here I can't see you using any timing. And with cellphone buttons you have to click a button three times in a specific time frame to print "c" (e.g.) into a textbox. How you do that?

How you detect what text box to print to?

Anyway, I have written simple application to achieve what you probably need. I use Timer class (win forms).

Notice: all button handlers are same except a char array.

So, add a timer to your application, set it's interval say to 50. Using this time you may adjust your response time.

The application has three textboxes with names you provided, buttons btnABC, btnDEF (add any more)., and a timer timer1. See the snippet
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
namespace CellPhoneStyleTest
{
    public partial class Form1 : Form
    {
        // private variables
        private int clickCounter = 0;// how many time current button was clicked?
        private Button currentButton = null;// which letter button was clicked, "abc" or "def" or etc.
 
        private bool isTimerTicking = false;
        private int timerCount = 0;
        private int maxTimerCount = 10;
        private string currentChar = null;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void btnABC_Click(object sender, EventArgs e)
        {
            char[] letterArray = { 'a', 'b', 'c' };// basicly, this should be the only different line for all buttons
            buttonClickHandler(sender, letterArray);
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (timerCount >= maxTimerCount)
            {
                isTimerTicking = false;
                currentButton = null;
                clickCounter = 0;
                timer1.Stop();
                timerCount = 0;
 
                // find what TextBox is Enabled and set current textbox object
                TextBox currentTextBox = null;
                if (txtFirstName.Enabled) { currentTextBox = txtFirstName; }
                else if (txtSurName.Enabled) { currentTextBox = txtSurName; }
                else if (txtPIN.Enabled) { currentTextBox = txtPIN; }
                else { MessageBox.Show("Error"); }
 
                currentTextBox.Text += currentChar;
            }
            else
            {
                isTimerTicking = true;
                timerCount += 1;
            }
        }
 
        private void btnDEF_Click(object sender, EventArgs e)
        {
            // just an example to have entire code here, not in a separate function
            if (isTimerTicking && (currentButton == (Button)sender)) // cast from sender object - code will be same for all buttons
            {
                this.clickCounter += 1;
            }
            else if (isTimerTicking && !(currentButton == (Button)sender))
            {
                timer1.Stop();
                timer1.Start();
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
                currentChar = "";
            }
            else if (!isTimerTicking && currentButton == null)
            {
                timer1.Start();
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
                currentChar = "";
            }
            else
            {
                MessageBox.Show("Error");
                return;
            }
 
 
 
            // we may click many time - so wrap around the letters
            char[] letterArray = { 'd', 'e', 'f' };// basicly, this should be the only different line for all buttons
            int currentCharIndex = this.clickCounter % letterArray.Length;
            currentChar = "" + letterArray[currentCharIndex];
        }
 
        private void buttonClickHandler(object sender, char[] letterArray)
        {
            if (isTimerTicking && (currentButton == (Button)sender)) // cast from sender object - code will be same for all buttons
            {
                this.clickCounter += 1;
            }
            else if (isTimerTicking && !(currentButton == (Button)sender))
            {
                timer1.Stop();
                timer1.Start();
                currentChar = ""; ;
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
            }
            else if (!isTimerTicking && currentButton == null)
            {
                timer1.Start();
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
                currentChar = "";
            }
            else
            {
                MessageBox.Show("Error");
                return;
            }
 
            // we may click many time - so wrap around the letters
            int currentCharIndex = this.clickCounter % letterArray.Length;
            currentChar = "" + letterArray[currentCharIndex];
        }
 
    }
}

Open in new window

0
 
LVL 15

Author Comment

by:angus_young_acdc
ID: 22622931
Hi there,

No I wasn't using any timing in that example, it was just a count so that if button1 was pressed twice the letter would be 'b'

---How you detect what text box to print to?
I have no idea, thats one of the many questions I am trying to find out the answer too.  I may just scrap this idea however - at least for now.

That code looks great, I will have a play with it now and see how I get on.  But that definately seems to cut down on the amount of useless code I have :)

I'm assuming that I could put the code below into one method and simply call that waiting for a true/false value in order to perform the action?

//Code inside the button for DEF
if (isTimerTicking && (currentButton == (Button)sender)) // cast from sender object - code will be same for all buttons
            {
                this.clickCounter += 1;
            }
            else if (isTimerTicking && !(currentButton == (Button)sender))
            {
                timer1.Stop();
                timer1.Start();
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
                currentChar = "";
            }

Open in new window

0
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 22628539
Yes, you can put the code into one method and call it everywhere. That's was my intention - to write something "coding-saving" :)

By the way, I have fixed my buttonClickHandler. Basicly, I have added just one line ("timerCount = 0"), it will better simulate cellphone style behaviour. See the snippet.

About text fields. I don't know how you want to manage text fields. I just assume that just one field is enabled at the time, I select this enabled field, make to reference to it and enter text to it. Say, we have three fields, txtFirstname, txtSurName and txtPIN. txtSurname is enabled currently. Timer tick handler checks what text box is enabled:

                // find what TextBox is Enabled and set current textbox object
                TextBox currentTextBox = null;
                if (txtFirstName.Enabled) { currentTextBox = txtFirstName; }
                else if (txtSurName.Enabled) { currentTextBox = txtSurName; }
                else if (txtPIN.Enabled) { currentTextBox = txtPIN; }
                else { MessageBox.Show("Error"); }
 and enters a character into the currentTextBox.

' OK, how to enable-disable text boxes. What if you use another property, readonly? In this case you may use 'Enter' event to to set this property to false for a current box and true for others. And in the timer I have to check if the text box is NOT readonly to .

OK, check the updated snippet for entire form. Ask any questions. You need a timer on the form to get it working.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
namespace CellPhoneStyleTest
{
    public partial class Form1 : Form
    {
        // private variables
        private int clickCounter = 0;// how many time current button was clicked?
        private Button currentButton = null;// which letter button was clicked, "abc" or "def" or etc.
 
        private bool isTimerTicking = false;
        private int timerCount = 0;
        private int maxTimerCount = 10;
        private string currentChar = null;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void btnABC_Click(object sender, EventArgs e)
        {
            char[] letterArray = { 'a', 'b', 'c' };// basicly, this should be the only different line for all buttons
            buttonClickHandler(sender, letterArray);
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (timerCount >= maxTimerCount)
            {
                isTimerTicking = false;
                currentButton = null;
                clickCounter = 0;
                timer1.Stop();
                timerCount = 0;
 
                // find what TextBox is Enabled and set current textbox object
                TextBox currentTextBox = null;
                if (!txtFirstName.ReadOnly) { currentTextBox = txtFirstName; }
                else if (!txtSurName.ReadOnly) { currentTextBox = txtSurName; }
                else if (!txtPIN.ReadOnly) { currentTextBox = txtPIN; }
                else { MessageBox.Show("Error"); }
 
                currentTextBox.Text += currentChar;
            }
            else
            {
                isTimerTicking = true;
                timerCount += 1;
            }
        }
 
        private void btnDEF_Click(object sender, EventArgs e)
        {
            char[] letterArray = { 'd', 'e', 'f' };
            buttonClickHandler(sender, letterArray);
        }
 
        private void buttonClickHandler(object sender, char[] letterArray)
        {
            if (isTimerTicking && (currentButton == (Button)sender)) // cast from sender object - code will be same for all buttons
            {
                timerCount = 0;
                this.clickCounter += 1;
            }
            else if (isTimerTicking && !(currentButton == (Button)sender))
            {
                timer1.Stop();
                timer1.Start();
                currentChar = ""; ;
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
            }
            else if (!isTimerTicking && currentButton == null)
            {
                timer1.Start();
                currentButton = (Button)sender;// set currentButton to this button
                this.clickCounter = 0;// it's clicked just one time
                currentChar = "";
            }
            else
            {
                MessageBox.Show("Error");
                return;
            }
 
            // we may click many time - so wrap around the letters
            int currentCharIndex = this.clickCounter % letterArray.Length;
            currentChar = "" + letterArray[currentCharIndex];
        }
 
        private void txtSurName_Enter(object sender, EventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine("txtSurName_Enter");
            txtSurName.ReadOnly = false;
            txtFirstName.ReadOnly = true;
            txtPIN.ReadOnly = true;
        }
 
        private void txtFirstName_Enter(object sender, EventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine("txtFirstName_Enter");
            txtSurName.ReadOnly =  true;
            txtFirstName.ReadOnly =false;
            txtPIN.ReadOnly = true;
 
        }
 
        private void txtPIN_Enter(object sender, EventArgs e)
        {
            //System.Diagnostics.Debug.WriteLine("txtPIN_Enter");
            txtSurName.ReadOnly = true;
            txtFirstName.ReadOnly = true;
            txtPIN.ReadOnly = false;
        }
 
    }
}

Open in new window

0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Entity Framework is a powerful tool to help you interact with the DataBase but still doesn't help much when we have a Stored Procedure that returns more than one resultset. The solution takes some of out-of-the-box thinking; read on!
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question