Wednesday 21 December 2011

Disabling the screen saver

At some point in a programmers life, he or she must learn how to disable the screen saver through code. Earlier the way used to be to install a WH_GETMESSAGE windows hook and monitor the WM_SYSCOMMAND message. If the wParam of the message would be SC_SCREENSAVE, you would not let the message do anything by returning either 1 or 0 or any value(I don't remember exactly). But for Windows Vista and above, Microsoft says that the screen saver will be activated no matter what an application does to the SC_SCREENSAVE message.
That is where the problem rises now. A solution is that one can set a timer for his application using SetTimer() windows API function and then when the WM_TIMER message arrives after a specified time out, he can simulate a key press event on keyboard using keybd_event() windows API function. This way windows will continuously receive key press events after a specified time out and thus the screen saver will not be activated. A word of caution: you need to make sure that the time out specified in SetTimer() function should be less than 60 seconds ideally because the minimum time that can be set for screen saver under windows is 60 seconds.
Below is a program snippet that shows the window procedure function in which first the timer is set during dialog initialization, and WM_TIMER messages are processed.

BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_INITDIALOG:
            SetTimer(hwndDlg, 100, 45000, NULL);
            return TRUE;

        case WM_CLOSE:
            EndDialog(hwndDlg, 0);
            return TRUE;

        case WM_TIMER:
            //Simulate a key press
            keybd_event(VK_F16, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
            //Simulate a key release
            keybd_event(VK_F16, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
            return 0;
   
        case WM_COMMAND:
            ..........................
            ..........................
            ..........................

        return FALSE;
    }

When the window procedure first receives the WM_INITDIALOG message, the timer is set to 45000 millisecons(45 seconds). 100 passed as the second parameter is the timer ID and is used if more than one timer was used. Here it can be any value.
Inside the WM_TIMER case, I have first simulated a key press of a virtual F16 key. Then there is the simulation of a key release of the same key. Thus a simulation of a key press of F16 key takes place after every 45 sconds. This ensures that the screen saver is never activated.
For more information on SetTimer and keybd_event functions, see the following links:
SetTimer
keybd_event

Please update me if you find any errors or outdated information in this post.

No comments:

Post a Comment