別アプリのステータスバーの文字列を取得するには?

解決


ヤシュ・クック・モ  2004-12-15 00:26:58  No: 12281

自作アプリから、別のアプリのステータスバーの文字列を
取得したいのですが、うまくいきません。
ステータスバーっていくつかに分かれていますよね。
そのうち左端の枠(第1ペイン?)の文字列は、
ステータスバーのクラス名からハンドルを取得して
GetWindowText(API)で取得できるのですが、
第2ペインの文字列が取得できません。
知りたいのは第2ペインの文字列なのです。(T_T)
どなたか良い解決法をご存知でしたらお願いします。


ヤシュ・クック・モ  2004-12-15 00:34:38  No: 12282

すいません、環境を書き忘れてました。
Windows2000(SP4)+Delphi6personalです。
ちなみに知りたいステータスバーのクラス名は
「msctls_statusbar32」です。


にしの  2004-12-15 03:36:53  No: 12283

SB_GETTEXTメッセージで、WParamに1を、LParamに文字列を入れるためのバッファを渡せばよろしいかと。
# 申し訳ない、未確認です。


にしの  2004-12-15 03:38:31  No: 12284

追記。
SB_GETTEXTは定義されていないようなので、$0402としてください。


にしの  2004-12-15 03:41:20  No: 12285

さらに訂正です^^;
CommCtrlに定義されていました。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/status/messages/sb_gettext.asp


らくしょう☆  2004-12-15 05:25:18  No: 12286

にしのさん  ものしりですね
すげぇ  ほんと表示されるよ。

ワクワクしたから、ついカキカキしてためしてしまった

procedure TForm1.Button1Click(Sender: TObject);
  const
    SB_GETTEXT        = WM_USER+2;
    SB_GETTEXTLENGTH  = WM_USER+3;
    SB_GETPARTS       = WM_USER+6;
    SB_ISSIMPLE       = WM_USER+14;
  var Buffer : PChar;
      Handle, i , PanelCount ,BufferSize: integer;
      s : string;
      SimpleMode : Boolean;
begin
  s := '';
  Handle := StatusBar1.Handle;
  SimpleMode := (SendMessage(Handle,SB_ISSIMPLE,0,0)<>0);
  PanelCount := SendMessage(Handle,SB_GETPARTS,0,0);
  for i := 0 to PanelCount-1 do
    begin
      BufferSize := SendMessage(Handle,SB_GETTEXTLENGTH,i,0);
      GetMem(Buffer, BufferSize+1);
      try
        SendMessage(Handle,SB_GETTEXT,i,Integer(Buffer));
        Buffer[BufferSize] := Char(0); // 念のため
        s := s + Buffer + #13+#10;
      finally
         FreeMem(Buffer);
      end;
      if (SimpleMode) then Break;
    end;
  ShowMessage(s);
end;


ヤシュ・クック・モ  2004-12-16 00:20:44  No: 12287

にしのさん、らくしょう☆さん、レスありがとうございます。
早速らくしょう☆さんのコードで試してみました。
ところが、SB_GETTEXTLENGTHで各ペインの文字列の長さ(バイト長)までは
取得できているのですが、SB_GETTEXTで文字列そのものが
取得できないのです。

ShowMessge(s)で表ヲさせてみると、
文字のあるペインは「・Mホ」(半角のようですが、全角で表ヲしました)
文字の無いペインは「fF」(これは半角のまま表ヲしました)
と文字化けしてしまいます。

ちなみに、目的のアプリとは別の、例えばエクスプローラのステータスバーも
同じクラス名だったので試したところ、やはり同じように
文字化けします。
なぜなのでしょうか。ソ問ばかりですみませんがお願いします。


ヤシュ・クック・モ  2004-12-16 00:48:14  No: 12288

あれ。発言内容まで文字化けしている。おかしいな?
表ヲ->表示
ソ問->質問
もしかして僕のパソコンに問題ありか?
というわけで、この投稿は別の端末からしてみました。
うまく表示されますように。(ToT)丿


名無しやめんねん  2004-12-16 00:48:56  No: 12289

単純にバッファアドレスの指定の仕方が
変なんじゃないの?


にしの  2004-12-16 00:55:13  No: 12290

ウィンドウによっては、Unicodeかもしれませんので、その場合はSendMessageWを利用すればできると思います。


Basser  2004-12-16 01:24:19  No: 12291

別プロセスだからじゃないでしょうか?
Mr.XRAYさんのホームページにあるHalbowさんの資料館で説明されています。
"API With Delphi VCL"の第8章です。

http://homepage2.nifty.com/Mr_XRAY/


jok  2004-12-16 01:24:27  No: 12292

他アプリなんだから文字列バッファに VirtualAllocEx() か CreateFileMapping() をつかうのでは。


らくしょう☆  2004-12-16 05:56:35  No: 12293

他のアプリにアクセスしていなかったので気が付きませんでした。
IEにアクセスしたら落ちました(-_-)
すみませんテキストの長さの部分間違っていました。
誤:  BufferSize := SendMessage(Handle,SB_GETTEXTLENGTH,i,0);
訂:  BufferSize := SendMessage(Handle,SB_GETTEXTLENGTH,i,0) and $ff;
です
他のアプリ
WM_GETTEXTLENGTHなら表示できるんですけど
SB_GETTEXT  のときは空白がかえってきますね・・・
メモリも書き換えた方がよさそうですね。
僕お手上げです  では(+_+)/~~~


らくしょう☆  2004-12-16 06:10:08  No: 12294

名前のつけかたがよくないので
テキストの長さにBufferSize 入れてしまっているので
メモリ割り当ての時まちがうから、
nullの文字の分の1バイトを最初から足してたほうがいいですね
BufferSize := 1 + SendMessage(Handle,SB_GETTEXTLENGTH,i,0) and $ff;

では(>_<)/~~~


jok  2004-12-16 08:23:10  No: 12295

> BufferSize := 1 + SendMessage(Handle,SB_GETTEXTLENGTH,i,0) and $ff;

and $FF だと255までですね。ヘルプによれば

The low word specifies the length, in characters, of the text. 

だから and $FFFF だと思います。


らくしょう☆  2004-12-16 09:18:34  No: 12296

すみません。  最近つかってないので間違えました
&Fが4ビットだということを忘れていました  (^_^;

上に書かれているMr.XRAYさんのTCommonMemory  使うと
他のソフトへアクセスできました。

Class[msctls_statusbar32]が使われているもので試しましたら
IE, outolook,Explorer は文字取得できました。

MicrosoftDocument Explorer では、取得できなかったです。
( SB_GETTEXTLENGTH  で、長さが0がかえってくるようです)

procedure TForm1.Button1Click(Sender: TObject);
 const
    SB_GETTEXT        = WM_USER+2;
    SB_GETTEXTLENGTH  = WM_USER+3;
    SB_GETPARTS       = WM_USER+6;
    SB_ISSIMPLE       = WM_USER+14;
  var Buffer : PChar;
      Handle, MemHdl,  i , PanelCount ,BufferSize ,TextLen : integer;
      SimpleMode : Boolean;
      s : string;
   var
     TempCM : TCommonMemory;
 begin
  s := '';
  Handle := StatusBar1.Handle;
  SimpleMode := (SendMessage(Handle,SB_ISSIMPLE,0,0)<>0);
  PanelCount := SendMessage(Handle,SB_GETPARTS,0,0);
  for i := 0 to PanelCount-1 do
    begin
      BufferSize := 1 + LOWORD(SendMessage(Handle,SB_GETTEXTLENGTH,i,0));
      TempCM := GetCommonMemory(Handle,BufferSize);
      try
        GetMem(Buffer,BufferSize+1);
        try
          if (BufferSize = 1) then
            Buffer[0] := Char(0)
          else
          if (BufferSize > 1) then
          begin
            TextLen := LOWORD(SendMessage(Handle,SB_GETTEXT,i,LPARAM(TempCM.MemPtr)));
            if (BufferSize > TextLen) then
             begin
               TempCM.Read(0,Buffer,TextLen);
               Buffer[TextLen] := Char(0)
             end
              else
             begin
               ShowMessage(
                 Format(
                 'Handle[%d]' + #13+#10 +
                 ' Roop[%d/%d]' + #13+#10 +
                 'エラー:BufferSize[%d] < TextLen[%d] '
                ,[ Handle
                   , i+1 ,PanelCount
                   ,BufferSize,TextLen
                     ]));
                Buffer[0] := Char(0);
              end;
          end;
          s := s + Buffer + #13+#10;
          if (SimpleMode) then Break;
        finally
           FreeMem(Buffer);
        end;
      finally
        TempCM.Free;
      end;
    end; // for
  ShowMessage(s);
end;


らくしょう☆  2004-12-16 09:23:02  No: 12297

if (SimpleMode) then Break;
消すか移動してください。
メモリ解放わすれになってしまいます


ヤシュ・クック・モ  2004-12-17 22:11:59  No: 12298

わたしもMr.XRAYさんのところのTCommonMemoryを利用させてもらって
できました。
しかし、よそのプロセスのメモリを読み込むだけでなく
書き込むこともできちゃうんですね。
これってかなり凄いことじゃないかと思うんですがどうでしょう?

とにかくみなさんありがとうございました。


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

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






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