Я пытаюсь получить текст Richedit Control из другой программы.
Поэтому я нашел EM_STREAMOUT для SendMessage.
Это мой код (также из другой темы Stackoverflow):
DWORD CALLBACK EditStreamOutCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
{
std::stringstream *rtf = (std::stringstream*) dwCookie;
rtf->write((char*)pbBuff, cb);
*pcb = cb;
return 0;
}
int main() {
std::stringstream rtf;
EDITSTREAM es = {0};
es.dwCookie = (DWORD_PTR) &rtf;
es.pfnCallback = &EditStreamOutCallback;
SendMessage((HWND) 0x00000000000A06E8, EM_STREAMOUT, SF_RTF, (LPARAM)&es);
}
Единственное, что происходит, это то, что SendMessage возвращает 0 — так что очевидно, что не было прочитано ни одного байта — и программа, из которой я пытаюсь получить информацию, уходит до 100% загрузки ЦП.
Некоторые сообщения, такие как WM_GETTEXT
, маршалинг Windows для вас. Вот почему вы можете получить текст окна через границы процесса. EM_STREAMIN/OUT
не являются автоматически маршалируемыми. Вот почему ваш код падает. EDITSTREAM
Структура и код обратного вызова должны существовать в адресном пространстве того же процесса, который владеет RichEdit.
Для многих немаршированных сообщений, которые должны пересекать границы процесса, вы можете выделить буферы ввода / вывода, используя VirtualAllocEx()
, заполните их, используя WriteProcessMemory()
и читать из них, используя ReadProcessMemory()
, Но потому что EDITSTREAM
Код обратного вызова должен быть в том же процессе, вам лучше переместить весь EM_STREAMOUT
логику в DLL, а затем внедрить его в целевой процесс, используя CreateRemoteThread()
или другой метод инъекции. Ты можешь использовать GetWindowThreadProcessId()
чтобы получить идентификаторы процессов / потоков, которым принадлежит RichEdit. Затем ваша DLL может извлечь данные RichEdit и отправить их обратно в основное приложение, используя любой механизм IPC (межпроцессное взаимодействие) по вашему выбору, например именованный канал, почтовый ящик, WM_COPYDATA
сообщение и т. д.
Других решений пока нет …