句柄无法获取到,试过很多都没有得到

y9165102 2009-06-03 08:00:58
我实在想不明白我的问题所以来请教一下您希望能给个明灯。。

其实也就是句柄问题.我的程序上面有一个StatusBar1控件.增加了3个Panels.现在我想再另外写一个软件来实时监控第二个Panels的text。可是我在网上找了很多都没解决掉。也试过用EnumChildWindows(hFrm, @TryGetText, LPARAM(Self))获取父窗口然后列举所有子窗口也没有成功。。
所以想请大哥帮帮忙看看如何才能获取得到,晚上可以再加分
...全文
659 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
y9165102 2009-06-04
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 ccrun 的回复:]
引用 13 楼 y9165102 的回复:
谢谢大哥...不过在delphi的sta中用'msctls_statusbar32' 这一个值并不能获取pan。要换成TStatusBar。。嘿嘿。真的很感谢


是的,VCL中的状态栏,类名是TStatusBar,而Windows的状态栏原生类名是msctls_statusbar32
[/Quote]
嗯。再次上来谢谢。哈哈
ccrun.com 2009-06-04
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 y9165102 的回复:]
谢谢大哥...不过在delphi的sta中用'msctls_statusbar32' 这一个值并不能获取pan。要换成TStatusBar。。嘿嘿。真的很感谢
[/Quote]

是的,VCL中的状态栏,类名是TStatusBar,而Windows的状态栏原生类名是msctls_statusbar32
y9165102 2009-06-03
  • 打赏
  • 举报
回复
过了十二点钟我加完分再给你结
y9165102 2009-06-03
  • 打赏
  • 举报
回复
谢谢大哥...不过在delphi的sta中用'msctls_statusbar32' 这一个值并不能获取pan。要换成TStatusBar。。嘿嘿。真的很感谢
ccrun.com 2009-06-03
  • 打赏
  • 举报
回复
干脆好事做到底,帮你翻译了过来,并做了测试:
uses commctrl;

procedure CrnGetStatusBarItem(hStatusBar: THandle; pList: TStrings);
var
dwProcessID: DWORD;
hProcess: THandle;
lpCommon: Pointer;
nAllocSize: integer;// = 255;
szBuf: array [0..255] of char;
dwBytesRead: DWORD;
nPnlCount: integer;
i: integer;
begin
nAllocSize := 255;
nPnlCount := SendMessage(hStatusBar, SB_GETPARTS, 0, 0);
pList.Add('StatusBar的项目数: ' + IntToStr(nPnlCount));

GetWindowThreadProcessId(hStatusBar, @dwProcessID);
hProcess := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ, false, dwProcessID);
lpCommon := VirtualAllocEx(hProcess, nil, nAllocSize,
MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);

for i := 0 to nPnlCount - 1 do
begin
SendMessage(hStatusBar, SB_GETTEXT, i, LPARAM(lpCommon));
ReadProcessMemory(hProcess, lpCommon, @szBuf, 255, dwBytesRead);
pList.Add(szBuf);
end;

VirtualFreeEx(hProcess, lpCommon, 0, MEM_RELEASE);
CloseHandle(hProcess);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
hTopWnd, hWnd: THandle;
begin
hTopWnd := FindWindow('MSPaintApp', nil);
if IsWindow(hTopWnd) then
begin
hWnd := FindWindowEx(hTopWnd, 0, 'msctls_statusbar32', nil);
if IsWindow(hWnd) then
CrnGetStatusBarItem(hWnd, Memo1.Lines);
end;
end;


在窗体上添加一个按钮和一个Memo,然后打开画笔(mspaint.exe),编译并运行这个程序,点击按钮就可以看到效果。
y9165102 2009-06-03
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 ccrun 的回复:]
上面这个例子只适合读取本进程的StatusBar信息。
我这里有一段C++的代码,你自己翻译成Delphi代码就可以了:


C/C++ codevoid __stdcall CrnGetStatusBarItem(HANDLE hStatusBar, TStrings *pList)
{
DWORD dwProcessID;
HANDLE hProcess;
LPVOID lpCommon;
int nAllocSize = 255;
int nPnlLen;
char szBuf[255];
DWORD dwBytesRead;
int nPnlCount = SendMessage(hStatusBar, …
[/Quote]

好的我先改一下
ccrun.com 2009-06-03
  • 打赏
  • 举报
回复
上面这个例子只适合读取本进程的StatusBar信息。
我这里有一段C++的代码,你自己翻译成Delphi代码就可以了:

void __stdcall CrnGetStatusBarItem(HANDLE hStatusBar, TStrings *pList)
{
DWORD dwProcessID;
HANDLE hProcess;
LPVOID lpCommon;
int nAllocSize = 255;
int nPnlLen;
char szBuf[255];
DWORD dwBytesRead;
int nPnlCount = SendMessage(hStatusBar, SB_GETPARTS, 0, 0);
pList->Add("StatusBar的项目数: " + String(nPnlCount));

GetWindowThreadProcessId(hStatusBar, &dwProcessID);
hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
PROCESS_VM_WRITE, false, dwProcessID);
lpCommon = VirtualAllocEx(hProcess, NULL, nAllocSize,
MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

for(int i=0; i<nPnlCount; i++)
{
SendMessage(hStatusBar, SB_GETTEXT, i, LPARAM(lpCommon));
ReadProcessMemory(hProcess, lpCommon, szBuf, 255, &dwBytesRead);
pList->Add(szBuf);
}
VirtualFreeEx(hProcess, lpCommon, 0, MEM_RELEASE);
CloseHandle(hProcess);
}
y9165102 2009-06-03
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 ccrun 的回复:]
楼主显然没有看到我在6楼的回复。

只要成功获取到StatusBar的句柄(通过FindWindow/FindWindowEx/EnumWindows等都可以),读取文本用SB_GETTEXT消息。
[/Quote]

楼上的朋友不好意思呀刚刚洗了个澡..我看了一下SB_GETTEXT这个参数..但是不知道怎么将值读出来.下面是我写的。如何才能改成我需要的效果呢(是不是要将DLL注入到某窗体上呢?)


function HandleTEXT(Handlea:THandle):string;
var
s:array[0..255] of Char;
dw:DWORD;
begin
SendMessage(Handlea, SB_GETTEXT,Length(S), Integer(@S));
Result:=S;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
HWindow,hedit: THandle; //句本柄变量
szText: string; //得到的字符串
begin
HWindow:=0;
HWindow:=FindWindow(nil,'学习句柄');
HWindow:=FindWindowEx(HWindow,0,'TStatusBar',nil);//找Sta句柄
szText:=HandleTEXT(HWindow); //将sta的pan值取出来
ShowMessage(IntToStr(HWindow));
ShowMessage(szText);
end;


ccrun.com 2009-06-03
  • 打赏
  • 举报
回复
楼主显然没有看到我在6楼的回复。

只要成功获取到StatusBar的句柄(通过FindWindow/FindWindowEx/EnumWindows等都可以),读取文本用SB_GETTEXT消息。
y9165102 2009-06-03
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 sxy_9761 的回复:]
两个程序都是你写的不好办吗,进程间通讯有很多方法.消息,管道,内存文件,COM...
[/Quote]

谢谢你的思路
但是我想的是在不改变"被监控"的软件结构就能由监控软件来获取得到他的值。。。
我也知道除了直接找到他的相关位置然后取他用getwindowtext方式取得他的值之外还可以用读取他的内取来获得相关值。
我只是想知道为什么没有找不到他的句柄
ccrun.com 2009-06-03
  • 打赏
  • 举报
回复
StatusBar的Panel并没有句柄,StatusBar才有。

获取本进程或其他进程中StatusBar的Panel文本,可以通过向StatusBar发送SB_GETTEXT消息来搞定,不过需要注意的是,如果是获取其他进程中的StatusBar信息,需要注入到目标进程,开辟缓冲,获取Panel文本后再用ReadProcessMemory读回。
y9165102 2009-06-03
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 b43ok 的回复:]
1.用SPY++偷看一下那个Panels的句柄,
如果SPY++都看不到,你再怎么Enum也是没用的

2.那个程序能不能给个下载地址,方便我们试试
[/Quote]

1:用SPY++也看不到~~只看到panels的第一个值.第二个和第三个都看不到。。但是既然程序都能找到相应的方式更新那一个值。应该有相关的句柄才对呀。。难道panels后二个值是画上去的?不明白...


2:就是在delphi上面增加一个StatusBar1控件,然后建几个子就可以测试了呀。没有下载地址
sxy_9761 2009-06-03
  • 打赏
  • 举报
回复
两个程序都是你写的不好办吗,进程间通讯有很多方法.消息,管道,内存文件,COM...
b43ok 2009-06-03
  • 打赏
  • 举报
回复
1.用SPY++偷看一下那个Panels的句柄,
如果SPY++都看不到,你再怎么Enum也是没用的

2.那个程序能不能给个下载地址,方便我们试试
y9165102 2009-06-03
  • 打赏
  • 举报
回复
谢谢~~~~~~~
mathsfan 2009-06-03
  • 打赏
  • 举报
回复
帮顶吧,呵呵。

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧