皆もすなるQiitaといふものを、儂もしてみむとてするなり。
と言う訳で、こん**は!はなっち!です。
この記事はUiPathブログ発信チャレンジ2023サマーの24日目の記事です。
【初めに】
UiPathブログ発信チャレンジ2023サマーの3日目の記事で、【UiPath】フルリモのお供。マウスを動かし続けるロボット
を書きました。
その後、実際に使ってみると、じっとしている分には申し分ないのですが、例えばPowerPointを作成中
で、右下にあるObjectを右上に移動
しようとすると、勝手にマウスが動いて
しまって、アタフタ
してしまう事が多々ありました。
本来はスクリーンセーバーが起動するのを抑止しようという目的で作成したものでしたが、このままだと別のイライラが募る
ばかり...
今回は、その後の対応策をまとめてみました。
1)移動させるマウス位置を固定にしなければいい!
前回の記事では、
最初のカーソルの位置は(X,Y)=(200,400)としました。次は (X,Y)=(X+α,Y+α) α=1 とすると、いずれは画面サイズを超えたところにカーソル位置を持っていくことになります。
スクリーンセーバーが起動されなければ、カーソル位置を常に新しい場所にする必要はなく、最低2点あれば十分ですので。int32型配列として保持する事にしました。
と、Int32型配列に、固定値として設定していました。
※今気が付いた。座標の話と張り込んだ画像がマッチしていないですね(^^♪
ここの固定値
を現在のマウスの位置
に変更し、マウスを動かす先は現在のマウスの位置
を基に +1
したポイントにする事にしました。
2)現在のマウスの位置をどう取得するのか?
UiPathアクティビティから、MOUSE
で検索すると...
ちょっと該当するアクティビティはなさそうです。
となると、.NETの機能を利用するのが手っ取り早いですね。得た結果が、以下の式でした。
'マウスポインタの位置を取得する
'X座標を取得する
Dim x As Integer = System.Windows.Forms.Cursor.Position.X
'Y座標を取得する
Dim y As Integer = System.Windows.Forms.Cursor.Position.Y
確認のため、「メッセージボックス」アクティビティで、マウスの位置を表示させてみましょう。
〔設定内容〕
〔実行#1〕
UiPath Studioの「現在のファイルを実行アイコン」の中ほどにマウスを置き、実行!(下図では赤い点の辺り)
〔実行結果#1〕
〔実行#2〕
画面の中央ほどにマウスを置き、実行!
〔実行結果#2〕
どうやら、ちゃんと取得できますね。
3)取得した現在のマウスの位置から...
スクリーンセーバーが起動が起動しない様に、現在のマウスの位置から +1
させていきましょう。
X = {1 + System.Windows.Forms.Cursor.Position.X}
Y = {1 + System.Windows.Forms.Cursor.Position.Y}
これを延々繰返していけばOKですね。
ただ、画面の最大サイズ位置
であるである右下にマウス
があった場合、異常終了するのではないか?と言う思いにいたり...だったら、画面の最大サイズ
を求めて、その画面サイズを超えないように制御すれば...
4)画面の最大サイズをどう取得するのか?
これも、.NETの機能を利用するのが手っ取り早いですね。得た結果が、以下の式でした。
'ディスプレイの高さ
Dim h As Integer = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height
'ディスプレイの幅
Dim w As Integer = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width
確認のため、「メッセージボックス」アクティビティで、画面の最大サイズを表示させてみましょう。
〔設定内容〕
〔実行結果〕
〔評価〕
マウスを中ほどにして取得した値と、画面サイズを見比べるとちゃんと取れていますね(当然と言えば当然)。
⇔
5)計算!
現在のマウスの位置を +1
させていき、画面サイズを超えたなら -1
させていく。そうなると、最終的には画面サイズの辺り(右下)を行ったり来たりの動きになってしまいますね。
だったら、繰り返して計算するのだから、
- 奇数回目は、現在のマウスの位置に
+1
する - 偶数回目は、現在のマウスの位置に
-1
する
ようにしてやれば、解決!
と考えたのですが、第一回目(奇数回目)のマウス位置が、そもそも画面サイズ
で、そこに+1
したら既に画面サイズからオーバーする値になってしまう!
と悶々とし始めたら、記事の冒頭の
画面の最大サイズ位置
であるである右下にマウス
があった場合、異常終了するのではないか?と言う思いにいたり...だったら、画面の最大サイズ
を求めて、その画面サイズを超えないように制御すれば...
の思いを翻して、そもそも画面のサイズを超えても、あるいはあり得ない値が設定されても大丈夫ではないか?と考えはじめ...
6)場外乱闘
画面サイズの高さ(.HEIGHT)、幅(.WIDTH)は、0以上の整数
ですから、究極の場外乱闘は、負の整数
ですね。
-
「ホバー」アクティビティ の
Xのオフセット
とYのオフセット
の値に、直接-1
を設定して実行しみます。

お見せ出来ませんが、画面の左上にマウスが移動しました!!
-
「ホバー」アクティビティ の
Xのオフセット
とYのオフセット
の値に、直接10000
を設定して実行しみます。

お見せ出来ませんが、画面の右下上にマウスが移動しました!!
と言う事は、特に場外乱闘値を考慮しなくてもよさそうですね。
7)再考した計算!
現在のマウスの位置
は取得出来た。繰り返しの奇数回には+1
、偶数回には-1
をしてあげれば、現在のマウスの位置
辺りをちょろっと動きます。その+1
あるいは-1
を求めるのに、こんな風に考えてみました。
その1
奇数回目か、偶数回目かは、「繰り返し (コレクションの各要素)」アクテイビティの「現在のインデックス」の値を、2で割った際の余りが1だったら奇数
、0だったら偶数回
と言う事はわかりますね。
この条件分岐後の処理の中で、現在のマウスの位置を +1
させていったり、 -1
させていったりすれば良い訳です。
その2
奇数回目か、偶数回目か。状態は2つしかありません。この2つしかない
ことに着目すると、Boolean型を利用できそうです。
Boolean型は、True値またはFalse値を取りうる変数の型です。Boolean型をInt32型に変換すると、True値は-1
に、False値は0
になります。
逆に、Int32型をBoolean型に変換すると、0はFalse
に、0以外はTrue
になります。
Boolean型が、-1または0を持つInt32型の値
に変換出来るのですから、その値を直接利用しない手はありませんね。
計算式:CINT(DISTANCE) * 2 + 1
DISTANCE(Boolean型)がTrueの場合
CINT(DISTANCE) * 2 + 1
= CINT(True) * 2 + 1
= -1 * 2 + 1
= -2 + 1
= -1
DISTANCE(Boolean型)がFalseの場合
CINT(DISTANCE) * 2 + 1
= CINT(False) * 2 + 1
= 0 * 2 + 1
= 0 + 1
= 1
8)態々計算する必要ある?
今まで、スクリーンセーバが起動されないためには、マウスを移動させなければならないと考えていました。
ここまで来て今更なのですが、もしかしたら、マウスを移動させなければならないのではなく、マウスを移動する行為をしなければならないのではないかと。
+1
あるいは-1
したマウスの位置をもって 「ホバー」アクティビティを実行しなくても、±0
したマウスの位置をもって、つまり今のマウスの位置をそのまま設定し、 「ホバー」アクティビティを実行すればいいのではないかと。。。
やってみたら、正にその方法で正解でした。
こうすると、実にスッキリしたロジックになりますね。
まとめ
- 一つの完成形から、
不都合
を探してみよう - その
不都合
から、改善の方法
を考えてみよう、やってみよう -
改善の方法
を、複数トライ
してみよう - その中で、
最適解
で実装し、しばらく使ってみよう - また
不都合
を探してみよう- 現在の不具合は、手でマウスを移動している最中に、「ホバー」アクティビティが実行され、手でのマウス移動が終了した時に、「ホバー」アクティビティが実行された時点のマウス位置にマウス移動してしまう(戻ってしまう)事が、ややイライラのタネですね。
おわりに
いかがでした?
今回も読んでいただきありがとうございました!
是非UiPathでのロボ開発の一助になればと思っています。
ありがとうございました!