Передача структуры в Windows API в Python ctypes
Я пытаюсь установить дату в SysDateTimeObject в приложении на Windows 7. Я использую Python 2.7 и библиотеку ctypes со следующим кодом, который пытается отправить сообщение DTM_SETSYSTEMTIME в SysDateTimeObject:
from ctypes import *
from ctypes.wintypes import BOOL,HWND,RECT,LPCSTR,UINT,INT,DWORD,WORD
import sys
import time
class SYSTEMTIME(Structure):
_fields_=[('wYear',WORD),
('wMonth',WORD),
('wDayOfWeek',WORD),
('wDay',WORD),
('wHour',WORD),
('wMinute',WORD),
('wSecond',WORD),
('wMilliseconds',WORD)]
self.user32 = windll.user32
my_time=SYSTEMTIME(2035,0,0,0,0,0,0,0)
self.user32.SendMessageW(window,c_uint(0x1002),0,byref(my_time))
window - это HWND для правильного SysDateTimeObject, а 0x1002 - это код сообщения DTM_SETSYSTEMTIME. Третий параметр SendMessageW - это константа для включения или отключения DateTimeControl. Я могу установить его на 1, и он отключит контроль, как и ожидалось. Четвертый параметр - указатель на заполненную структуру SYSTEMTIME. Тем не менее, кажется, ничего не делает, как написано выше. Я могу отправлять другие сообщения, но когда функция требует указатель на структуру, вещи начинают терпеть неудачу. Я неправильно использую ctypes?
1 ответ
Я использовал pywinauto, столкнулся с этой необходимостью и сумел ее решить. Причина проблемы в том, что вы пытаетесь запустить его в другом процессе, в то время как ваш SYSTEMTIME
структура находится в личной памяти вашего собственного процесса. Таким образом, всякий раз, когда он пытается что-то сделать с переданной структурой, он терпит неудачу - доступ запрещен. Вам нужен удаленный блок памяти для решения проблемы.
pywinauto.controls.common_controls._RemoteMemoryBlock
делает именно это
В конечном итоге вы получите такой код:
remote_mem = common_controls._RemoteMemoryBlock(window)
remote_mem.Write(my_time)
user32.SendMessageW(window, win32defines.DTM_SETSYSTEMTIME,
win32defines.GDT_VALID, remote_mem)
Если вам нужно использовать DTM_GETSYSTEMTIME, вы должны поставить my_time = remote_mem.Read(my_time)
после вызова SendMessage.