B(ug)log

開発とかぼやきとかLINEスタンプとか http://line.me/S/sticker/1245783 職探し中

UIAssistant の機能考え中(迷走中)

新機能として、コンテキストメニュー的なものを作成中

下の画像はコンテキストメニューの例で、「無題 - メモ帳」を選択して、コンテキストメニューを表示させて、「文字列をコピー」した結果を貼り付けるまでの動画です。

f:id:u338steven:20161001222447g:plain

とりあえずお試しで実装して動かしてみたけれど、微妙な点がいくつか浮上。

微妙な点

大改造必至

UIAssistant 本体側にコンテキストメニューを使用する土台をインフラ的に用意しておいて、 プラグイン側で、それを利用して楽にコンテキスメニューを実現できる状態にしたい、のだけれど、 今の UIAssistant の実装だと実現が面倒なので、大改造必至。

この機能、本当に使うか?

あると便利だろうけど、そんなしょっちゅう使う機能か?を考えると使用頻度は低いと思う。(個人の感想です)

今後

現状での実装の大変さと、結果の便利さが釣り合わないので、正式に実装するのに二の足を踏んでいます。 動かしてみた感じだと面白そうではあるのですが……とりあえず放置する方向。

UIAssistant 0.3.7.3 公開

コンテキストメニュー内の検索機能を追加しました。 すこし問題はあるのですが、対処のしようがない(下記、既知の問題点参照)ので、公開します。 だいたいの場合は問題にならない……はずです。

ダウンロード

以下からどうぞ。

github.com

更新内容

コンテキストメニューの検索

機能概要

ホットキー押下でコンテキストメニューを自動で開いて検索できます。

f:id:u338steven:20160901123045g:plain

使用方法

ホットキーの設定で、以下のコマンドを指定してください。

/ ContextMenu

注意事項

UIAssistant 内で仮想的にアプリケーションキーを押下させてコンテキストメニューを開いているので、 AutoHotkey などでアプリケーションキーに別のキーを割り当てていると、コンテキストメニューが開かれず検索できません。

既知の問題点

  • 検索後、実行できないメニュー項目がある

下図のようにコンテキストメニューの中身が多い場合、初期状態で見えていないメニュー項目(スクロールが必要な項目)は実行できません

f:id:u338steven:20160901123116p:plain

メニューをスクロールできる機能が UI Automation に無く、 UIAssistant から矢印の上下キーを送信して無理矢理にスクロールさせて、見えていなかったメニュー項目を表示させても実行できなかったので、 どうすれば実行できるようになるのか対処方法が不明です。 スクロールが必要になるくらいメニュー項目が多くなる場合は、たいてい階層化(ネスト化)してスクロールの必要がなくなるように対処するはずなので、あまり問題にはならない……といいなぁ。

(UIAssistant から矢印キー、Enter キーを送信して実行させるという手段しか無いのかなぁ。)

コンテキストメニューが開いたのを検知する方法

右クリックで出てくるアレの出現を検知したかったのです。 UIAssistant でコンテキストメニューの要素を扱えたら便利じゃないかと思って調べてみた結果がこれです。

対象

TL;DR

対象が非WPFアプリケーションの場合、以下のどちらかで検知できます。

  • Win32API SetWinEventHook関数(EVENT_SYSTEM_MENUPOPUPSTARTを利用)
  • UI Automation AddAutomationEventHandlerメソッド(UIA_MenuOpenedEventIdを利用)

対象がWPFアプリケーションの場合、以下でのみ検知できます。

  • UI Automation AddAutomationEventHandlerメソッド(UIA_MenuOpenedEventIdを利用)

なので、どの場合でも検知できるようにするには、UI Automation の AddAutomationEventHandler メソッドを使うとよいです。

動機

コンテキストメニューの UI を差し替えるなり、拡張できたら便利ではないだろうかと思った」などと供述している模様。

すなわち、

  1. コンテキストメニューが開かれるのを検知する
  2. 検知したら、コンテキストメニュー内の要素を取得する
  3. その要素の中から、入力した文字列によって検索、選択できるような UI を付加する

こんなことができれば便利かもしれないと考えました。UI を付加するのであれば、従来通りにも使えて、既存の使い勝手をなるべく阻害しない形になります。

SetWinEventHook

下記のサイト経由で、コンテキストメニューが開いたのを検知できると知り、試してみることに。

Windowsのイベントを拾う - hoge

SetWinEventHook の引数に EVENT_SYSTEM_MENUPOPUPSTART を指定すると、コンテキストメニューが開かれたときに引数で指定した関数がコールバックされます。その際、コンテキストメニューのウィンドウハンドルを受けとれます。

Event Constants (Windows)

というわけで ContextMenuObserverWin32 を作成してみました。(ソースコード@Gist)

以下のようなコマンドで、ビルドできます。(csc.exe にパスが通っているかの確認と、.NETFramework のバージョンについては環境ごとに変更する必要があります)

csc /t:winexe /lib:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1" /r:UIAutomationClient.dll /r:UIAutomationTypes.dll ContextMenuObserverWin32.cs

WPF(Win32, Windows Forms)の場合

検知して、メニュー項目を取得できました。

f:id:u338steven:20160823113730p:plain

WPF の場合

こちらは、検知できませんでした。

f:id:u338steven:20160823113803p:plain

WPF とそれ以外では、コンテキストメニューの作られ方が異なり、そのため検知不可になっているのだと思われます。(下図参照)

Win32 アプリケーションのコンテキストメニュー

f:id:u338steven:20160823113814p:plain

WPF アプリケーションのコンテキストメニュー

f:id:u338steven:20160823113823p:plain

WPF も検知できる方法を探す → UI Automation を試す

以下のように、WPF だろうとなんだろうと利用できると公式に記載されていました。よさげです。

The UI Automation requirements apply to all menu controls, whether Microsoft Windows Presentation Foundation (WPF), Microsoft Win32, or Windows Forms.

...

Required UI Automation Events

Menu controls must raise the UIA_MenuOpenedEventId event when they appear on the screen.

UI Automation Support for the Menu Control Type

試してみた結果

ContextMenuObserverUIA を作成してみました。(ソースコード@Gist)

SetWinEventHook のときと同様に、以下のようなコマンドで、ビルドできます。

csc /t:winexe /lib:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1" /r:UIAutomationClient.dll /r:UIAutomationTypes.dll ContextMenuObserverUIA.cs

WPF でも問題なく検知できて、以下のようにコンテキストメニューの内容を取得できました。

Win32 アプリケーション

f:id:u338steven:20160823113837p:plain

WPF アプリケーション

f:id:u338steven:20160823113846p:plain

さいごに(所感)

たぶん、この投稿の需要はほとんどないと思います。PC をがっつり使う人って、もうそんなにいないだろうし。 アプリケーションによっては、コンテキストメニュー内に項目が多くあるので、検索できれば使い勝手向上に役立ちそうとは思うのです。まぁ、実際に試してみないと便利かどうかは評価できないわけですが……。

UIAssistant 0.3.6.2 公開(Bugfix)

月刊 UIAssistant、今回もバグ修正のみです。
(別に月刊を狙っているわけでも無いのですが……)

ダウンロード

以下からどうぞ。

github.com

主な修正点

以下の3点。

  • キーバインド、使用方法の表示/非表示」がキーを押下しても表示されなかったのを修正(LCtrl+U のやつ)
  • ウィンドウの大きさをより正確に取得するように修正

    • before
      f:id:u338steven:20160801151155p:plain
    • after
      f:id:u338steven:20160801151159p:plain
  • ポップアップが表示された場合も最前面に UIAssistant が表示されるように修正

    • before
      f:id:u338steven:20160801151203p:plain
    • after
      f:id:u338steven:20160801151208p:plain

今後について

コンテキストメニュー(右クリックメニュー)内を文字で検索できたら楽しそう(実現できるかどうかは別として……)