Hi guys,
This tutorial sparked off from my own ventures to incorporate a particular feature in my own software - which uses mixed language (English & Thai) on a couple of screens to store user data. Certain fields, apart from First & Last Names & parts of address were to be entered in Thai. Now the current language can be easily switched by pressing Alt-Left Shift (or whatever key combination you've set your system to) - but when you consider the same key-combination has to be repeated for over 20 fields on each screen - and this times the number of records you have to enter, then is becomes a dull and humongously tedious venture. This might lead to a lot of typo's too. (In my case the users of my software had to enter over 4000 student records - soooooo... I had to do something to make the lives of those poor guys a little easier.)
So I thought, why not let the software do the language switching instead. I mean, the fields which were supposed to be in english and thai - were fixed, i.e. you couldn't use these languages alternatively.. so why not, let the system switch to Thai upon focus on such a thai data entry field and similarly for English ? So here I am with the solution - for anyone who might face such a situation (which I believe is very very common). This code will work for any language combination (or even more than two languages) with extremely minor modifications. Of course, you HAVE TO HAVE all these language packs installed on Windows to be able to switch back and forth between them.
First things first: One convention I found very useful in achieving this effect, is to include part of the language name in the Name property of Textbox - this can then be used to easily determine which language to switch to in the corresponding textbox. Following this, I named all my Thai textboxes ending with the word "Thai" and "Engl" for the English textboxes. In reality, this is irrelevant. You can name your textboxes to whatever you feel like, as there is a better way to do it. Each control in .NET has a very little used property called .Tag - which can be used to store any kind of information about that control for internal use. We'll use this .Tag property to store the language of the control.
Step 1
Let us start by firing up the VS.NET Studio & creating an empty VB.NET project with just one form. Add at least TWO textboxes to this form (feel free to add more and experiment around with them - but for demonstration's sake, am going to use just two).
Now, in this example we'll use two Constants to store the words "ENGL" and "THAI" - so that we don't have to rewrite these words on every instance, lessening our chances of error. Let's consider these two words as nicknames to refer to these languages.
CODE
'Constant for english language
Private Const _ENGLISH As String = "ENGL"
'Constant for thai language
Private Const _THAI As String = "THAI"
'A Temporary variable to hold the color of a control
Private OriginalColor As Color
Private Const _ENGLISH As String = "ENGL"
'Constant for thai language
Private Const _THAI As String = "THAI"
'A Temporary variable to hold the color of a control
Private OriginalColor As Color
In the Property Inspector enter txtNameThai as the name of the first box, and txtNameEnglish for the second one.
AND, the real part:
- Set the .Tag property of txtNameEnglish to "ENGL"
- Set the same for txtNameThai to "THAI"
Step 2
Go to the Code View of the form and create the empty skeleton procedures for the Focus event of the first textbox. When you first create a skeleton event handler procedure, using the dropdown boxes on top of the editor, the basic structure looks like this:
CODE
Private Sub txtNameThai_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameThai.GotFocus
End Sub
Handles txtNameThai.GotFocus
End Sub
Now, supposing we have over 20 different textboxes on the form - writing the language switching code for ALL of them is tedious and produces useless, redundant code. So we'll point the event handlers for ALL the textboxes to this one procedure. I simply modified the code a triffle bit to handle the focus event for the second textbox too. READ THE COMMENTS.
CODE
' Modified code to handle focus events of ALL textboxes
' Notice how I simply added the the focus event of the second textbox after the Handles clause
' If you have more than two textboxes, add the names of all of them here separated by commas.
Private Sub TextBoxes_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameEnglish.GotFocus, txtNameThai.GotFocus
End Sub
' Notice how I simply added the the focus event of the second textbox after the Handles clause
' If you have more than two textboxes, add the names of all of them here separated by commas.
Private Sub TextBoxes_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameEnglish.GotFocus, txtNameThai.GotFocus
End Sub
Next steo is to incorporate the actual code to switch languages. Since this subroutine handles the focus events of multiple textboxes, we'll use the arguement sender to determine which control has current focus - and also determine the language to be switched to using the same.
Add this code inside the sub:
CODE
'Method to handle GotFocus events for both textboxes
Private Sub TextBoxes_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameEnglish.GotFocus, txtNameThai.GotFocus
'===========================================================================
' FIRST PART - LANGUAGE SWITCHING
'===========================================================================
'We'll use the case statement to inspect the sender objects .Tag property
Select Case sender.Tag
Case _THAI 'If the Tag contains the word "THAI"
'Loop through all the installed languages on this system
For Each Lng As InputLanguage In InputLanguage.InstalledInputLanguages
'If there exists a language whose DisplayName has got the
'word "THAI" in it
If Lng.Culture.DisplayName.ToUpper.StartsWith(_THAI) Then
'Change current input language to that
InputLanguage.CurrentInputLanguage = Lng
'Exit for - coz we have found our language and no need to
'go through the rest of the loop
Exit For
End If
Next
Case _ENGLISH 'If the Tag contains the word "ENGL"
'Loop through all the installed languages on this system
For Each Lng As InputLanguage In InputLanguage.InstalledInputLanguages
'If there exists a language whose DisplayName has got the
'word "ENGL" in it
If Lng.Culture.DisplayName.ToUpper.StartsWith(_ENGLISH) Then
'Change current input language to that
InputLanguage.CurrentInputLanguage = Lng
'Exit for - coz we have found our language and no need to
'go through the rest of the loop
Exit For
End If
Next
End Select
End Sub
Private Sub TextBoxes_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameEnglish.GotFocus, txtNameThai.GotFocus
'===========================================================================
' FIRST PART - LANGUAGE SWITCHING
'===========================================================================
'We'll use the case statement to inspect the sender objects .Tag property
Select Case sender.Tag
Case _THAI 'If the Tag contains the word "THAI"
'Loop through all the installed languages on this system
For Each Lng As InputLanguage In InputLanguage.InstalledInputLanguages
'If there exists a language whose DisplayName has got the
'word "THAI" in it
If Lng.Culture.DisplayName.ToUpper.StartsWith(_THAI) Then
'Change current input language to that
InputLanguage.CurrentInputLanguage = Lng
'Exit for - coz we have found our language and no need to
'go through the rest of the loop
Exit For
End If
Next
Case _ENGLISH 'If the Tag contains the word "ENGL"
'Loop through all the installed languages on this system
For Each Lng As InputLanguage In InputLanguage.InstalledInputLanguages
'If there exists a language whose DisplayName has got the
'word "ENGL" in it
If Lng.Culture.DisplayName.ToUpper.StartsWith(_ENGLISH) Then
'Change current input language to that
InputLanguage.CurrentInputLanguage = Lng
'Exit for - coz we have found our language and no need to
'go through the rest of the loop
Exit For
End If
Next
End Select
End Sub
A little explanation: I'm using the sender.Tag property to bring up the name string of the currently focused control. Remember, how I emphasized on setting the Tag properties for both to the nicknames we chose for each of the languages - notice how it comes to handy here.
If sender.name.endswith("Thai") - determines if the control's name endswith the string "Thai". If found so, we step into the next line, which is a For Each loop.
Now we can skip this line and switch the language directly, but a better way would be to use the For..Each loop, as this implements an extra check for the installed languages on the system. This safeguards the case, where the desired language is missing from the system - and block the possibilities of runtime errors when the code tries to switch to a non-existant language. READ THE COMMENTS.
CODE
Select Case sender.Tag
Case _THAI 'If the Tag contains the word "THAI"
'Loop through all the installed languages on this system
For Each Lng As InputLanguage In InputLanguage.InstalledInputLanguages
'If there exists a language whose DisplayName has got the
'word "THAI" in it
If Lng.Culture.DisplayName.ToUpper.StartsWith(_THAI) Then
'Change current input language to that
InputLanguage.CurrentInputLanguage = Lng
'Exit for - coz we have found our language and no need to
'go through the rest of the loop
Exit For
End If
Next
'English code follows exactly same syntax - except that THAI is replaced by ENGL
End If
Case _THAI 'If the Tag contains the word "THAI"
'Loop through all the installed languages on this system
For Each Lng As InputLanguage In InputLanguage.InstalledInputLanguages
'If there exists a language whose DisplayName has got the
'word "THAI" in it
If Lng.Culture.DisplayName.ToUpper.StartsWith(_THAI) Then
'Change current input language to that
InputLanguage.CurrentInputLanguage = Lng
'Exit for - coz we have found our language and no need to
'go through the rest of the loop
Exit For
End If
Next
'English code follows exactly same syntax - except that THAI is replaced by ENGL
End If
If you need to switch between more than two languages, you need to implement more cross-checks by using more than two CASE statements for the .Tag property and implement appropriate language switching cycles in each case.
Another small trick than you can add to this to enhance your interface is - change the background color of the textbox which has current focus. This allows the user to follow the field being currently edited in a much easier manner. All you've to do, is in this same GotFocus procedure, you add a couple of more lines after switching the language. This code Saves the current back color of the control and switches it to our desired color.
CODE
'===========================================================================
' SECOND PART - COLOR SWITCHING
'===========================================================================
'First Store the Original Color
OriginalColor = sender.BackColor
'Simply switch the back-color of the sender
sender.BackColor = Color.PapayaWhip
' SECOND PART - COLOR SWITCHING
'===========================================================================
'First Store the Original Color
OriginalColor = sender.BackColor
'Simply switch the back-color of the sender
sender.BackColor = Color.PapayaWhip
Remember, if you use this trick - you'll also have to include the LostFocus procedure which will reset the textboxe's back-color to white upon loosing focus - else all your textboxes will end up with the focus color as you navigate through them.
CODE
'Method to turn the fields white on lostfocus
Private Sub TextFields_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameThai.LostFocus, txtNameEnglish.LostFocus
'===========================================================================
' COLOR SWITCHING - BACK TO THE ORIGINAL
'===========================================================================
'Switch the back color to the original one
sender.BackColor = OriginalColor
End Sub
Private Sub TextFields_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles txtNameThai.LostFocus, txtNameEnglish.LostFocus
'===========================================================================
' COLOR SWITCHING - BACK TO THE ORIGINAL
'===========================================================================
'Switch the back color to the original one
sender.BackColor = OriginalColor
End Sub
As demonstrated here - this code switches the back-color to the original color upon loosing focus - and once again handles all your textfield in a single procedure.
Hope these two nifty tricks help you enliven your application - I for one find them very very useful - and from personal experience, these make the users happy too - as they have to use far less keys.
Comments & Feedbacks much appreciated.
Attached File: Sample working project containing the above code.[attachment=282:attachment]

