スクリーンセーバー起動の回避 のバックアップソース(No.2)

更新

[[公開メモ]]

#contents

* スクリーンセーバー起動の回避 [#o8cb7cc4]

長時間ユーザーの入力なしに画面表示を行うことを目的としたアプリケーション、
例えばスライドショーソフト、ビデオ再生ソフト、ゲームパッドのみを用いる
ゲームソフト、計器の状態を表示し続ける測定ソフトなどでは、その動作中に
スクリーンセーバーが起動してしまうと不都合な場合がある。

これを回避するための方法をインターネット上で探すと~
http://d.hatena.ne.jp/NyaRuRu/20080925/p1

- SetThreadExecutionState を使う
- WM_SYSCOMMAND メッセージを補足する(フォアグランドアプリケーションのみ可能)
- SetCursorPos でカーソル位置を移動させる
- ・・・

などなどいろいろ記述が見つかるが、

- Windows Vista
- 再開時にパスワードが必要

の条件が重なるとなかなかうまく行かない。

* 解決法 [#fd875e32]

探し回ったあげく、ここにあった方法はそれなりの効果があった。

http://groups.google.com/group/microsoft.public.win32.programmer.kernel/browse_thread/thread/976caa9de9a5e359

以下の関数を定期的に(1分以下の間隔で)呼んでやることで
スクリーンセーバーは起動しない。

ただ、マウスカーソルが始終プルプル動くので、
フルスクリーンでマウスカーソルを消して実行しているような、
スライドショーやビデオ再生ソフトくらいでしか使えない?

 LANG:C#(linenumber)
 void PreventScreenSaverFromStarting()
 {
     Point pos = Cursor.Position;
     Cursor.Position = new Point(pos.X + 1, pos.Y + 1);
     if ( Cursor.Position == pos )
         Cursor.Position = new Point(0, 0);
 
     INPUT input = new INPUT();
     input.type = INPUT_MOUSE;
     input.mi = new MOUSEINPUT();
 
     input.mi.dwExtraInfo = IntPtr.Zero;
     // mouse co-ords: top left is (0,0), bottom right is (65535, 65535)
     // convert screen co-ord to mouse co-ords...
     Random ran = new Random();
     input.mi.dx = ran.Next(0, 2000);
     input.mi.dy = ran.Next(0, 3000);
     input.mi.time = 0;
     input.mi.mouseData = 0;
     input.mi.dwFlags = 0x0001 | 0x8000; // MOVE | ABSOLUTE
 
     int cbSize = Marshal.SizeOf(typeof(INPUT));
     uint r = SendInput(1, ref input, cbSize);
 }
 
 #region Win32 API
 [StructLayout(LayoutKind.Sequential)]
 struct MOUSEINPUT
 {
     public int dx;
     public int dy;
     public uint mouseData;
     public uint dwFlags;
     public uint time;
     public IntPtr dwExtraInfo;
 }
 const int INPUT_MOUSE = 0;
 
 [StructLayout(LayoutKind.Sequential)]
 struct KEYBDINPUT
 {
     ushort wVk;
     ushort wScan;
     uint dwFlags;
     uint time;
     IntPtr dwExtraInfo;
 }
 
 [StructLayout(LayoutKind.Sequential)]
 struct HARDWAREINPUT
 {
     uint uMsg;
     ushort wParamL;
     ushort wParamH;
 }
 
 [StructLayout(LayoutKind.Explicit)]
 struct INPUT
 {
     [FieldOffset(0)]
     public int type;
     [FieldOffset(4)] //*
     public MOUSEINPUT mi;
     [FieldOffset(4)] //*
     public KEYBDINPUT ki;
     [FieldOffset(4)] //*
     public HARDWAREINPUT hi;
 }
 
 [DllImport("user32.dll", SetLastError = true)]
 static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
 
 [FlagsAttribute]
 public enum EXECUTION_STATE: uint
 {
     ES_SYSTEM_REQUIRED = 0x00000001,
     ES_DISPLAY_REQUIRED = 0x00000002,
     // Legacy flag, should not be used.
     // ES_USER_PRESENT   = 0x00000004,
     ES_CONTINUOUS = 0x80000000,
 }
 
 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
 #endregion

* 改善案 [#p9cee7ab]

手元で試した限り、マウスカーソルを動かさなくても
ダミーのインプット(実際にはカーソルを動かさない)
を送り続けている限りスクリーンセーバーの起動は
阻止できるみたいだった。

これならカーソルが勝手に動くこともないので使いやすそう。

 LANG:C#(linenumber)
 void PreventScreenSaverFromStarting()
 {
     INPUT input = new INPUT();
     input.type = INPUT_MOUSE;
     input.mi = new MOUSEINPUT();
 
     input.mi.dwExtraInfo = IntPtr.Zero;
     input.mi.dx = 0;
     input.mi.dy = 0;
     input.mi.time = 0;
     input.mi.mouseData = 0;
     input.mi.dwFlags = 0x0001; // MOVE (RELATIVE)
     int cbSize = Marshal.SizeOf(typeof(INPUT));
     uint r = SendInput(1, ref input, cbSize);
 }

* コメント [#n7785aed]

#article_kcaptcha


Counter: 16945 (from 2010/06/03), today: 1, yesterday: 0