tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトル指定のハンドルに矢印キーの送信 postmessage
記事No16445
投稿日: 2018/08/14(Tue) 16:42
投稿者jusu
お世話になります。
ある、パッケージアプリがあり、そこへの入力をある程度自由化しようと試みています。
ターゲットウィンドウ(キャプション hogehoge)には、
選択項目が3つあり、下段に OK、キャンセル、ヘルプボタンがあります。

hogehoge
-------------------------(1)
-------------------------(2)
-------------------------(3)
[OK] [キャンセル] [ヘルプ]

ここで、1〜3を選択するのは矢印キー上下か、マウスクリックです。
矢印キーの入力を自動化できないかと思っています

hWnd = FindWindowEx(0, 0, "ウィンドウクラス", "hogehoge") 'このウィンドウを選択
Cwnd = GetWindow(hwnd, 5)
Cwnd = GetWindow(Cwnd, 2)  
冗長ですがこんな感じで、(1)(2)(3)ウィンドウハンドルを取得しました

そこで、矢印キーを送信したのですが選択肢が動きません
Ret = PostMessage(Cwnd, WM_KEYUP, VK_DOWN, 1)

結果をspyで見ました
プログラム結果
Cwnd P WM_KEYUP nVirtKey:VK_DOWN cRpeat:1 ScanCode:00 fExtended:0...
直接下矢印を押した結果
Cwnd P WM_KEYUP nVirtKey:VK_DOWN cRpeat:1 ScanCode:50 fExtended:1 ...
Scancode? Extennted ?

何かヒントでもありましたらお願いします。

ちなみに、OKボタンは、OKボタンのハンドルを取得して
lngRet = SendMessage(Mwnd, BM_CLICK, 0, 0) にて押すことができます。

[ツリー表示へ]
タイトルRe: 指定のハンドルに矢印キーの送信 postmessage
記事No16446
投稿日: 2018/08/15(Wed) 18:17
投稿者魔界の仮面弁士
> ある、パッケージアプリがあり、そこへの入力をある程度自由化しようと試みています。
IAccessible インターフェイスの
accSelect メソッド / accDoDefaultAction メソッドを使ってみるのはいかがでしょう。


> 選択項目が3つあり、下段に OK、キャンセル、ヘルプボタンがあります。
その選択項目とは何のオブジェクトですか?
ListBox なのか Button なのか、あるいは単に描画されているだけなのか。


> hWnd = FindWindowEx(0, 0, "ウィンドウクラス", "hogehoge") 'このウィンドウを選択
> Cwnd = GetWindow(hwnd, 5)
> Cwnd = GetWindow(Cwnd, 2)
5 は GW_CHILD 、2 は GW_HWNDNEXT ですね。


> そこで、矢印キーを送信したのですが選択肢が動きません
そのアプリは、WM_KEYUP / WM_KEYDOWN を処理する仕様になっているのでしょうか。
処理しているとしたら、親ウィンドウと子ウィンドウ、どちらで受ける仕様でしょうか。
(たとえば、GetAsyncKeyState にて判定する実装だったりするかもしれません)


> Ret = PostMessage(Cwnd, WM_KEYUP, VK_DOWN, 1)
WM_KEYUP なのに lParam (というか lKeyData) に 1 を渡しているのは意図的なものですか?
http://chokuto.ifdef.jp/urawaza/message/WM_KEYUP.html


> Cwnd P WM_KEYUP nVirtKey:VK_DOWN cRpeat:1 ScanCode:50 fExtended:1 ...
> Scancode? Extennted ?

cRepeat   = CLng(lKeyData And &H0000FFFF&)'\ &H00000001&
ScanCode  = CLng(lKeyData And &H00FF0000&) \ &H00010000&
fExtended = CLng(lKeyData And &H01000000&) \ &H01000000&
Reserved  = CLng(lKeyData And &H1E000000&) \ &H02000000&
fAltDown  = CLng(lKeyData And &H20000000&) \ &H20000000&
fRepeat   = CLng(lKeyData And &H40000000&) \ &H40000000&
fUp       = CLng(lKeyData And &H80000000&) \ &H80000000&

[ツリー表示へ]
タイトルRe^2: 指定のハンドルに矢印キーの送信 postmessage
記事No16447
投稿日: 2018/08/16(Thu) 18:21
投稿者jusu
> IAccessible インターフェイスの
> accSelect メソッド / accDoDefaultAction メソッドを使ってみるのはいかがでしょう。
はい、該当のオブジェクトまで
Wnd = FindWindowEx(0, 0, クラス名, タイトル)
AccessibleObjectFromWindow
      Wnd, OBJID_CLIENT, IID_IAccessible, objAcc
lngCount = objAcc.accChildCount  
ReDim list(lngCount - 1) As Variant
lngRet = AccessibleChildren(objAcc, 0, lngCount, 指定オブジェクト, lngCount)
にてたどり着きました。
このオブジェクトは def actionが無く
objacc.accSelect(SELFLAG_TAKEFOCUS)で画面がアクティブになりました
ここにキーを送信というのはどうやるのでしょうか



> ListBox なのか Button なのか、あるいは単に描画されているだけなのか。
恐らく描画だと思いますが、調べる方法がわかりません

> 処理しているとしたら、親ウィンドウと子ウィンドウ、どちらで受ける仕様でしょうか。
> (たとえば、GetAsyncKeyState にて判定する実装だったりするかもしれません)
spyのログを親ウィンドウから子ウィンドウを追加して、キー送信ログをみたところ
該当のウィンドウで受けっとているようです。

> WM_KEYUP なのに lParam (というか lKeyData) に 1 を渡しているのは意図的なものですか?
> http://chokuto.ifdef.jp/urawaza/message/WM_KEYUP.html
できるだけ、spyのログにあわせようとしていました
ご指導いただいた情報で、ログとまったく一致になったのですが
やはり反応しませんね。(;´∀`)

[ツリー表示へ]
タイトルRe^3: 指定のハンドルに矢印キーの送信 postmessage
記事No16448
投稿日: 2018/08/17(Fri) 10:17
投稿者魔界の仮面弁士
> objacc.accSelect(SELFLAG_TAKEFOCUS)で画面がアクティブになりました
SELFLAG_何某SELECTION でアイテムを選択できますか?
https://msdn.microsoft.com/ja-jp/library/cc447533.aspx


> ここにキーを送信というのはどうやるのでしょうか
「矢印キー上下」か「マウスクリック」で選択できると聞いたので、
MSAA で選択できるではないかと踏んだのですが、
もしかして選択することが目的なのではなく、選択後に
さらにキー送信を行うことまでが目的なのでしょうか?

となると SendInput とか。
ウィンドウのアクティブ化は必要にはなりますけれども。


> > ListBox なのか Button なのか、あるいは単に描画されているだけなのか。
> 恐らく描画だと思いますが、調べる方法がわかりません
Spy++、UIAutomationSpy、Inspect などでクラス名だけでも得られないでしょうか。


> やはり反応しませんね。(;´∀`)
そのパッケージアプリとやらの内部実装がどうなっているか分からないですしね…。

たとえば DirectInput でキー入力を捉えているようなアプリだと、
PostMessage/SendMessage でメッセージキューを送りつけても意味が無いので、
SendInput で仮想キーとスキャンコードを送り付けてみる必要があったりとか。
https://dobon.net/vb/bbs/log3-36/22123.html

[ツリー表示へ]
タイトルRe^4: 指定のハンドルに矢印キーの送信 postmessage
記事No16449
投稿日: 2018/08/17(Fri) 16:48
投稿者jusu
> > objacc.accSelect(SELFLAG_TAKEFOCUS)で画面がアクティブになりました
> SELFLAG_何某SELECTION でアイテムを選択できますか?
> https://msdn.microsoft.com/ja-jp/library/cc447533.aspx
有効なのは SELFLAG_TAKEFOCUS  あとは、数値でもTAKESELECTIONでも反応しません

> > ここにキーを送信というのはどうやるのでしょうか
> 「矢印キー上下」か「マウスクリック」で選択できると聞いたので、
> MSAA で選択できるではないかと踏んだのですが、
> もしかして選択することが目的なのではなく、選択後に
> さらにキー送信を行うことまでが目的なのでしょうか?
いえいえ、マウスクリックまたは、上矢印キーで項目を選択して
 最終的にはこのダイヤログのOKボタンを押すことを自動化できればよいのです。
 OKボタンのクリックはSendmessegeで可能でした

> > > ListBox なのか Button なのか、あるいは単に描画されているだけなのか。
> > 恐らく描画だと思いますが、調べる方法がわかりません
> Spy++、UIAutomationSpy、Inspect などでクラス名だけでも得られないでしょうか。
UIAUtomationSpyeについては、今研究しています
クラス名というのは、そのアプリケーションでオリジナルなものですよね
spyで見たところ
そのウィンドウのtopはクラス名の一部に、Dialogとあり、対象の選択エリアには
**MServerとありました。全公開していいのかな(;´∀`)
ちなみに、別の状況があって、そこにF-3を送信しているのはうまくいきます
このクラスはEditです。
やはり特殊な処理のなのでしょうか

> たとえば DirectInput でキー入力を捉えているようなアプリだと、
> PostMessage/SendMessage でメッセージキューを送りつけても意味が無いので、
> SendInput で仮想キーとスキャンコードを送り付けてみる必要があったりとか。
> https://dobon.net/vb/bbs/log3-36/22123.html
SendInputをやってみました。見事に上矢印の送信ができて選択項目も変わりました。
ただ、これは、対象ウィンドウがアクティブ化していないといけませんよね。
これを許しちゃうと、他の作業との混乱の元かなと

[ツリー表示へ]
タイトルRe^5: 指定のハンドルに矢印キーの送信 postmessage
記事No16450
投稿日: 2018/08/17(Fri) 18:44
投稿者魔界の仮面弁士
> spyで見たところ
> そのウィンドウのtopはクラス名の一部に、Dialogとあり、
MFC のダイアログっぽい名前ですね。


> **MServerとありました。全公開していいのかな(;´∀`)
何でしょうね。

非標準のウィンドウだと、WM_USER が飛んでいる可能性もありますし、
あるいはそもそも、ウィンドウメッセージを見ていないという可能性も。

仮に DirectInput で受けていたとすれば、メッセージキューは恐らく無視されますし、
強調レベル DISCL_FOREGROUND でマウスあるいはキーボード入力を受けていたりすると、
非アクティブ時にはそもそも入力を検出できない可能性も無いとは言えず。


> このクラスはEditです。
こちらは標準の EditBox (TextBox) でしょうから、あまり問題なさそう。

[ツリー表示へ]
タイトルRe^6: 指定のハンドルに矢印キーの送信 postmessage
記事No16451
投稿日: 2018/08/20(Mon) 14:11
投稿者jusu
魔界の仮面弁士様 お助けありがとうございました。

結論として、アプリケーションを外部からコントロールする場合
アクティブ化していないとコントロールできない
オブジェクトもあるということですね。

[ツリー表示へ]