メモ帳から文字列を取得して表示するには?

解決


shimippy  2004-08-14 03:38:04  No: 10408

Delphi初心者です。
作成環境:WinXP pro Delphi7

メモ帳に書かれたテキストを取得し、メモコントロールなどに出力したいのですが、色々なサイトなどで、調べた結果
-------------------------------------------------
var
buf:integer;

begin
SendMessage(WND,WM_GETTEXT,255,integer(@buf));
-------------------------------------------------

SendMessageでWM_GETTEXTを投げるという所までは、わかったのですが、第4引数のinteger(@buf)だと、integer型なので、16バイト以上取得しようとすると、メモリの書き込みエラーですといったような事になってしまいます。
どんな長さでも、自由に取得できる方法があれば、教えてください。


ふぐちゃん  2004-08-14 03:59:28  No: 10409

> var
> buf:integer;
bufはテキストを受け取るバッファですので、例えば
  buf: array[0..1024] of Char;
というような宣言になると思いますよ。


shimippy  2004-08-14 04:20:24  No: 10410

むちゃくちゃ早いレスありがとうございます!!m(__)m
文字列の取得できました!!。

質問には、メモ帳と書きましたが、わかりやすいと思い書いた物で、実際には、他アプリのリッチエディットから文字列を取得したいという物です。

ふぐちゃんさんの教えてくださった通り、buf: array[0..1024] of Char;で宣言したら、取得はできたのですが、0〜1024までのインデックスを持つ配列を宣言しているんですよね?
ど素人なもので、、なぜ配列なのかが理解できません。。。(すいません・・・)もしよろしければ、そのあたりの、解説をヨロシクお願いします。  すいません。。。


ふぐちゃん  2004-08-14 05:42:07  No: 10411

> なぜ配列なのかが理解できません。。。
APIでは文字型の配列が文字列なので、APIから文字列を受け取る場合には
Char型の配列を使うことが多いです。
Delphiの文字列型を使ってもできないことはないです。
その場合、SetLengthでメモリを確保して使います。


shimippy  2004-08-14 07:15:40  No: 10412

Msg := SendMessage(WND,WM_GETTEXTLENGTH,0,0);
で、取得するデータのサイズを取りたいのですが、メモリーなんとかエラーが出てしまいます。。。
buf: array[0..1024] of Char;という固定的なサイズでしか使用できないのでしょうか、、、
また、取得したデータをリッチエディットに出力していますが、内容を見るのに、毎回行の一番上にカーソル(スクロール)が行ってしまいますが、これを逆(一番下の行)にするプロパティなどはないのでしょうか。

脱線した質問になってしまいすいません。別スレ立てたほうがよいのでしょうか。。。


ふぐちゃん  2004-08-14 11:21:40  No: 10413

> Msg := SendMessage(WND,WM_GETTEXTLENGTH,0,0);
> で、取得するデータのサイズを取りたいのですが、メモリーなんとかエラーが出てしまいます。。。
ヌルの分のメモリを確保していないということはないでしょうか?
Msgという変数名も気になります。
できればもう少しコードを提示してください。

> buf: array[0..1024] of Char;という固定的なサイズでしか使用できないのでしょうか、、、
上でも書きましたが、長い文字列型の変数とSetLengthで実行時にサイズを設定できます。

> また、取得したデータをリッチエディットに出力していますが、内容を見るのに、
> 毎回行の一番上にカーソル(スクロール)が行ってしまいますが、
> これを逆(一番下の行)にするプロパティなどはないのでしょうか。
> 脱線した質問になってしまいすいません。別スレ立てたほうがよいのでしょうか。。。
そうですね、別のスレッドにした方がよいと思います。
参考までに、私ならバーチャルキーを使うかもわかりません。


shimippy  2004-08-14 16:48:34  No: 10414

すいません。中途半端なソースの提示で、よけいややこしくなってしまいますね。。。以下がその部分のソースです。クラス名などは、とりあえず****に置き換えてあります。ソース上ではきちんと書いています。
------------------------------------------------------------------
procedure TForm1.Timer1Timer(Sender: TObject);
var
  WND: HWND;
  Msg:integer;
  buf: array[0..8024] of char;
begin
  //ハンドル取得
  WND := FindWindow('AfxFrameOrView42', nil);
  WND := GetWindow(WND,GW_CHILD);
  WND := GetWindow(WND,GW_HWNDNEXT);
  WND := GetWindow(WND,GW_HWNDNEXT);
  WND := FindWindowEx(WND,0,'****', '****');
  WND := FindWindowEx(WND,0,'RICHEDIT', nil);
     try
      Msg := SendMessage(WND,WM_GETTEXT,8160,integer(@buf));
      RichEdit1.text := string(integer(@buf));
     except
      RichEdit1.text := '取得に失敗しました';
     end;
end;
----------------------------------------------------------------

以上がソースです。
タイマーを使って毎秒取得しています。


jok  2004-08-14 19:01:10  No: 10415

わたしの D5 では Windows.pas で

function SendMessage(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

type
  LRESULT = Longint;

となっていますので SendMessage() の戻り値は LongInt です。

ワードパッドからテキストを取得し、それを RichEdit1 に表示し、キャレットを
末尾にもっていって、スクロールする例をあげておきます。

procedure TForm1.Button1Click(Sender: TObject);
var
  hRichEdit:HWND;
  Ret:LongInt;
  s:string;
begin
  hRichEdit := FindWindow('WordPadClass',nil);
  hRichEdit := FindWindowEx(hRichEdit,0,'RichEdit20W',nil);

  if hRichEdit = 0 then exit;
  
  Ret := SendMessage(hRichEdit,WM_GETTEXTLENGTH,0,0);
  s := StringOfChar(#0,Ret+1);
  Ret := SendMessage(hRichEdit,WM_GETTEXT,Ret,LParam(PChar(s)));

  SetLength(s,Ret);
  RichEdit1.Text := s;
  RichEdit1.SelStart := Length(s);
  Richedit1.Perform(EM_SCROLLCARET,0,0);
  RichEdit1.SetFocus;
end;


ふぐちゃん  2004-08-14 21:42:07  No: 10416

jokさんの書いてくださったコード、私もとても勉強になりました。
どうもありがとうございます。

>shimippyさん
環境はXPとのことですので、XP上でjokさんのコードを試されるときには、
hRichEdit := FindWindowEx(hRichEdit,0,'RichEdit20W',nil);

hRichEdit := FindWindowEx(hRichEdit,0,'RichEdit50W',nil);
に変更するのをお忘れなく。


shimippy  2004-08-15 08:09:57  No: 10417

jokさん、ふぐちゃんさん、大変参考になる内容ありがとうございます。
無事解決しました。と言っても、ほとんど丸写しの様な結果になってしまいましたが(汗)・・・
私は、クラス名やキャプションを取得するのに、Winspector spy  というツールを使っています。今回のリッチエディットのクラス名が、'RICHEDIT'だったんですが、20Wとか50Wというのは、リッチエディットのバージョンなのでしょうか。そのツールを使って、ワードパットのエディット部分のクラス名を見たら、50Wが付いていたので、今回、取得している物とは、別の物なのかなと思います。

なにわともあれ、お二人には大変感謝しています。
今後、頂いたサンプルコードの理解を深めていきたいと思います。

複数回にわたる返信ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加