Triggering Scripts on HMI Screen Close in TIA Portal WinCC

David Krause12 min read
SiemensTutorial / How-toWinCC
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Statement

HMI screens in TIA Portal WinCC expose a rich Open event model (OnOpen, OnActivate, OnLoaded) but lack a symmetric, first-class Close event. When an operator navigates away from a faceplate, pop-up, or sub-screen, there is no built-in OnClose callback in which the programmer can execute cleanup logic such as resetting a "screen-active" bit, flushing a buffer tag, or releasing a held alarm acknowledgement.

This is a recurring requirement for symmetric bit handling: set a status bit when the screen opens, clear it when the screen closes. The most robust, documented solution in WinCC Comfort, WinCC Professional, and WinCC Runtime Advanced is to host the screen in a Picture Window object and bind logic to its Display property event. Several alternative approaches exist (direct connection, global script with ActiveScreen, Win32 API handle lookup) and each is detailed below with parameter tables, VBScript examples, and commissioning steps.

Prerequisites

  • Siemens TIA Portal V15.1 or later (V16, V17, V18, V19 also supported). Earlier V13/V14 projects can use the same procedure.
  • WinCC Comfort, WinCC Advanced, or WinCC Professional runtime license.
  • A target HMI device configured in the project tree (HMI_1 / KTP / Comfort Panel / IPC).
  • A boolean PLC tag or internal HMI tag to act as the screen-active marker, for example HMI_Tag_ScreenActive of type Bool.
  • For VBScript methods: the runtime scripting environment enabled (default in Comfort/Professional; check HMI device → Runtime settings → Services → VBScript).
  • For Win32 API methods: administrative access to the engineering station for testing; runtime panels do not expose Win32 handles.
Note. All code samples below assume a tag named ScreenActive. Substitute your project-specific tag name where shown. Tag addresses in the examples use symbolic naming; physical addresses (e.g. %DB101.DBX0.0) can be substituted if direct symbolic binding is not used.

Architecture: Screen Lifecycle in WinCC Runtime

Before implementing a close-trigger, it helps to model the screen lifecycle as a state machine. Every WinCC screen object in the runtime exposes four observable lifecycle transitions:

  1. Loaded — the screen object is instantiated in memory.
  2. Opened / Activated — the screen is the active picture; OnActivate fires.
  3. Deactivated — the operator navigates to a sibling screen; the object remains instantiated.
  4. Closed / Unloaded — the object is removed from memory (pop-ups, dynamically loaded screens, picture windows that switch source picture).

The Picture Window is special because it owns its own Display property — a boolean that toggles between 1 (visible) and 0 (hidden). This single property is the canonical hook for any logic that needs to fire on visibility change, and it is the recommended solution because it does not depend on screen change events that are not raised during certain navigation paths.

Method 1 — Picture Window Display Event (Recommended)

The Picture Window control (object type Picture Window, catalog under Controls → WinCC Controls) maintains a runtime property called Display. The property is accessible under Events → Property Topics → Miscellaneous → Display and is updated by the runtime whenever the picture transitions between visible and hidden states.

The Display event raises a Value parameter with the following semantics:

Value State Meaning
1 Display = True Picture Window is currently visible (operator opened the screen)
0 Display = False Picture Window is hidden or unloaded (screen was closed)

Configuration Steps

  1. Open the parent screen (e.g. Screen_Overview) in the TIA Portal editor.
  2. From Toolbox → Controls, drag a Picture Window onto the canvas.
  3. In the Picture Window properties, configure the Picture Name property to the screen you want to host (e.g. Screen_Detail). You can leave this empty if you plan to assign the picture dynamically.
  4. Right-click the Picture Window → Properties → Events.
  5. Navigate to Property Topics → Miscellaneous → Display.
  6. Add a new function list, VBScript, or direct connection that uses the Value parameter (see options below).

Option A: Function List with System Functions

Configure the function list to evaluate Value and either set or reset the tag:

  1. Insert Set Bit as the first action. Operand: ScreenActive. Set/Reset: Set. (Optional — fires when screen opens.)
  2. Insert a conditional branch: If → Compare tag → Value (local event parameter) = 0.
  3. Inside the branch, insert Reset Bit on ScreenActive.

Option B: VBScript on the Display Event

Right-click the Display event and select Add VBScript function. Replace the generated stub with:

' Name: PictureWindow_Display_Changed
' Triggered by: Property Topics > Miscellaneous > Display (Value parameter)
Sub PictureWindow_Display_Changed(ByVal Item)
    Dim pvDisplay
    pvDisplay = Item.Value            ' 1 = opened, 0 = closed

    If pvDisplay = 1 Then
        SmartTags("ScreenActive") = True
    ElseIf pvDisplay = 0 Then
        SmartTags("ScreenActive") = False
        ' Additional cleanup actions on close:
        SmartTags("PopupDirty") = False
        SmartTags("EditBuffer") = ""
    End If
End Sub

The Item.Value argument is supplied automatically by the runtime and corresponds to the new Display property value after the transition.

Method 2 — Direct Connection on the Display Property

For the simplest possible implementation — no scripting required — use a direct connection between the Picture Window Display property and a tag.

  1. Right-click the Picture Window → Properties → Events → Property Topics → Miscellaneous → Display.
  2. Click the small lightning-bolt icon to create a Direct Connection.
  3. On the left side, select This object → Display as the source property.
  4. On the right side, select Tag → ScreenActive.
  5. Accept the default direction (read tag → write property). The runtime will write 1 when the picture is visible and 0 when it is not visible.
Note. A direct connection mirrors the property into the tag in real time without conditions. If you need conditional logic (e.g. only reset the bit if no other screen is still active), use Method 1 with VBScript or a function list.

Method 3 — Global VBScript Using ActiveScreen

If the host screen does not use a Picture Window, you can monitor the runtime's ActiveScreen property from a global scheduled task or a cyclic C/VBScript. HMIRuntime.ActiveScreen returns a reference to the currently active screen object.

Scheduled Task Configuration

  1. Open HMI device → Scheduled Tasks.
  2. Add a new task, name it ScreenLifecycle_Watch, set trigger to Cyclic → 500 ms (or use Screen change event for reduced overhead).
  3. Attach a VBScript action with the body below.
' Name: ScreenLifecycle_Watch
' Triggered by: Scheduled task (cyclic 500 ms) or Screen change event
Dim currentScreen, lastScreen, screenName
Set currentScreen = HMIRuntime.ActiveScreen
screenName = currentScreen.ScreenName

If screenName <> lastScreen Then
    ' Screen transition detected. If the new screen is NOT our tracked
    ' screen, the previously active screen was effectively closed.
    If screenName <> "Screen_Detail" Then
        SmartTags("ScreenActive") = False
        SmartTags("LastClosedScreen") = lastScreen
    Else
        SmartTags("ScreenActive") = True
    End If
    lastScreen = screenName
End If
Note. lastScreen must be declared as a module-level variable outside the Sub to retain state between cycles. In TIA Portal V17 and later, use Dim at script top-level scope, or persist lastScreen to an internal HMI tag.

Method 4 — Button-Triggered Toggle on Screen Change

If the screen is always opened from a known button, you can drive the bit from the button's click event and from the next screen's OnOpen:

  1. On the Open Screen button: Activate Screen action → target screen; Set Bit action → ScreenActive.
  2. On the target screen's OnOpen event: confirm ScreenActive = 1 (optional).
  3. On the target screen's Back button: Reset BitScreenActive, then Activate Screen → previous screen.

This pattern is reliable for hierarchical navigation but breaks down when the operator closes the screen via an alarm, an external tag-driven ActivateScreen call, or a script.

Method 5 — Win32 API Window Handle Lookup

For WinCC Professional on a Windows-based runtime PC, the active picture window has a native Win32 handle accessible via the Win32 API. This is the most fragile method and is not supported on Comfort Panels. Use only when Methods 1–4 are unavailable.

' Declare at module top level
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function IsWindowVisible Lib "user32.dll" _
    (ByVal hwnd As Long) As Long

Sub CheckWindowHandle()
    Dim hWnd As Long
    hWnd = FindWindow(vbNullString, "Screen_Detail")
    If hWnd = 0 Then
        ' Window not found — treat as closed
        SmartTags("ScreenActive") = False
    ElseIf IsWindowVisible(hWnd) = 0 Then
        ' Window exists but is hidden
        SmartTags("ScreenActive") = False
    Else
        SmartTags("ScreenActive") = True
    End If
End Sub
Caution. Win32 API calls in WinCC runtime are officially undocumented for this use case and may break across TIA Portal major versions. Always validate in your target runtime before production deployment.

Method Comparison Matrix

Method Scope Requires Scripting Reliability Performance Impact Panel Support
1A — Picture Window Display (Function List) Picture Window host No High Negligible Comfort, Advanced, Professional
1B — Picture Window Display (VBScript) Picture Window host Yes High Negligible Comfort, Advanced, Professional
2 — Direct Connection Picture Window host No High None Comfort, Advanced, Professional
3 — Global Script / ActiveScreen Global Yes Medium Low (cyclic) / None (event) Advanced, Professional
4 — Button-driven Toggle Per screen No Medium None All
5 — Win32 API Handle Global (PC only) Yes Low Moderate Professional (Windows runtime)

Tag and Variable Configuration

Create the following tags in the HMI tag table (or connect to PLC tags of the same name):

Tag Name Data Type Source Purpose
ScreenActive Bool HMI internal or PLC Set when target screen opens; reset when closed
LastClosedScreen WString[32] HMI internal Captures which screen last triggered close (Method 3)
PopupDirty Bool HMI internal Optional — flag indicating unsaved edits
EditBuffer WString[64] HMI internal Optional — scratch buffer cleared on close

If ScreenActive is sourced from the PLC, mark the connection as cyclic continuous with a 100 ms acquisition cycle. If it is sourced locally on the HMI, mark it internal tag with no PLC acquisition.

Verification and Commissioning Procedure

  1. Compile the HMI project (TIA Portal → HMI device → Compile → Software (rebuild all)). Resolve any warnings about unused event parameters.
  2. Download to the target device. On Comfort Panels, use Ethernet or USB; on PC runtime, use Start Runtime from TIA Portal.
  3. Open the RT logger (WinCC RT → Tools → Trace) and add the ScreenActive tag for live monitoring.
  4. Navigate to the host screen. Confirm the Picture Window shows the child picture and ScreenActive traces 1.
  5. Navigate away from the host screen (button or ActivateScreen). Confirm ScreenActive transitions to 0 within one RT cycle (typically 100–500 ms).
  6. Force a screen change via PLC by setting a tag that drives ActivateScreenByTag in the HMI. Verify the close logic still fires.
  7. Power-cycle the panel. Verify the bit starts at 0 after boot (expected because the Picture Window is not visible until invoked).
  8. Repeat steps 4–6 with the operator logged out, to confirm the logic does not depend on user-rights state.

Troubleshooting Matrix

Symptom Likely Root Cause Remediation
Bit never sets when screen opens Picture Window Picture Name property is empty Assign a screen to the Picture Name property under Miscellaneous
Bit never resets on close Event attached to wrong Picture Window instance Re-verify the event configuration under the correct object's Events → Property Topics → Miscellaneous → Display
Bit resets, then immediately re-sets Close handler triggers another event that re-opens the picture Inspect Activate Screen actions on the close handler; debounce with a 250 ms timer
VBScript error: Object variable not set Item parameter name typo or wrong argument order Use the engine-generated signature Sub Name(ByVal Item) exactly
Cyclic script lag > 1 s 500 ms cycle is too long for the application Reduce cycle to 200 ms, or switch to event-driven Screen change trigger
Direct connection writes stale value Direction configured as write property → tag instead of read → write In the direct connection dialog, set source = property, target = tag
Win32 API returns 0 in RT but works in simulator FindWindow window title mismatch on the device locale Print the actual caption with GetWindowText during a debug cycle

Performance and Runtime Considerations

For panels with RT cycles below 200 ms, the cyclic ActiveScreen approach (Method 3) introduces measurable CPU load when more than ~10 screens are cycled per second. Prefer Screen change event scheduling in that case. The Picture Window Display event (Method 1) is fired by the runtime only on actual visibility transitions, so its overhead is independent of the RT cycle and is the most scalable approach for projects with frequent pop-ups.

VBScript runtime is single-threaded per HMI device. If your cleanup handler performs heavy work (file I/O, recipe operations), offload the time-critical reset to a function list and reserve VBScript for I/O-bound cleanup only.

Security and Audit Considerations

If the cleanup action is tied to a user-rights change (e.g. logging which user closed the screen), record the operator in a separate audit tag inside the same Display handler:

Sub PictureWindow_Display_Changed(ByVal Item)
    If Item.Value = 0 Then
        SmartTags("AuditLastCloseUser") = _
            HMIRuntime.Runtime.Users.CurrentUser.Name
        SmartTags("AuditLastCloseTime") = Now
    End If
End Sub

Tags used for audit must be configured with adequate length (WString[64] minimum for usernames) and excluded from RT retention unless the project complies with the regulator's logging requirements.

Frequently Asked Questions

Does WinCC TIA Portal have a built-in OnClose event for screens?

No. WinCC Comfort, Advanced, and Professional expose OnLoaded, OnOpen, OnActivate, and OnDeactivate events, but no first-class OnClose. The recommended workaround is to host the screen in a Picture Window and use the Display property event, where Value = 0 corresponds to a hidden or unloaded picture.

Can the Picture Window Display event fire multiple times in quick succession?

Yes. If the picture changes rapidly (e.g. animated pop-up), Display fires on every transition. Debounce in the handler if downstream logic is expensive. A 100–250 ms minimum interval is typical for stable cleanup logic.

Why does my direct connection write the bit in the wrong direction?

The direct connection defaults to "write property from tag". Reverse the source and target so the source is the Picture Window's Display property and the target is your ScreenActive tag. Re-test by navigating away from the screen.

Will Method 3 (ActiveScreen) detect screen changes via PLC-driven ActivateScreen calls?

Yes. HMIRuntime.ActiveScreen reflects the runtime's current active picture regardless of whether the navigation originated from a button, a scheduled task, or a PLC-driven tag change. The cyclic script will detect the transition on its next scan.

Is VBScript required, or can I use C scripting for the cleanup handler?

C scripting is available on WinCC Professional only. The event signature is the same: void OnDisplayChanged(HMIObject* pObj, long Value) with Value = 1 for visible and Value = 0 for hidden. On Comfort Panels and WinCC Advanced, use VBScript or function lists.

Back to blog