#スクリーンセーバの動作を抑止したい
会社のスクリーンセーバの設定時間が短くなり、電話応対時などにいちいち解除するのがうっとうしかったので、マウスを自動的にぷるぷる動かしてスクリーンセーバの動作を抑止するアプリを作ります。言語はC#で、タスクトレイ常駐型にします。
#作り方
##タスクトレイ常駐型にする
###フォームが起動しないように、 Application.Runメソッドの引数にFormを渡さないようにする。
using System;
using System.Windows.Forms;
namespace ScreensaverDeter
{
static class ScreensaverDeter
{
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// フォームを表示しない
new ScreensaverDeterForm();
Application.Run();
}
}
}
###Formに「NotifiIcon」を追加して、Iconプロパティに適当な画像を設定する
##ホットキーで開始/停止を制御する
「CTRL + SHIT + S」で開始、「CTRL + SHIT + D」で停止する。
###user32.dllを読み込んで、ホットキーの登録、解除用メソッドを設定する
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ScreensaverDeter
{
public partial class ScreensaverDeterForm : Form
{
// ホットキー関連の定数
// モディファイアキー
const int MOD_ALT = 0x0001;
const int MOD_CONTROL = 0x0002;
const int MOD_SHIFT = 0x0004;
const int MOD_WIN = 0x0008;
// ホットキーのイベントを示すメッセージID
const int WM_HOTKEY = 0x0312;
// ホットキー登録の際に指定するID
// 0x0000〜0xbfff 内の適当な値を指定
const int APP_START_HOTKEY_ID = 0x0001;
const int APP_STOP_HOTKEY_ID = 0x0002;
// ホットキーの登録
[DllImport("user32.dll")]
extern static int RegisterHotKey(IntPtr HWnd, int ID, int MOD_KEY, int KEY);
// ホットキーの解除
[DllImport("user32.dll")]
extern static int UnregisterHotKey(IntPtr HWnd, int ID);
}
}
###コンストラクタで実際に登録する。他のアプリ等で既に登録済みの場合はアプリを終了する。
// 初期化処理
public ScreensaverDeterForm()
{
InitializeComponent();
// ホットキーの登録
// CTRL + SHIFT + S で機能開始
if (RegisterHotKey(this.Handle, APP_START_HOTKEY_ID, MOD_CONTROL | MOD_SHIFT, (int)Keys.S) == 0)
{
MessageBox.Show("「CTRL + SHIFT + S」をホットキーに登録できませんでした。");
appExit();
}
// CTRL + SHIFT + D で機能停止
if (RegisterHotKey(this.Handle, APP_STOP_HOTKEY_ID, MOD_CONTROL | MOD_SHIFT, (int)Keys.D) == 0)
{
MessageBox.Show("「CTRL + SHIFT + D」をホットキーに登録できませんでした。");
appExit();
}
}
###WndProcメソッドをオーバーライドして、対応するホットキーのメッセージを受け取ったら開始、停止用のメソッドを実行する
// OSから渡されるメッセージ処理をオーバーライド
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_HOTKEY)
{
if ((int)m.WParam == APP_START_HOTKEY_ID)
{
// 機能開始
autoMouseRunStart();
}
else if ((int)m.WParam == APP_STOP_HOTKEY_ID)
{
// 機能停止
autoMouseRunStop();
}
}
}
##マウスを自動的に動かす
現在のマウスポインタの位置を始点にして、左右にぷるぷる動かす。
Cursor.Positionだとスクリーンセーバを抑制できなかったので、SendInputを利用する。
###SendInputメソッドでマウスを制御するための設定をする
// マウスイベント関連の定数
const int MOUSEEVENTF_MOVED = 0x0001;
const int MOUSEEVENTF_ABSOLUTE = 0x8000;
const int screen_length = 0x10000;
// マウス操作を制御するためのMOUSEINPUT構造体
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
// SendInputメソッド用の構造体
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public int type;
public MOUSEINPUT mi;
}
// SendInputメソッドを宣言
[DllImport("user32.dll")]
extern static uint SendInput(
uint nInputs, // INPUT 構造体の数(イベント数)
INPUT[] pInputs, // INPUT 構造体
int cbSize // INPUT 構造体のサイズ
);
###機能開始、停止用のメソッドを実装する。停止用のホットキーメッセージを受信できるように、開始用メソッドは非同期にする。
// 機能の開始/停止を制御するフラグ
Boolean isAppRun= false;
// 機能開始
private async void autoMouseRunStart()
{
isAppRun= true;
// マウスポインタの位置を取得する
// X座標を取得する
int x = System.Windows.Forms.Cursor.Position.X * (65535 / Screen.PrimaryScreen.Bounds.Width);
// Y座標を取得する
int y = System.Windows.Forms.Cursor.Position.Y * (65535 / Screen.PrimaryScreen.Bounds.Height);
// マウス操作イベントの作成
INPUT[] input = new INPUT[2];
input[0].mi.dx = x;
input[0].mi.dy = y;
input[0].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE;
input[1].mi.dx = x + 80;
input[1].mi.dy = y;
input[1].mi.dwFlags = MOUSEEVENTF_MOVED | MOUSEEVENTF_ABSOLUTE;
await Task.Run(() =>
{
while (isAppRun)
{
// イベントの実行
SendInput(2, input, Marshal.SizeOf(input[0]));
}
});
}
// 機能停止
private void autoMouseRunStop()
{
isAppRun = false;
}
##アプリケーションの終了メニューを追加する
タスクトレイのアイコンを右クリックして、アプリを終了する。
###Formに「contextMenuStrip」を追加して終了メニューを作る
###「NotifyIcon」のContextMenuStripプロパティに、上記で作成したメニューを設定する。
###終了用のイベントを実装する。ホットキーを解除して、アイコンを非表示にして、終了する。
// 終了メニュー押下
private void AppExitToolStripMenuItem_Click(object sender, EventArgs e)
{
appExit();
}
// アプリケーションの終了
private void appExit()
{
// ホットキーの解除
UnregisterHotKey(this.Handle, APP_START_HOTKEY_ID);
UnregisterHotKey(this.Handle, APP_STOP_HOTKEY_ID);
// アプリ終了
notifyIcon.Visible = false;
Application.Exit();
}