Tabbing Through Controls - Programmatically

Mar 21, 2008 at 8:16am
zimzum17_1998@hotmail.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
virtual bool IsInputKey(Keys keyData) //override

{

if (Keys::Tab == keyData)

{

return true;

}

else

{

return false;

}

//check keyData is key value and return true or false

//return false;

}


I have this because i want to test for the TAB key BEFORE the control is lost and change the first character of the text property to a captial. Now the reason i want to override the IsInputKey to test the TAB keydata, is because i do not want the user to move from one control to the next, if the Text property is NULL - i.e. the the user has to input some text.



The problem is, i dont know how to handle the LostFocus/GetFocus events. How do i handle this and pass focus to the next control. Remembering that this is done within my Textbox class, but i could have other types of controls instantiated on the form (comboboxes etc).

IM USING VISUAL STUDIO 2005

Last edited on Mar 21, 2008 at 8:18am
Mar 21, 2008 at 9:26am
Any thoughts?[
Mar 21, 2008 at 11:06am
closed account (z05DSL3A)
Win32/MFC/WTL/.NET?
Mar 21, 2008 at 11:33am
.NET. Sorry
Mar 21, 2008 at 12:23pm
Any thoughts. Im new to this, and i tried lookin on othersites like MSDN but to no avail!
Mar 21, 2008 at 1:10pm
closed account (z05DSL3A)
I'm playing around with a few ideas, I use C# for my .net stuff not C++.

You said 'Remembering that this is done within my Textbox class' have you created a UserControl with a TextBox on it?

The best thing that I can think off at the moment is for the form to hand the Leave event of the TextBox. To 'wire up' the event you can right click on the TextBox, select Prosperities. In the properties window click on the lightning bolt and look down the list for Leaving, double click in the empty box and you should get all the code inserted into your project.

In the ‘leaving’ code you could do something like this:

1
2
3
4
5
6
7
8
9
10
11
if (this->textBox1->Text == String::Empty)
{
    // tell the user he can't go yet!
     // then call
     this->textBox1->Focus();
}
else
{
    //Substatue your own string mod here
   this->textBox1->Text = this->textBox1->Text->ToString()->ToUpper();
}



If I have misunderstood anything let me know, I have to get back to work now so will not be able to reply for a while.
Last edited on Mar 21, 2008 at 1:13pm
Mar 21, 2008 at 1:35pm
Grey Wolf: CHEERS MATE for replying. I will explain alittle better. I'm try to create my own class called myTextboxName (which is dervived from mytexbox another one of my classes. I will go through what i have done so far with it piece by piece:

The following bit of code is where i overridethe IsInputChars so i can test for TAB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
_gc class myTextBoxName : public myTextBox
{

protected	:

	Control		*nextControl;

	virtual bool IsInputKey(Keys keyData) //override
	{
			if (Keys::Tab == keyData)
			{
				return true;
			}
			else
			{
				return false;
			}

          //check keyData is key value and return true or false
          //return false;
	}



The next bit of code is setting up my prototypes etc for the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public		:

	bool nonNumEnt;
	bool Empty;
	bool SpecialChar;
	
	void textboxLostFoc(Object *Sender, EventArgs *Args);
	void validateKeyDown(Object *, System::Windows::Forms::KeyEventArgs *);
	void validateKeyPress(Object *, System::Windows::Forms::KeyPressEventArgs *);
	void validateKeyUp(Object *, System::Windows::Forms::KeyEventArgs *);
	void trimText(TextBox *);

	
	myTextBoxName();
	myTextBoxName(Int32, Int32, Int32);

};


The next bit of code from my class is the overloaded contructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
myTextBoxName::myTextBoxName(Int32 x, Int32 y, Int32 w) : myTextBox(x,y,w)
{		
		/* Now we will validate which key pressed:

		a) KeyDown = what key is being pressed. It will set nonNumEnt to TRUE if
					 a Alpha character is pressed.

		b) KeyPress = Will handle the nonNumEnt and if it is false, wont accept the
					  non character into the textbox	

		*/
		
		this->AcceptsTab = true;
		this->TabStop = true;
	
		
		KeyDown += new KeyEventHandler(this,&myTextBoxName::validateKeyDown);
		KeyPress += new KeyPressEventHandler(this, &myTextBoxName::validateKeyPress);
		KeyUp += new KeyEventHandler(this, &myTextBoxName::validateKeyUp);

		nextControl = new  Control();

		
		
		
}


The next bit is my KeyDown event. Here i test the to makesure the inputs are only alphas and no numbers and sets the nonNumEnt too TRUE if the input is alphas only, if not is should output an error. ALso is SpecialChar = true, if the KeyData = TAB. In addition if the Text property is empty then sets the Empty flag to true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void myTextBoxName::validateKeyDown(Object *, System::Windows::Forms::KeyEventArgs * e)
{
	nonNumEnt = false;
	Empty = false;
	SpecialChar = false;

	SpecialChar = IsInputKey(e->KeyCode);


	if(SpecialChar == true && this->Text->Length == 0)
	{
		nonNumEnt = false;
		Empty = true;
		myErrorCapture * ErrorDialog = new myErrorCapture(S"tab and length N= 0",2 ,this);

	}

	if ( e->KeyCode < Keys::D0 || e->KeyCode > Keys::D9 )
      {
         // Determine whether the keystroke is a number from the keypad.
         if ( e->KeyCode < Keys::NumPad0 || e->KeyCode > Keys::NumPad9 )
         {
            // Determine whether the keystroke is a backspace.
            //if ( e->KeyCode = Keys::Back )
			// A non-numerical keystroke was pressed.
            // Set the flag to true and evaluate in KeyPress event.
               
			 nonNumEnt = true;
           
			}
         }
 

	if (nonNumEnt == false)
	{
		//myErrorCapture * ErrorDialog = new myErrorCapture(S"Error Message - 1",1 ,this);
	}
}



The next is my KeyPress event which checks for the nonNomEnt. if it is false, the it HANDLES the key press which keeps the cursor in the same control whithout leaving:

1
2
3
4
5
6
7
8
9
10
11
void myTextBoxName::validateKeyPress( Object * /*sender*/, System::Windows::Forms::KeyPressEventArgs *e )
{
      // Check for the flag being set in the KeyDown event.
	if (nonNumEnt == false)
	{
		  // Stop the character from being entered into the control since it is non-numerical.
         e->Handled = true;
		 //myErrorCapture * ErrorDialog = new myErrorCapture(S"E = HANDLED",2 ,this);
    }

}


The next is my KeyUp event. This is where im trying too leave the control IF the SpecialChar = true (tab pressed) and Empty = false (Not empty!)

What im doing is using GetNextControl to get the next control into nextControl. Im using this because i could have comboboxes etc on the form, and because this is in the class, i dont k now what the next control will be (Could instantiate anything on the form).

Then i use SelectNextControl using the nextControl as a parameter.

Then i use InvokeLostFocus to change focus to the nextControl.

Then i instantiate a Leave event.

i

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void myTextBoxName::validateKeyUp(Object *, System::Windows::Forms::KeyEventArgs *e)
{
	if(SpecialChar == true && Empty == false)
	{
		
		//nextControl = ;
		

            if(nonNumEnt == false)
			{
				nextControl = this->GetNextControl(this,true);
				this->SelectNextControl(nextControl, true, true, true, true);
				this->InvokeLostFocus(nextControl,e);
				Leave+= new EventHandler(this,&myTextBoxName::textboxLostFoc);
			}
		}
		
		/*
		if(this->SelectNextControl(this,true,false,true,false) == true)
		{

			if(nonNumEnt == false)
			{	
				
				Leave+= new EventHandler(this,&myTextBoxName::textboxLostFoc);
		
			}
		}
		*/
		
}


The leave event code is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void myTextBoxName::textboxLostFoc(Object *Sender, EventArgs *Args)
{
	if(this->Text->Length > 1)
	{
		trimText(this);
	}
	else
	{
		myErrorCapture * ErrorDialog = new myErrorCapture(S"Error Message - 2",2 ,this);

	}

}

void myTextBoxName::trimText(TextBox __gc *data)
{	
	data->Text->Trim();
	data->Text = data->Text->ToLower();
	data->Text = String::Concat(data->Text->Substring(0,1)->ToUpper(),data->Text->Substring(1,data->Text->Length-1));
}


My problem is that i cannot get the focus to change to the new control. I have instantiated 2 myTextBoxName called Surname/Forename on a form, but the cursor remains within the first, which is Surname. I cannot get the InvokeLostFocus etc to work!!
Mar 21, 2008 at 2:18pm
closed account (z05DSL3A)
1
2
3
4
5
6
7
8
9
What im doing is using GetNextControl to get the next control into 
nextControl. Im using this because i could have comboboxes etc on the 
form, and because this is in the class, i dont k now what the next control 
will be (Could instantiate anything on the form).

Then i use SelectNextControl using the nextControl as a parameter.

Then i use InvokeLostFocus to change focus to the nextControl.


You might try InvokeGetFocus to change the focus to the nextControll.

Leave+= new EventHandler(this,&myTextBoxName::textboxLostFoc); should go in the constructor with the others.


I also noticed that you are using new, should it not be gcnew?
Last edited on Mar 21, 2008 at 2:19pm
Mar 21, 2008 at 3:31pm
Hi Grey Wolf,

tried your ideas mate, but with no success! :(

I used new and compiles fine.

Using:

Common Language Runtime Support, Old Syntax (/clr:oldSyntax)
Mar 21, 2008 at 3:55pm
closed account (z05DSL3A)
Hmmm!

I'll try to look at it over the weekend.

Just so I have it clear in my head, you have a class, myTextBoxName, derived from myTextBox. What is myTextBox derived from?

What you want it to do is; before focus is shifted way from myTextBoxName check to see is Text is empty and if it is disallow the change in focus else change the first letter to a capital then change focus.

Mar 21, 2008 at 4:27pm
My myTextbox is devrived from Textbox.

Thats it! I want all the logic to be within my class, thats why i used nextControl variable, because i dont know what the next control will be within the class.

Im trying too but as much logic within the class, so i dont have to put much code when instaniating objects on the form.

Cheers Greywolf, you have been an excellent help.
Mar 24, 2008 at 1:04pm
closed account (z05DSL3A)
Garfbradaz,
Sorry have not had any time to look into this and am still snowed under. I can recommend a few mailing lists that are good for asking questions regarding managed C++ et al:

Discussion relating to the specifics of the C# and Managed C++ languages
http://discuss.develop.com/dotnet-cx.html

Discussion forum for developers using Windows Forms to build apps and controls
http://discuss.develop.com/dotnet-winforms.html

Discussion of advanced .NET topics.
http://discuss.develop.com/advanced-dotnet.html
Topic archived. No new replies allowed.