您的位置:首页 > 其它

如何获得另一个应用程序窗口中的文本 BY hangwire

2006-12-12 11:17 344 查看
问题:
我想从一个程序获得另一个程序编辑框的文本。用GetWindowText试了一下,它总返回NULL。请问大虾有没有办法来获得另一个程序窗口中的文本?如果能,如何实现? 另外,在VC知识库的论坛中,也有人热烈地讨论过此问题,并且自己找到的解决方案。
解答:
噢,我喜欢讨论垒球问题;它们使我看起来很睿智。要想获得另一个进程窗口的文本,只需直接发送WM_GETTEXT。
CWnd* pWnd = GetOtherAppWindow();
TCHAR buf[512];
pWnd->SendMessage(WM_GETTEXT,
sizeof(buf)/sizeof(TCHAR),
(LPARAM)(void*)buf);

如果您在用C编程,自然用HWND代替CWnd。有人肯定会问:嘿,等一下——如果这样做可以的话,为什么GetWindowText不起作用呢?WM_GETTEXT不就是GetWindowText发送的吗?错也,GetWindowText只在窗口属于当前进程时才发送WM_GETTEXT,否则它干别的事情。这一点文档中说得很清楚:
如果目标窗口属于另一个进程,并且有窗口标题,则GetWindowText获得窗口标题文本。如果没有窗口标题,则GetWindowText返回空串。这是设计行为,也就是说,在设计时就是这么处理的。
换句话说,你可以获得另一个进程主窗口的标题,但得不到窗口中象编辑框、组合框或者按钮这样的子窗口的文本。
为什么会这样呢?为什么这是“设计行为”呢?因为文档又解释道:
“它允许目标窗口所在进程挂起的情况下,应用程序无需挂起而调用GetWindowText,”真是妙哉,不是吗?GetWindowText提供了禁地(never-never land)调用保护。当然老道的程序员可能会想:那有什么好的?GetWindowText得不到文本,如果想要得到文本必须用SendMessage发送WM_GETTEXT,它可能挂起。那何以保护呢?即便不使用SendMessage!你还能用SendMessageTimeout,即使是调用进入一个死锁进程, 它肯定能返回。在多任务世界中,要考虑的繁琐事情真是太多了。
真正的问题是:为什么微软公司的那帮家伙不让GetWindowText函数做它该做的事情?也就是说,如果窗口在当前进程中,为什么GetWindowText 不做一次SendMessage(WM_GETTEXT),而窗口在另一个进程时,做一次SendMessageTimeout呢?很好的问题。只有Window 向导(Wizard)知道。我怀疑在从伪多任务到真正的多任务过渡的过程中,微软公司的那帮家伙在处理以前遗留下来的应用时有难言之隐......
按照惯例,我写了一个小程序GWTTest作示范。GWTTest显示从GetWindowText 和 SendMessageTimeout(WM_GETTEXT) 获得的顶层窗口及其编辑框控制的文本。如图一所示:

图一GetWindowText 与 WM_GETTEXT的比较
GWTTest程序本身没有什么用处,它只是用来示范GetWindowText 和 WM_GETTEXT之间的差别。从程序的运行结果可以看出,两种操作都能返回顶层窗口的标题,但只有WM_GETTEXT才能对其它进程中的编辑框控制起作用。GWTTest是一个简单的CListView应用程序;获取文本的函数是CMyView::AddWindowInfo,代码如下:
//AddWindowInfo.cpp源代码
//////////////////
// 添加窗口信息, 顶层或者编辑框控制
void CMyView::AddWindowInfo(int iItem, HWND hwnd)
{
CListCtrl& lc = GetListCtrl();
CWnd* pWnd = CWnd::FromHandle(hwnd);
int iSubitem = 1;

// 添加类名
CString s;
::GetClassName(hwnd, s.GetBuffer(STRINGLEN), STRINGLEN);
lc.SetItemText(iItem,iSubitem++,s);

// 用GetWindowText添加窗口文本
pWnd->GetWindowText(s);
lc.SetItemText(iItem,iSubitem++,s);
// 用WM_GETTEXT添加窗口文本
DWORD result;
SendMessageTimeout(hwnd,
WM_GETTEXT,
STRINGLEN,
(LPARAM)s.GetBuffer(STRINGLEN),
0,
1000,
&result);
lc.SetItemText(iItem,iSubitem++,s);
s.ReleaseBuffer();
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: