Running Screensaver from code

I can't seem to get the screensaver to run:

'Paste in a wider window to get decent formatting.
Private Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long)
Private 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

Sleep 1000
Debug.Print SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1&, 0&, 0&)
Debug.Print Err.LastDllError

The call to SystemParametersInfo returns 0, Err.LastDllError = 126
Why doesn't this work (like it should according to MSDN), or do you know any other way to start the screensaver from code?

Win95, VB6-SP3


Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Jeremy_DAuthor Commented:
Edited text of question.
TimCotteeHead of Software ServicesCommented:
The simple way is to shell the screensaver.

Shell "c:\windows\system32\sstext3d.scr"
Jeremy_DAuthor Commented:
> TimCottee: I considered this as a last option, but the plan is to run the normal (user selected) screensaver, so I first would have to get that, then locate the file (.scr files actually don't *need* to be in the windows or windows-system folder). All a bit obtrusive on the system when you consider there's a simple API to start the default screensaver. I really want this SystemInfoParameters call to work!
The Ultimate Tool Kit for Technolgy Solution Provi

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy for valuable how-to assets including sample agreements, checklists, flowcharts, and more!

here's some code I wrote, ooh, aboout an hour ago for just this thing (the reg class is nicked wholesale from VBAccelerator -

    Dim str As String
    Dim Reg As New cRegistry
    'Find Screensaver
    Reg.ClassKey = HKEY_CURRENT_USER
    Reg.SectionKey = "Control Panel\Desktop"
    Reg.ValueKey = "SCRNSAVE.EXE"
    Reg.ValueType = REG_SZ
    str = Reg.Value
    Shell str & " /s", vbNormalFocus


**the "/s" is the key.**

if you need it, here is the reg class (cRegistry) (it's been stripped and abused):

Option Explicit

' =========================================================
' Class:    cRegistry
' Author:   Steve McMahon
' Date  :   21 Feb 1997
' vbAccelerator - free, advanced source code for VB programmers.
' =========================================================

'Registry Specific Access Rights
Private Const KEY_QUERY_VALUE = &H1
Private Const KEY_SET_VALUE = &H2
Private Const KEY_CREATE_SUB_KEY = &H4
Private Const KEY_NOTIFY = &H10
Private Const KEY_CREATE_LINK = &H20
Private Const KEY_ALL_ACCESS = &H3F

'Open/Create Options

'Key creation/open disposition
Private Const REG_CREATED_NEW_KEY = &H1

'masks for the predefined standard access types
Private Const STANDARD_RIGHTS_ALL = &H1F0000

'Define severity codes
Private Const ERROR_SUCCESS = 0&
Private Const ERROR_INVALID_DATA = 13&
Private Const ERROR_MORE_DATA = 234 '  dderror
Private Const ERROR_NO_MORE_ITEMS = 259

'Registry Function Prototypes
Private Declare Function RegOpenKeyEx Lib "advapi32" Alias "RegOpenKeyExA" _
  (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, _
  ByVal samDesired As Long, phkResult As Long) As Long

Private Declare Function RegCloseKey Lib "advapi32" (ByVal hKey As Long) As Long

Private Declare Function RegQueryValueExStr Lib "advapi32" Alias "RegQueryValueExA" _
  (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
   ByRef lpType As Long, ByVal szData As String, ByRef lpcbData As Long) As Long
Private Declare Function RegQueryValueExLong Lib "advapi32" Alias "RegQueryValueExA" _
  (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
   ByRef lpType As Long, szData As Long, ByRef lpcbData As Long) As Long

' Other declares:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
Private Declare Function ExpandEnvironmentStrings Lib "kernel32" Alias "ExpandEnvironmentStringsA" (ByVal lpSrc As String, ByVal lpDst As String, ByVal nSize As Long) As Long

Public Enum ERegistryClassConstants
    HKEY_CLASSES_ROOT = &H80000000
    HKEY_CURRENT_USER = &H80000001
    HKEY_LOCAL_MACHINE = &H80000002
    HKEY_USERS = &H80000003
End Enum

Public Enum ERegistryValueTypes
'Predefined Value Types
    REG_NONE = (0)                         'No value type
    REG_SZ = (1)                           'Unicode nul terminated string
    REG_EXPAND_SZ = (2)                    'Unicode nul terminated string w/enviornment var
    REG_BINARY = (3)                       'Free form binary
    REG_DWORD = (4)                        '32-bit number
    REG_DWORD_LITTLE_ENDIAN = (4)          '32-bit number (same as REG_DWORD)
    REG_DWORD_BIG_ENDIAN = (5)             '32-bit number
    REG_LINK = (6)                         'Symbolic Link (unicode)
    REG_MULTI_SZ = (7)                     'Multiple Unicode strings
    REG_RESOURCE_LIST = (8)                'Resource list in the resource map
    REG_FULL_RESOURCE_DESCRIPTOR = (9)     'Resource list in the hardware description
End Enum

Private m_hClassKey As Long
Private m_sSectionKey As String
Private m_sValueKey As String
Private m_vValue As Variant
Private m_sSetValue As String
Private m_vDefault As Variant
Private m_eValueType As ERegistryValueTypes

Public Property Get Value() As Variant
Dim vValue As Variant
Dim cData As Long, sData As String, ordType As Long, e As Long
Dim hKey As Long

    e = RegOpenKeyEx(m_hClassKey, m_sSectionKey, 0, KEY_QUERY_VALUE, hKey)
    'ApiRaiseIf e

    e = RegQueryValueExLong(hKey, m_sValueKey, 0&, ordType, 0&, cData)
    If e And e <> ERROR_MORE_DATA Then
        Value = m_vDefault
        Exit Property
    End If
    m_eValueType = ordType

    sData = String$(cData - 1, 0)
    e = RegQueryValueExStr(hKey, m_sValueKey, 0&, _
                           ordType, sData, cData)
    vValue = sData
    Value = vValue
End Property

Public Property Get ValueType() As ERegistryValueTypes
    ValueType = m_eValueType
End Property
Public Property Let ValueType(ByVal eValueType As ERegistryValueTypes)
    m_eValueType = eValueType
End Property
Public Property Get ClassKey() As ERegistryClassConstants
    ClassKey = m_hClassKey
End Property
Public Property Let ClassKey( _
        ByVal eKey As ERegistryClassConstants _
    m_hClassKey = eKey
End Property
Public Property Get SectionKey() As String
    SectionKey = m_sSectionKey
End Property
Public Property Let SectionKey( _
        ByVal sSectionKey As String _
    m_sSectionKey = sSectionKey
End Property
Public Property Get ValueKey() As String
    ValueKey = m_sValueKey
End Property
Public Property Let ValueKey( _
        ByVal sValueKey As String _
    m_sValueKey = sValueKey
End Property

sorry, I completely forgot to explain what my code does... It look up the user-selected screensaver, and then runs it.

Jeremy_DAuthor Commented:
> Nutwiss: First of all, there's no [HKCU\Control Panel\Desktop\SCRNSAVE.EXE] key in my registry (might this be the reason it doesn't work?), but I do have a screensaver that is active. I have to distribute the app to over a 100 computers, so I can't rely on a registry value that might or might not be set.
Second, I still think it's overkill to read a registry-key and do a shell-command when there's an API available that, according to various examples on the net *and* the MSDN library *should* work OK.

Didn't anyone ever use this SystemParametersInfo call with the SPI_SCREENSAVEACTIVE flag? Did it work?

>First of all, there's no [HKCU\Control Panel\Desktop\SCRNSAVE.EXE] key in my registry

What?? that's the standard place!

(BTW there is no such thing as overkill, sledgehammers DO crack nuts :))
The SPI_SETSCREENSAVEACTIVE value only tells Windows to enable or disable the activation of the screensaver; it does not actually start the screensaver.

My old Win95 computer does not have the
HKCU\Control Panel\Desktop\SCRNSAVE.EXE
entry either.
Try this... run your code, then try pressing ctrl & alt & delete

If that doesn't work, then Erick37 is right, as that key combination is disabled when the screensaver is running.....

You'll have to use that long way of running the screensaver.
you're right, it's NT, sorry
The screen saver is stored in the system.ini file under the boot section and I can't find it in the registry anywhere. I have several screen saver settings under that key (delay till start, etc.) but not the screensaver itself. Once retrieved from the .ini file, it's a simple matter to use Shell to start it.
Give this a try:

Option Explicit
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&

Private Sub Command1_Click()
    Dim lRet As Long
    'Start the screensaver
    lRet = SendMessage(Me.hWnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0&)
End Sub

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Oh, yeah, duh, I knew that...I've used it before but completely forgot about it.

Looks like Erick37 got the points again!
Try declaring the lpvParam parameter as lpvParam As Any. Remove the ByVal for this parmeter.
Nope, if you had read the posts in this thread, you would have found that this API doesn't do what needs to be done AND that the correct answer has already been provided as a comment by Erick37.
lpvParam is already declared ByRef.

Jeremy, please reject t_b's proposed answer and grade my comment as answer.

The method I provided is the easiest way to start the ss as supported by the MS article:
Jeremy_DAuthor Commented:
t_buddy: lpvParam *is* declared ByRef and *is* declared As Any. Suggestions...? Maybe buy yourself some new glasses ;-)
Jeremy_DAuthor Commented:
Thanks Erick37. That was exactly the answer I was looking for. Best way to start your monday after a weekend of parties! Find the correct answer on EE.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.