Я пытаюсь получить данные из другой программы. И … это все время дает мне ошибку! Что-то не так?
HWND hWnd = FindWindow(NULL, L"MyProgram");
if (hWnd)
{
HWND TPageControl = FindWindowEx(hWnd, NULL, L"TPageControl", NULL);
TPageControl = FindWindowEx(hWnd, TPageControl, L"TPageControl", NULL);
HWND TTabSheet = FindWindowEx(TPageControl, NULL, L"TTabSheet", NULL);
HWND TEdit = FindWindowEx(TTabSheet, NULL, L"TEdit", NULL);
int editlength = SendMessage(TEdit, WM_GETTEXTLENGTH, 0, NULL);
TCHAR* Targets = new TCHAR( editlength + 1 );
int count = SendMessage(TEdit, EM_GETLINE, editlength + 1, (LPARAM) Targets);
std::wcout << Targets << "\n";
//delete Targets;
}
но если я отлаживаю, это работает.
Вы не следуете документации для EM_GETLINE
. Первый параметр указывает индекс строки. Я предполагаю, что вы отправляете это сообщение в однострочный элемент управления, и оно просто игнорируется. Второй параметр должен содержать длину буфера:
Перед отправкой сообщения установите в первом слове этого буфера размер буфера в TCHAR.
Замечания для элементов управления редактирования также актуальны:
Скопированная строка не содержит завершающего нулевого символа.
Пока параметры для EM_GETLINE
автоматически маршалировать через границы процесса (как и все параметры сообщений для сообщений в диапазоне 0
в W_USER-1
), вы можете рассмотреть возможность отправки WM_GETTEXT
вместо этого, если вы имеете дело с однострочным управлением редактирования:
int editlength = SendMessage(TEdit, WM_GETTEXTLENGTH, 0, NULL);
TCHAR* Targets = new TCHAR[editlength + 1];
int count = SendMessage(TEdit, WM_GETTEXT, editlength + 1, (LPARAM) Targets);
// NUL-terminate buffer in case the text did not fit
Targets[count] = _T('\0');
std::wcout << Targets << "\n";
Если вы отправляете WM_GETTEXT
к зависшему приложению ваше приложение также будет зависать. Вызов GetWindowText
обойти это. Секретная жизнь GetWindowText имеет дополнительную справочную информацию.
Если вам нужно получить определенную строку из многострочного редактора, вам больше подходит следующее. В отличие от вашего кода он отправляет EM_LINEINDEX
а также EM_LINELENGTH
сообщение для получения соответствующего размера буфера:
int characterIndex = SendMessage(TEdit, EM_LINEINDEX, lineIndex, 0);
int lineLength = SendMessage(TEdit, EM_LINELENGTH, characterIndex, 0);
TCHAR* pBuffer = new TCHAR[lineLength + 1];
// Set the size of the buffer
*(WORD*)pBuffer = lineLength + 1;
// Retrieve the line
int characterCount = SendMessage(TEdit, EM_GETLINE, lineIndex, (LPARAM)pBuffer);
// NUL-terminate buffer
pBuffer[characterCount] = _T('\0');
Несколько слов о том, почему первоначальный код работает, когда запускается под отладчиком: разница не в отладчике. Это Debug Build это делает. Конфигурация отладки заполнит выделенную память конкретные шаблоны байтов (0xCD для operator new[]()
). Результатом этого является то, что буфер передается при отправке EM_GETLINE
интерпретируется как имеющий размер 0xCDCD (52685 в десятичном виде). В конфигурации выпуска, с другой стороны, содержимое буфера обычно составляет 0x00, то есть буфер интерпретируется как имеющий размер 0. Это не означает, что отладочная сборка работает. Это просто маскирует ошибку.
Других решений пока нет …