スクリーンセーバー起動の回避 の履歴(No.2)
更新スクリーンセーバー起動の回避†
長時間ユーザーの入力なしに画面表示を行うことを目的としたアプリケーション、 例えばスライドショーソフト、ビデオ再生ソフト、ゲームパッドのみを用いる ゲームソフト、計器の状態を表示し続ける測定ソフトなどでは、その動作中に スクリーンセーバーが起動してしまうと不都合な場合がある。
これを回避するための方法をインターネット上で探すと
http://d.hatena.ne.jp/NyaRuRu/20080925/p1
- SetThreadExecutionState を使う
- WM_SYSCOMMAND メッセージを補足する(フォアグランドアプリケーションのみ可能)
- SetCursorPos でカーソル位置を移動させる
- ・・・
などなどいろいろ記述が見つかるが、
- Windows Vista
- 再開時にパスワードが必要
の条件が重なるとなかなかうまく行かない。
解決法†
探し回ったあげく、ここにあった方法はそれなりの効果があった。
以下の関数を定期的に(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
改善案†
手元で試した限り、マウスカーソルを動かさなくても ダミーのインプット(実際にはカーソルを動かさない) を送り続けている限りスクリーンセーバーの起動は 阻止できるみたいだった。
これならカーソルが勝手に動くこともないので使いやすそう。
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); }
コメント†
Counter: 25020 (from 2010/06/03),
today: 2,
yesterday: 2