##離席中でもWindowsをスリープさせたくない
体は離席しても、魂だけは在席してマウス操作しててほしい。
というわけで、プログラムでマウス操作させてみました。
##作ったアプリ
・カーソル移動 → スクロール → 待ち、を繰り返すアプリ
・それぞれの時間はランダム(配布版では「待ち」時間はもう少し長め)
・人がいなくても、人のぬくもりを感じるアプリになりました
##ソースコード
マウスをぷるぷる動かしてスクリーンセーバを抑制するアプリ を参考にさせていただきました。ありがとうございます。
上記ページのソースコードに、以下を追加しています。
(Wait, Move, Wheel のステート追加)
const int MOUSEEVENTF_WHEEL = 0x800;
INPUT[] mInput = new INPUT[1];
Stopwatch mStopwatch = new Stopwatch();
enum EState { Wait, Move, Wheel }
EState mState = EState.Wait;
Random mRandom = new Random();
int mTargetX = 0, mTargetY = 0;
private async void autoMouseRunStart()
{
isAppRun = true;
int screen_width = Screen.PrimaryScreen.Bounds.Width;
int screen_height = Screen.PrimaryScreen.Bounds.Height;
mStopwatch.Restart();
mInput[0].mi.dx = Cursor.Position.X * (65535 / screen_width);
mInput[0].mi.dy = Cursor.Position.Y * (65535 / screen_height);
mInput[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE;
// 開始時点でマウスがPrimaryScreenに無い場合、PrimaryScreenに強制移動させる
if (Cursor.Position.X > screen_width || Cursor.Position.Y > screen_height)
{
mInput[0].mi.dx = (screen_width / 2) * (65535 / screen_width);
mInput[0].mi.dy = (screen_height / 2) * (65535 / screen_height);
SendInput(1, mInput, Marshal.SizeOf(mInput[0]));
}
await Task.Run(() =>
{
while (isAppRun)
{
switch (mState)
{
case EState.Wait:
// 一定時間経過したら EState.Move に移行
if (mStopwatch.ElapsedMilliseconds > mWaitTime)
{
mState = EState.Move;
mMoveTime = mRandom.Next(1000, 3000); // 1~3秒でマウス移動
mTargetX = mRandom.Next(0, screen_width); // ランダムなX座標
mTargetY = mRandom.Next(0, screen_height); // ランダムなY座標
mInput[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE;
mStopwatch.Restart();
}
// 適当にスリープさせる
// さもないと、CPU100%で処理してしまう
System.Threading.Thread.Sleep(5);
break;
case EState.Move:
// 一定時間経過したら EState.Wheel に移行
if (mStopwatch.ElapsedMilliseconds > mMoveTime)
{
mState = EState.Wheel;
mWheelTime = mRandom.Next(100, 800); // 0.1~0.8秒でマウスホイール
mInput[0].mi.dwFlags = MOUSEEVENTF_WHEEL;
mInput[0].mi.mouseData = mRandom.Next(-1, 2);
mStopwatch.Restart();
}
// カーソルを目標に追従させる
mInput[0].mi.dx += (int)((mTargetX - Cursor.Position.X) * 0.07) * (65535 / screen_width);
mInput[0].mi.dy += (int)((mTargetY - Cursor.Position.Y) * 0.07) * (65535 / screen_height);
// 適当にスリープさせる
// さもないと、カーソル移動処理が実行されすぎて移動が速くなりすぎてしまう
System.Threading.Thread.Sleep(5);
break;
case EState.Wheel:
// 一定時間経過したら EState.Wait に移行
if (mStopwatch.ElapsedMilliseconds > mWheelTime)
{
mState = EState.Wait;
mWaitTime = mRandom.Next(10000, 30000); // 10~300秒でマウス停止
mInput[0].mi.dwFlags = 0;
mStopwatch.Restart();
}
// マウスホイールではスリープさせない
// スリープさせると滑らかなスクロールにならなかった
//System.Threading.Thread.Sleep(1);
break;
}
// イベントの実行
// Cursor.Position への代入や、SetCursorPos での座標セットではスリープ状態になってしまうので SendInput を使用
SendInput(1, mInput, Marshal.SizeOf(mInput[0]));
}
});
}
// 機能停止
private void autoMouseRunStop()
{
isAppRun = false;
mState = EState.Wait;
mTargetX = mTargetY = 0;
mWaitTime = mMoveTime = mWheelTime = 2000;
}
マウスホイール時に Thread.Sleep するとスクロールがガクガクしていました。
よって、EState.Wheel では Thread.Sleep していません。
CPU速度に依存するコードになっているので、高性能PCでは Thread.Sleep する必要があるかもしれません。
プロジェクトは以下にあります。
##アプリを使用してみる
- こちら の「Download SoulMouse.zip」からダウンロード
- zip を展開
- SoulMouse.exe を実行するとタスクトレイに登場(灰色矢印アイコン)
- 「CTRL + SHIT + S」で開始(カーソルが自動で動き出す)
- 「CTRL + SHIT + D」で停止
- タスクトレイのアイコンを右クリック「終了」でタスクトレイから削除
・よくPCスリープになってしまう人は是非
・テレワーク監視はスリープ時間チェックから行われることが多い
・Webカメラを定期送信するなどの本気の監視には対応できないですが
・いずれにせよ、用法・用量を守って正しくお使いください