How to Create a Custom QWERTY Keyboard

Last modified by Microchip on 2025/01/02 10:32

Introduction

A QWERTY keyboard UI refers to a keyboard layout that is similar to the standard keyboard layout found on most mobile phones and computers. The name "QWERTY" comes from the first six letters in the top row of the keyboard. This layout includes alpha-numeric and special characters, as well as keys for backspace, enter, arrows, space, escape, and shift.

This how-to guide shows how to use keypad widgets and buttons to create a custom English QWERTY keyboard of a specific key layout. The same concept can be applied to create QWERTY keyboards of any layout.

MGS Example Project

Refer to the project in GitHub for the example.

Information

This example requires Microchip Graphics Suite (MGS) Harmony gfx repo version 3.16 or later.

MGS Simulator Output

This is how the application runs:

  • Selecting the Text Field widgets for the Last Name or Confirmation Number will pop up an English QWERTY keyboard.
  • Press the keys to enter the Last Name and Confirmation Number.
  • When done, press the Enter (→) key to hide the keyboard.
  • Press Continue to check the Last Name and Confirmation Number. 
  • If the right Last Name ("mchp") and Confirmation Number ("1234") are entered, the welcome pop up screen will be shown. 
  • If not, an error pop up will be shown.
Qwerty Keyboard Example (interactive)

Back to Top

MGS Harmony Composer Design

Here is what the screen design looks like in MGS Harmony Composer. The On Show, On Hide, On Update event callbacks are enabled for this screen. These screen callbacks will be used to initialize and update the screen at run-time.

Composer Design

Figure 1. Composer Design

The visible screen area contains the two text field widgets for the Last Name and Confirmation Number entries and the Continue button.

Text field and Button widgets

Figure 2. Widgets in screen

Selecting these Text Field widgets will show their properties in the Object Editor window. Observe the properties of these Text Field widgets:

  • A Hint String was set to show information about the text field.
  • The Font was set to the desired font used to show the input string in the text field. Make sure that the font contains the glyphs for the characters in the QWERTY keyboard.
  • The Focus Changed event callback is enabled. This will be used in the application to show the QWERTY keyboard when the text field is selected or touched (in focus).
Text Field widget properties

Figure 3. Text Field widget properties

Off-screen on the left are the two pop-up dialog boxes used to show if the entries are valid or not.

Pop up dialog boxes

Figure 4. Pop up dialog boxes

Off-screen on the bottom is a parent panel that contains multiple widgets used to create the QWERTY keyboard.

Multiple Keypad widgets were used to create the edit keys, the keys that append, delete, or edit the entry in the Last Name and Confirmation Number text fields.

Edit keys

Figure 5. Edit keypad widgets

Selecting each of these Keypad widgets and clicking the Configure property will show how they are configured.

Keypad widget properties

Figure 6. Keypad widget properties

Here's the configuration for the first row keypad.

Two sets of images are set for the Pressed Icon and Released Icon properties to show different pressed and released states of the keys. The Image Position is set to Behind to show the String on top.

Edit key image properties

Figure 7. Edit key image properties

For the character keys, the String and Edit Value properties are set to a string asset in the String Manager.

Edit key string and edit properties

Figure 8. Edit key string and edit properties

The String Manager was used to create the unique string assets that correspond to the character for that key, including for the normal, shift, and numbers/symbols modes of the keyboard. For example, the q key uses a strq string asset in the String Manager that has a "q" value.

String Manager

Figure 9. String Assets

Information

Since multiple Keypad widgets used have similar configurations, it can be faster to create and configure one Keypad widget, then duplicate it by copying and pasting instances of the pre-configured Keypad widget, and reconfiguring them based on the actual keys they represent.

Other non-character edit keys (like Backspace) are set to the corresponding Edit Action.

Backspace

Figure 10. Backspace key properties

For the non-edit keys, like shift, enter, and symbols, regular button widgets were used.

Special Keys

Figure 11. Button widgets for special keys

The Pressed event callback was enabled for each of these buttons. The callback functions are defined in the application source code.

Button Widget Events

Figure 12. Button Widget pressed event callback is enabled

Back to Top

Application Code

The application code that manages the screen behavior and the callback functions for handling the screen and widget events are defined in the app_ConfirmScreen.c file. 

Back to Top

Screen State Machine

The screen state machine is managed in the screen update event callback function, LastNameConfScreen_OnUpdate.

In the running state (CONF_RUN), the function checks if any of the non-edit buttons were pressed. This includes:

  • Checking if the shift or number/symbol (?123) buttons are pressed to change the key mapping,
  • Checking if the enter button is pressed to switch the edit focus, and
  • Checking if the continue button is pressed to transition to the RESULT screen state.

In the RESULT state, the function validates the user-supplied Last Name and Confirmation Number and shows the dialog box to confirm if they are valid or not.

Back to Top

Button Widget Event Callbacks

Button widget pressed or released events are handled using the event handler functions defined in the application code. These handler functions simply set the corresponding application screen event, which are then checked in the screen state machine.

Here's an example callback function that handles the pressed event for the Continue button.

/* continue button released event handler */
void event_LastNameConfScreen_btnContinue_OnReleased(leButtonWidget* btn)
{
    ConfScreen_SetEvent(CONF_EVT_KEYBRD_CONTINUE);
}

Back to Top

Key Character Mapping

To enable the keypad widgets to switch to different keys when the shift or number/symbol (?123) keys are pressed, arrays of structures are used to provide the string asset mapping for each keyboard mode, for each Keypad widget. For example, keyPadRow1 contains the mapping for the first-row keypad.

/* chars used for first row keys for each config (shift, normal, numbers/symbols) */
KEY_CONFIG_t keyPadRow1[NUM_KEYS_ROW1] =
{
    {&string_strQ, &string_strq, &string_str1}, /* row 1, key 1 */
    {&string_strW, &string_strw, &string_str2}, /* row 1, key 2 */
    {&string_strE, &string_stre, &string_str3}, /* row 1, key 3 */
    {&string_strR, &string_strr, &string_str4}, /* row 1, key 4 */
    {&string_strT, &string_strt, &string_str5}, /* row 1, key 5 */
    {&string_strY, &string_stry, &string_str6}, /* row 1, key 6 */
    {&string_strU, &string_stru, &string_str7}, /* row 1, key 7 */
    {&string_strI, &string_stri, &string_str8}, /* row 1, key 8 */
    {&string_strO, &string_stro, &string_str9}, /* row 1, key 9 */
    {&string_strP, &string_strp, &string_str0}, /* row 1, key 10 */
};

Each of these string assets was added using the String Manager.

The remapping is done inside the ConfScreen_SetKeyboardConfig function, where each key (cell) in each Keypad widget is assigned the appropriate String and Key Value depending on the keyboard mode (shift, normal, or numbers/symbols).

Here's a code snippet that shows how each cell in the keypad is referenced and configured.

    /* configures the keys for first row keypad based on keyboard configuration */
   for (i = 0; i < NUM_KEYS_ROW1; i++)
    {
       /* get the cell/key at specific index */
       leButtonWidget * cell = LastNameConfScreen_keysRow1->fn->getCellButton(LastNameConfScreen_keysRow1, 0, i);

       /* set the string for the cell/key (what's shown on the GUI) */
       cell->fn->setString(cell, (leString *) keyPadRow1[i].text[conf]);

       /* sets the edit string for the key/cell (what's appended to text field */
       LastNameConfScreen_keysRow1->fn->setKeyValue(LastNameConfScreen_keysRow1, 0, i, (leString *) keyPadRow1[i].text[conf]);
    }

Back to Top

Hiding/Showing the Keyboard

The keyboard is contained inside the parent panel widget, pnlKeyboard. By default, the keyboard is hidden by positioning the panel off-screen.

To show the keyboard when the text field widgets are clicked, the OnFocusChanged event callback for the text field widgets was defined so that they reposition the panel widget to show the keyboard in the screen.

/* last name text field widget focused event handler */
void event_LastNameConfScreen_txtFieldLastName_OnFocusChanged(leTextFieldWidget* btn, leBool state)
{
   /* if text field widget is selected, show the keyboard panel */
   if (state == LE_TRUE)
    {
       /* Show the keyboard by setting position in frame */
       LastNameConfScreen_pnlKeyboard->fn->setY(LastNameConfScreen_pnlKeyboard, 440);
    }
}

To hide the keyboard, it's repositioned off-screen when the ENTER button key is pressed.

LastNameConfScreen_pnlKeyboard->fn->setY(LastNameConfScreen_pnlKeyboard, 800);

Back to Top

Updating the Text Field widget

A Keypad widget will automatically target the Text Field widget has gained focus. So when a Text Field widget is touched or clicked, any edit action from a Keypad widget will be directed to that text field.

To direct edit action to a specific Text Field widget, the setFocus widget API is used. For example, when the user presses the Enter button while updating the Last Name Text Field widget, the setFocus API is called to direct the next edit action to the Confirmation Number Edit Field widget. Here's how it is implemented in the application code.

/* Enter button is pressed */
case CONF_EVT_KEYBRD_ENTER:
{
   /* If lastname textfield widget is being edited, switch to confirmation number textfield widget */
   if (leGetEditWidget() == (leEditWidget*) LastNameConfScreen_txtFieldLastName)
    {
       LastNameConfScreen_txtFieldConfNum->fn->setFocus(LastNameConfScreen_txtFieldConfNum);
    }

Back to Top

Learn More

Back to Top