スクリーンセーバー起動の回避 の履歴(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: 27431 (from 2010/06/03),
today: 7,
yesterday: 4