C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[11]: OS上での文字列選択を感知したい


(過去ログ 16 を表示中)

[トピック内 19 記事 (1 - 19 表示)]  << 0 >>

■5692 / inTopicNo.1)  OS上での文字列選択を感知したい
  
□投稿者/ まどか (336回)-(2007/07/20(Fri) 17:57:51)

分類:[Windows 全般] 

OSを使用中にあらゆるものをマウスで範囲選択することは日常的にありますよね。
で、常駐アプリにて「範囲選択されたよ!」ってのを感知してその文字列を取得したいのだがというのがあります。

実際の実装方法ではなく、実現方法の概要をお分かりの方教えてくださいませ。
#「グローバルフック使うのじゃ」とか。
#「範囲選択を含むウィンドウはこうやって求めるのじゃ」とか。

引用返信 編集キー/
■5697 / inTopicNo.2)  Re[1]: OS上での文字列選択を感知したい
□投稿者/ 中博俊 (1124回)-(2007/07/20(Fri) 19:34:53)
中博俊 さんの Web サイト
グローバルフックにそこまでのことをできるんかなー?
でも選択肢はグローバルフックくらいしかないような。

よくわかんない<じゃ書かなきゃいいのに(^^;
引用返信 編集キー/
■5700 / inTopicNo.3)  Re[1]: OS上での文字列選択を感知したい
□投稿者/ とっちゃん (172回)-(2007/07/20(Fri) 19:58:47)
とっちゃん さんの Web サイト
No5692 (まどか さん) に返信
> OSを使用中にあらゆるものをマウスで範囲選択することは日常的にありますよね。
> で、常駐アプリにて「範囲選択されたよ!」ってのを感知してその文字列を取得したいのだがというのがあります。
>
結論から言うと、かなり難しいです。

Native のレベルでみると
範囲選択の動作は

WM_LBUTTONDOWN
SetCapture の呼び出し
終了

WM_MOUSEMOVE
選択範囲の更新(画面フィードバック)

WM_LBUTTONUP
ReleaseCapture の呼び出し
範囲選択結果をどこかに格納
終了

という感じになります。

ウィンドウによってはマウスムーブでスクロールすることもありますが。

で、これとまったく同じ処理にドラッグドロップがあります。
OLE の DoDragDrop を使う場合もあるでしょうけど、アプリ内でやってる場合もあります。
ウィンドウ内だけで閉じているものもあれば、アプリ内で閉じているものもあります。

もちろん、アプリ間であっても、OLEのDoDragDropを使わずに実現することも
可能ですので、そういうことをしているソフトもあるかもしれません。


なので、これだけの情報でそれが選択だったのか、ドラッグなのかは全くわからない
と言えます。

特定のアプリケーションのみ、あるいは、特定のウィンドウのみということであれば
ある程度の精度は出せるとは思いますが、汎用的なものと言うのはたぶん不可能です。

VisualStudioのテキストエディタで試してみるとわかりますが、
選択されたところでマウスダウンした場合は、ドラッグ処理に、そうではない場合は選択処理になります。

こういった条件で動作が変わるソフトもありますので、一概にどっちということは
判断できないのではないかと。

他にも、グラフィック系だと、回転とかもありますし、ソフトによっては変形というのもあります。


それに、Vista になると権限の問題とかもからんでくるので、さらにややこしいことになります。

結果からいえば、グローバルフックで動作をトレースすることはできたとしても
それが具体的に何を行っているかは、特定のウィンドウ以外は判断することはできないと思います。

引用返信 編集キー/
■5701 / inTopicNo.4)  Re[1]: OS上での文字列選択を感知したい
□投稿者/ れい (11回)-(2007/07/20(Fri) 20:02:36)
No5692 (まどか さん) に返信
> 実際の実装方法ではなく、実現方法の概要をお分かりの方教えてくださいませ。

ほぼ全てのアプリに対して範囲選択を取得するっていうのは無理 なのじゃ。
自分で描いてる場合とか、できなそうですよね? なのじゃ。

でも、コモンコントロール限定とかなら
「グローバルフック使うのじゃ」で
いけますねぇ なのじゃ。

テキストボックスは範囲選択したときに
固有なNotification投げますからそれを拾ってごにょれば なのじゃ。

#回答の語尾を指定した質問って、ここではよくあるんですか?
#わんくまってつらいなぁ
引用返信 編集キー/
■5704 / inTopicNo.5)  Re[2]: OS上での文字列選択を感知したい
□投稿者/ まどか (337回)-(2007/07/20(Fri) 22:37:49)
みなさん、ありがとうございます。

予想通りでした。(もしくは「なるほどね」と意外に簡単な答えと予想してました)
この話を聞いたときに、
難しいと思いますよ、
実現に向けては条件を絞っていくことも必要ですよ
と想像で答えていましたがやはりでしたか。

話によるとそういうソフトがあるそうです。
選択した文字列が電話番号と認識したら、自動で電話をかけるっていうしろもんらしいです。

こんなんできるんかなぁ程度の話でしたので深刻ではないのが幸いです。
なわけで、共通的見解が聞けてよかったです。

> #回答の語尾を指定した質問って、ここではよくあるんですか?

質問のレベルがわかってましたので仙人みたいな人が答えてくれるだろうと十分予想できました。(笑
解決済み
引用返信 編集キー/
■5705 / inTopicNo.6)  Re[3]: OS上での文字列選択を感知したい
□投稿者/ 渋木宏明(ひどり) (276回)-(2007/07/21(Sat) 00:14:54)
渋木宏明(ひどり) さんの Web サイト
> 話によるとそういうソフトがあるそうです。

バビロンもそーですね。

昔、噂レベルで聞いた話では「DrawText をフックして…」というものもあるそうです。


引用返信 編集キー/
■5706 / inTopicNo.7)  Re[4]: OS上での文字列選択を感知したい
□投稿者/ れい (12回)-(2007/07/21(Sat) 00:18:08)
No5705 (渋木宏明(ひどり) さん) に返信
> 昔、噂レベルで聞いた話では「DrawText をフックして…」というものもあるそうです。

フックというかDLL置き換えでは?

最近はDLL置き換えもできなくなりましたねぇ。

引用返信 編集キー/
■5707 / inTopicNo.8)  Re[5]: OS上での文字列選択を感知したい
□投稿者/ 渋木宏明(ひどり) (277回)-(2007/07/21(Sat) 00:28:46)
渋木宏明(ひどり) さんの Web サイト
> フックというかDLL置き換えでは?

あー、この場合のフックは Windows フックではなくて API フックです。

DLL インジェクションしてリモートスレッドを起動し、ターゲットプロセスの User32.dll などのインポートテーブルを書き換えるのです。

引用返信 編集キー/
■5709 / inTopicNo.9)  Re[6]: OS上での文字列選択を感知したい
□投稿者/ れい (13回)-(2007/07/21(Sat) 02:03:20)
No5707 (渋木宏明(ひどり) さん) に返信
>>フックというかDLL置き換えでは?
> DLL インジェクションしてリモートスレッドを起動し、ターゲットプロセスの User32.dll などのインポートテーブルを書き換えるのです。

インポートテーブル書き換えはAPI Hookでしたね。
私の周りでは置き返えって呼んでた。
置き換えだと偽DLL使う方法と間違えてよくないですね。

引用返信 編集キー/
■5710 / inTopicNo.10)  Re[4]: OS上での文字列選択を感知したい
□投稿者/ NyaRuRu (7回)-(2007/07/21(Sat) 04:51:55)
No5705 (渋木宏明(ひどり) さん) に返信
>>話によるとそういうソフトがあるそうです。
>
> バビロンもそーですね。

一応その用途だと IAccessible を中核とした MSAA も,もしかしたら,使えるかもしれませんということで.
私は全然知らないのでむしろ誰か代わりに調べてくれるなら,という感じですが.
引用返信 編集キー/
■5712 / inTopicNo.11)  Re[5]: OS上での文字列選択を感知したい
□投稿者/ 中博俊 (1127回)-(2007/07/21(Sat) 10:03:38)
中博俊 さんの Web サイト
>昔、噂レベルで聞いた話では「DrawText をフックして…」というものもあるそうです。

GDI+や、WPFな世界では通用しないですね。
複雑な世の中になったもんだ(^^

引用返信 編集キー/
■5713 / inTopicNo.12)  Re[5]: OS上での文字列選択を感知したい
□投稿者/ 渋木宏明(ひどり) (278回)-(2007/07/21(Sat) 10:32:58)
渋木宏明(ひどり) さんの Web サイト
> 一応その用途だと IAccessible を中核とした MSAA も,もしかしたら,使えるかもしれませんということで.

実装していないアプリが山盛りあるので、適用範囲が限定されてしまうのが欠点ですね>アクセシビリティ

引用返信 編集キー/
■5721 / inTopicNo.13)  Re[6]: OS上での文字列選択を感知したい
□投稿者/ NyaRuRu (8回)-(2007/07/21(Sat) 15:05:43)
No5713 (渋木宏明(ひどり) さん) に返信
>>一応その用途だと IAccessible を中核とした MSAA も,もしかしたら,使えるかもしれませんということで.
>
> 実装していないアプリが山盛りあるので、適用範囲が限定されてしまうのが欠点ですね>アクセシビリティ

まあ Common Control や Internet Explorer がサポートしていれば結構適用範囲は広いような気もしますけどね.
あと試してませんが Explorer や Microsoft Office なんかも対応してそうな気がします.MSIME の候補文字列取得にも使えたような.
引用返信 編集キー/
■5730 / inTopicNo.14)  Re[7]: OS上での文字列選択を感知したい
□投稿者/ まどか (338回)-(2007/07/21(Sat) 21:48:32)
> DLL インジェクションしてリモートスレッドを起動し、ターゲットプロセスの User32.dll などのインポートテーブルを書き換えるのです。

むかしN88BASICではROM内からRAMのアドレスを呼び出す部分が組み込まれていましたねぇ。
SyntaxErrorをフックしてエラー文字列をファイル名と解釈してフロッピーからロードして実行する、
なんてCP/Mもどきに改造してたりしてたことを思い出しますです。

おっしゃってる方法はまさに横取りですね。
いかにも今の世の中ではセキュリティ等などで無理そうってな感じはします。
まぁそういうやり方そのものも今後闇に消えてくんでしょうかね。

WM_DRAGSELECTEDみたいなものを全ウィンドウにブロードキャストみたいに送ってくれれば一発解決なんだろうけどなぁ。
#そういえばそういう仕組みって聞いたこと無い。。。

なんか解決済みにしても解除されそうなんでしばらくこのままに。
満足された段階で(ソースが出た!とか)解決済みにしてくださいまし>仙人の方々

引用返信 編集キー/
■5733 / inTopicNo.15)  Re[7]: OS上での文字列選択を感知したい
□投稿者/ NyaRuRu (9回)-(2007/07/22(Sun) 01:09:42)
2007/07/22(Sun) 01:11:36 編集(投稿者)

No5721 (NyaRuRu さん) に返信
> まあ Common Control や Internet Explorer がサポートしていれば結構適用範囲は広いような気もしますけどね.
> あと試してませんが Explorer や Microsoft Office なんかも対応してそうな気がします.MSIME の候補文字列取得にも使えたような.

ちょっと時間がとれたので調べてみました.
といっても全部やり出すと数日は調査が必要な規模だと分かったので,後はお仕事な人にお任せします.

================

SetWinEventHook API で EVENT_OBJECT_TEXTSELECTIONCHANGED を取得すれば,ある程度のテキスト選択は検知できました.
低レベルキーボードフックと同じで,SetWinEventHook は DLL にフックプロシージャを必要としないモードもあるので,利用自体は簡単でした.
困ったのはここからで,フックプロシージャ内で AccessibleObjectFromEvent から IAccessible ポインタを取得し,IAccessible::get_accValue を使用すると,テキストボックス全体のテキストは得られるのですが,選択されている文字列そのものを得る方法はどうも見つかりませんでした.
対象のウィンドウハンドルは取得できるのでメッセージベースの方法で何とかするか,DLL タイプのフックにして内部から API で取得するかは必要そうな印象を受けました.結局 MSAA の標準機能で何とかできるかどうかはよく分かりません.

一方,.NET 3.0 に含まれる UI Automation を利用すると,マネージクライアントからアンマネージアプリケーションのテキスト選択を検知し,選択された文字列を取得することができるようです.
もちろん全てのアプリケーションとはいかず,コモンコントロール V6 や,WPF アプリケーションなどに対象は制限されます.
http://msdn2.microsoft.com/ja-jp/library/ms744822(VS.80).aspx

ワードパッドの選択文字列をリアルタイムに取得するサンプルが Windows SDK に含まれています.
UI Automation は Vista のみでなく XP や Windows Server 2003 もサポートされていルとのことですので,試してみて下さい.
(RichEdit コントロールは,Windows Vista 以降に付属するバージョンが必要なようです)

C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\WPFSamples.zip
Accessibility\FindText

引用返信 編集キー/
■5738 / inTopicNo.16)  Re[8]: OS上での文字列選択を感知したい
□投稿者/ れい (15回)-(2007/07/22(Sun) 07:19:00)
No5733 (NyaRuRu さん) に返信
> 困ったのはここからで,フックプロシージャ内で AccessibleObjectFromEvent から IAccessible ポインタを取得し,IAccessible::get_accValue を使用すると,テキストボックス全体のテキストは得られるのですが,選択されている文字列そのものを得る方法はどうも見つかりませんでした.
> 対象のウィンドウハンドルは取得できるのでメッセージベースの方法で何とかするか,DLL タイプのフックにして内部から API で取得するかは必要そうな印象を受けました.結局 MSAA の標準機能で何とかできるかどうかはよく分かりません.

http://msdn2.microsoft.com/en-us/library/ms696179.aspx
には
> Note to clients
> Active Accessibility does not expose the text selection in edit and rich edit controls.

と書かれているので
選択文字はActive Accessiblityでは無理っぽいですね。
選択範囲変更の通知は受け取れるのに、変な話ですが。

EM_GETSELをSendMessageすればEdit ControlとRich Edit Controlで
選択範囲の文字列が取れるようですので、これを使えということでしょう。きっと。

ComboBoxは中身のEdit Controlの変更を取得できるようなので、
MSAAのSetWinEventHookとWindowメッセージのEM_GETSELを組み合わせれば
Edit、RichEdit、ComboBox
の3つのコントロールで文字列選択を監視できるだろうということになりますね。
試してませんが。

List Box、List View、Tree Viewも処理したいなら
get_accNameで選択項目の文字列を取れるようです。

MSAAでは結構簡単にコモンコントロールは網羅できそうです。

どこかのスレッドの話ではないですが、
自分でエディタ描いた場合などではMSAAは全くダメですよね。

DrawText監視はどんな感じになるんでしょう…?

引用返信 編集キー/
■5739 / inTopicNo.17)  Re[9]: OS上での文字列選択を感知したい
□投稿者/ れい (16回)-(2007/07/22(Sun) 08:02:05)
No5738 (れい さん) に返信
> DrawText監視はどんな感じになるんでしょう…?

DrawTextそのもので選択範囲がわかるわけないので
DrawTextを発生させたWindowを取得して
その種類がEditやRichEditだったらEM_GETSELを飛ばすという処理になるんでしょうか?
それとも描画する色から判断?

無理・無駄が多いなぁ。

DrawTextフックができれば
これもMSAAと同じようにコモンコントロールに対応は簡単そうですが、
あまりきれいじゃないですね。

定期的にFocusのあるコントロールを探して、
EditかRichEditだったなら、EM_GETSELを送るだけでもいい気がしてきました。
これならコモンコントロール全部に簡単に対応できますし、
COMも使わなくていいのでかなり簡単です。

「定期的にFocusのあるコントロールを探して」の部分はグローバルフックなどで置き換えたら
少し無駄が減るかもしれませんが、
セキュリティの問題を楽に回避するならTIMERもいいかと。

IEとOfficeで動けばかなりいけるとおもうんですが
EM_GETSELは動かないでしょうから個別対応かと思います。

他にいい方法ないでしょうか?
今のとこでた案は以下の通り。

1 メッセージフックでマウスイベント監視
Dragとの区別がつらそう。
権限の問題あり。
2 DrawTextフックでごにょごにょ
どうやってやるのか(私には)不明。
権限の問題あり。
3 MSAA+EM_GETSEL
ComCtlはOK。
IE、Officeは変更タイミングは確実に取得可能。選択文字は?
COMをいじる必要あり(IAccessibleは.Netにあるのでかなり楽かな?)
無駄は少ない。
4 TIMER+EM_GETSEL
ComCtlはOK。
IE、Officeは?
COMをいじる必要なし。
無駄は多いが、ほとんどマネージで済みそう。

引用返信 編集キー/
■5740 / inTopicNo.18)  Re[10]: OS上での文字列選択を感知したい
□投稿者/ れい (17回)-(2007/07/22(Sun) 08:14:40)
UI Automationを忘れてました

5 UI AutomationのITextProvider::GetSelection(かな?)
ComCtl、WPF
IE、Officeは?(知らない。IEのAutomationはダメダメだと聞いてますがどうなんでしょう?)

引用返信 編集キー/
■5931 / inTopicNo.19)  Re[11]: OS上での文字列選択を感知したい
□投稿者/ まどか (341回)-(2007/07/26(Thu) 14:44:01)
とりあえず、終了。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -