Автоматизация операций в устаревшей программе часто требует нестандартных подходов, особенно когда доступ к исходному коду программы ограничен. В данном случае, рассматривается вопрос изменения даты в компоненте TDateTimePicker через его HWND, когда программа, в которой он используется, не имеет доступного исходного кода и выполняется в отдельном процессе.
Оригинальный вопрос
Пользователь разрабатывает модуль для работы с устаревшей программой, в которой присутствует компонент TDateTimePicker. Поскольку исходный код программы недоступен, модуль должен выполняться в отдельном процессе. Необходимо автоматизировать операцию выбора даты в указанном компоненте, зная только его HWND.
Решение проблемы
Для изменения даты в TDateTimePicker можно использовать сообщение DTM_SETSYSTEMTIME, однако это сообщение требует, чтобы указатель на структуру SYSTEMTIME был валиден в адресном пространстве процесса, который владеет компонентом. Следовательно, необходимо выполнить следующие шаги:
Открыть процесс, который владеет HWND TDateTimePicker.
Выделить память для SYSTEMTIME в этом процессе.
Скопировать данные SYSTEMTIME из процесса пользователя в выделенную память.
Отправить сообщение DTM_SETSYSTEMTIME с указателем на выделенную память.
После выполнения этих шагов, TDateTimePicker обновит внутреннюю переменную TDateTime на новую дату, но это не приведёт к автоматическому обновлению уведомления DTN_DATETIMECHANGE. Для его генерации потребуется инжектировать код в процесс, который владеет TDateTimePicker, и отправить уведомление DTN_DATETIMECHANGE внутри этого процесса.
Пример кода на Object Pascal (Delphi)
Ниже приведён пример кода на Object Pascal, который демонстрирует процесс изменения даты в TDateTimePicker через его HWND:
uses
..., CommCtrl, Windows;
var
Wnd: HWND;
Pid: DWORD;
hProcess: THandle;
ST: TSystemTime;
PST: PSystemTime;
Written: SIZE_T;
begin
Wnd := ...; // HWND компонента TDateTimePicker
DateTimeToSystemTime(... , ST); // Задаем желаемую дату/время
GetWindowThreadProcessId(Wnd, Pid);
hProcess := OpenProcess(PROCESS_VM_WRITE or PROCESS_VM_OPERATION, FALSE, Pid);
if hProcess = 0 then
RaiseLastOSError;
try
PST := PSystemTime(VirtualAllocEx(hProcess, nil, SizeOf(ST), MEM_COMMIT, PAGE_READWRITE));
if PST = nil then
RaiseLastOSError;
try
if not WriteProcessMemory(hProcess, PST, @ST, SizeOf(ST), Written) then
RaiseLastOSError;
SendMessage(Wnd, DTM_SETSYSTEMTIME, GDT_VALID, LPARAM(PST));
finally
VirtualFreeEx(hProcess, PST, SizeOf(ST), MEM_DECOMMIT);
end;
finally
CloseHandle(hProcess);
end;
end;
Для отправки уведомления DTN_DATETIMECHANGE потребуется использовать функцию SendMessageRemote, которая реализует необходимую инъекцию кода в процесс владельца TDateTimePicker.
Заключение
Автоматизация операций в устаревшей программе через HWND может быть сложной задачей, требующей глубокого понимания работы оконных сообщений и межпроцессного взаимодействия. Однако, с правильным подходом и использованием функций Windows API, такая задача становится выполнимой.
Описание контекста: Пользователь разрабатывает модуль для автоматизации выбора даты в компоненте `TDateTimePicker` устаревшей программы без доступа к исходному коду, используя межпроцессное взаимодействие через HWND.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.