获取当前选定的文本?

时间:2014-10-28 22:41:36

标签: string delphi text selected

我需要独立获取当前选择文本的窗口(浏览器,文本编辑器,游戏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;

1 个答案:

答案 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内容,由内部维护浏览器应用程序。

如果应用程序实现了一个自定义窗口类来呈现某些任意内容,那么您无法在不了解所讨论的特定应用程序和/或该应用程序支持的已发布机制的情况下检索该内容,以实现您想要的内容