概要
WSHで実現が難しいものの一つにマウス操作があります。
打開策として
- Excelを経由してWin32APIを叩く
- rundll32.exeで利用できるラッパーDLLを作成する
などが考えられます。
今回は2の手法について、Win32APIの汎用入力関数であるSendInputのラッパーDLLを作成して、マウス操作を実現します。
コードとバイナリはこちら
従来の手法からの改善点
予め用意したDLLをrundll32.exeで叩くマウス操作は、こちらでも紹介されています。
これらのDLLは SetCursorPos / mouse_event を利用しており、マルチディスプレイ環境で期待した動作をしない(プライマリディスプレイ内しか移動できない)という課題がありました。
SendInputを利用することにより、セカンダリ以降のディスプレイにもカーソルを移動させることが可能です。
また、入力にはINPUT構造体を模したJSON形式の文字列を採用しました。もっともJScriptで利用できるJSONは、stringifyに一癖ありますが...
サンプル
円形にマウスを移動させるサンプルです。
SendInput.dllをスクリプトと同じディレクトリに配置して、cscriptで実行してください。終了はCtrl+Cです。
var global = Function('return this')();
if (!global.JSON) {
var html = new ActiveXObject('htmlfile');
html.write('<meta http-equiv="x-ua-compatible" content="IE=11" />');
global.JSON = html.parentWindow.JSON;
html.close();
}
var oWshShell = new ActiveXObject("WScript.Shell");
var INPUT_MOUSE = 0;
var MOUSEEVENTF_MOVE = 0x0001;
var MOUSEEVENTF_ABSOLUTE = 0x8000;
var angle = 0;
WScript.StdOut.Write("");
while(true) {
var x = 500 + Math.floor(Math.sin(angle) * 100);
var y = 500 + Math.floor(Math.cos(angle) * 100);
var input = {
"type": INPUT_MOUSE,
"mi": {
"dx": x,
"dy": y,
"dwFlags": MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE
}
};
oWshShell.Run('rundll32 SendInput.dll,_SendInput ' + JSON.stringify(input));
WScript.StdOut.Write("\r" + x + "," + y);
angle = angle < 2 * Math.PI ? angle + 0.1 : 0;
}
TODO
- 各種定数を定義する
- INPUT構造体(を模したJSON)の配列に対応させる。複数イベントの同時送信
- 配列のstringifyが配列にならないので困る、より本格的なpolyfillを導入することで解決できるかも
全体的にあまり確認が済んでいないため、バグなど見つけたらPRください。