我需要独立获取当前选择文本的窗口(浏览器,文本编辑器,游戏wtc。)
我在stackoverflow中找到了这个代码,但它不起作用。
...
var
Buff: array[0..65535] of char;
...
function CurrentSelectedText: string;
var
hFocus: hWnd;
aStart, aEnd: integer;
begin
//added by andrei, attach input to current thread
AttachThreadInput(GetCurrentThreadId, GetWindowThreadProcessId(GetForegroundWindow), true);
hFocus:= GetFocus;
SendMessage(hFocus, WM_GETTEXT, 65535, integer(@buff));
SendMessage(hFocus, EM_GETSEL, Integer(@aStart), Integer(@aEnd));
result:= Copy(StrPas(Buff), 1+aStart, aEnd-aStart);
end;
答案 0 :(得分:3)
存在一些可能存在的重大问题(无法分离线程输入,不允许当前线程中的前台窗口,完全没有错误检查)以及可以对您进行的小改进(缓存线程ID)代码,但实质上它应该工作。
我在 TTimer 中实现了这个稍微修改过的代码版本,设置为每1/4秒(250)将当前焦点窗口文本检索到 TEdit 控件中ms),它完全符合预期。
var
buff: array[0..65535] of char;
thisThread: Integer;
focusThread: Integer;
hForeground: HWND;
hFocus: HWND;
a, b: Integer;
attached: Boolean;
begin
hForeground := GetForegroundWindow;
// ** check hForegound is valid
thisThread := GetCurrentThreadID;
focusThread := GetWindowThreadProcessID(hForeground);
// ** check focusThread is valid
attached := thisThread <> focusThread;
if attached then
begin
AttachThreadInput(thisThread, focusThread, TRUE);
// ** check attach was successful
end;
try
hFocus := GetFocus;
// ** check hFocus is valid/not null
SendMessage(hFocus, WM_GETTEXT, 65535, Integer(@buff));
// ** check SendMessage was successful
Edit1.Text := String(@buff);
if SendMessage(hFocus, EM_GETSEL, Integer(@a), Integer(@b)) <> 0 then
Edit1.Text := Copy(Edit1.Text, 1 + a, b - a);
finally
if attached then
AttachThreadInput(thisThread, focusThread, FALSE);
end;
end;
如果此代码对您不起作用,那么您可以(并且无论如何应该)在我用**注释指示的点处添加错误检查代码,以确定它在您的特定情况下不起作用的原因。 / p>
请注意,您无法将线程附加到自身,如果两个线程不同,则仅通过附加(和分离)在上面修改的代码中考虑该线程。
EM_GETSEL问题:
您遇到的问题很可能特别是尝试检索选择范围。如消息编号( EM _... )所示,这是仅有EDIT控件响应的消息,因此如果当前前景窗口不是编辑控件,那么这几乎肯定会失败。
您应该明确检查 SendMessage(.. EM_GETSEL ..)调用的成功/失败,仅从窗口文本中提取范围您收到对该邮件的有效回复。
我还发现尝试直接在 buf char数组的演员版本上使用 Copy()不起作用。这让我感到惊讶并且可能会进一步调查,但为了避免此区域可能出现的任何问题,只需先转换为字符串,然后执行复制()以从字符串中提取范围。
在我上面的工作示例中,这是通过将转换后的 buf 分配给 Edit1.Text 属性,然后在 Edit1上使用Copy()来实现的。 .Text 属性。在实践中,您将使用中间字符串变量。
WM_GETTEXT限制
在您的问题中,您需要一种适用于任何窗口类型的技术,包括浏览器和游戏。我不认为有一种通用的方法可以实现这一点,缺少屏幕捕获和OCR的组合。这是因为浏览器和游戏等应用程序甚至一些“普通应用程序”都实现了窗口类,这些窗口类的内容独立于“窗口文本”的任何概念,如 WM_GETTEXT 所报告的那样。例如浏览器窗口的“窗口文本”通常是浏览器/选项卡标题文本,不它当前显示的页面的HTML内容,由内部维护浏览器应用程序。
如果应用程序实现了一个自定义窗口类来呈现某些任意内容,那么您无法在不了解所讨论的特定应用程序和/或该应用程序支持的已发布机制的情况下检索该内容,以实现您想要的内容