2013年1月17日木曜日

Windowsのスクリーンセーバーの起動防止

いろいろ事情があってWindowsのスクリーンセーバーの設定が無効に出来ないことはあると思いますが、
それでもさらに事情があってスクリーンセーバーを起動させたくないこともあります。
そんなときにはアプリケーションをひとつ作って、
そのアプリケーションの中でスクリーンセーバー起動要求メッセージを遮断してしまえば実現できます。

Visual Studio 2012 Express for Windows Desktopをインストールし、
[ファイル]-[新しいプロジェクト]メニューから
[Visual C++]-[Win32]の[Win32 プロジェクト]を
"preventscreensaver"というプロジェクト名で標準状態で作成し、
"preventscreensaver.cpp"のWndProc()関数の
switch(message)ブロックのdefault句の直前に
case WM_SYSCOMMAND:
 if(wParam==SC_SCREENSAVE)
  return 1;
 if(wParam==SC_MONITORPOWER)
  return 1;
 return DefWindowProc(hWnd, message, wParam, lParam);
とでも追加してビルドすれば完成です。
出来上がった"preventscreensaver.exe"を実行しておけばスクリーンセーバーは立ち上がりません。

なお、スクリーンセーバーの設定で
Windows7なら[再起動時にログイン画面に戻る]が、
WindowsXPなら[パスワードによる保護]がチェックされているとこの手は通用しません。
そういう場合はマウスかキーボードからのダミー入力を定期的に発生してやればいいのです。
都合のいいことにマウスの入力イベントを発生させるmouse_event()APIは、
マウスポインタの移動を伴わず(相対移動量が0)にMOUSEEVENTF_MOVEイベントを発行できるので
先のプログラムに比較的簡単に機能追加できます。
つまり、グローバル変数に
UINT_PTR nTimer=0;
を追加して、関数のプロトタイプに
VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime);
を追加し、30秒間隔のイベント発生のためInitInstance()関数の終了直前で
nTimer=SetTimer(hWnd,nTimer,30000,TimerProc);
を実行し、_tWinMain()関数の終了直前に
KillTimer(msg.hwnd,nTimer);
を実行するようにしておいて、
ファイルの最後に
VOID CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
 mouse_event(MOUSEEVENTF_MOVE,0,0,0,0);
}
を追加すれば完成です。
ウィンドウが大きくて邪魔なので小さくしたいというなら、
InitInstance()関数内で呼び出しているCreateWindow()関数の第6,7引数が、
起動時のウィンドウサイズの横,縦のピクセル数になるので適当に調整すればいいでしょう。
ビルドして出来上がった"preventscreensaver.exe"を実行しておけば、
今度こそスクリーンセーバーは立ち上がりません。

せっかく作ったのでバイナリを公開したいところですが、
Expressバージョンでビルドしたものを一般公開していいのかどうか
(少なくとも太古の昔はだめだった)、
はっきりとわからないのでとりあえず公開は控えておきます。
使いたければ自分でビルドしてみてください。

0 件のコメント:

コメントを投稿