2

Is there a standard message that can be sent to a text editor window or a certain WinApi call, that will retrieve the contents of the currently edited text?

For example, to retrieve the current contents of a Notepad window. (assumed that the most up to date text wasn't yet written to a file)

I've tried retrieving the text via SendMessage using WM_GETTEXTWM_GETTEXTLENGTH but I was able to retrieve the title text only.

golosovsky
  • 638
  • 1
  • 6
  • 19
  • 1
    Use `WM_GETTEXTLENGTH` to know how many characters are in the editor, then allocate a buffer of that size and use `WM_GETTEXT` or `GetWindowText()` to fill it with editor's actual text. If you just want the selected text, use `EM_GETSEL`/`EM_EXGETSEL` afterwards to determine the start/end indexes of the range of selected characters within that text, and then copy those characters out to another buffer. – Remy Lebeau Aug 19 '20 at 20:29
  • Typically you enumerate all processes IDs, check that the process has the required name, e.g. "notepad.exe". Then enumerate all threads for this process. Then use ```EnumThreadWindows``` API to get windows handles. Then check the window type/class - you only need text editboxes. Lastly you may use ```char text[256]; LRESULT result = SendMessage(windowHandle, WM_GETTEXT, sizeof(text), LPARAM(text));``` – dgrandm Aug 19 '20 at 20:38
  • 1
    `WM_GETTEXT` will work reliably on some programs, but more generally you want to use the Accessibility APIs that "screen reader" software uses – Ben Voigt Aug 19 '20 at 21:18
  • *"Is there a standard message"* - In general, no. *"\[...\] or a certain WinApi call"* - Yes, [UI Automation](https://learn.microsoft.com/en-us/windows/win32/winauto/entry-uiauto-win32). – IInspectable Aug 19 '20 at 21:18
  • https://stackoverflow.com/a/11042272/103167 – Ben Voigt Aug 19 '20 at 21:18
  • 2
    For an arbitrary text editor, no. The closest you will get is UI Automation – David Heffernan Aug 19 '20 at 21:35

1 Answers1

3

In general no there is no standard message for this.

But Windows' Notepad has an "Edit" child which responds to WM_GETTEXT and WM_GETTEXTLENGTH - messages normally used to retrieve text from input controls.

Here's a PoC demonstrating the idea:

#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);
}

Works on Windows 10:

retrieve text from running notepad winapi

rustyx
  • 80,671
  • 25
  • 200
  • 267