String 是否获取当前选定的文本?

String 是否获取当前选定的文本?,string,delphi,text,selected,String,Delphi,Text,Selected,我需要获得当前的选择文本独立的windows浏览器,文本编辑器,游戏世贸中心 我在stackoverflow中找到了这段代码,但它不起作用 ... var Buff: array[0..65535] of char; ... function CurrentSelectedText: string; var hFocus: hWnd; aStart, aEnd: integer; begin //added by andrei, attach input t

我需要获得当前的选择文本独立的windows浏览器,文本编辑器,游戏世贸中心

我在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;

无法分离线程输入、不允许当前线程中的前台窗口、完全没有错误检查以及缓存线程ID(可以对代码进行缓存)的轻微改进可能存在一些重大问题,但本质上应该可以工作

我在TTimer中实现了这个稍微修改过的代码版本,设置为每1/4秒250毫秒将当前聚焦的窗口文本检索到一个TEdit控件中,它完全按照预期工作

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;
如果此代码不适用于您,那么您可以并且在任何情况下都应该在我用**注释指出的点添加错误检查代码,以确定其在您的特定情况下不起作用的原因

请注意,您不能将线程附加到自身,在上面修改的代码中,如果两个线程不同,则仅通过附加和分离来考虑这一点

EM_GETSEL问题:

很可能您遇到的问题特别是在尝试检索选择范围时。如消息编号EM所示。。。这是一条只有编辑控件响应的消息,因此,如果当前前景窗口不是编辑控件,则几乎肯定会失败

您一定要检查SendMessage的成功/失败。。埃穆盖塞尔。。调用,并仅在收到对该消息的有效响应时从窗口文本中提取范围

我还发现,试图在buf char数组的强制转换版本上直接使用Copy是行不通的。这让我很惊讶,可能需要进一步研究,但为了避免这方面可能存在的任何问题,只需先转换为字符串,然后执行复制以从字符串中提取范围

在我上面的工作示例中,这是通过将转换后的buf低效地分配给Edit1.Text属性,然后对Edit1.Text属性使用Copy来实现的。实际上,您将使用中间字符串变量

WM_GETTEXT限制

在你的问题中,你需要一种适用于任何窗口类型的技术,包括浏览器和游戏。我不认为有一种通用的方法可以实现这一点,除非将屏幕捕获和OCR结合起来。这是因为浏览器和游戏等应用程序,甚至一些普通应用程序,都实现了窗口类,这些窗口类使其内容独立于窗口文本的任何概念,正如WM_GETTEXT所报告的那样。e、 g.浏览器窗口的窗口文本通常是浏览器/选项卡标题文本,而不是当前显示页面的HTML内容,由浏览器应用程序内部维护


如果应用程序实现自定义窗口类以呈现某些任意内容,如果您不熟悉相关的特定应用程序和/或该应用程序支持的已发布机制以实现您的目标,您就无法检索该内容。

这不是一个对我们有用的问题描述。让我们备份一下。它怎么不起作用?你收到错误信息了吗?如果是的话,哪一行失败了?不管英语语法是什么,你都没有告诉我们为什么或者如何它不起作用。你期望它做什么?到底发生了什么?这些是提问的基础,不仅仅是在这里,而是在任何地方。去问一个机修工,它坏了。你认为修理工能解决你汽车的问题吗?@MartynA:我的第一个评论是想向用户指出,这个问题没有提供任何信息。回复是我发布了它,这样你就不会说它是重复的,没有额外的细节,没有更多的信息,也没有努力改进这个问题。上面提到的问题对未来的读者没有多大用处。只是说说而已。你用的是哪个版本的Delphi?我这样问是因为您使用的是char类型,这意味着根据Delphi版本的不同而有所不同。2009及以上版本的char是Unicode WideChar,而之前的版本char是AnsiChar。我仍然认为这是一个简单的Unicode混合。这在浏览器页面、游戏或任何非前台窗口的应用程序中都不起作用。不投反对票;只是提到它并没有回答被问到的极其模糊的问题。@KenWhite非常正确,如果它是一个浏览器,比如OP的第一个使用示例,则不能保证您在浏览器内容中得到所选内容,因为它的光标跟踪完全独立于标准。事实上。我回答了问题中需要回答的部分,即如何使发布的代码按预期工作,以获取当前前景窗口的文本,发布的窗口确实不起作用,因为我认为这两种假设都是有效的EM_GETSEL结果。我将补充澄清,这是 仅限于通过WM_GETTEXT检索任何可用的文本,这当然不会处理外来/复杂的自定义窗口类实现(如浏览器和游戏)中的文本内容。还必须验证hFocus是否是有效的编辑小部件。