Last Updated 2007/12/02
Programming Tips Windows スクリーンセーバー  索 引 
スクリーンセーバーの解除
2002/01/16

SetCursorPos() や mouse_event() などを使用する.
マウスの座標が同じ位置だと解除できない恐れあり.

また,以下の関数でも可能
(KB:Q140723)

void StopScreenSaver()
{
    OSVERSIONINFO osInfo;
    osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    ::GetVersionEx(&osInfo);

    if(osInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
    //Windows95
        HWND hWnd = ::FindWindow("WindowsScreenSaverClass",NULL);
        if(hWnd != NULL)
            ::PostMessage(hWnd,WM_CLOSE,0,0L);
    } else if(osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
    //WindowsNT
        HDESK hDesk;
        hDesk =:: OpenDesktop("Screen-saver", 0,
                    FALSE, DESKTOP_READOBJECTS |DESKTOP_WRITEOBJECTS);
        if(hDesk) {
            ::EnumDesktopWindows(hDesk, StopScreenSaverProc, 0);
            ::CloseDesktop(hDesk);
        }
    }
}

BOOL CALLBACK StopScreenSaverProc(HWND hWnd, LPARAM)
{
    ::PostMessage(hWnd, WM_CLOSE, 0, 0);
    ::SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, 0,
                                        SPIF_SENDWININICHANGE);
    return TRUE;
}

上記のコールバック関数ではスクリーンセーバーの起動回数が40回を超えるとスクリーンセーバーが起動しなくなってしまう.
以下のコールバック関数だと40回以上の起動でも問題はない.

BOOL CALLBACK StopScreenSaverProc(HWND hWnd, LPARAM lParam)
{
    static char szBuf[256];
    ::GetClassName(hWnd, szBuf, sizeof(szBuf));
    if(strcmp(szBuf, "WindowsScreenSaverClass")) {
        return TRUE;
    }
    ::PostMessage(hWnd, WM_CLOSE, 0, 0);
    ::SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, 0,
                                           SPIF_SENDWININICHANGE);
    return TRUE;
}


NT 系の OS の場合上記の方法でスクリーンセーバーが動作中か否か分かりません.
SystemParametersInfo() に SPI_GETSCREENSAVERRUNNING で動作中か否か取得出来ます.
その場合 SetCursorPos でしか解除の方法を知りません.
GetCursorPos にてカーソル位置を取得,SetCursorPos にて移動,そして元の位置へ戻せば問題ないでしょう.

あと NT 系の OS でも 95 系の方法を用い,フォアグラウンドウィンドウの実行ファイルの拡張子で判断すればいいみたいです.


参照
スクリーンセーバーの起動
クラス内コールバック関数
前後のTips
スクリーンセーバーの解除

DSS ProgrammingTipsCGI Ver2.01