C++ 从另一个应用程序窗口中的文本字段读取
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/352236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading from a text field in another application's window
提问by Tuminoid
Is there a way for a Windows application to access another applications data, more specifically a text input field in GUI, and grab the text there for processing in our own application?
Windows 应用程序有没有办法访问另一个应用程序数据,更具体地说是 GUI 中的文本输入字段,并在我们自己的应用程序中获取文本以进行处理?
If it is possible, is there a way to "shield" your application to prevent it?
如果可能,有没有办法“屏蔽”您的应用程序以防止它?
EDIT: The three first answers seem to be about getting the another applications window title, not a specific text input field in that window.
编辑:前三个答案似乎是关于获取另一个应用程序窗口标题,而不是该窗口中的特定文本输入字段。
I'm no Windows API expect, so could you be more exact how do I find a certain text field in that window, what are the prequisites for it (seems like knowing a window handle something is required, does it require knowing the text field handle as well? How do I get that? etc...)
我不是 Windows API 期望的,所以你能更准确地说我如何在该窗口中找到某个文本字段,它的先决条件是什么(似乎需要知道窗口句柄,是否需要知道文本字段也处理?我怎么得到它?等等...)
Code snippets in C++ really would be really appreciated. MSDN help is hard to browse since Win32-API has such horrible naming conventions.
C++ 中的代码片段真的很受欢迎。MSDN 帮助很难浏览,因为 Win32-API 有如此可怕的命名约定。
Completed!See my answer below for a how-to in C++.
完全的!有关 C++ 的操作方法,请参阅下面的答案。
采纳答案by Raj
For reading text content from another application's text box you will need to get that text box control's window handle somehow. Depending on how your application UI is designed (if it has a UI that is) there are a couple of different ways that you can use to get this handle. You might use "FindWindow"/"FindWindowEx" to locate your control or use "WindowFromPoint" if that makes sense. Either way, once you have the handle to the text control you can send a "WM_GETTEXT" message to it to retrieve its contents (assuming it is a standard text box control). Here's a concocted sample (sans error checks):
要从另一个应用程序的文本框中读取文本内容,您需要以某种方式获取该文本框控件的窗口句柄。根据您的应用程序 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 );
I used "Spy++" to get the handle to a text box window that happened to be lying around.
我使用“Spy++”来获取碰巧位于周围的文本框窗口的句柄。
As for protecting your own text boxes from being inspected like this, you could always sub-class your text box (see "SetWindowLong" with "GWL_WNDPROC" for the "nIndex" parameter) and do some special processing of the "WM_GETTEXT" message to ensure that only requests from the same process are serviced.
至于保护您自己的文本框不被这样检查,您始终可以将您的文本框子类化(请参阅“SetWindowLong”和“GWL_WNDPROC”作为“nIndex”参数)并对“WM_GETTEXT”消息进行一些特殊处理以确保只为来自同一进程的请求提供服务。
回答by Tuminoid
OK, I have somewhat figured this out.
好的,我有点想通了。
The starting point is now knowing the window handle exactly, we only know partial window title, so first thing to do is find that main window:
现在出发点是确切知道窗口句柄,我们只知道部分窗口标题,所以首先要做的是找到主窗口:
...
EnumWindows((WNDENUMPROC)on_enumwindow_cb, 0);
...
which enumerates through all the windows on desktop. It makes a callback with each of these window handles:
它枚举了桌面上的所有窗口。它对每个窗口句柄进行回调:
BOOL CALLBACK on_enumwindow_cb(HWND hwndWindow, LPARAM lParam) {
TCHAR wsTitle[2048];
LRESULT result;
result = SendMessage(hwndWindow, WM_GETTEXT, (WPARAM) 2048, (LPARAM) wsTitle);
...
and by using the wsTitle and little regex magic, we can find the window we want.
通过使用 wsTitle 和小正则表达式魔法,我们可以找到我们想要的窗口。
By using the before mentioned Spy++ I could figure out the text edit field class name and use it to find wanted field in the hwndWindow:
通过使用前面提到的 Spy++,我可以找出文本编辑字段类名并使用它在hwndWindow 中找到想要的字段:
hwndEdit = FindWindowEx(hwndWindow, NULL, L"RichEdit20W", NULL);
and then we can read the text from that field:
然后我们可以读取该字段中的文本:
result = SendMessage(hwndEdit, WM_GETTEXT, (WPARAM) 4096, (LPARAM) wsText);
I hope this helps anyone fighting with the same problem!
我希望这可以帮助任何与同样问题作斗争的人!
回答by MZywitza
Look at AutoHotkey. If you need an API for your application, look at their sources. To prevent it, use a custom widget instead of WinForms, MFC or Win32 API. That is not foolproof, but helps.
看看AutoHotkey。如果您的应用程序需要 API,请查看它们的来源。要防止它,请使用自定义小部件而不是 WinForms、MFC 或 Win32 API。这并非万无一失,但有帮助。
回答by Stefan
Yes it is possible in many ways (one way is to use WINAPI GetWindow and GetWindowText).
是的,可以通过多种方式实现(一种方式是使用 WINAPI GetWindow 和 GetWindowText)。
First, get a handle to the textbox you want to retrieve text from (using FindWindow, EnumChildWindows and other APIs), then:
首先,获取要从中检索文本的文本框的句柄(使用 FindWindow、EnumChildWindows 和其他 API),然后:
Old VB6-codeexample, declaration of API:
旧的 VB6 代码示例,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
Code to extract text:
提取文本的代码:
Dim MyStr As String
MyStr = String(GetWindowTextLength(TextBoxHandle) + 1, Chr$(0))
GetWindowText TextBoxHandle, MyStr, Len(MyStr)
MsgBox MyStr
回答by akalenuk
You can also get text from a richedit control with EM_GETTEXTRANGE message, but it works only in the same process in which the control was created.
您还可以使用 EM_GETTEXTRANGE 消息从 Richedit 控件获取文本,但它只能在创建控件的同一进程中工作。
回答by Stefan
About how to shield the application to prevent it, you could do many things. One way would be to have a own control to handle text input that build up the text from lets say a couple of labels placed where the text would be, or that draws the text graphically.
关于如何屏蔽应用程序来阻止它,你可以做很多事情。一种方法是拥有一个自己的控件来处理文本输入,该文本输入可以从假设放置文本所在位置的几个标签或以图形方式绘制文本来构建文本。
回答by abatishchev
HWND FindWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName
);