13. FAQ o Win API

Q> Как запустить(придушить) скринсэйвер
A>

How do I start, detect and stop screen savers ?

Starting
The method for starting a screen saver is simple, but surprising. You post your 
own window a message ! Post yourself the WM_SYSCOMMAND message with the 
SC_SCREENSAVE parameter :
   // Uses MFC CWnd::PostMessage
   PostMessage (WM_SYSCOMMAND, SC_SCREENSAVE);  

Detecting and Stopping
Stopping a screen saver is somewhat more complex. The Microsoft-documented way 
of doing this is to look for the special screen-saver desktop, enumerate all 
windows on that desktop, and close them, as follows:
   hdesk = OpenDesktop(TEXT("Screen-saver"),
                       0,
                       FALSE,
                       DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
   if (hdesk)
   {
      EnumDesktopWindows (hdesk, (WNDENUMPROC)KillScreenSaverFunc, 0);
      CloseDesktop (hdesk);
   }

   // ----------------------------------------------------------------

   BOOL CALLBACK KillScreenSaverFunc (HWND hwnd, LPARAM lParam)
   {
      PostMessage(hwnd, WM_CLOSE, 0, 0);
      return TRUE;
   }

However, I can't recommend this approach. I have found when using this code, NT4 
very occasionally seems to get confused and pass you back the normal desktop 
handle, in which case you end up trying to close all the normal application 
windows. Note, in MS' defence, that the code above for closing 32 bit savers is 
derived from a sample that is only marked as valid for NT3.51 - there is no 
mention of NT4 in the sample. Unfortunately, there is also nothing to indicate 
that it doesn't always work properly.
However, you can avoid this problem by taking advantage of the fact that all 
screen savers built using the MS standard lib file will have the same window 
class name. So if you change the above callback function code to read as follows 
:
   BOOL CALLBACK KillScreenSaverFunc (HWND hwnd, LPARAM lParam)
   {
      char szClass [32];
      GetClassName (hwnd, szClass, sizeof(szClass)-1);
      if (strcmpi (szClass, "WindowsScreenSaverClass") == 0)
         PostMessage (hwnd, WM_CLOSE, 0, 0);
      return TRUE;
   }

Then the code will only close the correct window when the OS returns the correct 
desktop handle, and won't do any damage on those rare occasions when the OS 
gives you the wrong handle.
Yet another alternative is now available, which depends upon new functionality 
in SystemParametersInfo :
   BOOL bSaver;
   if (::SystemParametersInfo (SPI_GETSCREENSAVEACTIVE,0,&bSaver,0))
   {
      if (bSaver)
      {
         ::PostMessage (::GetForegroundWindow(), WM_CLOSE, 0L, 0L);
      }
   }

So you can try that one as well. However I have found that under certain 
circumstances, GetForegroundWindow can return NULL, so this method might fail as 
well <sigh>.
    

2000(c) DM

Электронные Книги по компьютерным программам
На правах рекламы:
Логин
Пароль
Запомнить меня