Overview
When the default Siemens on-screen keyboard does not fit the screen layout, language requirements, or aesthetic of a panel design, engineers often build a custom QWERTY screen in WinCC flexible 2008 Standard (SP2 through SP5 are the most widely deployed maintenance releases in the field). The design is straightforward at first glance: place a set of I/O fields for the user inputs, lay out a button grid that mimics Q, W, E, R, T, Y, ... and write a script that copies the pressed character into the active field. Two problems derail every first attempt at this build:
- Two-touch problem. The first touch on an I/O field selects the entire contents (this is the default behavior and is desirable). The second touch should drop the cursor inside the string so the user can edit, but the WinCC flexible I/O field exposes only a single Click event. There is no native DoubleClick event, no native way to detect the transition from "select-all" to "place-cursor".
- Mid-string insertion problem. Even if the cursor can be positioned, WinCC flexible does not publish the cursor offset of an I/O field to a tag, system function, or script. Without that offset, the keyboard can only append characters at the end of the string.
This article documents a working pattern for both problems using only standard WinCC flexible objects: an I/O field, a few internal integer tags, a set of soft-key buttons, and a VBScript function library. The pattern is fully compatible with the 2008 SP5 runtime and with the migration path to TIA Portal WinCC described in the Siemens FAQ "How do you create your own on-screen keyboard for a WinCC Runtime Advanced Station?". Where WinCC flexible 2008 reaches its limits, the article flags the upgrade path to WinCC Runtime Advanced / RT Professional and the documented keyboard layout handling at Select keyboard layout (Professional) - WinCC Runtime Professional.
Prerequisites
Before implementing the custom keyboard, confirm the following are available in the engineering station and on the target panel:
- Engineering software: SIMATIC WinCC flexible 2008 Standard, SP2 or later. SP5 (released 2012) is the recommended service pack for all custom-script work because it ships the most stable VBScript runtime on Panels and Runtime PC.
- Target panel family: any panel that supports WinCC flexible 2008 Standard (OP 77B, TP 177B, TP 177A, MP 177, MP 277, MP 377, or WinCC Runtime PC). The custom-keyboard pattern works on all of them; only the I/O field count limit per screen differs.
- Panel type setting in the project: OP 77B, TP 177A, or older 4-inch panels do not support VBScript. Verify the panel type permits VBScript before committing to this design.
- Tag budget: plan for at least 5 internal tags per I/O field that participates in the custom keyboard: one string tag for the value, one integer tag for the cursor position (offset, 0-based), one integer tag for the press state (0=idle, 1=armed, 2=editing), and one tag each for the active-field selector. A typical 10-field login screen therefore needs ~50 internal tags.
- Script editor: open WinCC flexible's Scripts > VBScripts view; confirm Microsoft VBScript Regular Expressions is enabled (it is by default in 2008 SP3+).
I/O Field Two-Touch Behavior Explained
WinCC flexible I/O fields support exactly three events that fire on a touch:
| Event | Trigger | Available in WinCC flexible 2008 |
|---|---|---|
| Click | Fires once on press (release on the same pixel) — the same event whether it is the first or the Nth touch | Yes |
| Change | Fires when the operator accepts a new value (typically the "Enter" or the moment focus leaves the field) | Yes |
| Activate / Deactivate | Focus gain / loss | Yes |
| DoubleClick | — | Not available on the I/O field object |
The default touch sequence is therefore:
- Touch #1 → Click event fires → I/O field enters selection mode → entire string is highlighted.
- Touch #2 → Click event fires again → I/O field drops into edit mode → cursor is placed at the touch point inside the string.
From a VBScript perspective, both touches look identical: a single Click notification with no "which-press-of-the-day" qualifier. The detection must therefore be reconstructed in the application layer with a state tag.
Detecting the Second Touch with State Tags
The pattern uses a small finite state machine driven by a single integer tag per I/O field. The tag carries three meaningful values; all other values are reserved for future use and should be treated as idle.
| Value | State name | Meaning | Next valid value(s) |
|---|---|---|---|
| 0 | IDLE | Field is not the active edit target. | 1 |
| 1 | ARMED | Field has been touched once; full string is selected. | 0, 2 |
| 2 | EDITING | Field has been touched a second time; cursor is positioned and character insertion is enabled. | 0, 1 |
Wire the I/O field's Click event to a single VBScript function OnFieldClick(iFieldIndex). The function reads the current state tag, transitions it, and writes the result back. The pseudocode for the transition is:
Sub OnFieldClick(fieldIndex)
Dim s : s = SmartTags("field_state_" & fieldIndex)
Select Case s
Case 0
SmartTags("field_state_" & fieldIndex) = 1 ' ARMED: full string selected
SmartTags("active_field") = fieldIndex
Case 1
SmartTags("field_state_" & fieldIndex) = 2 ' EDITING: cursor is placed
SmartTags("active_field") = fieldIndex
Case 2
SmartTags("field_state_" & fieldIndex) = 0 ' IDLE: explicit clear
SmartTags("active_field") = -1
End Select
End Sub
The transition from 1 → 2 is the second-touch event the project needs. At that point, the keyboard's soft-key buttons switch from Replace mode to Insert mode, and the cursor-position tag becomes the authoritative target for character insertion.
Tracking Cursor Position in I/O Fields
WinCC flexible I/O fields do not expose the caret offset as a property, so a synthetic cursor must be maintained. Three viable approaches exist, listed in order of complexity:
| Approach | Mechanism | Pros | Cons |
|---|---|---|---|
| 1. Virtual caret with arrow buttons | Two dedicated soft keys (◀ ▶) on the custom keyboard increment/decrement a cursor integer tag clamped to [0, Len(value)]
|
Trivial to implement; works on every panel | User has to tap arrow keys; no direct tapping inside the string |
| 2. Numeric input split into "row,column" coordinates | On entering EDITING, switch the I/O field to a numeric mode and require the user to enter the column position as a number | No extra UI | Awkward UX; not a real QWERTY experience |
| 3. ActiveX text control with published .SelStart | Replace I/O fields with a Siemens-supplied or third-party ActiveX text control that exposes caret position | Real cursor awareness, supports selection, supports long-press | ActiveX may not be available on every panel; licensing differs per panel family |
For a Panel-class target (TP/MP) Approach 1 is the practical choice because Approach 3 requires ActiveX support that is not present on 4-inch and 6-inch panels. The arrow keys live on the same screen as the QWERTY layout, and the cursor tag is a single 16-bit integer that the script clamps on every update.
Sub MoveCursor(direction)
' direction = -1 for left, +1 for right
Dim idx : idx = SmartTags("active_field")
If idx < 0 Then Exit Sub
Dim val : val = SmartTags("field_value_" & idx)
Dim pos : pos = SmartTags("field_cursor_" & idx)
pos = pos + direction
If pos < 0 Then pos = 0
If pos > Len(val) Then pos = Len(val)
SmartTags("field_cursor_" & idx) = pos
End Sub
The clamp is critical: if the cursor index falls outside the string the Mid() call in the next section will raise a runtime error and abort the script. The bound is [0, Len(value)], not [0, Len(value)-1], because the caret is conceptually allowed to sit one position past the last character (the standard text-editor convention).
Mid-String Insertion Logic
Once the state machine is in EDITING (state = 2) and the cursor integer has a valid value, character insertion is a direct application of VBScript's Left(), Mid(), and string concatenation:
Sub InsertChar(ch)
Dim idx : idx = SmartTags("active_field")
If idx < 0 Then Exit Sub
If SmartTags("field_state_" & idx) <> 2 Then
' IDLE or ARMED: behave as append (overwrite is also acceptable)
SmartTags("field_value_" & idx) = SmartTags("field_value_" & idx) & ch
Exit Sub
End If
' EDITING: insert at cursor position
Dim val : val = SmartTags("field_value_" & idx)
Dim pos : pos = SmartTags("field_cursor_" & idx)
If pos < 0 Then pos = 0
If pos > Len(val) Then pos = Len(val)
Dim newVal
newVal = Left(val, pos) & ch & Mid(val, pos + 1)
SmartTags("field_value_" & idx) = newVal
SmartTags("field_cursor_" & idx) = pos + 1 ' advance caret by 1
End Sub
Three behaviors fall out of this single function:
-
IDLE state (no field is active): the function exits without writing. Bind the QWERTY buttons' Enabled property to the inverted state of
active_field <> -1to grey out the keys. - ARMED state (full string selected): characters append. This matches the convention that the next typed character replaces the selection on the next Change event.
- EDITING state (cursor positioned): characters insert at the caret, the string length grows by one, and the caret advances by one. The user can therefore type a continuous stream of letters in the middle of the field.
The companion deletion function uses the same cursor tag:
Sub DeleteChar()
Dim idx : idx = SmartTags("active_field")
If idx < 0 Then Exit Sub
Dim val : val = SmartTags("field_value_" & idx)
Dim pos : pos = SmartTags("field_cursor_" & idx)
If pos <= 0 Then Exit Sub
Dim newVal
newVal = Left(val, pos - 1) & Mid(val, pos + 1)
SmartTags("field_value_" & idx) = newVal
SmartTags("field_cursor_" & idx) = pos - 1
End Sub
Building the Custom Keyboard Screen
A single screen carries the I/O fields at the top and the QWERTY grid below. The recommended layout for a 10-inch panel is:
-
Row 1: the user-editable I/O fields (login name, password, parameter name, etc.), each linked to a
field_value_Ntag and configured with Display > Appearance > "Output / input". -
Row 2: QWERTY row 1:
Q W E R T Y U I O P. -
Row 3: QWERTY row 2:
A S D F G H J K L. Offset row 2 by half a key for a true QWERTY look; on 4-inch panels keep the keys aligned to the grid. -
Row 4: QWERTY row 3:
Z X C V B N M. -
Row 5: space bar (wide button),
<(cursor left),>(cursor right),DEL(delete char),CLR(clear field),ENT(accept & leave field).
Every key in rows 2-5 calls the same InsertChar function with the appropriate character literal. The CLR button resets the active field to the empty string and the cursor to 0. The ENT button transitions the field state back to IDLE and clears active_field.
Verification & Commissioning
After the screen compiles, run through the following checks on the live panel or in the WinCC flexible RT simulation. Every check should pass before the project is released.
-
Append on first touch. Touch an empty I/O field, then tap
A. The string should readA. -
Select-all on re-touch. Touch the same field again. The full string
Ashould be highlighted. -
Cursor placement on third touch. Touch the field a third time. The state should transition to EDITING and the cursor should land at the touched position (use an LED indicator bound to
field_state_0 == 2for visual confirmation). -
Mid-string insertion. Press the left arrow twice so the cursor tag reads 0, then tap
B. The string should readBAand the cursor tag should now read 1. -
Delete at boundary. Move the cursor to position 0 and tap
DEL. The script must exit cleanly (no runtime error) and the string must remain unchanged. - Cross-field focus. Touch a second I/O field while the first is in EDITING. The first should auto-transition to IDLE and the second to ARMED. Verify with state LEDs.
- Long string stability. Type 64 characters into a field, then move the cursor with arrows to position 32 and insert another character. The string must remain exactly 65 characters long and the cursor must read 33.
For a deeper walk-through of the panel-side wiring and the recommended object arrangement see the official Siemens FAQ "How do you create your own on-screen keyboard for a WinCC Runtime Advanced Station?". The patterns described in that FAQ (button grid + tag for the active field + script that copies the pressed character into the active field) are the same primitives this article extends with cursor awareness.
Troubleshooting Matrix
| Symptom on panel | Likely root cause | Fix |
|---|---|---|
| QWERTY keys do nothing |
active_field is -1; no I/O field has been touched, or the field's Click event was never wired to OnFieldClick
|
Confirm the Events > Click property of every I/O field calls OnFieldClick with the correct index |
| Characters always append, never insert mid-string | State tag never reaches value 2 (the EDITING transition is missing) | Check the second-touch logic: state must go 0 → 1 → 2; confirm the Click event fires twice on rapid taps |
Runtime error "Subscript out of range" in Mid()
|
Cursor tag exceeded Len(value) or fell below 0 |
Re-clamp with the If pos < 0 / If pos > Len(val) guards shown above |
| Cursor jumps to end after every insert | Cursor tag is being reset to Len(val) by the I/O field's own Change event |
Bind the Change event of the I/O field to a no-op or to a script that preserves field_cursor_N
|
| Touches mis-registered on 4-inch panel | Key size below the 20 × 20 px tap target minimum | Increase key size or reduce the number of keys per row to 8 |
| Works in RT simulation, fails on panel | Panel firmware older than the project target; or the panel was compiled against a SP that the runtime does not have | Update the panel image, or recompile the project against the panel's installed SP |
| Custom keyboard layout disappears after migration to TIA Portal | WinCC flexible 2008 projects are migrated with the TIA Portal migration tool; VBScript is preserved but tag naming conventions may need manual adjustment | Use the TIA Portal migration tool, then re-check all SmartTags() references; consider switching to the documented WinCC keyboard layout handling at Select keyboard layout (Professional) on RT Professional targets |
Migration Notes: From WinCC flexible 2008 to TIA Portal
WinCC flexible 2008 reached end-of-life with the TIA Portal migration. Projects that use the custom keyboard pattern described in this article migrate cleanly, but three differences are worth flagging during commissioning on a TIA Portal target:
-
Tag access syntax. The
SmartTags("name")VBScript accessor is retained in WinCC V15 and later, but the recommended pattern in current documentation isHMIRuntime.Tags("name").Read/.Writefor explicit read-write clarity. - Runtime target. On TIA Portal the same pattern ports to WinCC Runtime Advanced (PC-based) and to WinCC Runtime Professional. On RT Professional, the documented keyboard layout can be selected directly from the project settings, which may make the custom keyboard unnecessary if the default layout is acceptable.
- Event model. Comfort Panels and Unified Panels expose an explicit DoubleClick event on the I/O field. Once a project is migrated to a Comfort or Unified panel the entire state-machine workaround collapses into a single OnDoubleClick handler.
Field-Proven Caveats
Three constraints show up repeatedly on commissioning sites and should be checked before sign-off:
-
Tag change polling. WinCC flexible updates
SmartTags()at the configured acquisition cycle, default 1 s. If the cursor tag is bound to a rapid input (such as a hardware keyboard) the value seen by the script may lag the user. Lower the cycle to 100 ms for the cursor tag only — global changes slow down all other HMI updates. - String length cap. WinCC flexible string tags are limited to 254 characters (S7-300/400 compatible) or 4000 characters (S7-1500 / TIA Portal compatible). The custom keyboard should refuse to insert beyond the cap with a visible warning.
- Password fields. When the custom keyboard is used to type a password, bind the I/O field's Display > Password input property. The string value in the tag is plain text; protect the PLC connection with the standard WinCC flexible user administration.
How do I detect the second touch on a WinCC flexible I/O field?
The I/O field fires only a single Click event for any press. Detect the second touch by attaching a state tag (0=IDLE, 1=ARMED, 2=EDITING) to the Click event handler. The first press writes 1, the second writes 2; the keyboard reads the transition from 1 to 2 to enable mid-string insertion.
How do I insert a character at the cursor position in a WinCC flexible I/O field?
Maintain a cursor integer tag that holds the caret offset (0 to Len(value)). Use the VBScript expression Left(val, pos) & ch & Mid(val, pos + 1) to splice the new character in, then increment the cursor tag by 1. Clamp the tag to [0, Len(value)] on every update to avoid runtime errors in Mid().
Can I read the real cursor position from a WinCC flexible I/O field?
No. The I/O field object in WinCC flexible 2008 does not publish the caret offset. The pragmatic workaround is to track a synthetic cursor with arrow soft keys and to enforce the boundary in the script. On TIA Portal Comfort and Unified panels the I/O field exposes a DoubleClick event and the synthetic cursor becomes unnecessary.
What is the minimum VBScript cycle to make a custom keyboard feel responsive?
Set the cursor tag acquisition cycle to 100 ms. Leave the rest of the project at the default 1 s cycle. Lowering the global cycle slows down all tag updates and is the most common cause of sluggish HMI behavior in custom-keyboard projects.
Where can I find Siemens' official guidance on custom on-screen keyboards?
Siemens publishes the FAQ "How do you create your own on-screen keyboard for a WinCC Runtime Advanced Station?" which describes the button-grid + active-field pattern. For TIA Portal targets the documented keyboard layout handling is described under Select keyboard layout (Professional) - WinCC Runtime Professional.