© 1996-1999 Lucian Wishcik
Main execution of application - ScrExecute - ScrExecuteEx - ScrPrefs
Screensaver window - Scr Timers - Recieving change messages - General settings - Active config - Verify password - Dialog start/stop - DefScreenSaverProc
Configuration dialog - Execution of config dialog - Monitor class - Sending change messages - Context help - About Scrplus
This reference will be of interest to you if you are trying to achieve something not covered in the tutorial. It will also be of interest if you wish to create an encapsulation of Scrplus in whichever framework you like to use.
If you are writing an encapsulation of Scrplus for some framework, then you would probably place a call to one of these functions in your main Application::Run method.
typedef LRESULT (CALLBACK SCREENSAVERPROC) (HWND hWnd,UINT msg,WPARAM,LPARAM); typedef BOOL (CALLBACK SCREENSAVERCONFIGUREDIALOG) (HWND hDlg,UINT msg,WPARAM,LPARAM); typedef BOOL (CALLBACK REGISTERDIALOGCLASSES) (HANDLE hInstance); typedef BOOL (CALLBACK SCREENSAVERCHANGEPASSWORD) (HWND hparent); extern "C" int WINAPI ScrExecute ( HINSTANCE hScreenSaverInstance, SCREENSAVERPROC *ScreenSaverProc, SCREENSAVERCONFIGUREDIALOG *ScreenSaverConfigureDialogProc=NULL, REGISTERDIALOGCLASSES *RegisterDialogClassesProc=NULL, SCREENSAVERCHANGEPASSWORD *ScreenSaverChangePasswordProc=NULL);
ScreenSaverProc is the window-procedure for your saver window. This procedure will be called both for preview windows and for full-screen windows. To tell within your ScreenSaverProc whether it is preview or full-screen, you can do GetParent(hwnd): if the parent is NULL, then it is running full screen; otherwise, not. Your screensaver window procedure should call DefScreenSaverProc instead of DefWindowProc. When your screensaver is created it will get a WM_INIT message (or is that a WM_CREATE?). As is conventional, a pointer to its CREATESTRUCT structure will be passed in lParam. The 'CREATESTRUCT.lParam' extra field will be one of the constants SCRCREATE_FULL, SCRCREATE_MAINPREVIEW, SCRCREATE_CONFIGPREVIEW.
ScreenSaverConfigureDialogProc is the dialog-procedure for your own 'options' page in the configuration dialog. If you leave this NULL, then only the first 'general' page will be present. RegisterDialogClassProc gives you a chance to register classes required for your dialog. It's return value is ignored.
ScreenSaverChangePasswordProc is in case you want to provide your own password technology. It's return value is currently ignored. If you leave this NULL, then the default Master Password Router will be used. If you do not leave it null, and you do want to implement your own password stuff, then you should also provide a response to the message SCRM_VERIFYPW that will be sent to your saver window.
#define ICON_APP 100 #define DLG_SCRNSAVECONFIGURE 2003 #define DLG_ABOUT 2004You must provide your resources with these identifiers. ICON_APP will be used as the icon for your properties dialog, and for alt-tabbing. DLG_SCRNSAVECONFIGURE will be used for your 'options' page in the properties dialog. DLG_ABOUT, if supplied, will be the dialog that comes in response to 'About' from the system menu.
The limitations of ScrExecute are as follows.
typedef HWND (CALLBACK LUCREATESAVER) (BOOL ispreview,CREATESTRUCT &); typedef int (CALLBACK LUCONFIG) (HWND hParent,CONFIGSHEETHEADER &, BOOL isactive); typedef int (CALLBACK LUABOUT) (HWND hparent); typedef int (CALLBACK LUCHANGEPASSWORD) (HWND hParent); extern "C" int WINAPI ScrExecuteEx(HINSTANCE hScreenSaverInstance, LUCREATESAVER *LuCreateSaverProc, LUCONFIG *LuConfigProc=NULL, LUABOUT *LuAboutProc=NULL, LUCHANGEPASSWORD *LuChangePasswordProc=NULL);
LuCreateSaverProc is the routine to create your saver window. It should return the HWND of the saver immediately the saver is executed. It's first parameter, ispreview, says whether or not the window will be a preview window. You may wish to use this to create different sorts of window for preview vs. full-screen. The CREATESTRUCT provides recommended parameters for your creation of the window. In particular, CREATESTRUCT.lParam will be one of SCRCREATE_FULL, SCRCREATE_MAINPREVIEW, SCR_CONFIGPREVIEW. You should make sure that your saver-proc will use DefScreenSaverProc as its default.
LuConfigProc is the routine to execute your config dialog. This should be a modal dialog, and you should not return until it is done. You should return the return value of that execution. Its second parameter is a CONFIGSHEETHEADER. This is really a PROPSHEETHEADER in disguise, and you can treat it like a PROPSHEETHEADER. But property sheets only came in with the new win32 headers, so if you're stuck with the old header files then you can't really use this argument. It contains suggested values for the configuration dialog. The PROPSHEETHEADER itself contains default values for the property sheet. It points to an array of two property-page structures. The first one has been filled in with suggested defaults for the general page. If you want just one extra page, you might as well use the space in this array. If you want more, you will have to create a larger array and copy stuff into it. You may decide simply to ignore the PROPSHEETHEADER and do your own totally different properties dialog from scratch. If you leave this argument to ScrExecuteEx NULL, or if you have it return the result DLGCODE_DOSCRDEFAULT, then the default behaviour will occur (which is a property-sheet with just a single 'general' tab).
LuAbout is the routine to execute your about dialog. If you did choose to use the suggested property sheet, and if you have not disabled the about feature using ScrPrefs, then it is this procedure that will be called for you to execute your own about box. You should create a modal box, and your LuAbout procedure should not return until the about box is done. It should return the result code. If you return the result DLGCODE_DOSCRDEFAULT, or if the LuAbout argument is NULL, then the standard About-Scrplus dialog box will be used.
LuChangePassword is the routine that will be executed when the user clicks on 'change password' from the main display properties configuration dialog. You should override this (and also respond to the message SCRM_VERIFYPW to your screen saver window) if you intend to provide your own password validation techniques. If you leave this NULL, or if you return the result DLGCODE_DOSCRDEFAULT, then the default behaviour will occur which is to use the Master Password Router.
You should include an icon with resource ICON_APP. This will be the one suggested by the PROPSHEETHEADER struct, and it will also be the one that will be used for alt-tabbing.
TScrPrefs *p=ScrCreatePrefs(); p->AllowActiveConfig=true; ScrSetPrefs(p);Note that ScrCreatePrefs allocates a bit of memory, and ScrSetPrefs deallocates that memory. If you failed to either delete it or call ScrSetPrefs you would end up with a memory leak. If you did not wish to change the preferences, then you could have ignored this section altogether.
The TScrPrefs structure is as follows.
Only a single ScrTimer can be associated with a saver window. There are two calls to start and stop this timer.
extern "C" void WINAPI ScrStartTimer(HWND); extern "C" void WINAPI ScrStopTimer (HWND);Normally you don't have to worry about either.
ScrStartTimer is automatically called after WM_CREATE has been processed. So, the timer turns itself on automatically. But if you had turned it off (either with ScrStopTimer, or by returning a period of INFINITE to the SCRM_TIMER message), then you can use ScrStartTimer to restart it. It doesn't do any harm to have it called even when it is already on.
ScrStopTimer is automatically called when a screensaver window is destroyed. You can call it yourself at any time: it will do no harm to be called if has already been stopped.
SCRM_TIMER is sent to your saver window periodically. If you wish to use the SCRM_TIMER mechanism, then you should return the period (in milliseconds) that you expect between SCRM_TIMER messages. If the CPU is heavily loaded then it might not be able to do these as fast as you request. The values you can return are as follows.
When a change message comes, an additional SCRM_TIMER message gets sent to your saver window. This is in case something in the configuraton dialog changed the length of time you expect to wait between SCRM_TIMERs, so you have a chance to change it. For instance, you might have a config. option called 'flat out': if checked, then your SCRM_TIMER would return the number 1; if unchecked, then it would return 50, say.
SCRM_CHANGE Code = (wParam & SCRCHANGE_GETCODE); From = (wParam & SCRCHANGE_GETFROM); To = (wParam & SCRCHANGE_GETTO); meaning of lParam depends on 'code'
The meanings of the components are as follows.
See the section General settings below for a discussion of the code SCRCHANGE_GENERAL.
Remember that, after there has been an SCRM_CHANGE message, a SCRM_TIMER message will be sent.
You can also get a copy of the current general settings at any time by using the following command.
extern "C" void WINAPI ScrGetGeneralSettings(TScrGeneralSettings *); // This is how you'd use it: TScrGeneralSettings sgs; ScrGetGeneralSettings(&sgs);
You should return TRUE if you handle this message.
You might want to respond to this to provide your own password technology. If you respond to this message, you should return the true if they got the password correct, and false otherwise.
Be sure to pass the SCRM_DIALOG message on to DefScreenSaverProc. This is very improtant.
For instance, the following suggests how you might handle the message for a ModeX screensaver:
It's first feature is it's icon and title. You must supply both, with the constants
#define ICON_APP 100 #define STR_SETTINGSDLGTITLE 3501If you omit an icon, it will default to the Scrplus icon. if you omit a settings dialog title, it will default to "Screen Saver properties".
If you used ScrExecute, then the window hierarchy goes
Secret Scrplus window --> Property sheet --> Your options page --> General options pageIf you used ScrExecuteEx or ScrExecuteWin, then your Config routine is excecuted with the secret Scrplus window passed as its parent. So the secret window will always be present (but invisible).
The following code obtains information from the secret Scrplus window.
TScrDialgoInfo *di=(*TScrDialogInfo *)GetWindowLong(hparwnd,GWL_USERDATA); bool isactive=di->IsAnActiveDialog;You might use something like this at the start of your LuConfigProc, to tell whether you were being asked to execute an active config dialog or a regular one. You could put the hook in here to execute different sorts of config dialog for full screen vs. control panel. (For instance, the active-config could be smaller so you could see less of the screen).
The secret Scrplus window is also the thing that routes the SCRM_CHANGE messages from your dialog to your screensaver windows, be they full-screen windows or preview windows. more on this in the section Sending change messages below.
The monitor has classname
#define MonitorClassName "ScrplusMonitorClass"It can be used for three things:
The style MS_PREVIEW identifies it as a window to whom SCRM_CHANGE messages will be sent if they had SCRCHANGE_TOPREVIEW. What happens is that the monitor creates a child window inside it, whose size is exactly that of the screen of the monitor and whose background is the colour of the desktop. Preview windows get created as children of this.
If you want to create a preview window inside a monitor that has style MS_PREVIEW, you should use
extern "C" HWND WINAPI ScrCreatePreview(hMonitorWnd)where hMonitorWnd is the window handle of the monitor window.
TScrChangeRouter cr; cr.hsrcwnd=hPageWindow; cr.code = code | SCRCHANGE_FROMxxx | SCRCHANGE_TOxxx cr.lParam =The secret Scrplus window converts this TScrChangeRouter structure into something appropriate to pass on to saver windows.SendMessage(hSecretScrplusWindow,SCRM_CHANGE,0,(LPARAM)&cr);
b>cr.hsrcwnd is the 'source' of the message. If you are using a property sheet, then hsrcwnd should be the handle of the property sheet. (Not the page you are currently on). If you just have a dialog on its own, then hsrcwnd should be the handle of this dialog.
If you specified SCRCHANGE_TOPREVIEW or SCRCHANGE_TOBOTH, and if you have not set to true the prefs flag DisablePreviewBroadcast, then the secret Scrplus window will start at hsrcwnd and will recursively search out all monitor children that have the style MS_PREVIEW. When it finds one with a saver window in it, it sends it the message.
extern "C" void WINAPI ScrHelp(HWND,DWORD helpcommand,DWORD helptopic);
hwnd should be the handle of the control for which you want context help. helpcommand should be one of HELP_CONTEXT_MENU or HELP_WM_HELP. helptopic should be one from the list of standard help topics, listed below.
If you wanted to find the current version of Scrplus, perhaps to put inside a field in your own about dialog, use the following command.
extern "C" int WINAPI ScrGetVersionString(char *destbuff,int maxlen);This will copy no more than maxlen characters into the buffer, and that includes the terminating NULL which it always sends. If you called it with destbuff NULL, then it will return the number of characters in the version string.