Tech Support > Microsoft Windows > Development Resources > Activating a screensaver with SystemParametersInfo after it's been disabled by setting Screensaver to (none) in the Display Properties Screensaver tab
Activating a screensaver with SystemParametersInfo after it's been disabled by setting Screensaver to (none) in the Display Properties Screensaver tab
Posted by Tina on September 8th, 2005


I'm having a problem re-activating a screensaver with the
SystemParametersInfo call when it's initally been disabled. If a
screensaver is set to (none) in the screensaver dialog tab, how will it
know which screensaver to set it to once a user makes a call to
SystemParametersInfo to activate it? Is there a way to specify which
screensaver to user at this point?

Things to note are that I don't have a problem when I initially
activate the screensaver and then deactivate with SystemParametersInfo
and then activate again. This seems fine, but doing it the other way
around dosen't allow me to reactivate the screensaver with the
appropriate call to SystemParametersInfo. Also, the call returns
correctly when I activate the screensaver with SystemParametersInfo
when it was deactivate with the screensaver dialog tab. Can anyone help
me out here? Thanks.

Posted by Lucian Wischik on September 8th, 2005


On 8 Sep 2005 09:54:23 -0700, "Tina" <mstinawu@gmail.com> wrote:
I don't know the answer to your question...

but the standard way to disable screensaver for the duration of your
app is to override WM_SYSCOMMAND/SC_SCREENSAVE. Just gobble up the
message. It's only when it gets passed to DefWindowProc that the saver
runs. This is the intended way for an app to stop the saver from
running.

--
Lucian


Posted by Alf P. Steinbach on September 8th, 2005


* Tina:
The system doesn't know, the call should fail unless it uses a default
screensaver. Of course I haven't looked at the documentation, I'm answering
just based on earlier experience with screensaver activation. I suggest you
take a look at the documentation (RTFM, as it's known), and try to
understand the difference between enable/disable and screensaver selection.


Yes, the system dialogs do not do anything magical, but the system doesn't
know what the earlier screensaver selection was.

You'll have to track that if that's your goal.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Posted by Tina on September 8th, 2005


I suppose I can find a "work around" to this problem by specifying what
screensaver to use after I reenable the screensaver. I notice that I am
able to set the time when it was deactivated but the screensaver
remains deactivated with whatever the timeout I set it to was. And yes,
I've read the documentation over and over already and it dosen't have
any remarks regarding enabling a screensaver when it was initially
disabled and returning it back to whatever orginal screensaver it was
supposed to be using.

Also, it's strange but the function dosen't fail when I try to enable
the screensaver with SystemParametersInfo when it was deactivated in
the screensaver dialog tab.

In any case, if I can use my workaround I'll be happy with it for the
time being. Is there a Windows function I can use to do that?

Posted by Alf P. Steinbach on September 8th, 2005


* Tina:
I'm sorry but I do not understand what it is you're trying to achieve.

As Lucian Wishik wrote, when the goal is to disable the screensaver while a
particular application is active, then

Otherwise, for global screensaver management, there is a way to
enable/disable, and there is a way to select a screensaver. Which can
de-activate by selecting "none". Here's some olde code for that:


// Indent = Tab = 4

//////////////////////////////////////////////////////////////////////////////
//
// Module ScreenSaverUtil
// implementation
//
// Free-standing functions for controlling and obtaining info about screensavers.
// Copyright (c) Alf P. Steinbach, 2002.
//
// This file is part of Alf's ScreenSaver Manager.
//
// Alf's ScreenSaver Manager is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// Alf's ScreenSaver Manager is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Alf's ScreenSaver Manager; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

#include "ScreenSaverUtil.h"



//-------------------------------------- Dependencies


#include <stdexcept> // std::runtime_error

#ifndef CPP_WINDOWS_H_
# include <win32/cpp_windows.h> // Wrapper for <windows.h>.
#endif

#ifndef KERNELUTIL_H_
# include <win32/KernelUtil.h> // IsWindow9x()
#endif

#ifndef _INC_SCRNSAVE
# include <scrnsave.h> // IDS_DESCRIPTION
#endif

#ifndef _INC_SHLWAPI
# include <shlwapi.h> // PathFindFileName()
#endif





//-------------------------------------- Implementation

namespace alfs { namespace windowing {


bool ScreenSaverIsEnabledFlag()
{
BOOL isEnabled = FALSE;

if( !::SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0, &isEnabled, 0 ) )
{
throw std::runtime_error( "Unable to find whether the screensaver is enabled" );
}
return !!isEnabled;
} // ScreenSaverIsEnabledFlag


bool ScreenSaverIsEnabled()
{
// In some Windows versions, or due to some faulty program, the ScreenSaverIsEnabledFlag()
// may be set even when there is no selected screensaver.
return (ScreenSaverIsEnabledFlag() && AScreenSaverIsSelected());
} // ScreenSaverIsEnabled


void SetScreenSaverIsEnabled( bool const newValue )
{
if( newValue == true && !AScreenSaverIsSelected() )
{
throw std::runtime_error( "Cannot enable the screensaver when none is selected" );
}

if( !::SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, newValue, NULL, SPIF_SENDCHANGE ) )
{
if( newValue == true )
{
throw std::runtime_error( "Unable to enable the screensaver" );
}
else
{
throw std::runtime_error( "Unable to disable the screensaver" );
}
}
} // SetScreenSaverIsEnabled


std::string const NameOfScreenSaver( char const ssPath[] )
{
// See KB article Q126239.
// "ssPath" is the "screen saver path", path to the screensaver executable.

HMODULE const moduleHandle = ::LoadLibraryEx( ssPath, NULL, LOAD_LIBRARY_AS_DATAFILE );

if( moduleHandle == 0 )
{
throw std::runtime_error( "Unable to find or load the screensaver" );
}

unsigned const maxNameLength = 25; // See <scrnsave.h>.
char name[maxNameLength + 1];

int const nChars = ::LoadString( moduleHandle, IDS_DESCRIPTION, name, sizeof( name ) );
::FreeLibrary( moduleHandle );
return (nChars == 0? ::PathFindFileName( ssPath ) : name );
} // NameOfScreenSaver


void StartEnabledScreenSaver()
{
// Ver. 0.5: Changed ::GetDesktopWindow() to HWND_TOPMOST, as per
// KB article Q262646, "How to Lock a Workstation from the Command Line".

// Ver. 0.51: Changed it back to ::GetDesktopWindow, 'cause the documented
// way didn't work!

:efWindowProc( ::GetDesktopWindow(), WM_SYSCOMMAND, SC_SCREENSAVE, 0 );
} // StartEnabledScreenSaver


static char const* GetSelectedScreenSaverNT( char pathBuffer[MAX_PATH+1] )
{
HKEY keyHandle = 0;

LONG const rokeResult = ::RegOpenKeyEx(
HKEY_CURRENT_USER,
"Control Panel\\Desktop",
0, // Options, reserved.
KEY_READ,
&keyHandle
);
if( rokeResult != ERROR_SUCCESS )
{
throw std::runtime_error(
"Unable to open registry key [HKEY_CURRENT_USER\\Control Panel\\Desktop]"
);
}
else
{
DWORD valueType = 0;
DWORD byteCount = MAX_PATH + 1;

pathBuffer[0] = '\0';
LONG const rqveResult = ::RegQueryValueEx(
keyHandle,
"SCRNSAVE.EXE",
0, // Reserved.
&valueType,
reinterpret_cast<LPBYTE>( reinterpret_cast<ULONG_PTR>( pathBuffer ) ),
&byteCount
);
::RegCloseKey( keyHandle );

if( rqveResult == ERROR_SUCCESS || rqveResult == ERROR_FILE_NOT_FOUND )
{
return pathBuffer;
}
else
{
throw std::runtime_error( "Unable to read screensaver path value from registry" );
}
}
} // GetSelectedScreenSaverNT


static char const* GetSelectedScreenSaver9x( char pathBuffer[MAX_PATH+1] )
{
// Windows 9x code.
//
// This actually also works on Windows NT, since GetPrivateProfileString is
// redirected to the registry for backwards compatibility with Windows 3.x.
//
// Mainly based on KB article Q193794 "The Previous Screen Saver Is Still Used
// After You Change It", which for Windows 95 and 98 states that "When you change
// a screen saver, the change is recorded in the System.ini file in the [Boot]
// section on the 'scrnsave.exe=' line".


// No documented meaningful error status from GetPrivateProfileString.
::GetPrivateProfileString(
"boot", // Section name.
"scrnsave.exe", // Key name.
"", // Default result.
pathBuffer,
MAX_PATH + 1,
alfs::FileSpec( win32::WindowsDirectoryPath(), "\\system.ini" ).ToString().c_str()
);
return pathBuffer;
} // GetSelectedScreenSaver9x


static inline char const* GetSelectedScreenSaver( char pathBuffer[MAX_PATH+1] )
{
// TODO: Make a real choice when IsWindows9x has been confirmed to work.
return (
true || alfs::win32::IsWindows9x()
? GetSelectedScreenSaver9x( pathBuffer )
: GetSelectedScreenSaverNT( pathBuffer )
);
} // GetSelectedScreenSaver


std::string const SelectedScreenSaver()
{
char pathBuffer[MAX_PATH + 1];

return GetSelectedScreenSaver( pathBuffer );
} // SelectedScreenSaver


bool AScreenSaverIsSelected()
{
char pathBuffer[MAX_PATH + 1];

// Equivalent to (SelectedScreenSaver().length() > 0), but more efficient.
return !!*GetSelectedScreenSaver( pathBuffer );
} // AScreenSaverIsSelected()


void ShowScreenSaverProperties()
{
// The following command is *UNDOCUMENTED*. The documented command is "control desktop".
// But the documented command doesn't give any way to select which page (tab) should be
// initially displayed. The following displays the screensaver page on Windows XP, unless
// the applet is already running, in which case it's activated with no change of current
// page. Hopefully this command works on other Windows versions, too...
//
// Partial doc of this command (the general scheme) can be found in KB article Q135068,
// "HOWTO: Start a Control Panel Applet in Windows 95 or Later".
//
// "control.exe" is unqualified in case it resides in the Windows directory on Windows 9x.
// The applet is used instead of just "desktop" because the latter ignores parameters.

win32::Start(
"control.exe " +
alfs::FileSpec( win32::SystemDirectoryPath(), "desk.cpl,@0,1" ).ToString()
);
} // ShowScreenSaverProperties

} } // namespace alfs::windowing

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


Similar Posts