[delphi-users:2798] Re:ToolbarWindow32クラスのボタン状態取得

283 views
Skip to first unread message

ムネ

unread,
Oct 9, 2012, 1:43:40 AM10/9/12
to delphi...@freeml.com
自己レス、その4です。

ターゲットアプリのバージョンアップによって、 Toolbar内のボタンが1つ増えた。
iTBCount:=SendMessage(hToolBarW,TB_BUTTONCOUNT,0,0);
取得するiTBCountがバージョンアップ前の26から27に増えた。
よってここまでは上手く出来ている。

共有メモリを使う。
var
pBtnInfo : PTBButton;
hFileMap: THANDLE;
begin
hFileMap := CreateFileMapping(THANDLE($FFFFFFFF),
nil, PAGE_READWRITE, 0, SizeOf(TTBButton), 'MyMap');
pBtnInfo := MapViewOfFile(hFileMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
for i:=0 to iTBCount-1 do begin
j:= SendMessage(hToolBarW, TB_GETBUTTON, i, LPARAM(pBtnInfo));
{a: j=1(True) となるので SendMessage は成功したのではないか}
Memo1.Lines.Add(IntToStr(i) + ' : ' + IntToStr(pBtnInfo^.fsState));
{b: pBtnInfo^.fsState 以外のpBtnInfo^ 内の全ての値が 0 である}
end;
UnmapViewOfFile(pBtnInfo);
CloseHandle(hFileMap);
end;

a:について
Delphi5 IDE から実行(F9)するたびに、j=1 になったり
j=0 になったりする。
exe を直接実行しても同様、10回に1回くらい j=1 になる。

b:について
j=0, j=1 に関わらず、常に pBtnInfo^.fsState 、他の全てが0 である。

共有メモリの使用法に問題があるでしょうか。
今試している環境はwin7pro, Delphi5 です。



MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
今すぐ遊べる!本格ブロック崩し
http://ad.freeml.com/cgi-bin/sa.cgi?id=iXc8Z
------------------------------------------------------[freeml byGMO]--

Fukushi

unread,
Oct 9, 2012, 4:15:33 AM10/9/12
to delphi...@freeml.com
山本さん、Mr.XRAYさん、こんにちは。福士と申します。横から失礼します。

> 共有メモリの使用法に問題があるでしょうか。

キーワード"TB_BUTTONCOUNT TB_GETBUTTON"で検索してみたところ、

タスクトレイに登録したアイコンの位置を知るには?
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200512/05120034.txt

にTB_GETBUTTONではTBBUTTON構造体について相手側プロセスでの
メモリの確保が必要なのではないかという指摘があります
(2005/12/08 21:18:54のかぶさんの発言)。VBなので微妙に
見づらいですが参考になるのではないでしょうか。

外していたらすいません。

---
東洋テクニカルシステム株式会社 システム開発部 福士 光
Hikaru Fukushi (Toyo Technical System Inc.)
mailto:fuk...@tts-inc.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
アイテム満載のクレーンゲーム【クレーン夫人】
http://ad.freeml.com/cgi-bin/sa.cgi?id=iXffY
------------------------------------------------------[freeml byGMO]--

Mr.XRAY

unread,
Oct 9, 2012, 5:26:37 AM10/9/12
to delphi...@freeml.com
【[delphi-users:2799] Re: Re:ToolbarWindow32クラスのボタン状態取得】 へ
のレスです.

こんにちは.Mr.XRAYです.福士さん,どうもです.

>にTB_GETBUTTONではTBBUTTON構造体について相手側プロセスでの
>メモリの確保が必要なのではないかという指摘があります

ということでやってみました.
ToolbarWindow32クラスの適当なアプリを思いつかないので,
Windows の通知領域のテキストを取得してみました.
共有メモリは,手抜きで,以下の,Halbow資料館のコードを使いました.

http://mrxray.on.coocan.jp/Halbow/VCL08.html#VChap8-3

implementation

uses CommCtrl, CommonMemoryUnit;

{$R *.dfm}

//----------------------------------------------------------------------
// TB_GETBUTTONメッセージの使用例
//
// タスクトレイの通知領域のテキストを取得
// TTBButton.dwDataが空でない時に取得
// Halbow資料館の共有メモリクラスのコード(CommonMemoryUnit.pas)を使用
//
// 動作確認環境 Windows XP(SP3) + Delhi 5(UP1) Pro
// Windows 7 64bit では 64bit版のEXEを作成する必要がある
// (CommonMemoryUnit.pasの変数numReadの型をNativeUIntに変更する)
//---------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
AppClassName : String;
h1 : HWND;
BtnCount : integer;
i : Integer;
BtnInfo : TTBButton;
CommMem : TCommMemNT;
InfoSize : Integer;
IdNo : Integer;
TextLength : Integer;
Buffer : array[0..MAX_PATH] of Char;
begin
AppClassName := 'Shell_TrayWnd';
h1 := FindWindow('Shell_TrayWnd', nil);
h1 := FindWindowEx(h1, 0, 'TrayNotifyWnd', nil);
h1 := FindWindowEx(h1, 0, 'SysPager', nil);
h1 := FindWindowEx(h1, 0, 'ToolbarWindow32', nil);
if h1 = 0 then Exit;

BtnCount := SendMessage(h1, TB_BUTTONCOUNT, 0, 0);

for i := 0 to BtnCount - 1 do begin
InfoSize := SizeOf(TTBBUTTON);
CommMem := TCommMemNT.Create(h1, InfoSize);
SendMessage(h1, TB_GETBUTTON, i, LPARAM(CommMem.MemPtr));
CommMem.Read(0, @BtnInfo, InfoSize);

if BtnInfo.dwData <> 0 then begin
IdNo := BtnInfo.idCommand;
CommMem.Free;

CommMem := TCommMemNT.Create(h1, MAX_PATH);
TextLength := SendMessage(h1, TB_GETBUTTONTEXT, IdNo,
LPARAM(CommMem.MemPtr));
FillChar(Buffer, SizeOf(Buffer), #0);
CommMem.Read(0, @Buffer, TextLength * SizeOf(Buffer[0]));

Memo1.Lines.Add(IntToStr(IdNo) + ' ' + Buffer);
CommMem.Free;
end;
end;
end;


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
最強の基地を築け!【ロボ・ウォーズ】
http://ad.freeml.com/cgi-bin/sa.cgi?id=iXg44
------------------------------------------------------[freeml byGMO]--

ムネ

unread,
Oct 9, 2012, 9:30:27 AM10/9/12
to delphi...@freeml.com
Mr.XRAYさん、福士さん、ありがとうございます。

それぞれご紹介頂いたことを合わせて整理しますと
他アプリの情報を得るにあたって
・SendMessage の戻り値で得られるものは共有メモリは不要。
・SendMessage の引数に取得データのポインタを指定する場合は 共有メモリが必要
共有メモリを確保することにおいて
・ 両方のアプリでそれぞれCreateFileMapping と OpenFileMapping を実行する必要がある。
・アクセスするアプリ側からのみの操作の場合は OpenProcess でメモリ確保する。
ということでよろしいでしょうか。
明日いずれか、あるいは下記で試してみたいと思います。

ちなみに、今日は oAccessible.accDoDefaultAction で他アプリの(クリック)操作まで出来まして、情報取得に取りかかろうというところでした。

頑張ってみますので引き続き見守って頂けるようお願いします。




MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
☆あなたはファッション大好きおしゃれ泥棒☆
http://ad.freeml.com/cgi-bin/sa.cgi?id=iXkVp
------------------------------------------------------[freeml byGMO]--

ムネ

unread,
Oct 10, 2012, 5:42:46 AM10/10/12
to delphi...@freeml.com
Mr.XRAYさん、福士さん、ありがとうございました。
解決しました。

先のメールで教えていただいた方法(共有メモリ使用)は、
会社の開発環境は win7 64bit , Delphi2007 で
64bitコンパイラがないので試せません。
実行環境は XP ですので D2007 で IAccessible 利用としました。

oAccessible.get_accState で状態取得できました。取得できたのは
STATE_SYSTEM_NORMAL (0x00000000)
STATE_SYSTEM_UNAVAILABLE (0x00000001)
STATE_SYSTEM_CHECKED (0x00000010) の3種類です。
これらの状態を監視しながら、必要に応じて
oAccessible.accDoDefaultAction で操作することにしました。

ほぼMr.XRAYさんの[678 ・・・]の通りです。
大変参考になりました。
ありがとうございました。




MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
学園生活でのときめく出会い☆
http://ad.freeml.com/cgi-bin/sa.cgi?id=iXzTD
------------------------------------------------------[freeml byGMO]--

Reply all
Reply to author
Forward
0 new messages