【问题标题】:winapi - a standard way to retrieve text from running text editorwinapi - 从正在运行的文本编辑器中检索文本的标准方法
【发布时间】:2020-08-19 20:12:58
【问题描述】:

是否有标准的message 可以发送到文本编辑器窗口或某个WinApi 调用,以检索当前编辑文本的内容? p>

例如,检索 记事本 窗口的当前内容。 (假设最新的文本尚未写入文件)

我尝试使用WM_GETTEXTWM_GETTEXTLENGTH 通过SendMessage 检索文本,但我只能检索到标题文本。

【问题讨论】:

  • 使用WM_GETTEXTLENGTH 知道编辑器中有多少个字符,然后分配一个该大小的缓冲区并使用WM_GETTEXTGetWindowText() 用编辑器的实际文本填充它。如果您只想要选定的文本,请稍后使用EM_GETSEL/EM_EXGETSEL 确定该文本中选定字符范围的开始/结束索引,然后将这些字符复制到另一个缓冲区。
  • 通常您会枚举所有进程 ID,检查进程是否具有所需的名称,例如“记事本.exe”。然后枚举该进程的所有线程。然后使用EnumThreadWindows API 获取窗口句柄。然后检查窗口类型/类 - 你只需要文本编辑框。最后你可以使用char text[256]; LRESULT result = SendMessage(windowHandle, WM_GETTEXT, sizeof(text), LPARAM(text));
  • WM_GETTEXT 可以在某些程序上可靠运行,但更一般地,您希望使用“屏幕阅读器”软件使用的辅助功能 API
  • “是否有标准消息” - 一般来说,没有。 “[...] 或某个 WinApi 调用” - 是的,UI Automation.
  • 对于任意文本编辑器,没有。您将获得的最接近的是 UI 自动化

标签: c++ windows winapi


【解决方案1】:

一般没有标准的消息。

但 Windows 的 Notepad 有一个“编辑”子级,它响应 WM_GETTEXTWM_GETTEXTLENGTH - 通常用于从输入控件中检索文本的消息。

这是一个演示该想法的 PoC:

#include <iostream>
#include <vector>
#include <string.h>
#include <Windows.h>

BOOL CALLBACK enumProc(HWND hwnd, LPARAM) {
    std::vector<char> buf(100);
    GetClassNameA(hwnd, buf.data(), 100);
    if (strcmp(buf.data(), "Notepad")) return TRUE;
    hwnd = FindWindowEx(hwnd, NULL, "Edit", NULL);
    if (!hwnd) return TRUE;
    int textLength = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0) + 1;
    if (textLength <= 0) return TRUE;
    buf.resize(textLength);
    SendMessage(hwnd, WM_GETTEXT, textLength, (LPARAM)buf.data());
    std::cout << buf.data() << "\n";
    return TRUE;
}

int main() {
    EnumWindows(&enumProc, 0);
}

适用于 Windows 10:

【讨论】:

  • 我尝试过使用 WM_GETTEXT - 它不是只返回窗口标题吗?
  • 您需要获取“编辑”子项 - 查看我的代码,它可以工作。
  • 任何比记事本更高级的东西都不会使用编辑控件,所以我想知道这个答案到底有多有用。
  • @JonathanPotter 答案中的第一句话指出没有标准的方法来检索文本,这是(不幸的是)一个有效的答案。
  • 有一个标准的方法。它是 UI 自动化。但并非每个程序都支持这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
相关资源
最近更新 更多