TITLE:Screen Savers in MultiValue Environment

ISSUE:Multi-Value Solutions Nov'98

AUTHOR:Nathan Rector

COMPANY:Natec Systems



More and more people are integrating their MultiValue system on to Windows workstations. For those who have moved to Windows workstations, you found that you have lost some basic control over the workstation that you had with dumb terminals.

With dumb terminals, the IS department could control what people had access to and how the data moved through the system. They had control over what people could load on the system, or what they could use the system for.

With Windows terminals, the IS department loses these controls. As more and more employees learn how to work with Windows, they start playing with settings on the Windows workstations at work. They also start loading their own applications or games.

Not only do you have these problems you now have other people in the company that that know how to do these things. With a little searching or playing they may be able to access accounting information just by using the same computer that accounting uses when no one is around to control the access.

The question comes up on how to regain control over the workstations. There are a lot of things that can and need to be done. One is to use screen savers.

All Windows systems come with default screen savers. However, most are more playful than functional. In this article I'm going to show you how to make screen savers useful to the IS department.

All screen savers have a password option that requires the user to input a password before the screen saver disappears. The one problem is that the password exists on the local machine and is a generic overall password that is easily pass around to other coworkers. It also doesn't allow you the ability to control the time of the day and the days of the week the user may use the system.

Now imagine having a screen saver that validates a user name and password against information on the host system. In this article I'm going to show you how to make one. This program requires a little bit of knowledge of Visual Basic as well as Visual Basic hooks into the MultiValue database, eg: Winlink32, Pic-Lan, D3 Objects, or UniObjects.

Due to the length of this topic, I'll have to cover how to do this in more than one article.

For starters, create a new Visual Basic "Standard EXE" project. You need 2 form -- Savemain and frmLogin -- and one module. In this article, I'll cover the main code needed to make the screen saver function in Windows.

Due the complexity of some of the API code, I will not cover the actual detail on how each one of the APIs are used. The code supplied in this article is to be placed in the VB module.

Here is a basic description of what each routine in this set of code does.

Main() = used when the program is started. It decides what part of the routine to use with the switch Windows uses when the program is run.

cleanup_and_end() = runs right before the screen saver stops the program. It is used to clean up any open variables or system settings that need to be reset.

start_screensaver() = starts the screen saver. It launches the Savemain form that is displayed when the screen save is active.

Check_password() = sets the local screen saver password. This routine is run when the user tries to set the screen saver password in the Control Panel. In this example, if the user tries to do this, it displays a message saying the function is not available.

start_preview_box() = when displaying the screen saver in the Control Panel, there is a preview window that allows the user to see what the screen saver looks like when it is running.

run_configuration() = some screen savers allow users to configure what they do. For example, the speed or color of the information being displayed on the screen. For this example, the routine displays a message saying that there is no configuration screen.

Set_TFS() = this routine disables or enables the ctrl-alt-del keys so the user can't reset the computer to get around the screen saver.

GetVersion32() = gets the current version of the Windows OS the screen saver is running on. There are some options that work differently on Windows NT than Windows 95.

Option Explicit

' Constants List

Public Const WS_CHILD = &H40000000

Public Const GWL_STYLE = (-16)

Public Const GWL_HWNDPARENT = (-8)

Public Const HWND_TOP = 0&

Public Const SWP_NOZORDER = &H4

Public Const SWP_NOACTIVATE = &H10

Public Const SWP_SHOWWINDOW = &H40


' ScreenSaver Running Modes

Public Const RM_NORMAL = 1

Public Const RM_CONFIGURE = 2

Public Const RM_PASSWORD = 3

Public Const RM_PREVIEW = 4

' API call to turn mouse cursor on / off

Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As Long 'Version info

Private OsVers As OsVersionInfo

Type OsVersionInfo

dwVersionInfoSize As Long

dwMajorVersion As Long

dwMinorVersion As Long

dwBuildNumber As Long

dwPlatform As Long

szCSDVersion As String * 128

End Type

Private Declare Function GetVersionEx& Lib "kernel32" Alias "GetVersionExA" (lpStruct As OsVersionInfo) ' API calls required to talk to the preview window

Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long

Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long

Declare Sub 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)

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, _

ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, _

ByVal nIndex As Long) As Long

Public Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, _

ByVal uParam As Long, lpvParam As Any, ByVal fuWinIni As Long) As Long

' Public variable fields

Public CurrOS As String ' Name of operating system, 95 or NT

Public PWMode As Integer ' Screensaver password enabled flag

Public RunMode As Long

Public DispRec As RECT ' Rectangle values of display form

' Private variable fields

Private dispHWND, style As Long '

Types Public Type RECT

Left As Long

Top As Long

Right As Long

Bottom As Long

End Type


Sub Main()

' Ensure that only one instance of this screensaver is running

Randomize ' Seed the random number generator - may be required

' Check the command line arguments

If Left(Command$, 2) = "/p" Then

' The command-line argument /p is used to launch the preview box

RunMode = RM_PREVIEW start_preview_box

ElseIf Left(Command$, 2) = "/c" Then

' The command-line argument /c is used to launch the screen saver

in setup mode RunMode = RM_CONFIGURE run_configuration

ElseIf Left(Command$, 2) = "/s" Or Command$ = "" And Not

App.PrevInstance Then

' The command-line argument /s is used to launch the screen saver

in normal operating mode RunMode = RM_NORMAL start_screensaver

ElseIf Left(Command$, 2) = "/a" Then

' The command-line argument /a is used to launch the password mode

RunMode = RM_PASSWORD Check_password

End If

End Sub

Public Sub cleanup_and_end() ' Public exit - can be called from forms etc.

On Error Resume Next

ShowCursor True ' Unhide the mouse cursor

Set_TFS "enable" ' Restore CTL+ALT+DEL

End ' Endex here

End Sub

Private Sub start_screensaver()

On Error GoTo saver_error

ShowCursor True ' Hide the mouse cursor

' Get the O/S name using function in SysInfo code module

' Get the PW flag using a function in the ellreg code module.

CurrOS = GetVersion32 ' Find out the operating system, 95 or NT

' Find out if the user has enabled passwords for this screen saver If

CurrOS = "95" Then PWMode = 1 Set_TFS "disable" ' Stop CTL+ALT+DEL

Savemain.Show ' Start the screensaver Exit Sub


MsgBox "The screensaver has failed" & vbCrLf & vbCrLf &

Err.Description, vbOKOnly, "Saver"

End Sub

Private Sub Check_password()

MsgBox "The password change not available.", vbOKOnly, "PW"

End Sub

Private Sub start_preview_box()

On Error GoTo preview_error

' Convert preview window handle to long type

dispHWND = CLng(Right$(Command$, Len(Command$) - 3))

' Load up the preview form

Load Savemain

GetClientRect dispHWND, DispRec ' Get Preview Box Rectangle dimensions

style = GetWindowLong(Savemain.hwnd, GWL_STYLE) ' Get current window

style style = style Or WS_CHILD ' Append "WS_CHILD" style to the hWnd window style

SetWindowLong Savemain.hwnd, GWL_STYLE, style ' Add new style to window

SetParent Savemain.hwnd, dispHWND ' Set preview form into preview window

' Save the hWnd Parent in hWnd's window struct.

SetWindowLong Savemain.hwnd, GWL_HWNDPARENT, dispHWND

SetWindowPos Savemain.hwnd, HWND_TOP, 0&, 0&, DispRec.Right, DispRec.Bottom, _


preview_error: ' No error messages when in preview mode - looks messy End


Private Sub run_configuration()

MsgBox "This screensaver has no configuration options", vbOKOnly, "Setup"

End Sub

Public Sub Set_TFS(Command As String)

' Disable three finger salute (TFS) on Win 95.

' Call when you don't want people breaking past the screensaver

' when passwords are enabled. Command can be "enable" or "disable". '

Example - Set_TFS "enable" If PWMode = 1 And CurrOS = "95" Then

' only diable the Ctrl-Alt-Del When in Win95 or Win98

If LCase(Command) = "disable" Then

SystemParametersInfo SPI_SCREENSAVERRUNNING, 1&, 0&, 0&

End If

If LCase(Command) = "enable" Then

SystemParametersInfo SPI_SCREENSAVERRUNNING, 0&, 0&, 0&

End If

End If

End Sub

Public Function GetVersion32() As String

' Call to get the 32 Bit O/S ID. Returned values are either "95" or

' "NT" or "Unknown"

' Example - MyString = GetVersion32 '

OsVers.dwVersionInfoSize = 148& GetVersionEx OsVers If

OsVers.dwPlatform = 1& Then

GetVersion32 = "95"

ElseIf OsVers.dwPlatform = 2& Then

GetVersion32 = "NT"


GetVersion32 = "Unknown"

End If

End Function