[C#]すばやく画面を切り替える。

実家で暮らしていると、突然家族に自分の部屋のドアをあけられるかもわかりません。

そこで、ショートカットキーを使って、すばやくパソコンの画面を切り替えるプログラムを書いてみた。

ポイントとなるのは、バックグランドで起動させておき、いつでも反応させることと、音をミュートにしてしまうところ。
はじめはESCキー連打で切り替えを行おうかと思ってたけど、最終的に選んだのはSpaceキー+ESCキー同時押し。この組み合わせが押しやすかったので。
問題点は、キーフックを強制している画面(ゲームとか)だと利かないってところかな。

キーボードのグローバルフックとサウンドのMUTE操作は意外と面倒なのでネットで参照したライブラリを使用。
今回使用したShell32.dllとサウンドのAPIとグローバルキーフックのdllはほかにも何かに使えそう。
どうやって可能にしているかってのを押さえておくのは大事なことだけど、既存の組み合わせでコーディングが少ないのってやっぱりいいね。

開発環境
Windows7 Home Premium(64bit)
Visual Studio 2010 C#

作成方法

1.C#のWindowsフォームアプリケーションを新規作成する。
2.参照dllに次のものを追加する。

[サウンド操作用]
Vista Core Audio API Master Volume Control
http://www.codeproject.com/Articles/18520/Vista-Core-Audio-API-Master-Volume-Control
CoreAudioApi.dllを参照に追加。

[キーフック操作用]
Processing Global Mouse and Keyboard Hooks in C#
http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C
Gma.UserActivityMonitor.dllを参照に追加。

[デスクトップの表示用]
COM参照からMicrosoft Shell Controls And Automation(C:\Windows\SysWOW64\shell32.dll)を追加。

3.Formクラスのソースのusingに次を追加する。

using Shell32;
using Gma.UserActivityMonitor;
using CoreAudioApi;

4.Formクラスのプライベート変数として次のコードを追加する。

        // Spaceキー + Escapeキー の判定用
        bool _flag = false;

        // サウンドデバイス操作
        MMDevice _soundDev;

5.Formクラスのコンストラクタに次のコードを追加する。


            // サウンドデバイス操作用APIの初期化
            var devEnum = new MMDeviceEnumerator();
            _soundDev = devEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);

            // KeyDownイベントのグローバルフック処理追加
            HookManager.KeyDown += (s, e) =>
            {

                // Spaceの押下ON
                if (e.KeyCode == Keys.Space)
                {
                    // フラグON
                    _flag = true;
                }

                // Escapceの押下ON
                if (e.KeyCode == Keys.Escape)
                {
                    // Spaceが押下されている
                    if (_flag)
                    {
                        // デスクトップの表示・非表示の切り替え
                        var shell = new Shell();
                        shell.ToggleDesktop();

                        // サウンドをMUTE ON/OFFする
                        _soundDev.AudioEndpointVolume.Mute ^= true;
                    }
                }
            };

            // KeyUpイベントのグローバルフック処理追加
            // Spaceキーの押下が終了したときは何もしないように
            // フラグをOFFにする
            HookManager.KeyUp += (s, e) =>
            {
                // Escapceの押下解除
                if (e.KeyCode == Keys.Space)
                {
                    // フラグOFF
                    _flag = false;
                }
            };

            // 起動時はFormを非表示にする、ように見せる 
            this.ShowInTaskbar = false;
            this.WindowState = FormWindowState.Minimized;

6.ビルドの構成マネージャーを開き、プラットフォームを[Any CPU]に変更する。
(これをしないとShell32が動かない)

7.二重起動防止策として、Program.csに以下を追加する。

            // Mutexにより二重起動防止
            // "KeyHook"の部分は任意の文字列
            var mutex = new System.Threading.Mutex(false, "KeyHook");
            if (mutex.WaitOne(0, false) == false)
            {
                return;
            }

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new KeyHook());

            // Mutex開放
            mutex.ReleaseMutex();

8.ビルドして終了。
スタートアップにショートカットのコピーをおいておけば、起動時から反応してくれるから楽。なお、強制終了したい場合は、タスクマネージャーを開いて強制終了させるしかないけど。

今回作成したプロジェクトはこちら(自己責任で)
keyhook.zip