HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0825
SADOUSマウス直下の入力フォームの有無 確認、調査13解決


SADOUS

リンク

2014/8/25(Mon) 01:14:02|NO.64204

質問というよりはもう、答えを教えてもらいたいのです。
以前にマウス直下のGUIオブジェクトの調査サンプルを頂いて使わせてもらっていますが、
これの数値をいじれば直下にあるオブジェクトも判別できるんじゃないかと思いました。
しかし、サンプルを貰った当時に入れたコメントにウィンドウハンドルをどうのと
書いてあります。

;GUIオブジェクト調査用関数 #cfunc WindowFromPoint "WindowFromPoint" int,int #cfunc GetAncestor "GetAncestor" int,int;p2 2直近上位のトップレベルウィンドウを返す ; 3所有されていないトップレベルウィンドウを返す

;マウス直下の有効gui if rend=0 or rend_fr\k_btn=0 { gsel 0,0 umouse_gui=0:umouse_hwnd=0 umouse_gui =windowfrompoint(gmx,gmy) ;guiオブジェクトのハンドルを返す umouse_hwnd =getancestor(umouse_gui,2) ;p2=2:直近上位のトップレベルwindowを返す thishwnd=hwnd:actwinid=ginfo(2):umouse=0 if umouse_hwnd=thishwnd/* & actwinid=0 */: umouse=1 ;1で自windowマウス直下に有り }
※変数gmx,gmyはデスクトップ上のマウスの座標

もしかしたらumouse_guiに代入されるデータで入力可能なフォームがあるかどうか
判別できる???とは思ったものの、ここから先は未知の領域でした。
ただ、少し調べてみると
http://hsp.tv/play/pforum.php?mode=pastwch&num=48981のcatsさんのサンプルで、
自分で生成したオブジェクトのハンドルとを比較しているようで
マウス直下の入力可能なオブジェクトの判定は可能ではあると思うのですが、
僕はマウス直下にある文字入力可能なオブジェクト全てを判定したいのです。
でも、何とWindowFromPointの返り値を比較すればいいのかサッパリ・・・

#uselib "user32.dll" #cfunc WindowFromPoint "WindowFromPoint" int,int sdim buf,256 buf="入力してください" input buf,200,20 sInput=stat hInput=objinfo(stat,2) repeat await 30 switch WindowFromPoint(ginfo(0),ginfo(1)) case hInput if buf="入力してください":objprm sInput,"" swbreak default if buf="":objprm sInput,"入力してください" swend loop



この記事に返信する


cats

リンク

2014/8/25(Mon) 02:10:43|NO.64206

ウィンドウハンドルだけでは、それが入力フォームなのかは分かりません。
そこでクラス名というものを使います。
クラス名は、オブジェクトが持つデータの1つで、オブジェクトの種類を
表すものだと考えてください。
GUIオブジェクトだけでなく、ウィンドウハンドルを持つものすべてにクラス名があります。
ウィンドウハンドルからクラス名を取得するにはGetClassNameという関数を使います。

GetClassName ウィンドウハンドル , クラス名を入れる変数 , 変数のサイズ
で第2パラメータの変数に、クラス名が代入されます。

では、実際に入力ボックスのクラス名がどうなっているかを調べましょう。

// クラス名を調査してみる #uselib "user32.dll" #func GetClassName "GetClassNameA" int, var, int sdim class, 256 ; クラス名 input class : hwnd_1 = objinfo(stat, 2) mesbox class : hwnd_2 = objinfo(stat, 2) GetClassName hwnd_1, class, 256 mes "インプットボックス:" + class GetClassName hwnd_2, class, 256 mes "テキストボックス:" + class stop
結果を見れば分かるように、入力ボックスには"Edit"というクラス名があります。
つまり、マウス直下のウィンドウハンドルを取得して、そこからクラス名を割り出し、
そのクラス名が"Edit"であるかを比較すれば良いのです。

#uselib "user32.dll" #cfunc WindowFromPoint "WindowFromPoint" int, int #func GetClassName "GetClassNameA" int, var, int sdim class, 256 // ループで監視する *Watch redraw 0 // 取得部分 gx = ginfo(0) : gy = ginfo(1) ; マウス位置 hwnd_ = WindowFromPoint( gx, gy ) ; マウス直下のウィンドウハンドル取得 GetClassName hwnd_, class, 256 ; 取得したウィンドウハンドルのクラス名取得 // 描画部分 color 255, 255, 255 : boxf : color pos 0, 0 mes "マウス直下のオブジェクトのクラス名は" + class + "です。" if class = "Edit" { mes "( "+ gx +" , "+ gy +" ) に入力フォームを確認しました。" } redraw 1 await 15 goto *Watch
ただし、クラス名はオブジェクトの種類であるとはいえ、一概に同じとはいえません。
例えば同じ入力ボックスでも、HSP3のエディタは独自のプラグインを使用していますので
クラス名は"Edit"ではなく"Footy2View"です。
上のソースでマウス直下のクラス名が表示されますので、
それを見てクラス名を調べるとよいでしょう。



SADOUS

リンク

2014/8/25(Mon) 02:29:10|NO.64207

>catさん
あれ、あのcatsさん!?
クラス名・・・聞き覚えはあります・・・。
ウィンドウハンドルを元にクラス名を取得できる関数があったのですね。
ただ、ソフトウェアごとにクラス名が変わってくるとなると一個一個指定していくのは
切りがないように思えます。

他に・・・マウス直下に「入力可能なものがある!」と判定する方法はないでしょうか;
修正中のツールがあらゆる場面のテキスト入力中に誤動作してしまうので処理を止めたいのです。

と書き込んで気が付きましたが、
「「現在アクティブなオブジェクトが入力フォームの類である」かを判定する方法」
の方が正しいです。



SADOUS

リンク

2014/8/25(Mon) 02:43:06|NO.64208

もうマウス関係なくなってしまいましたが、
現在アクティブなオブジェクトがテキスト入力可能なオブジェクトであるかを判定したいです。

また、それっぽい関数がありそうですけれど、HSP以外に手を付けたことがなくて
どの関数を呼び出せばいいのかも検討もつきません。
関数一覧の載っているページを探しているのですが、
それっぽいページは見つかるのですが、微妙に的はずれなものばかりで・・・
関数一覧の乗っているサイトとかはありませんか?



skyblue

リンク

2014/8/25(Mon) 09:54:02|NO.64210

Windowsで使用できる関数を探したいならMSDN画お勧め。
特に英語版



cats

リンク

2014/8/25(Mon) 10:25:40|NO.64211

>ソフトウェアごとにクラス名が変わってくる
ソフトウェアごとに変わる訳ではないです。
基本的に「Edit」のクラス名の入力ボックスが使われます。
ただし、独自のシステムを使う入力ボックスであればクラス名は変わります。
例えばwebサイトの入力ボックスは取得できません。
私の知る限りでは、一概に入力フォーム全てを判別できる
スッキリした方法は無いです。

>あらゆる場面のテキスト入力中に誤動作してしまう
具体的にどのような処理を行いたいのか是非教えてください。



SADOUS

リンク

2014/8/25(Mon) 10:28:46|NO.64212

>skyblueさん
http://msdn.microsoft.com/ja-jp/library/cc392726.aspx
ありがとうございます!目当てのものを探していたら、別の用途で使えそうな関数が
いくつか見つかりました。

しかし、やはり僕にはどの関数を使えばいいのか分からないです。
「キーボードフォーカスを持つウィンドウのハンドルを取得」というのがありましたが、
戻り値の解説がただのgetkeyに似ているように思えるし、そもそもの
[キーボードフォーカス=縦棒がチカチカして文字打つばかりの状態]
かどうかも怪しいし・・・

滅多に聞かない単語が飛び交って、もう軽く混乱状態です。



SADOUS

リンク

2014/8/25(Mon) 10:35:55|NO.64214

>catsさん
>>具体的にどのような処理を行いたいのか是非教えてください。
一部の人はもう勘付いいておられると思いますが、ツールMCM+のWキーをおした時の
擬似クリック機能についてのバグです。

wkeyを押すとあらゆる場面で「クリック」されるため、
テキスト入力中にwキーを押すと[文字を選択する状態]になったり、
[選択した文字を移動(画面外に消し去る)]してしまい、→誤動作という結果に。
キー割り当てを変えれば済む話かとも思います。
なので、キー割り当ても実装するつもりですが、自分の使いたいキーの中には
文字入力に使うキーもあるのです。

マウス直下にキーボードフォーカス?入力フォーカス?が無ければ
擬似クリックを許可。あれば、wキークリック無効(if:false)。
みたいなプログラムを組みたいんです。



cats

リンク

2014/8/25(Mon) 11:08:12|NO.64217

>「キーボードフォーカスを持つウィンドウのハンドルを取得」というのがありましたが
これをヒントに探してみるとGetGUIThreadInfoというものがあり、
気になったので使ってみたら思いつきました。
入力フォームにはキャレット位置というものがあり、
入力フォーム上で何行目、何文字目にいるかが分かります。
そして、GetGUIThreadInfoでそれが取得できます。
入力フォームにキャレット位置があるときは、必ずキャレット情報は
0より大きくなります。
つまり、GetGUIThreadInfoでキャレット情報を取得して、
それが0でないときには入力フォームにいるということです。

以下がソースコードです。

#uselib "user32.dll" #cfunc WindowFromPoint "WindowFromPoint" int, int #cfunc GetWindowThreadProcessId "GetWindowThreadProcessId" int, int #func GetGUIThreadInfo "GetGUIThreadInfo" int, int /************************************************ GUIThreadInfo構造体は Type GUITHREADINFO cbSize As Long flags As Long hwndActive As Long hwndFocus As Long hwndCapture As Long hwndMenuOwner As Long hwndMoveSize As Long hwndCaret As Long rcCaret As RECT End Type のようになっています。(http://bit.ly/1p73yiD) ************************************************/ dim GUIThreadInfo, 12 ; GUIThreadInfo構造体を初期化 GUIThreadInfo(0) = 48 ; 構造体サイズ *Watch // マウス直下のハンドルを取得する hwnd_ = WindowFromPoint( ginfo(0) , ginfo(1) ) // 取得したハンドルからプロセスIDを調べる tID = GetWindowThreadProcessId( hwnd_, 0 ) // キャレット情報を取得 GetGUIThreadInfo tID, varptr( GUIThreadInfo(0) ) if stat == 0 : dialog "Failed.", 1 : end // 描画部分 redraw 0 color 255, 255, 255 : boxf : color pos 0, 0 : mes "キャレット情報:" repeat 4, 8 mes GUIThreadInfo(cnt) loop // キャレットから判定 if GUIThreadInfo(8) != 0 { mes "\n入力フォームにキャレットがあります!" } redraw 1 await 15 goto *Watch

ちなみに、GetWindowThreadProcessIdでプロセスIDというものを
取得していますので、興味があれば調べてみてください。
今回はGetWindowThreadProcessIdとGetGUIThreadInfoがひとまとまりだと
考えてもらっても構いません。

この方法の問題点として、非常に特殊な場合は、誤判定や失敗を
してしまうことが挙げられます。
例えば、実験した限りでもFirefoxでの入力で一度誤判定を起こしました。
とはいえ、クラス名などに比べれば非常に高い精度になっているでしょう。

<参考>
http://msdn.microsoft.com/ja-jp/library/cc364641.aspx
http://msdn.microsoft.com/ja-jp/library/cc364710.aspx
http://msdn.microsoft.com/ja-jp/library/cc364779.aspx
http://msdn.microsoft.com/ja-jp/library/microsoft.teamfoundation.common.internal.nativemethods.guithreadinfo%28v=vs.110%29.aspx
http://msdn.microsoft.com/ja-jp/library/windows/desktop/ms632604%28v=vs.85%29.aspx
http://tokovalue.jp/Structure.htm#GUITHREADINFO%E6%A7%8B%E9%80%A0%E4%BD%93



SADOUS

リンク

2014/8/25(Mon) 12:45:25|NO.64222

>catsさん
サンプルありがとうございます。わかりやすかったです。
だいぶやりたいことに近づいてきましたが、ウィンドウに入力フォームがあるか
どうかしか判別できない・・・と思います。
サンプルのGUIThreadInfo(0~11)全てを表示して確認してみましたが
チカチカする縦棒(キャレット?)の有無にかかわらず、
ウィンドウ内に入力フォームがあるかどうかしか判別できないような気がします。

chrome,hsp edit,メモ帳,スタートメニューなどで実験

やっぱり大まかにしかわからないのかな・・・



cats

リンク

2014/8/25(Mon) 13:13:14|NO.64223

>ウィンドウ内に入力フォームがあるかどうかしか判別できないような気がします。
先ほどのスクリプトは、とにかく入力できる状態にある時を判別します。
マウスカーソルが入力フォームの上にあるときのみ取得したいのであれば、
入力フォームの位置とサイズを取得して、フォーム上にあるかを判別してください。
Wキーで操作すると書いてあったので、Wキーの誤入力を防ぎたいのかと思い込んでました。
入力フォームのサイズの取得はGetWindowRect関数でウィンドウハンドルを指定してやればできます。

ちなみに、キャレットというのは入力状態にある場所です。縦棒の事と考えていいです。
つまりキーを入力したら、「キャレット位置」に文字が入力されるのです。



SADOUS

リンク

2014/8/25(Mon) 14:05:56|NO.64226

hspエディタではキャレットがある場合にGUIThreadInfo(8~11)に反応がありますが、
ブラウザchromeでは、キャレットの有無にかかわらず反応してしまいます。
いや、ウィンドウがアクティブであればキャレットの有無にかかわらず反応するのか。

GetWindowRectは指定ウィンドウの座標が取得できるんですよね、
入力フォームの座標・サイズが分からないとあたり判定?できなさそうですし、
またしても、それらしい関数を見つけられない・・・



cats

リンク

2014/8/25(Mon) 17:51:43|NO.64257

GUIThreadInfoに入力フォームのハンドルの情報が含まれていますので、
WindowFromPointで取得したハンドルと比較すればマウス直下かが分かります。
GetWindowRectいりませんでしたね。
ただ、Chromeも含めたブラウザ系でのフォームを検出するのは難しいと思います。
いまだにWキーの問題がいまいち理解できていないので可能かどうかは何とも言えませんが。



SADOUS

リンク

2014/8/26(Tue) 14:13:03|NO.64306

>catsさん
GUIThreadInfoの入力フォームのハンドルとWindowFromPointを比較して、
「キャレットが存在かつマウス直下に入力フォーム有り」を判別することができました。
>>ただ、Chromeも含めたブラウザ系でのフォームを検出するのは難しいと思います。
chromeを含む一部のソフトでは正しく認識できませんでした。
諦めたほうがいいのかな?

一応やりたいことはできたので解決とします。
catsさんskyblueさん、ご協力感謝です。



ONION software Copyright 1997-2023(c) All rights reserved.