13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

マウスをぷるぷる動かしてスクリーンセーバを抑制するアプリ

Last updated at Posted at 2016-04-22

#スクリーンセーバの動作を抑止したい
会社のスクリーンセーバの設定時間が短くなり、電話応対時などにいちいち解除するのがうっとうしかったので、マウスを自動的にぷるぷる動かしてスクリーンセーバの動作を抑止するアプリを作ります。言語はC#で、タスクトレイ常駐型にします。

#作り方
##タスクトレイ常駐型にする

###フォームが起動しないように、 Application.Runメソッドの引数にFormを渡さないようにする。

C#
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プロパティに適当な画像を設定する
WS000004.JPG

##ホットキーで開始/停止を制御する
「CTRL + SHIT + S」で開始、「CTRL + SHIT + D」で停止する。

###user32.dllを読み込んで、ホットキーの登録、解除用メソッドを設定する

C#
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);
    }
}

###コンストラクタで実際に登録する。他のアプリ等で既に登録済みの場合はアプリを終了する。

C#
        // 初期化処理
        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メソッドをオーバーライドして、対応するホットキーのメッセージを受け取ったら開始、停止用のメソッドを実行する

C#
        // 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メソッドでマウスを制御するための設定をする

C#
        // マウスイベント関連の定数
        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 構造体のサイズ
        );

###機能開始、停止用のメソッドを実装する。停止用のホットキーメッセージを受信できるように、開始用メソッドは非同期にする。

C#
        // 機能の開始/停止を制御するフラグ
        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」を追加して終了メニューを作る
WS000000.JPG

###「NotifyIcon」のContextMenuStripプロパティに、上記で作成したメニューを設定する。
WS000005.JPG

###終了用のイベントを実装する。ホットキーを解除して、アイコンを非表示にして、終了する。

C#
        // 終了メニュー押下
        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();
        }

##完成品
https://github.com/ms-ogawara/ScreensaverDeter

13
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?