Introduction
Since I work in a company, when I leave my desk I like to lock my computer, as a good security practice. I used to do this by typing the Windows+L key combination. But this brings up that ugly default dialog box. I'd much rather start the screensaver and have it configured so the machine will be blocked when the screensaver is interrupted.
The problem is: how to start the screensaver in a handy way? This utility, ScreenSaverNow, does this.
Background
My search for a utility to start the screensaver was not very successful. I wouldn't pay US$ 20 for a program just to do that. And I didn't want some memory-resident thing using resources and notification area space unnecessarily. So I decided to build my own program.
Finding instructions on how to do this was not so easy either. I couldn't find anything about this on the .NET Framework documentation. After wading through a lot of irrelevant search results, I found some Visual Basic 6 code to do it using the Windows API:
Declare Function GetDesktopWindow Lib "user32" () As Long
Public Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hWnd As Long, ByVal _
wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const WM_SYSCOMMAND As Long = &H112&
Public Const SC_SCREENSAVE As Long = &HF140&
Function gf_StartScreenSaver() As Boolean
Dim hWnd&
On Error Resume Next
hWnd& = GetDesktopWindow()
Call SendMessage(hWnd&, WM_SYSCOMMAND, SC_SCREENSAVE, 0&)
gf_StartScreenSaver = (Err.Number = 0)
End Function
Microsoft also has a sample in Visual Basic 6:
[general declarations]
#If Win32 Then
Private Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Const WM_SYSCOMMAND = &H112&
Const SC_SCREENSAVE = &HF140&
#Else
Private Declare Function SendMessage Lib "User" (ByVal _ hWnd
As Integer, ByVal wMsg As Integer, ByVal wParam As _ Integer,
lParam As Any) As Long
Const WM_SYSCOMMAND = &H112
Const SC_SCREENSAVE = &HF140&
#End If
Private Sub Command1_Click()
Dim result As Long
result = SendMessage(Form1.hWnd, WM_SYSCOMMAND, _
SC_SCREENSAVE, 0&)
End Sub
There was nothing for .NET. So I decided to convert these examples from Visual Basic 6 to Visual Basic .NET.
Using the code
This is the source code for ScreenSaverNow:
Public Class Main
Private Declare Function GetDesktopWindow Lib "user32" () As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As Integer, ByVal wMsg As Integer, _
ByVal wParam As Integer, ByRef lParam As Integer) As Integer
Const WM_SYSCOMMAND As Integer = &H112
Const SC_SCREENSAVE As Integer = &HF140
Private Shared Sub StartScreenSaver()
Dim hWnd As Integer
hWnd = GetDesktopWindow()
SendMessage(hWnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0)
End Sub
Public Shared Sub Main()
Try
StartScreenSaver()
Catch ex As Exception
MsgBox("Error: " & ex.Message)
End Try
End Sub
End Class
The two Declare
statements declare the Windows API functions that will be called. The two Const
statements are just predefined values that the API expects.
StartScreenSaver
is the main method. It uses the GetDesktopWindow
API function to get the handle for the Windows Desktop window. Then the WM_SYSCOMMAND
message is sent to that window with the SC_SCREENSAVE
parameter.
When Windows processes this message, it starts the default screensaver. If the screensaver is configured, in the Display Properties dialog box, for password protection, Windows will guarantee that the workstation will be locked when the screensaver is interrupted.
Finally, the Sub Main
just runs the main method.
Points of Interest
First of all, this information is not so easy to discover nowadays as we don't look up the Windows API so much anymore and we expect that the .NET Framework will encapsulate anything we want to do on the underlying Windows system. Not quite.
Second, this was a great exercise on how to leverage old-school Visual Basic API calling on a .NET project. I consider it a great thing that backward compatibility remains and that we can still use the Windows API if and when we need to.
References
History
Software developer with more than 20 years of experience in developing business applications. Currently working with Visual Basic .NET 2003.