Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

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

Posted on 2008-10-01
3
Medium Priority
?
567 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 30

Accepted Solution

by:
anarki_jimbel earned 2000 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 30

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

Nothing ever in the clear!

This technical paper will help you implement VMware’s VM encryption as well as implement Veeam encryption which together will achieve the nothing ever in the clear goal. If a bad guy steals VMs, backups or traffic they get nothing.

Question has a verified solution.

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

Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
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.
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Suggested Courses

971 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