- ベストアンサー
SDKでの文字列検索で躓いています
- 最近”猫でもわかる”でSDKの勉強を始めました。現在第76章を勉強中なのですが、この章で躓いております。
- この章では文字列検索の方法を学んでいますが、特に最後の文字列検索部分が理解できません。
- また、DWORD型やポインタの扱いについても疑問があります。分かる方からのご指導をお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
★文字数ではなく『選択範囲されている終了オフセット値』です。 ・『オフセット値』とはテキストの文字列の先頭からの文字位置を表したもので、 ちょうど配列の指定と同じになります。つまり、テキストの文字列の最初から 0、1、2、…と数値が増えていきます。もし、テキストの最初に『mail』という 文字列ならば、 『m』→『0』 『a』→『1』 『i』→『2』 『l』→『3』 ←次の文字が『4』 ・となりますが範囲選択の指定では、 開始位置→『0』…mailの『m』の場所 終了位置→『4』…mailの『l』の次の場所 を指定するのです。 ・確かに表現がちょっと正しくないですね。私も前回の回答で 『選択範囲されている終了オフセット値』と表現してしまいましたが、正しくは 『選択範囲されている終了オフセットの次の値』となりますね。 ・よって WPARAM…『範囲選択の開始位置=始点』 LPARAM…『範囲選択の終了位置=終点』の『終点』は範囲選択された『終点』の 次の位置のことを指した言葉です。決して文字数ではありません。しいて言えば 『終点』=『始点』+『文字数』のことになります。 ・つまり、始点が『12345』で文字数が『1000』ならば、 『始点』…12345 『終点』…13345=12345+1000 となります。 ・以上。おわり。→表現の意味の解釈が説明不足という事ですね。
その他の回答 (1)
- Oh-Orange
- ベストアンサー率63% (854/1345)
★おはようございます。 ・まず『dwCurPos = SendMessage( hEdit, EM_GETSEL, 0, 0 );』で取得した『dwCurPos』には 下位16ビット…選択範囲されている開始オフセット値(アドレスとはちょっと違う) 上位16ビット…選択範囲されている終了オフセット値(アドレスとはちょっと違う) が 32 ビットの DWORD 型の整数値でセットされます。 『dwPos = LOWORD(dwCurPos);』は下位ワードのみを dwPos に代入する処理と考えて良いです。 『dwPos = HIWORD(dwCurPos);』は上位ワードのみを dwPos に代入する処理と考えます。 ・『&buf[LOWORD(dwPos)]』の『LOWORD(dwPos)』は int 型で扱っても良いです。 理由は、dwCurPos を使って 16 ビットで範囲位置を扱っていますので int でいいのです。 もしも、EM_GETSEL メッセージの戻り値を使わずに wParam、lParam に long 型の変数のポインタを 引数にセットする使い方ならば、int 型ではなくて long 型(DWORD型)にしないといけません。 つまり、『SendMessage( hEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd );』という使い方 ならば long 型(DWORD型)にします。 ・『dwPos = lpFindPoint - buf;』は検索文字列の見つかったオフセット値を計算しています。予想通りです。 でもキャストした方が良いでしょう。→『dwPos = (DWORD)(lpFindPoint - buf);』とね。 ・上記の解説で疑問は解けましたか? 最後に: ・選択範囲を 16 ビットして処理していますのでテキストが 65535 バイト以上だと正常に検索できなくなると 思います。注意して下さい。改良するには『SendMessage( hEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd );』 として開始オフセット値、終了オフセット値を 32 ビットとして取得して処理すれば対応できます。 ・以上。おわり。→ちゃんと理解していると思いますよ。
お礼
的確な回答ありがとうございました。 一応予想はあっているらしいですね(笑) 自分としては配列変数を無理やり &buf[(int)(LOWORD(dwPos))]としてint型としてキャストを行っていたのですが、意味がないですね^^ ついでにすまないんですがもう1つ質問しても良いでしょうか? カーソルをつける作業に SendMessage(hEdit, EM_SETSEL, dwPos, strlen(lpfr->lpstrFindWhat)+dwPos); を行っています。 このEM_SETSELメッセージを送信する場合、WPARAMの値はstart位置、LPARAMはend位置と説明にありますが、これは間違いではないでしょうか? 例えば mail という文字を検索する事を考え、buf[0]から検索したとして最初から見つかったとします。 そうすると上記のプログラムだと、 SendMessage(hEdit, EM_SETSEL, 0, 4); ということになります。 プログラムの説明からbuf[0]からbuf[4]までをカーソルすることになりますが、これでは5つにカーソルをつけてしまうため1つ余計です。 しかし、このプログラムを実行させた場合きちんと文字列部分にカーソルがつくため、プログラム自体は間違えていないと思います。 結論から言うとプログラムの説明が間違えていたのかなと考えました。 つまりあのプログラムの説明は、WPARAMにカーソルの始点を、LPARAMに始点からのカーソルをつける文字数。 ということでよいのでしょうか?
お礼
的確な説明ありがとうございました! 確かに、文字列の長さを指定したとすると strlen(lpfr->lpstrFindWhat)+dwPos このように、「文字列長さ+選択開始位置」はおかしいですよね。 なるほど。終了オフセットの次の値になるんですね。 色々とご教授ありがとうございました。