秀丸のウィンドウクラスまわりについて、No.08251
天翔記jp さん 16/08/18 02:22
 
先の入力補完直前のコールバック等々は自分でもC層でなんとかできそうです。
(秀丸が自動入力補完を出そうとする直前に、マクロを介することなく、C層のコー
ルバック関数を走らせることが出来ました!!)

さっそく、秀丸の「エディットウィンドウ(テキストウィンドウ)」文字列の長さや
文字列を取得しようとしたのですが、
瞬殺だろうと思っていたのですが、なかなか取得できないので、確認させてください。
もしかすると、秀丸独自ののWM_MESSAGEになっているのかな? と。
(あるいは私がボケてるだけかもしれません…)

◎秀丸の各プロセス構成時のウィンドウクラス名は以下のようになっていると思いま
す。
 ■秀丸の各プロセス
 Hidemaru32Class
  ├ Edit
  ├ HM32CLIENT
  └ 他もろもろ

質問@
 「Edit」というクラスは何をしていますか?
質問A
 「エディットウィンドウ(テキストウィンドウ)」に相当するものは、HM32CLIENT
だと内部解析でも外部解析でも推測できるのですが、
 テキストの長さやテキストをSendMessage, WM_GETTEXTだろうと、EM_GETTEXTだろう
と取得することが出来ません。

 やりたいことは、単純で「 テキストの長さ」、「テキスト内容」、「カレット位
置」を取得するためには、
 「どのクラスウィンドウ」に「何番で」問い合わせればよいのか、ということです。
 (カレット位置は結構それっぽSendMessageが飛び交っているので、普通の番号か
な? と予測しいています)

 番号を明示してないenumなのでしょっちゅう番号ズレるので教えるわけにはいかな
いということであれば、
   その旨投稿していただければありがたいです)


◎秀丸の入力補完がらみの構成は以下のようになっていると思います。
 ■入力補完時がらみの構成
 Hidemaru32ReceiveEndSession
 └HidemaruAutocomp
    └ listbox

質問B
 Hidemaru32ReceiveEndSessionは何をしていますか?

[ ]
RE:08251 秀丸のウィンドウクラスまわりにNo.08252
天翔記jp さん 16/08/18 11:36
 
少し追記させていただきます。

 ■秀丸の各プロセス
 Hidemaru32Class
   ├ Edit
   ├ HM32CLIENT
   └ 他もろもろ
ですが、
 Hidemaru32Class
   ├ Edit
   ├ HM32CLIENT
   ├ ListBox
   └ 他もろもろ

と「ListBox」もぶら下がっていて、カレットカーソルなどを左右に動かすと、
頻繁にこのリストボックスにset/getの問い合わせがいきます。

このあたりのこともあり、エディットウィンドウと呼べるものの実体は
「Edit?」「HM32CLIENT?」「ListBox?」とよくわからない状態です。

概要だけでも教えていただけると助かります。
よろしくお願いします。

[ ]
RE:08252 秀丸のウィンドウクラスまわりにNo.08253
秀丸担当 さん 16/08/18 13:53
 

>質問@
> 「Edit」というクラスは何をしていますか?

Editがあるとしたら、それはWindows標準のエディットコントロールです。
ツールバーの検索ボックスが表示されていたらコンボボックスの中にある場合が
あります。
アウトプット枠があれば本体とは別のプロセスとしてある場合があります。


>質問A

マクロであればできますが、マクロ以外ということになると、外部からテキスト
内容を取得するEM_GETTEXTのような方法は基本的には無いです。

たまに、常駐系のソフトでどんなアプリからでも取得するみたいなものがありま
すが、範囲選択してCtrl+Cのキーを送り付けているものがあるようです。そうい
ったものはキー割り当てが違ったら動作しないです。

あと最近ではアクセシビリティ(MSAA, IAccessible)で読み上げのために外部か
らカーソル行のテキストを取得するものにも対応していますが、クセがあって扱
いづらいと思います。カーソル桁位置は対応していないです。
[その他]→[動作環境]→[環境]→[読み上げ]→[アクセシビリティ対応]をONに
すると有効になり、Windows8以降では標準の「ナレーター」がMSAAクライアント
に対応していて、読み上げます。
本来であればMicrosoftの目指している標準的な仕組みとして、MSAAかそれに続
くUIオートメーションで、誰しもがテキストを取得できるものになっているのが
理想的だと思います。
C++だと厄介ですが、C#だと楽なのかもしれません。


>質問B
> Hidemaru32ReceiveEndSessionは何をしていますか?

Hidemaru32ReceiveEndSessionはもともとはタブモードのときに、Windowsシャッ
トダウン時のWM_ENDSESSION等を受け取るものです。
トップレベルのウィンドウでないと受け取れないので、タブごとに受け取るため
に存在します。
それを単語補完の関係でたまたま利用しているもので、タブモードでなければ無
いですし、同一スレッドのウィンドウであれば別のクラスを使う可能性もありま
す。


>と「ListBox」もぶら下がっていて、カレットカーソルなどを左右に動かすと、
>頻繁にこのリストボックスにset/getの問い合わせがいきます。

ListBoxとなっているのは、Windows標準のリストボックスを意味しますが、ここ
だけは特殊なケースがあります。
アウトライン解析の枠は、実体はリストボックスではないですが、表面的にはリ
ストボックスのように振る舞うようになっています。
これによって、読み上げソフトがMSAAなどを使わなくても、標準的な部品として
項目のテキストを取得できるようにしています。

もしSpy++を使われているとしたら、プロセスにぶら下がるものより、ウィンド
ウ一覧で親子関係を見るか、ウィンドウ検索コマンドで見るとわかりやすいと思
います。

[ ]
RE:08253 秀丸のウィンドウクラスまわりにNo.08258
天翔記jp さん 16/08/20 01:04
 
返答ありがとうございます。

※現在1つ1つ剥がしていって実装していっています。

・秀丸の入力補完表示前、消滅後のコールバック
・秀丸の入力補完ウィンドがリストボックス系だった場合に、
 選択項目を上下した場合のコールバック
・秀丸エディタにキー入力を打つたびに実行するコールバック

このあたりは、実装出来ました。
(この段階で、辞書内容に応じたヘルプを出すといったことは
 自分自身で実装できそうです)


※やはりエディットウィンドウと、カレット位置が問題か

 対応するようなマクロを実行した際に、
 秀丸がネイティブで何をしているのか、調査する予定でいますが、
 先に実装の概要を教えていただけると時間が短縮できて助かります。

 ハンドルやメッセージを外部から利用して、
 テキストやカレット位置を入手する口は設けていない、
 とのことでしたので、で質問は2点致します。

 @普段秀丸のC++のインプロセスからテキストを得る際に、
 どのような経路でテキストを入手していますか?
  
 その際、何らかのクラスウィンドウを経由させていますか?
 (上記、Hm32Client等々)

 Aカレット位置に関しても同様の質問となります。
  インプロセスからカレット位置を入手する際は、どのような経路で
  入手していますか?

 概要をざっくりで教えていただけると助かります。


以上、よろしくお願いします。

[ ]
RE:08258 秀丸のウィンドウクラスまわりにNo.08259
秀まるお2 さん 16/08/20 09:56
 
 僕の方でお返事させていただきます。

>  @普段秀丸のC++のインプロセスからテキストを得る際に、
>  どのような経路でテキストを入手していますか?

 秀丸エディタの中でのテキストデータは、単純な1つのメモリブロックに全部
入れてる訳じゃなくて、細かいブロックに分けた上で、それぞれのブロックが
「メモリ上で書き換え可能な状態」、「メモリ上で参照のみ可能な状態」、「テ
ンポラリファイル上にあってメモリ上に無い状態」の3種類存在するような、そ
ういうややこしい管理をしています。

 あと、元々ユニコード対応じゃないのを無理矢理ユニコード対応にしてる(未
だにWindows98とかも対応してる)関係もあって、内部のデータの形式が、基本
Shift-JIS形式で、Shift-JISの範囲から外れる文字(ユニコード文字)は、独自
の方式で4バイトにして持つような、ややこしいこともしています。

 この辺の内部構造はどこにも公開してないです。

 ユニコードを4バイトに変換してる形式については、特定のユーザーさん(特
別に速度を必要とする変換モジュールの作者さん)にだけは公開してますけども。

 ご質問の「どのような経路で」ってことになると、それは普通のC++の関数
callでってことになります。

>  その際、何らかのクラスウィンドウを経由させていますか?
>  (上記、Hm32Client等々)

 ウィンドウのメッセージを経由して取得するような方法は無いと思います。

>  Aカレット位置に関しても同様の質問となります。

 カレット位置も、内部的に、x,y座標を持ってるだけで、普通の変数として持
ってるだけになります。

>   インプロセスからカレット位置を入手する際は、どのような経路で
>   入手していますか?

 普通に変数を参照してるだけになります。

 天翔記さんの作成されるdllからこの辺のデータにアクセスしたいってことで
あれば、やるとしたら、hidemaru.exeに何か関数をエクスポートしてそれを呼び
出してもらう作戦はあるかと思います。

 簡単なのは、hidemaru.exeに関数を用意して、LoadLibraryして
GetProcAddressして呼び出してもらう作戦ですけども。

 単純に、現在編集中のテキストデータ全体を1つのメモリブロック
(ユニコードの文字列)にして返す用の、

    HGLOBAL GetTotalText();

 とか、カーソル位置を取得する用の

    void GetCaretPos( int* pxOut, int* pyOut );

 みたいな関数を用意する程度ならやってもいいかなぁと思いますけども。

[ ]
RE:08259 秀丸のウィンドウクラスまわりにNo.08260
天翔記jp さん 16/08/20 10:37
 
> 秀丸エディタの中でのテキストデータは、単純な1つのメモリブロックに全部
>入れてる訳じゃなくて、細かいブロックに分けた上で、それぞれのブロックが
>「メモリ上で書き換え可能な状態」、「メモリ上で参照のみ可能な状態」、「テ
>ンポラリファイル上にあってメモリ上に無い状態」の3種類存在するような、そ
>ういうややこしい管理をしています。
>
> あと、元々ユニコード対応じゃないのを無理矢理ユニコード対応にしてる(未
>だにWindows98とかも対応してる)関係もあって、内部のデータの形式が、基本
>Shift-JIS形式で、Shift-JISの範囲から外れる文字(ユニコード文字)は、独自
>の方式で4バイトにして持つような、ややこしいこともしています。
う〜ん、やはり!

>あれば、やるとしたら、hidemaru.exeに何か関数をエクスポートしてそれを呼び
>出してもらう作戦はあるかと思います。
>
> 簡単なのは、hidemaru.exeに関数を用意して、LoadLibraryして
>GetProcAddressして呼び出してもらう作戦ですけども。

それは願ったりかなったりです!

汎用的な処理の関数ポインタを取得できるよう、
hidemaru.exeにて直接 関数ポインタへのラベル代わりに、
export してもらうのは面白い解決方法です。

少し話がそれてしまいますが、
現在でも、DebugExportというのがexeからexportされていますが、
これな何の機能ですか?



[ ]
RE:08260 秀丸のウィンドウクラスまわりにNo.08261
秀まるお2 さん 16/08/20 17:59
 
 編集中のテキストデータの取得およびカーソル位置の取得関数のエクスポート
は、トライしてみてどうか試す必要があるので、進捗があったらまたコメントさ
せていただきます。

 それと、DebugExport関数ですが、これはハングアップチェッカーから秀丸
エディタを強制終了させる(保護違反を発生させて無理矢理終了させる)用に用
意してる関数のようで、普通の人が使える物では無さそうです。

[ ]
RE:08260 秀丸のウィンドウクラスまわりにNo.08268
秀丸担当 さん 16/08/23 15:13
 

V8.66β1で関数を追加しようとしています。
テキストの取得と、カーソル位置の取得と、中断すべきかの判断する関数を追加
します。
外部DLL側から、GetProcAddressを使って関数アドレスを取得して呼び出します。

テキストの取得は、全体の取得と、行単位でもできたほうがいいと思うのですが、
行単位もあったほうがいいでしょうか?
とりあえず両方できるようにしておこうと思います。

シングルスレッドで呼ぶことが前提で、そのため中断すべきかの判断する関数に
よって、ユーザーがキー入力を続けてするときなど、処理に時間がかかる場合に
抜け出すかを判断できるようにします。

[ ]
RE:08268 秀丸のウィンドウクラスまわりにNo.08269
天翔記jp さん 16/08/23 15:48
 
>V8.66β1で関数を追加しようとしています。
ありがとうございます!

>テキストの取得は、全体の取得と、行単位でもできたほうがいいと思うのですが、
>行単位もあったほうがいいでしょうか?
そうですね。
・あると使用者側のパース等が省略できるかと思います。
・全体としてはテキストがデカイものの、多数の改行はある、
 といった場合などもイテレートしやすい…かな?

>シングルスレッドで呼ぶことが前提で、そのため中断すべきかの判断する関数に
>よって、ユーザーがキー入力を続けてするときなど、処理に時間がかかる場合に
>抜け出すかを判断できるようにします。
なるほど。

[ ]
RE:08269 秀丸のウィンドウクラスまわりにNo.08283
秀丸担当 さん 16/08/25 15:11
 

V8.66β1で、エクスポートされた関数を追加しました。

現時点の使い方は、マクロヘルプの
目次− DLL呼び出し機能− DLL側から秀丸エディタの関数呼び出し
のところに書いてあります。
もし不都合などがあったら変更するかもしれません。

[ ]
RE:08283 秀丸のウィンドウクラスまわりにNo.08287
天翔記jp さん 16/08/25 17:48
 
>
≪全文引用されていたのでコミュニテックス会議室システムが引用部分を省略処理し
ました。≫
>もし不都合などがあったら変更するかもしれません。
スレッドは違いますが、
「codepage」や「ヒアドキュメント」の実装もありがとうございます。

又、この「C層での直接のテキスト読み取り等」も動作確認させていただきます。

「単語補完の拡張プログラム製作者用の基盤dll」みたいなものが
今週土曜日あたりを目処にマクロライブラリに提出出来そうですので、
そちらでも実践してみて確認してみたいと思います。


[ ]