RPAExpress徹底解析(1) -マウス操作- 補助ツール作成

# 補助ツールの作成
RPAExpressのマウス操作にバグ(?)があるっぽいので、マウス操作のプログラムを自作してみました。
他のツールも色々探してみましたが、コマンドで叩けるツールが無かったので、作ってみました。
RPAExpressでの仕様に特化したマウス操作ツールとなります。


# 開発環境
Microsoft Visual C# 2010 Express

# 動作環境
windows 7 / 10

# プログラム名
rpac.exe

# 引数一覧
/l  : タスクリストの表示
/a  : アプリケーションのアクティブ化
/p  : マウスポジションの取得
/c  : 指定位置を左クリックする
/r  : 指定位置を右クリックする
/d  : 指定位置をダブルクリックする
/cc : 指定位置を左クリック→（少し待って）左クリックする
/cr : 指定位置を左クリック→（少し待って）右クリックする


# 使い方
私は、環境設定を行い、お気に入りショートカットコマンド[Win+R]から実行できるようにしております。
環境設定してる前提で説明します。

以下コマンドを利用して、コマンドを作成します。
1. 指定位置にマウスカーソルを置く。
2. [Win+R]→[rpac /p]を実行
3. クリックコマンドがクリップボードにコピーされております。
4. RPAExpressにて[Win+R]コマンドをキーボード入力を作成
5. RPAExpressにて[3で取得したコマンドを貼り付けた]コマンドをキーボード入力を作成
6. RPAExpressにて[Enter]コマンドをキーボード入力を作成

これでクリックは出来るはずです。
実行前後のタイマーがうまく処理できれば、使い勝手が良くなるかなと。

※環境設定をしない場合
Cドライブ直下にダウンロードした[rpac.exe]を配置してください。
2の[rpac /p]を[C:\rpac /p]を変更
5の[3で取得したコマンドを貼り付けた]を[C:\3で取得したコマンドを貼り付けた /p]を変更

Cドライブ直下以外にした場合、[C:\]を書き換えてください。


# 動画
前回行った操作をRPAExpressで似たような操作を行ってみます。
Excelの方眼紙を使って、実装してみます。
Excelだと微妙に使い勝手が悪かったんで、コマンドを追加しております。

コマンド実行時に、コマンドプロンプトが起動してしまい、クリック操作に邪魔になっておりました。
対策として、プロジェクト設定を「コマンドライン」から「フォームアプリケーション」に変更しております。
よって、コマンドラインからの実装に一部微妙になっております。
今後の課題ですな。

[YouTube(音無し)](https://youtu.be/YciAuPuqA9U)



# ソースコード
参照設定は必要ですが、このまま動くはずです。

```ruby:qiita.rb
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;


namespace rpac
{
    class Program
    {

        // マウスクリック用の定数
        private const int MOUSEEVENTF_LEFTDOWN = 0x2;
        private const int MOUSEEVENTF_LEFTUP = 0x4;
        private const int MOUSEEVENTF_RIGHTDOWN = 0x8;
        private const int MOUSEEVENTF_RIGHTUP = 0x10;

        // コールバックメソッドのデリゲート
        private delegate int EnumerateWindowsCallback(IntPtr hWnd, int lParam);

        // APIの定義
        #region Win32API
        // マウスカーソルセット用の宣言
        [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)]
        static extern void SetCursorPos(int X, int Y);

        // マウスクリック用の宣言
        [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)]
        static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        // EnumWindows API関数の宣言
        [DllImport("user32.dll", EntryPoint = "EnumWindows")]
        private static extern int EnumWindows(EnumerateWindowsCallback lpEnumFunc, int lParam);

        // GetWindowText API関数の宣言
        [DllImport("user32.dll", EntryPoint = "GetWindowText", CharSet = CharSet.Auto)]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        // IsWindowVisible API関数の宣言
        [DllImport("user32.dll", EntryPoint = "IsWindowVisible")]
        private static extern int IsWindowVisible(IntPtr hWnd);
        #endregion


        [STAThreadAttribute]
        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0)
                {
                    StringBuilder s_help = new StringBuilder();
                    s_help.AppendLine("/l : タスクリストの表示");
                    s_help.AppendLine("/a : アプリケーションのアクティブ化");
                    s_help.AppendLine("/p : マウスポジションの取得");
                    s_help.AppendLine("/c : 指定位置を左クリックする");
                    s_help.AppendLine("/r : 指定位置を右クリックする");
                    s_help.AppendLine("/d : 指定位置をダブルクリックする");
                    Console.WriteLine(s_help.ToString());
                    return;
                }

                // タスクリストをコマンドに表示
                if (args[0] == "-l" || args[0] == "/l")
                {
                    EnumWindows(new EnumerateWindowsCallback(EnumerateWindows), 0);
                    return;
                }

                // 指定したアプリケーションをアクティブにする
                if (args[0] == "-a" || args[0] == "/a")
                {
                    try
                    {
                        Microsoft.VisualBasic.Interaction.AppActivate(args[0]);
                        return;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }


                    System.Diagnostics.Process[] ps = System.Diagnostics.Process.GetProcesses();

                    for (int i = 0; i < ps.Length; i++)
                    {
                        if (ps[i].ProcessName.IndexOf(args[0]) > 0)
                        {
                            Microsoft.VisualBasic.Interaction.AppActivate(ps[i].Id);
                        }
                    }
                    return;
                }

                // 現在のマウスカーソルPOSを取得し、コマンドとしてクリップボードに貼り付ける
                if (args[0] == "-p" || args[0] == "/p")
                {
                    IDataObject data = Clipboard.GetDataObject();
                    String s_clip = "rpac /c " + Cursor.Position.X.ToString() + " " + Cursor.Position.Y.ToString();
                    Clipboard.SetText(s_clip);
                    return;
                }

                // 指定位置を左クリックする
                if (args[0] == "-c" || args[0] == "/c")
                {
                    int x = int.Parse(args[1]);
                    int y = int.Parse(args[2]);

                    SetCursorPos(x, y);
                    // 少し待ってからクリックする
                    System.Threading.Thread.Sleep(1000);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);              // マウスの左ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);                // マウスの左ボタンアップイベントを発生させる
                }

                // 指定位置をダブルクリックする
                if (args[0] == "-d" || args[0] == "/d")
                {
                    int x = int.Parse(args[1]);
                    int y = int.Parse(args[2]);

                    SetCursorPos(x, y);
                    // 少し待ってからクリックする
                    System.Threading.Thread.Sleep(1000);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);              // マウスの左ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);                // マウスの左ボタンアップイベントを発生させる
                    System.Threading.Thread.Sleep(5);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);              // マウスの左ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);                // マウスの左ボタンアップイベントを発生させる
                }

                // 指定位置を右クリックする
                if (args[0] == "-r" || args[0] == "/r")
                {
                    int x = int.Parse(args[1]);
                    int y = int.Parse(args[2]);

                    SetCursorPos(x, y);
                    // 少し待ってからクリックする
                    System.Threading.Thread.Sleep(1000);
                    mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);             // マウスの右ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);               // マウスの右ボタンアップイベントを発生させる
                }


                // 指定位置をゆっくり２回クリックする
                if (args[0] == "-cc" || args[0] == "/cc")
                {
                    int x = int.Parse(args[1]);
                    int y = int.Parse(args[2]);

                    SetCursorPos(x, y);
                    // 少し待ってからクリックする
                    System.Threading.Thread.Sleep(1000);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);              // マウスの左ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);                // マウスの左ボタンアップイベントを発生させる
                    System.Threading.Thread.Sleep(2000);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);              // マウスの左ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);                // マウスの左ボタンアップイベントを発生させる
                }


                // 指定位置を左クリック→→クリックする
                if (args[0] == "-cr" || args[0] == "/cr")
                {
                    int x = int.Parse(args[1]);
                    int y = int.Parse(args[2]);

                    SetCursorPos(x, y);
                    // 少し待ってからクリックする
                    System.Threading.Thread.Sleep(1000);
                    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);              // マウスの左ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);                // マウスの左ボタンアップイベントを発生させる
                    System.Threading.Thread.Sleep(2000);
                    mouse_event(MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0);             // マウスの右ボタンダウンイベントを発生させる
                    System.Threading.Thread.Sleep(10);
                    mouse_event(MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);               // マウスの右ボタンアップイベントを発生させる
                }



            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.Source);
                return;
            }
        }

        // ウィンドウを列挙するためのコールバックメソッド
        public static int EnumerateWindows(IntPtr hWnd, int lParam)
        {
            const int BUFFER_SIZE = 0x1000;
            StringBuilder sb = new StringBuilder(BUFFER_SIZE);

            // ウィンドウが可視の場合
            if (IsWindowVisible(hWnd) != 0)
            {
                // ウィンドウのキャプションを取得
                if (GetWindowText(hWnd, sb, BUFFER_SIZE) != 0)
                {
                    Console.WriteLine(sb);
                }
            }
            // 列挙を継続するには0以外を返す必要がある
            return 1;
        }
    }
}

```

# ダウンロード

Microsoft Visual Studio C# 2010 Express Procject
[こちらからダウンロードしてください。](http://www.zero-one-system.co.jp/wp-content/uploads/2018/05/rpac_desctop.zip)

実行パス
rpac.zip\rpac\rpac\bin\Release\rpac.exe


本来はGitHub等で公開するのが良いのですがね。。。




# 参考ページ
とても助かりました。ありがとうございます。
勝手に感謝いたします。

[[MSDN] mouse_event](https://msdn.microsoft.com/ja-jp/library/cc410921.aspx)

※ 他にもあるんですが、見当たらない・・・。別途更新します。






でわでわ