The Screen SaverInitInstance() Method |
This page discusses the InitInstance() method of the screen saver's application class, and shows the code that needs to be inserted.
I've had enough! I want to go home
I want to see the previous page
InitInstance() is a method of the CWinApp class, and it gets executed when your screen saver starts execution. This method needs to examine the command line arguments, then cause the appropriate windows to be created and displayed.
The App Wizard generates a default InitInstance() body for you. One of the first steps you made was to delete most of the code from it.
Now display the InitInstance() method again, and make the changes that follow.
You should change the ‘SetRegistryKey’ call that gets automatically
generatedcall to use a name that is appropriate to you. The string you specify
is used as the company name in the registry key that your program will create
and use :
I just use my name ("Mindcaster").
The application name (
The ‘SetRegistryKey’ function lets you use the
‘GetProfileInt’, ‘GetProfileString’,
‘WriteProfileInt’ and ‘WriteProfileString’ functions
to retrieve and store registry values.
If you are going to use the proper registry API’s instead
(‘RegCreateKeyEx’, ‘RegSetValueEx’,
‘RegOpenKeyEx’, ‘RegQueryValueEx’ and
‘RegCloseKey’) then you can delete the ‘SetRegistryKey’
call, although you'll have to figure out how to do this yourself.
Replacement Code :
The rest of the code is inserted after the 'SetRegistryKey' call.
This code examines the first command line parameter, which tells your screen
saver what it should do. This will be :
For ‘/a’, ‘/p’ and ‘/c’, a window handle may
follow, in the form of a string containing an integer value. Sometimes a
space character separates the command from the handle, and sometimes it is
a colon character. The code below looks for either a space or a colon.
One of the examples I read mentioned that the command may have a hyphen ("-")
instead of a slash ("/") in front of the letter, or no character at all.
The code also caters for this, just in case.
Code :
If the first command line parameter is "/s", the screen saver should be run
in full-screen mode.
All that needs to be done is to create an instance of the full-screen window,
and call its ‘Create’ function.
If the first command line parameter is "/a", it is a request to display the
"change password" dialog box.
This code converts the string containing the window handle to its integer
value and recasts it as a window handle. It then dynamically links to the
standard password change dialog box, specifying the window handle to be the
parent window.
If no window handle was supplied, the current foreground window gets used
as the parent.
I suppose I could have used 'strtol' to get the window handle value instead
of doing it myself. Change the code if you want!
If the first command line parameter is "/p", it is a request to display the
preview window, i.e. the small screen that sits in the Control Panel "Display
Properties" screen saver window.
The code converts the string containing the window handle to an integer value,
then recasts it as a window handle. It then creates the preview window,
specifying the window handle as the parent.
If there is no window handle, the preview window is not shown.
Note that when running the Debug version to test the preview window, you
will need to specify a value (doesn’t matter what it is) in the command
line parameters. For example, "/p 1234". (Remember my bit of code that ignores
the parent window handle for the preview window in the Debug version?)
Once again, you can use 'strtol' instead to get the window handle value,
if you want to.
If the first command line parameter is "/c" or there are no command line
parameters, it is a request to display the configuration dialog box.
If a window handle is given, it is used as the parent window (Windows NT
does this).
If there is no window handle, but the "/c" command was given, use the current
foreground window as the parent window (Windows 95 does this).
If there were no command parameters, run the configuration dialog box with
no parent window.
Insert this code into ‘InitInstance’ :
Insert a new class method, 'DoConfig'. This method transfers values between
the registry and the configuration dialog box, and causes the configuration
dialog box to be displayed.
The code below includes examples of how you can transfer values between the
registry and the dialog box.
Remember to put a prototype for it into the header file.
That's it! The next page mentions the other bits and pieces that you need
to actually get the screen saver displaying something.
// Change the registry key under which our settings are stored.
SetRegistryKey(_T("Mindcaster"));
Examine the first command line parameter
char token[201] ;
for ( int i = 0 ; i < 200 && i < strlen(m_lpCmdLine) && m_lpCmdLine[i] != ' '
&& m_lpCmdLine[i] != ':' ; i++ )
token[i] = m_lpCmdLine[i] ;
token[i] = '\0' ;
Run the full-screen saver ("/s")
if ( !strcmpi(token,"/s") ||
!strcmpi(token,"-s") ||
!strcmpi(token,"s") )
{
// Run as screen saver
FullScreenWnd* pWnd = new FullScreenWnd;
pWnd->Create();
m_pMainWnd = pWnd;
return TRUE;
}
Display the ‘change password’ dialog box ("/a")
if ( !strcmpi(token,"/a") ||
!strcmpi(token,"-a") ||
!strcmpi(token,"a") )
{
int iHandle = 0 ;
if ( i < 200 && i < strlen(m_lpCmdLine) )
{
// skip spaces up to the number
for ( ;
i < 200 && i < strlen(m_lpCmdLine)
&& m_lpCmdLine[i] == ' ' ;
i++ ) ;
if ( i < 200 && i < strlen(m_lpCmdLine) )
{
for ( ;
i < 200 && i < strlen(m_lpCmdLine)
&& m_lpCmdLine[i] >= '0'
&& m_lpCmdLine[i] <= '9' ;
i++ )
iHandle = iHandle * 10 + m_lpCmdLine[i] - '0' ;
}
}
// display "standard" screensaver password change screen
HWND hParent = (iHandle == 0 ) ? ::GetForegroundWindow() : (HWND)iHandle ;
// Load dynamically, because Windows NT doesn't have this
HINSTANCE hMprDll = ::LoadLibrary("MPR.DLL") ;
if ( hMprDll != NULL )
{
// dynamic call of standard screen saver password change screen
typedef VOID (WINAPI *PWDCHANGEPASSWORDA)(LPSTR,HWND,UINT,UINT) ;
PWDCHANGEPASSWORDA PwdChangePasswordA =
(PWDCHANGEPASSWORDA)::GetProcAddress(hMprDll, "PwdChangePasswordA");
if ( PwdChangePasswordA != NULL )
PwdChangePasswordA("SCRSAVE", hParent, 0, 0 );
}
::FreeLibrary ( hMprDll ) ;
return TRUE ;
}
Display the preview window
if ( !strcmpi(token,"/p") ||
!strcmpi(token,"-p") ||
!strcmpi(token,"p") )
{
// display preview window
// get window handle
int iHandle = 0 ;
if ( i < 200 && i < strlen(m_lpCmdLine) )
{
// skip spaces up to the number
for ( ;
i < 200 && i < strlen(m_lpCmdLine)
&& m_lpCmdLine[i] == ' '
&& m_lpCmdLine[i] != ':' ;
i++ ) ;
if ( i < 200 && i < strlen(m_lpCmdLine) )
{
for ( ;
i < 200 && i < strlen(m_lpCmdLine)
&& m_lpCmdLine[i] >= '0'
&& m_lpCmdLine[i] <= '9' ; i++ )
iHandle = iHandle * 10 + m_lpCmdLine[i] - '0' ;
}
HWND hWnd = (HWND)iHandle ;
PreviewWnd * pWnd = new PreviewWnd ;
pWnd->Create(hWnd);
m_pMainWnd = pWnd;
return TRUE ;
}
return FALSE ;
}
Display the Configuration dialog box
if (!strcmpi(token,"/c") ||
!strcmpi(token,"-c") ||
!strcmpi(token,"c") )
{
// Run config with a parent window
// get window handle
int iHandle = 0 ;
if ( i < 200 && i < strlen(m_lpCmdLine) )
{
// skip spaces up to the number
for ( ;
i < 200 && i < strlen(m_lpCmdLine)
&& (m_lpCmdLine[i] == ' '
|| m_lpCmdLine[i] == ':') ;
i++ ) ;
if ( i < 200 && i < strlen(m_lpCmdLine) )
{
for ( ; i < 200 && i < strlen(m_lpCmdLine)
&& m_lpCmdLine[i] >= '0'
&& m_lpCmdLine[i] <= '9' ; i++ )
iHandle = iHandle * 10 + m_lpCmdLine[i] - '0' ;
}
}
HWND hWnd ;
CWnd * pParent = NULL ;
if ( iHandle > 0 )
{
hWnd = (HWND)iHandle ;
pParent = CWnd::FromHandle(hWnd) ;
}
else
pParent = CWnd::GetForegroundWindow() ;
DoConfig(pParent) ;
}
else
{
// Run the config dlg with no parent (probably called from Explorer)
DoConfig(NULL);
}
void CSaverApp::DoConfig(CWnd* pParent)
{
CCfgDialog dlg(pParent);
// Set up the current params
dlg.m_CheckSounds =
( GetProfileInt("Config","Sounds",0) == 0 ) ? FALSE : TRUE ;
dlg.m_EditMaxNum = GetProfileInt("Config" , "Maximum Sprites" , 8 ) ;
// Do the dialog
if (dlg.DoModal() != IDOK)
return;
// Save the new params
WriteProfileInt("Config","Sounds", dlg.m_CheckSounds ? 1 : 0 );
WriteProfileInt("Config","Maximum Sprites", dlg.m_EditMaxNum ) ;
}