Creating a Windows Screen Saver using Visual Basic:
1. A Screen Saver is a program. Create a project and program it to do what you want your Screen Saver to do.
2. Windows can call your Screen Saver with various options. Your program must respond to the following:
- /S on the command line when Windows wants to run the Screen Saver or the user tests it.
- /P and a window handle to create the preview window on the Display Properties Dialog Box
- /A and a window handle when the user wishes to change the Screen Saver password.
See the code examples below.
3. When you are ready to Make EXE, you must follow these two important steps:
- Change the filename to end in .SCR instead of .EXE
- Click the Options button, and in the Application Title field insert SCRNSAVE: before the title of the Screen Saver.
4. In order to run your Screen Saver you must move the .SCR file into your Windows or Windows\System directory, then select it from your Display Properties.
5. To distribute your Screen Saver to other computers you should package it with any Controls and Libraries it uses.
Here are the declarations for all the following examples. Paste them into a Module in the (General) (Declarations) section.
Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal _
hWndNewParent As Long) As Long
Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect _
As RECT) As Long
Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, _
ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC _
As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function GetDesktopWindow Lib "user32" () As Long
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Declare Function ShowCursor& Lib "user32" (ByVal bShow&)
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, ByRef lpvParam As Any, ByVal fuWinIni As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public Const WM_CLOSE = &H10
Public Const SRCCOPY = &HCC0020 ' (DWORD) dest = source
Public Const HWND_TOPMOST = -1
Public Const SPI_SCREENSAVERRUNNING = 97
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public lpPrevWndProc As Long
Public gHW As Long, gHWF As Long
Public gKillMe As Boolean
Create a subroutine "Main" to handle the command line options. Select Tools/Options/Project and change Startup Form to Sub Main.

Sub main()
dim strCommand as string
strCommand = UCase(Command)
If InStr(strCommand, "/S") > 0 Then
frmScreenSaver.Show 1
ElseIf InStr(strCommand, "/P") > 0 Then
Load frmPreview
ElseIf InStr(strCommand, "/A") > 0 Then
frmPassword.Show 1
Else
frmSetup.Show 1
End If
End Sub
frmScreenSaver code is up to you. See tips later on this page.
frmPreview is the form you create to fill in the Preview window on the Display Properties Dialog. Windows calls your program with /P and a number which is a handle to the Preview window. Code for this form needs to detect the message Windows sends to close down your preview. This example form has a Timer control which loads images into a Picture control to simulate the Screen Saver in miniature.
Private Sub Form_Load()
On Error GoTo frmPreview_Load_err
Dim rectPreview As RECT
Dim hwndParent As Long
hwndParent = CLng(Right(Command, Len(Command) - 3)) ' window handle
x = GetWindowRect(hwndParent, rectPreview)
Picture1.Move 0, 0, (rectPreview.Right - rectPreview.Left) * Screen.TwipsPerPixelX, (rectPreview.Bottom - rectPreview.Top) * Screen.TwipsPerPixelY
oldParent = SetParent(Picture1.hWnd, hwndParent)
gHW = Picture1.hwnd
gHWF = Me.hwnd
Hook ' receive Windows messages so Window can close
Timer1.Enabled=True
frmPreview_Load_exit:
Exit Sub
frmPreview_Load_err:
MsgBox CStr(Err) & " " & Error$
Resume frmPreview_Load_exit
End Sub
Private Sub Timer1_Timer()
DoEvents
If gKillMe Then End ' received Windows close message
' ... code to update Picture1 with your screen saver preview
End Sub
These routines must be in a code module, not attached to the form, in order for "AddressOf" to work:
' Next three routines are used to hook Windows messages for frmPreview:
Public Sub Hook()
lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
AddressOf WindowProc)
End Sub
Public Sub Unhook()
Dim temp As Long
temp = SetWindowLong(gHW, GWL_WNDPROC, _
lpPrevWndProc)
End Sub
Sub WindowProc(ByVal hw As Long, ByVal umsg As Long, ByVal wp As Long, ByVal lp As Long)
Dim x As Long
If umsg = WM_CLOSE Then
Unhook
DoEvents
x = SetParent(gHW, gHWF)
DoEvents
gKillMe = True
Else
x = CallWindowProc(lpPrevWndProc, hw, umsg, wp, lp)
End If
End Sub
frmPassword should be a dialog to set the Windows Screen Saver password.
The following information about password handling is adapted from Microsoft's Knowledge Base Article ID: Q182382
The dialog box is displayed when the Screen Saver is started with a "/a <HWND>" argument, where <HWND> is an unsigned decimal number representing the HWND of the owner window of the password dialog box.
If no HWND is passed in the Password Change dialog box, the foreground window should own the Password Change dialog box.
When the Screen Saver runs it should check the HKEY_CURRENT_USER/ REGSTR_PATH_SCREENSAVE/REGSTR_VALUE_USESCRPASSWORD (REGSTR_PATH_SCREENSAVE and REGSTR_VALUE_USESCRPASSWORD can be found in regstr.h) registry key if it needs to use the Screen Saver's password protection.
If the Screen Saver does need to use its password protection, it needs to prevent the user from switching to other applications without giving the password. To do this the Screen Saver needs to call:
Dim nPreviousState
x = SystemParametersInfo(SPI_SCREENSAVERRUNNING, True, nPreviousState, 0)
This prevents the user from using ALT+TAB to switch to another application or CTRL+ALT+DELETE to kill the Screen Saver.
When the user hits a key or moves the mouse, the Screen Saver confirms the password. If the password is validated, the Screen Saver calls the following to re-enable task switching:
Dim nPreviousState
x = SystemParametersInfo(SPI_SCREENSAVERRUNNING, False, nPreviousState, 0)
frmSetup should give the user access to any settings or parameters your program allows. It is also a good place to handle registration for shareware Screen Savers. Use the SaveSetting and GetSetting commands to access the Windows Registry.
Private Sub Form_Load()
' make mouse pointer invisible
Do
Loop Until ShowCursor(False) <-5 Width="Screen.Width:" Height="Screen.Height" ' setwindowpos topmost X="SetWindowPos(hwnd," HWND_TOPMOST, 0, 0, 0, 0, 0) Call GrabScreen timer1.Enabled="True" End Sub Sub GrabScreen() DoEvents picSnag.Width="Screen.Width:" picSnag.Height="Screen.Height" picSnag.Cls hwndSrc%="GetDesktopWindow()" hSrcDC&="GetDC(hwndSrc%)" ' BitBlt requires coordinates in pixels. hDestDC&="picSnag.hdc" dwRop&="SRCCOPY" w%="Screen.Width" / Screen.TwipsPerPixelX : h%="Screen.Height" / Screen.TwipsPerPixelY Suc%="BitBlt(hDestDC&," 0, 0, w%, _ h%, hSrcDC&, 0, 0, dwRop&) Dmy%="ReleaseDC(hwndSrc%," hSrcDC&) Me.Picture="picSnag.Image" End Sub
For GrabScreen to work, you need a PictureBox control called picSnag on your form with the following properties:
Autoredraw=True
Scalemode=3 - Pixel
Visible=False