Получение имен столбцов из элемента управления SysHeader32 в другом процессе

Я делаю программу (program1), которая будет читать имя столбцов заголовка (SysHeader32), который находится в списке в виде отчета (SysListView32) в другой программе (program2).

Поэтому я хочу, чтобы моя программа вошла в другую программу и прочитала, как называется название для всех заголовков (SysHeader32), которые я нахожу. Поскольку в программе много разных списков и заголовков для каждого списка, я решил использовать EnumChildWindows функция с EnumChildProc функция обратного вызова для просмотра всех дескрипторов дочернего окна. С этими ручками я пользуюсь GetClassName() чтобы увидеть, что такое имя класса и когда я вижу, что это SysHeader32, я знаю, что нашел заголовок, который может содержать различные имена заголовков … но я понятия не имею, какой код я могу использовать для получения текста из этих различных заголовков, и я не знаю, как определить каждый заголовок …

Вот код, который у меня есть, который найдет дескриптор для каждого найденного заголовка SysHeader32:

BOOL CALLBACK EnumChildProc (HWND hWnd, LPARAM lParam)
{
char myBuffer [100];//buffer that will get the class name
GetClassName(hWnd, myBuffer, 100);
string myString (myBuffer);//converting myBuffer into a readable string

if (myString == "SysHeader32")
{
///here is where I am currently lost
///I just don't know how to get the text from the different titles/items
///in the header found
}
}

Вопрос 1 :: Как проверить, сколько разных заголовков / элементов в заголовке?

Вопрос 2 :: Как я могу получить текст для каждого из заголовков / элементов, найденных в заголовке?

Пожалуйста, предоставьте пример кода.

0

Решение

К сожалению, это не легко возможно при доступе к окну, созданному другой программой, потому что система не выполняет необходимую сортировку сообщений указателей в оконных сообщениях. Вам нужно будет сделать это из общего DLL-файла (создать в нем какой-нибудь общесистемный хук Windows для загрузки его в другие процессы) или с помощью других хаков, таких как доступ к памяти между процессами.


Если доступ к окну SysHeader32 в той же программе, это будет просто так:

  1. Отправить сообщение HDM_GETITEMCOUNT, возвращает количество предметов.

  2. Отправить сообщение HDM_GETITEM с wParam установить на индекс элемента для извлечения и lParam установить указатель для правильной установки HDITEM состав. Особенно установлено mask в HDI_TEXT и подготовить буфер для pszText и установите его длину в cchTextMax,

Пример:

int count = SendMessage(hWnd, HDM_GETITEMCOUNT, 0, 0);
std::cout << "There are " << count << " items.\n";

for (int i = 0; i < count; i++) {
TCHAR name[260];
HDITEM hdi;
hdi.mask = HDI_TEXT;
hdi.pszText = name;
hdi.cchTextMax = 260;
SendMessage(hWnd, HDM_GETITEM, i, reinterpret_cast<LPARAM>(&hdi));
std::cout << "  " << i << ") " << hdi.pszText << "\n";
}

Поскольку нам нужно хранить память ввода и вывода в пространстве другой программы, необходимо сделать что-то вроде этого (добавьте проверку ошибок и т. Д. По своему вкусу):

struct InterProcessData {
HDITEM hdi;
TCHAR buffer[260];
};

// Open the owning process and allocate a buffer big enough for
// our inter-process communication
DWORD dwProcessId;
GetWindowThreadProcessId(hWnd, &dwProcessId);
HANDLE hProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
FALSE, dwProcessId);
InterProcessData* pRemoteData = reinterpret_cast<InterProcessData*>(
VirtualAllocEx(hProcess, NULL, sizeof(InterProcessData), MEM_COMMIT, PAGE_READWRITE));

int count = SendMessage(hWnd, HDM_GETITEMCOUNT, 0, 0);
std::cout << "There are " << count << " items.\n";

for (int i = 0; i < count; i++) {
InterProcessData data;
data.hdi.mask = HDI_TEXT;
data.hdi.pszText = pRemoteData->buffer;
data.hdi.cchTextMax = 260;

// Write the HDITEM structure to the space in the remote process
// (without the buffer, its contents are undefined anyway)
WriteProcessMemory(hProcess, pRemoteData, &data, sizeof(data.hdi), NULL);

// Send the message itself, passing the remote address in lParam
SendMessage(hWnd, HDM_GETITEM, i, reinterpret_cast<LPARAM>(&pRemoteData->hdi));

// Read the data back, HDITEM and the buffer
ReadProcessMemory(hProcess, pRemoteData, &data, sizeof(data), NULL);

// The documentation says that the pszText can point elsewhere -
// copy it to our buffer in that case
if (data.hdi.pszText != pRemoteData->buffer)
ReadProcessMemory(hProcess, data.hdi.pszText, data.buffer, data.hdi.cchTextMax * sizeof(TCHAR), NULL);

std::cout << "  " << i << ") " << data.buffer << "\n";
}

// Cleanup
VirtualFreeEx(hProcess, pRemoteData, 0, MEM_RELEASE);
CloseHandle(hProcess);
0

Другие решения