2005年09月18日

TextBoxと未実装メッセージ(1)

TextBoxはScrollBarsプロパティを操作することでスクロールバーを表示することができます。

んが、表示はできても任意の所に動かしたり今どこを表示しているのか取得したりというメソッドがほとんど用意されていません。唯一ScrollToCaretメソッドがあるくらいです。

これは不便だがどうにかならないかと考えるに、そもそもTextBoxはWindowsのEditコントロールの薄いラッパークラス。メッセージの類はそのまま流用できたりします。そこでEditコントロールのメッセージを色々調べてみましょう。

あ、今更ですがちょっと解説。こういうWindows標準コントロールは普通、そのコントロールにSendMessage関数などを使用して特定のメッセージを送ることで色々な値を取得したり設定したりします。ほんとに今更ですね。

さてMSDNのEditコントロールです。メッセージが色々並んでますねー。しかしMicrosoftはこの辺(メッセージや構造体)和訳してくれないので解読も一苦労とは言いませんが一手間増えてやな感じです。

基礎のお勉強として、この未実装のメッセージをメソッドやプロパティとして実装していこうかと思います。

第一回目の今回は、まずそれぞれのメッセージを一つ一つ見ていき、どれが実装されていないのか、されていないので使えそうなのはあるのか、検証していくことにしましょう。

それでは一つ一つ見ていくとしましょう。まず実装済みなものからです。

EM_CANUNDO
アンドゥが可能かどうかを取得します。CanUndoプロパティが対応します。
EM_EMPTYUNDOBUFFER
アンドゥ用に確保されているバッファをクリアします。当然次の(アンドゥ対象となる)操作までアンドゥはできなくなります。ClearUndoメソッドが対応します。
EM_GETLIMITTEXT
テキストボックスに入力できる文字の最大長を取得します。MaxLengthプロパティのgetアクセサ側ですね。
EM_GETMODIFY
ユーザが内容を変更したかどうかを取得します。Modifiedプロパティのgetアクセサ分です。
EM_GETPASSWORDCHAR
パスワードのマスク用に使う文字を取得します。PasswordCharプロパティのgetアクセサ。
EM_GETSEL
選択中の文字列の、先頭のインデックスと末尾のインデックスを取得します。SelectionStartプロパティとSelectionLengthプロパティで代用します。後ろから前方向に選択しても必ずSelectionStartの方が小さい値を示すのも同じ。後ろから選択しているかどうかは、GetCaretPos関数あたりを駆使するしかないのかな……。
EM_LIMITTEXT
入力できる文字の最大長を設定。MaxLengthプロパティのsetアクセサですね。
EM_REPLACESEL
選択中の文字列を他の文字列に置換。SelectedTextプロパティのsetアクセサですねー。
EM_SCROLLCARET
キャレットが見える位置までスクロールします。ScrollToCaretメソッド。
EM_SETLIMITTEXT
EM_LIMITTEXTメッセージと同じです。当然対応するのもMaxLengthプロパティのsetアクセサ。
EM_SETMODIFY
ユーザが内容を変更したかどうかを強制的に設定します。Modifiedプロパティのsetアクセサです。
EM_SETPASSWORDCHAR
パスワード用の文字を設定します。PasswordCharプロパティのsetアクセサ。
EM_SETREADONLY
読み取り専用にするかどうかを設定します。ReadOnlyプロパティのsetアクセサですね。
EM_SETSEL
指定した範囲を選択します。SelectionStartプロパティとSelectionLengthプロパティを使ったり、Selectメソッドを使ったりで可能です。
EM_UNDO
アンドゥします。そのまんま、Undoメソッドです。

書き出してみると対応してるのが意外に少ないですね。明らかに未対応のメッセージの方が多いですよこれ。ということで未対応のものです。

EM_CHARFROMPOS
指定した点に存在する文字のインデックス(と行番号)を取得します。RichTextBoxではGetCharIndexFromPositionメソッドでサポート。.NET 2.0からはこのメソッドはTextBoxBaseに移動するので、TextBoxでも利用できるようになります。
EM_FMTLINES
ちょっと分かりづらい機能です。ソフト改行というのを、ワードラップによって見かけ上改行されている部分に挿入、または削除します。ソフト改行というのはC#では\r\r\nで表されます。もともと\r\nで改行されているところには挿入しません。これで追加されたソフト改行は、TextプロパティやLinesプロパティにも影響します。エディットコントロールの見た目上には影響しないと書かれていますが、少なくともTextBoxにおいては、サイズを変えた際に実際に改行が挿入されたのと同じようにその部分の改行が残ります。なお、Textプロパティに手で\r\r\nを入れても、このメッセージによるソフト改行と同等の扱いをされます。
EM_GETCUEBANNER
XPのVisualStyleで作用するようですが詳細不明(ていうか興味ないしー)
EM_GETFIRSTVISIBLELINE
表示されている一番若い行番号を仮想行単位で取得します。RichTextBoxでも.NET 2.0のTextBoxBaseでも何故か未定義。
EM_GETHANDLE
文字列を格納しているメモリ領域を表すハンドルを取得します。複数行のエディットコントロール限定。.NETになってまでこの辺をいじるのもどうかと。
EM_GETIMESTATUS
フォーカスが移動したときなどのIMEの振る舞いを取得します。詳しくはEM_SETIMESTATUSを参照。
EM_GETLINE
特定行の文字列を取得します。Linesプロパティで代用はできますけど、多分不効率です。
EM_GETLINECOUNT
総行数を取得します。Linesプロパティで代用できますがきっと不効率です。
EM_GETMARGINS
左右のマージンを取得します。要するに余白ですね。詳しくはEM_SETMARGINSの方で。
EM_GETRECT
有効文字描画範囲を取得。有効文字描画範囲というのはまあ読んで字の如く、その範囲にだけしか文字を描画しません。普通はエディットコントロールのクライアント領域全体ですね。詳細はEM_SETRECTのほうで。
EM_GETTHUMB
そもそもサポートされていないらしいです。試してみても機能しないし。本来はスクロールバーのツマミの位置を取得するはずですが。
EM_GETWORDBREAKPROC
ワードラップに使用するコールバック関数のポインタを取得します。.NET 2.0でなら、関数ポインタとデリゲートの相互変換ができるのでいじりようもありますが、.NET 1.0/1.1ではこれをどうこうするのは難しそうです。ちなみに.NET 2.0では、関数ポインタを返す関数のDllImport定義で返値に対応するデリゲートを直接宣言できたりします。頑張れマーシャラ。
EM_HIDEBALLOONTIP
XPのVisualStyleにおいて、バルーンチップを隠すらしいです。
EM_LINEFROMCHAR
指定したインデックスの文字を含んでいる行番号を取得します。RichTextBoxでGetLineFromCharIndexメソッドとして実装されています。.NET 2.0からはこのメソッドはTextBoxBaseに移動してTextBoxでも利用できるようになります。
EM_LINEINDEX
指定行の先頭文字のインデックスを取得します。.NET 2.0でTextBoxBaseにGetFirstCharIndexFromLineメソッドとして実装されます。
EM_LINELENGTH
指定したインデックスの文字を含む行の文字数を取得します。指定方法がマニアックですね。Linesプロパティで代用できますが恐らくは非効率。
EM_LINESCROLL
指定した文字・行数分スクロールします。普通にあって当然のメソッドだと思うのですが.NET 2.0でも未実装。TextBox系はどうにもスクロール関係に弱い印象です。弱いと言えばキャレット関係もですが。
EM_POSFROMCHAR
指定した文字インデックスの座標を取得します。RichTextBoxではGetPositionCharIndexメソッドとして実装。.NET 2.0からはTextBoxBaseに移動してTextBoxでも利用できるようになります。
EM_SCROLL
一行または一画面分スクロールさせます。一画面スクロールはPageUpキーやPageDownキーをSendKeysで送ることで擬似的には実装できますが、実に“やりたくない”実装方法ですね。
EM_SETCUEBANNER
XPのVisualStyleで作用するようですが詳細不明(全然興味ないしー)。日本語の情報も見あたりませんねー。
EM_SETHANDLE
文字列を格納しているメモリ領域を表すハンドルを設定します。EM_GETHANDLEと同じく、この辺をいじるのは.NET的になんか癪です。
EM_SETIMESTATUS
フォーカスが移動したときなどのIMEの振る舞いを設定します。フォーカスを失ったときに変換を確定させたり、得たときに入力中の文字をキャンセルさせたりできます。が、この辺のデフォルトの振る舞いを変更するのは個人的にはどうかと思います。
EM_SETMARGINS
左右のマージンを設定します。余白を設定してやればきちきちで見づらいと言うこともなくなりますね。ちなみにマージンはEM_SETRECTで設定したのとは違ってリサイズしても維持されます。が、EM_FMTLINESとかで急に解除されたりするようなのでちょっと注意。
EM_SETRECT
有効文字描画領域を設定します。通常はクライアント領域いっぱいを使って文字列が描画されますが、このメッセージを使うことで描画範囲を限定することができるようになります。スクロールバーとかもちゃんと追従してくれるので一安心。これを巧く使うことで、TextBoxの左端をちょっと空けて行番号を表示したりできるようになります。ただしリサイズされたりしたら領域が破棄されるので注意が必要です。.NET 2.0でTextBoxBaseにPaddingプロパティというのが導入されたのでこれかと思ったらどうやら違うようです。というかこのプロパティ、効果がさっぱり分かりません。ベータ2時点では未実装なだけなんですかね。
EM_SETRECTNP
EM_SETRECTと同じですが、こちらは設定したときに再描画を行わないという点が異なります。
EM_SETTABSTOPS
タブ間隔を設定します。RichTextBoxではSelectionTabsである程度代用されているようです。しかしこれの配列代入タイプがイマイチ不明。まあそんなマニアックなのは使わないでしょううん。
EM_SETWORDBREAKPROC
ワードラップに使用するコールバック関数のポインタを設定します。まあいじれるのは.NET 2.0になってからですし。
EM_SHOWBALLOONTIP
XPのVisualStyleにおいて、バルーンチップを表示するらしいです。

以上、一通り見てきましたが、“何故これが未実装?”的なメッセージが幾つかありました。個人的には.NET 2.0で実装されるようになる各種メソッドのほか、EM_GETFIRSTVISIBLELINEEM_GETLINEEM_SCROLLEM_SETTABSTOPS辺りでしょうか。

ということでこの辺の実装を進めていきたいと思います。では次回。



posted by Hongliang at 14:25| Comment(0) | TrackBack(1) | .NET | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック

Microsoft IME
Excerpt: Microsoft IMEMicrosoft IME(マイクロソフト・アイエムイー)とは、マイクロソフトが開発した日本語入力システム(日本語IME)である。MS-IME(エムエス・アイエムイー)と略さ..
Weblog: ソフトウェア・ソフトウェア会社情報
Tracked: 2005-10-09 06:25

ここ(hongliang.seesaa.net)で公開しているものについて、利用は自由に行って頂いて構いません。改変、再頒布もお好きになさって下さい。利用に対しこちらが何かを要求することはありません。

ただし、公開するものを使用、または参考したことによって何らかの損害等が生じた場合でも、私はいかなる責任も負いません。

あ、こんなのに使ったってコメントを頂ければ嬉しいです。

×

この広告は180日以上新しい記事の投稿がないブログに表示されております。