Sendmessageでのテキスト行取得の異常を回避するには?


たかみちえ  URL  2001-08-15 15:36:55  No: 74746  IP: [192.*.*.*]

Sendmessageでの行取得ですけど、
2000行あたりを越えると、横行数が異常な値になってしまうんですけど、(-21999ケタとか)
回避する方法はないんでしょうか?
どうやら、何行目で起こるかも一定でないようで…。

編集 削除
Say  2001-08-17 11:58:44  No: 74747  IP: [192.*.*.*]

TextBoxをMultiLine=TrueにしてSendMessageで
行数取得したときの話でしょうか?
だとすればTextプロパティの32KB制限にひっかかっている可能性があります。
そうでないのなら、もう少し詳しい状況がわからないと、なんともいえません。

編集 削除
たかみちえ  URL  2001-08-17 13:06:05  No: 74748  IP: [192.*.*.*]

RichTextBoxでの話です。
  たとえば、VB付属のREDIST.txtとか、
(ちょっと内輪っぽいけど、Museのテキスト版説明書とか)
639/4940行目で、-32748ケタ目になりました^^;
横最大行は正常ですけど。
Museのテキスト説明書では、1-2項目あたりかな

編集 削除
Say  2001-08-17 23:07:10  No: 74749  IP: [192.*.*.*]

多分、32767以下のとき正常で、32768以上のとき
負の数になってません?
負の数になったとき、その数に65536を足したら
正常な値になりません?
だとすると、どこかにIntegerがかかわってません?
オーバーフローが原因のような気がします。
取得変数がLongでも、式の途中で知らないうちにIntegerに
暗黙の型変換されることがあります。
とくに式中のリテラル定数などは、  「0&」のように
明示的にLong型指定したほうが安全です。

編集 削除
たかみちえ  2001-08-18 15:48:34  No: 74750  IP: [192.*.*.*]

はぁ…。
横行は30数桁しかないので、そんな30000もあるものはありませんけど…。
(唯一越えてるのは、SelStartで得られる数値くらいかな…)
あと、次の行に行っても数値は減少を続けていました。
でも、とりあえず試してみます。

編集 削除
Say  2001-08-28 13:23:15  No: 74751  IP: [192.*.*.*]

REDIST.txtつかってテストしてみましたが、きちんと表示します。
Sendmessageには問題ないようです。
(ただしNT4SP6a,VB6SP5の場合。)
(ちなみに、最終行,最終列は29368行,20列でした)
Sendmessageの引数はLong型ですから
32768行以上でも大丈夫でしょう。

一つ心当たりがあるのは、列位置を出すのにそこらのWeb Pageで
CursorPos = SendMessage(obj.hWnd, EM_GETSEL, 0, 0)
CursorPos2 = CursorPos \ 65536 - LineIndex
といったコードをみかけたことです。
これを参考にしたのなら、SendMessageの戻り値が
2,147,483,647を超えた時点でオーバーフローします。

これ以上は、実際のコードみないとなんともいえません。

編集 削除
たかみちえ  2001-08-28 14:52:15  No: 74752  IP: [192.*.*.*]

Private Const EM_GETSEL = &HB0
Private Const EM_LINEINDEX = &HBB
定数宣言は面倒です^^;実際コード内では定数宣言してません。
ここのサンプルとほぼ同じなんです。
作業環境はWindows98以外変わりなしです。

Public Function GetLineIndex(Targethwnd As Long)
    GetLineIndex = ((SendMessage(Targethwnd, &HB0, 0, 0)) \ 65536 - Top(Targethwnd)) / 2 + 1
End Function

Private Function Top(hWnd As Long)
    Top = SendMessage(hWnd, &HBB, -1, 0)
End Function

ところでこういうの、どこのサンプルでもEnum型ではないですけど、
何か問題あるんですか?
統計ではEnumのほうが(数ミリ秒)早いそうですけど

編集 削除
Say  2001-08-28 18:58:02  No: 74753  IP: [192.*.*.*]

SendMessage(Targethwnd, &HB0, 0, 0)の戻り値の上位16ビットに
wParamの下位16ビットの値が入ってくると思いますが、
wParam > 32767のとき、戻り値 > 2147483647 となり、
オーバーフローします。

というわけで、第二引数がEM_GETSELのときに
SendMessageの戻り値を利用することに問題があります。
wParamを利用してください。

コーディング例

Private Const EM_LINEFROMCHAR = &HC9 
Private Const EM_LINEINDEX = &HBB 
Private Const EM_GETSEL = &HB0    

'中略

LineNum = SendMessage(obj.hWnd, EM_LINEFROMCHAR, -1, 0) + 1
LineIndex = SendMessage(obj.hWnd, EM_LINEINDEX, -1, 0)
Call SendMessage(obj.hWnd, EM_GETSEL, VarPtr(lngSelStart), 0)
CursorPos = lngSelStart - LineIndex
MsgBox CStr(LineNum) & "行 " & CStr(CursorPos) & "列"

'以下略

VarPtrはVBでは隠れ関数化してますから、
こういうコーディングを見かけないのも無理ないかもしれません。
(C/C++で言うところのポインタみたいなもんです)

編集 削除