19

Windows 应用程序有没有办法访问另一个应用程序的数据,更具体地说是 GUI 中的文本输入字段,并在那里获取文本以便在我们自己的应用程序中处理?

如果可能的话,有没有办法“屏蔽”你的应用程序来防止它?

编辑:前三个答案似乎是关于获取另一个应用程序窗口标题,而不是该窗口中的特定文本输入字段。

我不是 Windows API 期望的,所以你能否更准确地说我如何在该窗口中找到某个文本字段,它的先决条件是什么(似乎知道窗口句柄是必需的,它是否需要知道文本字段也处理?我怎么得到那个?等等......)

C++ 中的代码片段真的会非常感激。MSDN 帮助很难浏览,因为 Win32-API 有如此可怕的命名约定。

完全的!有关 C++ 的操作方法,请参阅下面的答案。

4

6 回答 6

18

要从另一个应用程序的文本框中读取文本内容,您需要以某种方式获取该文本框控件的窗口句柄。根据您的应用程序 UI 的设计方式(如果它有一个 UI),您可以使用几种不同的方法来获取此句柄。您可以使用“FindWindow”/“FindWindowEx”来定位您的控件,或者在有意义的情况下使用“WindowFromPoint”。无论哪种方式,一旦你有了文本控件的句柄,你就可以向它发送一个“WM_GETTEXT”消息来检索它的内容(假设它是一个标准的文本框控件)。这是一个编造的样本(没有错误检查):

HWND hwnd = (HWND)0x00310E3A;
char szBuf[2048];
LONG lResult;

lResult = SendMessage( hwnd, WM_GETTEXT, sizeof( szBuf ) / sizeof( szBuf[0] ), (LPARAM)szBuf );
printf( "Copied %d characters.  Contents: %s\n", lResult, szBuf );

我使用“Spy++”来获取一个文本框窗口的句柄,该窗口恰好在附近。

至于保护您自己的文本框不被这样检查,您始终可以对您的文本框进行子类化(参见“SetWindowLong”和“GWL_WNDPROC”以获得“nIndex”参数)并对“WM_GETTEXT”消息进行一些特殊处理以确保只处理来自同一进程的请求。

于 2008-12-11T17:47:48.127 回答
6

好的,我有点想通了。

现在的起点是准确地知道窗口句柄,我们只知道部分窗口标题,所以首先要做的是找到那个主窗口:

...
EnumWindows((WNDENUMPROC)on_enumwindow_cb, 0);
...

它枚举了桌面上的所有窗口。它使用以下每个窗口句柄进行回调:

BOOL CALLBACK on_enumwindow_cb(HWND hwndWindow, LPARAM lParam) {
    TCHAR wsTitle[2048];
    LRESULT result;
result = SendMessage(hwndWindow, WM_GETTEXT, (WPARAM) 2048, (LPARAM) wsTitle);
    ...

通过使用 wsTitle 和 little regex 魔法,我们可以找到我们想要的窗口。

通过使用前面提到的 Spy++,我可以找出文本编辑字段类名并使用它在hwndWindow中找到想要的字段:

hwndEdit = FindWindowEx(hwndWindow, NULL, L"RichEdit20W", NULL);

然后我们可以从该字段中读取文本:

result = SendMessage(hwndEdit, WM_GETTEXT, (WPARAM) 4096, (LPARAM) wsText);

我希望这可以帮助任何有同样问题的人!

于 2008-12-12T07:23:45.843 回答
1

看看AutoHotkey。如果您的应用程序需要 API,请查看其来源。为防止出现这种情况,请使用自定义小部件而不是 WinForms、MFC 或 Win32 API。这不是万无一失的,但有帮助。

于 2008-12-09T09:45:59.693 回答
0

是的,可以通过多种方式实现(一种方法是使用 WINAPI GetWindow 和 GetWindowText)。

首先,获取要从中检索文本的文本框的句柄(使用 FindWindow、EnumChildWindows 和其他 API),然后:

旧 VB6-codeexample,API 声明:

Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long  
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long  

提取文本的代码:

Dim MyStr As String
MyStr = String(GetWindowTextLength(TextBoxHandle) + 1, Chr$(0))
GetWindowText TextBoxHandle, MyStr, Len(MyStr)
MsgBox MyStr
于 2008-12-09T09:47:09.333 回答
-1

关于如何屏蔽应用程序以防止它,您可以做很多事情。一种方法是拥有一个自己的控件来处理文本输入,该控件从假设放置文本所在位置的几个标签构建文本,或者以图形方式绘制文本。

于 2008-12-09T09:50:03.100 回答
-1

您还可以使用 EM_GETTEXTRANGE 消息从 Richedit 控件中获取文本,但它仅适用于创建控件的同一进程。

于 2008-12-13T12:29:56.730 回答