How to display a non-modal message window while a lengthy macro runs

  • 7023470
  • 23-Oct-2018
  • 24-Oct-2018

Environment

Reflection Desktop (including for IBM, or for UNIX and OpenVMS) 16.0 or later
InfoConnect Desktop (including Pro, for Unisys, for Airlines) 16.0 or later

Situation

If a macro is expected to take a relatively long time to complete, you may want to display a "Please wait..." message while it runs, to remind the Reflection user not to interact with the session while the macro does its work.

Resolution

It is possible to display a non-modal Visual Basic "form" with a "please wait" message while a macro runs. Using Windows API functions, you can remove the title bar from this form so the Reflection user will not be able to close this message, allowing you to keep it displayed until you want to close it when the macro completes.

First, in the Visual Basic Editor for your Reflection (or InfoConnect) Desktop session, add a new form to the "Forms" folder. Name this "PleaseWaitForm" as shown, and put a label on it with a helpful message of your choosing, for example:

Next, add a new module to the "Modules" folder...perhaps name the module "PleaseWait". Copy the following code to the new module:


Option Explicit

Private Const GWL_STYLE = (-16)
Private Const WS_CAPTION = &HC00000
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOZORDER = &H4
Private Const SWP_FRAMECHANGED = &H20
Private Const setwindowposFlags = SWP_NOSIZE Or SWP_NOMOVE Or _
           SWP_NOZORDER Or SWP_FRAMECHANGED
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
           (ByVal lpClassName As Any, ByVal lpWindowName As String) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
           (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
           (ByVal hwnd As Long, ByVal nIndex As Long, _
           ByVal dwNewLong As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, _
           ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, _
           ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Private pwForm As PleaseWaitForm

Public Sub ShowPleaseWaitForm()
    'If you forgot to close it before calling this function to
    'show it, kill off the current instance before creating a new one...
    ClosePleaseWaitForm
    'Create an instance of the form...
    Set pwForm = New PleaseWaitForm
    'Show it, not modal...
    pwForm.Show False
    'Set the caption to something that FindWindow can find...
    pwForm.caption = "my unique caption!!!"
    Dim hForm As Long
    'Get the handle of the form...
    hForm = FindWindow(0&, "my unique caption!!!")
    Dim longval As Long
    'Use the handle to get the style bits associated with the form...
    longval = GetWindowLong(hForm, GWL_STYLE)
    'Turn off the title bar...
    longval = longval And Not WS_CAPTION
    'Set the updated style back on the form...
    SetWindowLong hForm, GWL_STYLE, longval
    'Using SetWindowPos with SWP_FRAMECHANGED like this is required
    'after fiddling with a window's style...
    SetWindowPos hForm, 0&, 0&, 0&, 0&, 0&, setwindowposFlags
    'Tell the form to freshen up...
    pwForm.Repaint
End Sub

Public Sub ClosePleaseWaitForm()
    If Not pwForm Is Nothing Then
        Unload pwForm
    End If
End Sub


With the PleaseWaitForm and the code in this PleaseWait module in place in your Reflection Visual Basic project, you can now show this message at the outset of your lengthy macro using "ShowPleaseWaitForm" and when it's done, remove it with "ClosePleaseWaitForm". This is what will be seen while your macro runs:




Additional Information

On systems with multiple monitors, the "PleaseWaitForm" may not show up centered over the session if the session is not displayed on the primary monitor.

To prevent accidental keystrokes by the Reflection user while a macro runs, use IbmScreen.LockInput/UnlockInput, or for VT sessions Screen.LockInput/UnlockInput.