Вопрос

I am trying to create windows screensaver that turns monitor on and off depending on face detection. Here is the esential code (c++ and winapi):

#define TIMER 1010
unsigned int FREQUENCY_OF_CHECK = 5000;
LRESULT WINAPI ScreenSaverProc(
     HWND hwnd, 
     UINT message, 
     WPARAM wParam, 
     LPARAM lParam)
{
  if(!fChildPreview)
  {
    switch(message) 
    {
      case WM_CREATE:
        //start timer
        SetTimer(hwnd, TIMER, FREQUENCY_OF_CHECK, NULL);
        //create transparent see thru layer
        SetWindowLong(
               hwnd, 
               GWL_EXSTYLE, 
               GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED
               );
        break;

      case WM_DESTROY:
        SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1);
        KillTimer(hwnd, TIMER);
        break;

      case WM_TIMER:
        //separate process detects face and stores detection into registry
        if(!ProcessRunning("capture.exe")){
            ShellExecute(
               NULL,
               "open",
               "C:/camsaver/capture.exe",
               "",
               "", 
               SW_SHOWNOACTIVATE);
        }
        //load detection from registry and then turn monitor on/off
        bool face;
        readFaceFromRegistry(face);

        if (face){
            //turn monitor on
            SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1);
        }
        else {
            //turn monitor off
            SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2);
        }

        break;

      default:
        return DefScreenSaverProc(hwnd, message, wParam, lParam);
      }
    return 0;
  }
}

If the screensaver runs by itself when it doesnt detect face it just turns off the monitor and stops doing anything else.
I'd like it to continue running and turn the screen back on when there is a face detected. Like it does when run in preview mode.
My guess is that the line SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2); does something more than I am aware of.

Это было полезно?

Решение

So apparently in Win7 the SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2); not only turns off screen but also shuts down the screensaver (without even bothering sending it at least a destoy message first). There is no simple way to hack this.
Reference: I found this and it also leads to some other threads at msdn. (Which I cannot link right now due to my reputation...)

And while I am at it the above code won't work for Win8 either because SendMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1); doesn't turn on screen in Win8. However this should be easy to solve as in this C# workaround.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top