GetRawInputData模块的pData参数如何填写
How do I fill in the pData parameter of the GetRawInputData module
我是 ctypes 的新手,我在使用 GetRawInputData 函数时遇到了问题。我不确定如何填写第三个参数。这是代码现在的样子
def get_raw_input(handle):
dw_size = c_uint()
GetRawInputData(handle, RID_INPUT, None, byref(dw_size), sizeof(RawInputHeader))
lpb = LPBYTE(dw_size)
print(lpb.contents)
GetRawInputData(handle, RID_INPUT, lpb, byref(dw_size), sizeof(RawInputHeader))
print(lpb.contents)
return cast(lpb, POINTER(RawInput))
我是这样定义模块的:
GetRawInputData = user32.GetRawInputData
GetRawInputData.argtypes = INT, UINT, LPVOID, PUINT, UINT
GetRawInputData.restype = UINT
GetRawInputData.errcheck = errcheck
当 get_raw_input
为 运行 时,输出为以下之一:
c_byte(48)
c_byte(0)
c_byte(40)
c_byte(1)
有一些示例 C++ 代码 here,但我不确定在 Python.
中应该是什么样子
这是完整的 运行ning 代码(如果有点乱,请见谅):
window.py(运行s 的文件)
from ctypes import *
from ctypes.wintypes import *
from structures import *
from constants import *
from devices import get_raw_input, register_devices
import random
import sys
def errcheck(result,func,args):
if result is None or result == 0:
raise WinError(get_last_error())
return result
user32 = WinDLL('user32', use_last_error=True)
k32 = WinDLL('kernel32', use_last_error=True)
gdi32 = WinDLL('gdi32',use_last_error=True)
RegisterClass = user32.RegisterClassW
RegisterClass.argtypes = POINTER(WndClass),
RegisterClass.restype = ATOM
RegisterClass.errcheck = errcheck
CreateWindowEx = user32.CreateWindowExW
CreateWindowEx.argtypes = DWORD, LPCWSTR, LPCWSTR, DWORD, INT, INT, INT, INT, HWND, HMENU, HINSTANCE, LPVOID
CreateWindowEx.restype = HWND
CreateWindowEx.errcheck = errcheck
GetModuleHandle = k32.GetModuleHandleW
GetModuleHandle.argtypes = LPCWSTR,
GetModuleHandle.restype = HMODULE
GetModuleHandle.errcheck = errcheck
DefWindowProc = user32.DefWindowProcW
DefWindowProc.argtypes = HWND, UINT, WPARAM, LPARAM
DefWindowProc.restype = LRESULT
ShowWindow = user32.ShowWindow
ShowWindow.argtypes = HWND, INT
ShowWindow.restype = BOOL
UpdateWindow = user32.UpdateWindow
UpdateWindow.argtypes = HWND,
UpdateWindow.restype = BOOL
UpdateWindow.errcheck = errcheck
BeginPaint = user32.BeginPaint
BeginPaint.argtypes = HWND, POINTER(PaintStruct)
BeginPaint.restype = HDC
BeginPaint.errcheck = errcheck
FillRect = user32.FillRect
FillRect.argtypes = HDC, POINTER(RECT), HBRUSH
FillRect.restype = INT
FillRect.errcheck = errcheck
EndPaint = user32.EndPaint
EndPaint.argtypes = HWND, POINTER(PaintStruct)
EndPaint.restype = BOOL
EndPaint.errcheck = errcheck
PostQuitMessage = user32.PostQuitMessage
PostQuitMessage.argtypes = INT,
PostQuitMessage.restype = None
TranslateMessage = user32.TranslateMessage
TranslateMessage.argtypes = POINTER(MSG),
TranslateMessage.restype = BOOL
DispatchMessage = user32.DispatchMessageW
DispatchMessage.argtypes = POINTER(MSG),
DispatchMessage.restype = LRESULT
GetClientRect = user32.GetClientRect
GetClientRect.argtypes = HWND, POINTER(RECT)
GetClientRect.restype = BOOL
GetClientRect.errcheck = errcheck
GetMessage = user32.GetMessageW
GetMessage.argtypes = POINTER(MSG), HWND, UINT, UINT
GetMessage.restype = BOOL
DrawText = user32.DrawTextW
DrawText.argtypes = HDC, LPCWSTR, INT, POINTER(RECT), UINT
DrawText.restype = LRESULT
LoadIcon = user32.LoadIconW
LoadIcon.argtypes = HINSTANCE, LPCWSTR
LoadIcon.restype = HICON
LoadIcon.errcheck = errcheck
LoadCursor = user32.LoadCursorW
LoadCursor.argtypes = HINSTANCE, LPCWSTR
LoadCursor.restype = HCURSOR
LoadCursor.errcheck = errcheck
GetStockObject = gdi32.GetStockObject
GetStockObject.argtypes = INT,
GetStockObject.restype = HGDIOBJ
CreateSolidBrush = gdi32.CreateSolidBrush
CreateSolidBrush.argtypes = COLORREF,
CreateSolidBrush.restype = HBRUSH
TextOut = gdi32.TextOutW
TextOut.argtypes = HDC, INT, INT, LPCWSTR, INT
TextOut.restype = INT
SetBkMode = gdi32.SetBkMode
SetBkMode.argtypes = HDC, INT
SetBkMode.restype = INT
SetTextColor = gdi32.SetTextColor
SetTextColor.argtypes = HDC, COLORREF
SetTextColor.restype = COLORREF
def window_callback(handle, message, w_param, l_param):
ps = PaintStruct()
rect = RECT()
if message == WM_PAINT:
hdc = BeginPaint(handle, byref(ps))
GetClientRect(handle, byref(rect))
SetBkMode(hdc, -1)
SetTextColor(hdc, 0xFFFFFF)
FillRect(hdc, byref(ps.rcPaint), CreateSolidBrush(0x0))
DrawText(hdc, 'Testing oawguna', -1, byref(rect), DT_SINGLELINE|DT_CENTER|DT_VCENTER)
EndPaint(handle, byref(ps))
return 0
elif message == WM_INPUT:
raw_input = get_raw_input(l_param)
elif message == WM_DESTROY:
PostQuitMessage(0)
return 0
return DefWindowProc(handle, message, w_param, l_param)
def run():
instance = GetModuleHandle(None)
class_name = 'TestWindow'
wnd = WndClass()
wnd.style = CS_HREDRAW | CS_VREDRAW
wnd.lpfnWndProc = WNDPROC(window_callback)
wnd.hInstace = instance
wnd.hCursor = LoadCursor(None, IDC_ARROW)
wnd.lpszClassName = class_name
RegisterClass(byref(wnd))
handle = CreateWindowEx(
0, class_name, 'Python Window', WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
None, None, instance, None
)
ShowWindow(handle, SW_NORMAL)
UpdateWindow(handle)
register_devices(handle)
msg = MSG()
while GetMessage(byref(msg), None, 0, 0) != 0:
TranslateMessage(byref(msg))
DispatchMessage(byref(msg))
return msg.wParam
if __name__ == "__main__":
sys.exit(run())
devices.py:
from ctypes import *
from ctypes.wintypes import *
from structures import *
from constants import *
def errcheck(result,func,args):
if result is None or result == -1:
raise WinError(get_last_error())
return result
user32 = WinDLL('user32', use_last_error=True)
RegisterRawInputDevices = user32.RegisterRawInputDevices
RegisterRawInputDevices.argtypes = (RawInputDevice * 7), UINT, UINT
RegisterRawInputDevices.restype = BOOL
RegisterRawInputDevices.errcheck = errcheck
GetRawInputData = user32.GetRawInputData
GetRawInputData.argtypes = INT, UINT, LPVOID, PUINT, UINT
GetRawInputData.restype = UINT
GetRawInputData.errcheck = errcheck
def register_devices(hwnd_target=None):
page = 0x01
devices = (RawInputDevice * 7)(
RawInputDevice(page, 0x01, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x02, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x04, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x05, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x06, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x07, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x08, DW_FLAGS, hwnd_target),
)
RegisterRawInputDevices(devices, len(devices), sizeof(devices[0]))
def get_raw_input(handle):
dw_size = c_uint()
GetRawInputData(handle, RID_INPUT, None, byref(dw_size), sizeof(RawInputHeader))
lpb = LPBYTE(dw_size)
print(lpb.contents)
GetRawInputData(handle, RID_INPUT, lpb, byref(dw_size), sizeof(RawInputHeader))
print(lpb.contents)
return cast(lpb, POINTER(RawInput))
constants.py:
from ctypes.wintypes import *
from ctypes import c_int64, WINFUNCTYPE, c_void_p
LRESULT = c_int64
HCURSOR = c_void_p
USAGE_PAGE = 0x01
USAGE = 0x06
DW_FLAGS = 0
DW_TYPE = 2
WM_INPUT = 0x00FF
WM_PAINT = 0x000F
WM_DESTROY = 0x0002
WM_QUI = 0x0012
RIDI_DEVICENAME = 0x20000007
RIDI_DEVICEINFO = 0x2000000b
ERROR_INSUFFICIENT_BUFFER = 0x7A
WS_EX_CLIENTEDGE = 0x00000200
WS_BORDER = 0x00800000
CS_BYTEALIGNCLIENT = 0x1000
CS_HREDRAW = 2
CS_VREDRAW = 1
SW_NORMAL = 1
CW_USEDEFAULT = -2147483648
WS_OVERLAPPED = 0x00000000
WS_CAPTION = 0x00C00000
WS_SYSMENU = 0x00080000
WS_THICKFRAME = 0x00040000
WS_MINIMIZEBOX = 0x00020000
WS_MAXIMIZEBOX = 0x00010000
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
RID_INPUT = 0x10000003
PM_REMOVE = 0x0001
DT_SINGLELINE = 32
DT_CENTER = 1
DT_VCENTER = 4
IDI_APPLICATION = LPCWSTR(32512)
IDC_ARROW = LPCWSTR(32512)
WHITE_BRUSH = 0
WNDPROC = WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM)
structures.py:
from ctypes import Structure, windll, WINFUNCTYPE, c_int64, Union, c_byte, c_void_p
from ctypes.wintypes import *
from constants import *
HCURSOR = c_void_p
class RawInputDevice(Structure):
_fields_ = [
("usUsagePage", USHORT),
("usUsage", USHORT),
("dwFlags", DWORD),
("hwndTarget", HWND),
]
class RawInputDeviceList(Structure):
_fields_ = [
("hDevice", HANDLE),
("dwType", DWORD),
]
class RIDDeviceInfoHID(Structure):
_fields_ = [
("dwVendorId", DWORD),
("dwProductId", DWORD),
("dwVersionNumber", DWORD),
("usUsagePage", USHORT),
("usUsage", USHORT),
]
class RIDDeviceInfo(Structure):
_fields_ = [
("cbSize", DWORD),
("dwType", DWORD),
("hid", RIDDeviceInfoHID),
]
class WndClass(Structure):
_fields_ = [
("style", UINT),
("lpfnWndProc", WNDPROC),
("cbClsExtra", INT),
("cbWndExtra", INT),
("hInstance", HINSTANCE),
("hIcon", HICON),
("hCursor", HCURSOR),
("hbrBackground", HBRUSH),
("lpszMenuName", LPCWSTR),
("lpszClassName", LPCWSTR),
]
class PaintStruct(Structure):
_fields_ = [
("hdc", HDC),
("fErase", BOOL),
("rcPaint", RECT),
("fRestore", BOOL),
("fIncUpdate", BOOL),
("rgbReserved", BYTE * 32),
]
class RawInputHeader(Structure):
_fields_ = [
("dwType", DWORD),
("dwSize", DWORD),
("hDevice", HANDLE),
("wParam", WPARAM),
]
class RawHID(Structure):
_fields_ = [
("dwSizeHid", DWORD),
("dwCount", DWORD),
("bRawData", BYTE),
]
class MouseStruct(Structure):
_fields_ = [
("usButtonFlags", USHORT),
("usButtonData", USHORT)
]
class MouseUnion(Union):
_fields_ = [
("ulButtons", ULONG),
("data", MouseStruct)
]
class RawMouse(Structure):
_fields_ = [
("usFlags", USHORT),
("data", MouseUnion),
("ulRawButtons", ULONG),
("lLastX", LONG),
("lLastY", LONG),
("ulExtraInformation", ULONG),
]
class RawKeyboard(Structure):
_fields_ = [
("MakeCode", USHORT),
("Flags", USHORT),
("Reserved", USHORT),
("VKey", USHORT),
("Message", UINT),
("ExtraInformation", ULONG),
]
class RawUnion(Union):
_fields_ = [
("mouse", RawMouse),
("keyboard", RawKeyboard),
("hid", RawHID)
]
class RawInput(Structure):
_fields_ = [
("header", RawInputHeader),
("data", RawUnion),
]
清单[Python.Docs]: ctypes - A foreign function library for Python.
此(修复)已作为 的一部分涵盖。
问题是LPBYTE (POINTER(c_byte))初始化:
没有参数,包装一个NULL指针
使用参数(整数值),它将将该值存储在指向的区域(并且不使用它作为大小)。
更多,该区域将是 064bit 大 (通过实验发现)意味着尝试在其外部索引会触发 Undefined Behavior,即使程序没有崩溃(那是因为旁边的区域没有被认领由其他变量)
要分配一定大小的内存区域,使用create_string_buffer(或者一个数组——但是你会将其传递给需要指针的函数时必须 cast)。
>>> import ctypes as ct
>>> import ctypes.wintypes as wt
>>>
>>>
>>> pb0 = wt.LPBYTE()
>>> bool(pb0)
False
>>> pb0.contents
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: NULL pointer access
>>>
>>> ll = ct.c_longlong(0x010203040506070809) # Will be truncated (head part - due to little endianness)
>>> pb1 = wt.LPBYTE(ll)
>>> bool(pb1)
True
>>> pb1.contents
c_byte(9)
>>> [pb1[e] for e in range(0, 10)] # @TODO - cfati: will genarate UB !!!
[9, 8, 7, 6, 5, 4, 3, 2, 0, 0]
>>>
>>> buf = ct.create_string_buffer(12)
>>> len(buf)
12
>>> buf[0]
b'\x00'
>>> buf[12]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: invalid index
我是 ctypes 的新手,我在使用 GetRawInputData 函数时遇到了问题。我不确定如何填写第三个参数。这是代码现在的样子
def get_raw_input(handle):
dw_size = c_uint()
GetRawInputData(handle, RID_INPUT, None, byref(dw_size), sizeof(RawInputHeader))
lpb = LPBYTE(dw_size)
print(lpb.contents)
GetRawInputData(handle, RID_INPUT, lpb, byref(dw_size), sizeof(RawInputHeader))
print(lpb.contents)
return cast(lpb, POINTER(RawInput))
我是这样定义模块的:
GetRawInputData = user32.GetRawInputData
GetRawInputData.argtypes = INT, UINT, LPVOID, PUINT, UINT
GetRawInputData.restype = UINT
GetRawInputData.errcheck = errcheck
当 get_raw_input
为 运行 时,输出为以下之一:
c_byte(48)
c_byte(0)
c_byte(40)
c_byte(1)
有一些示例 C++ 代码 here,但我不确定在 Python.
中应该是什么样子这是完整的 运行ning 代码(如果有点乱,请见谅):
window.py(运行s 的文件)
from ctypes import *
from ctypes.wintypes import *
from structures import *
from constants import *
from devices import get_raw_input, register_devices
import random
import sys
def errcheck(result,func,args):
if result is None or result == 0:
raise WinError(get_last_error())
return result
user32 = WinDLL('user32', use_last_error=True)
k32 = WinDLL('kernel32', use_last_error=True)
gdi32 = WinDLL('gdi32',use_last_error=True)
RegisterClass = user32.RegisterClassW
RegisterClass.argtypes = POINTER(WndClass),
RegisterClass.restype = ATOM
RegisterClass.errcheck = errcheck
CreateWindowEx = user32.CreateWindowExW
CreateWindowEx.argtypes = DWORD, LPCWSTR, LPCWSTR, DWORD, INT, INT, INT, INT, HWND, HMENU, HINSTANCE, LPVOID
CreateWindowEx.restype = HWND
CreateWindowEx.errcheck = errcheck
GetModuleHandle = k32.GetModuleHandleW
GetModuleHandle.argtypes = LPCWSTR,
GetModuleHandle.restype = HMODULE
GetModuleHandle.errcheck = errcheck
DefWindowProc = user32.DefWindowProcW
DefWindowProc.argtypes = HWND, UINT, WPARAM, LPARAM
DefWindowProc.restype = LRESULT
ShowWindow = user32.ShowWindow
ShowWindow.argtypes = HWND, INT
ShowWindow.restype = BOOL
UpdateWindow = user32.UpdateWindow
UpdateWindow.argtypes = HWND,
UpdateWindow.restype = BOOL
UpdateWindow.errcheck = errcheck
BeginPaint = user32.BeginPaint
BeginPaint.argtypes = HWND, POINTER(PaintStruct)
BeginPaint.restype = HDC
BeginPaint.errcheck = errcheck
FillRect = user32.FillRect
FillRect.argtypes = HDC, POINTER(RECT), HBRUSH
FillRect.restype = INT
FillRect.errcheck = errcheck
EndPaint = user32.EndPaint
EndPaint.argtypes = HWND, POINTER(PaintStruct)
EndPaint.restype = BOOL
EndPaint.errcheck = errcheck
PostQuitMessage = user32.PostQuitMessage
PostQuitMessage.argtypes = INT,
PostQuitMessage.restype = None
TranslateMessage = user32.TranslateMessage
TranslateMessage.argtypes = POINTER(MSG),
TranslateMessage.restype = BOOL
DispatchMessage = user32.DispatchMessageW
DispatchMessage.argtypes = POINTER(MSG),
DispatchMessage.restype = LRESULT
GetClientRect = user32.GetClientRect
GetClientRect.argtypes = HWND, POINTER(RECT)
GetClientRect.restype = BOOL
GetClientRect.errcheck = errcheck
GetMessage = user32.GetMessageW
GetMessage.argtypes = POINTER(MSG), HWND, UINT, UINT
GetMessage.restype = BOOL
DrawText = user32.DrawTextW
DrawText.argtypes = HDC, LPCWSTR, INT, POINTER(RECT), UINT
DrawText.restype = LRESULT
LoadIcon = user32.LoadIconW
LoadIcon.argtypes = HINSTANCE, LPCWSTR
LoadIcon.restype = HICON
LoadIcon.errcheck = errcheck
LoadCursor = user32.LoadCursorW
LoadCursor.argtypes = HINSTANCE, LPCWSTR
LoadCursor.restype = HCURSOR
LoadCursor.errcheck = errcheck
GetStockObject = gdi32.GetStockObject
GetStockObject.argtypes = INT,
GetStockObject.restype = HGDIOBJ
CreateSolidBrush = gdi32.CreateSolidBrush
CreateSolidBrush.argtypes = COLORREF,
CreateSolidBrush.restype = HBRUSH
TextOut = gdi32.TextOutW
TextOut.argtypes = HDC, INT, INT, LPCWSTR, INT
TextOut.restype = INT
SetBkMode = gdi32.SetBkMode
SetBkMode.argtypes = HDC, INT
SetBkMode.restype = INT
SetTextColor = gdi32.SetTextColor
SetTextColor.argtypes = HDC, COLORREF
SetTextColor.restype = COLORREF
def window_callback(handle, message, w_param, l_param):
ps = PaintStruct()
rect = RECT()
if message == WM_PAINT:
hdc = BeginPaint(handle, byref(ps))
GetClientRect(handle, byref(rect))
SetBkMode(hdc, -1)
SetTextColor(hdc, 0xFFFFFF)
FillRect(hdc, byref(ps.rcPaint), CreateSolidBrush(0x0))
DrawText(hdc, 'Testing oawguna', -1, byref(rect), DT_SINGLELINE|DT_CENTER|DT_VCENTER)
EndPaint(handle, byref(ps))
return 0
elif message == WM_INPUT:
raw_input = get_raw_input(l_param)
elif message == WM_DESTROY:
PostQuitMessage(0)
return 0
return DefWindowProc(handle, message, w_param, l_param)
def run():
instance = GetModuleHandle(None)
class_name = 'TestWindow'
wnd = WndClass()
wnd.style = CS_HREDRAW | CS_VREDRAW
wnd.lpfnWndProc = WNDPROC(window_callback)
wnd.hInstace = instance
wnd.hCursor = LoadCursor(None, IDC_ARROW)
wnd.lpszClassName = class_name
RegisterClass(byref(wnd))
handle = CreateWindowEx(
0, class_name, 'Python Window', WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
None, None, instance, None
)
ShowWindow(handle, SW_NORMAL)
UpdateWindow(handle)
register_devices(handle)
msg = MSG()
while GetMessage(byref(msg), None, 0, 0) != 0:
TranslateMessage(byref(msg))
DispatchMessage(byref(msg))
return msg.wParam
if __name__ == "__main__":
sys.exit(run())
devices.py:
from ctypes import *
from ctypes.wintypes import *
from structures import *
from constants import *
def errcheck(result,func,args):
if result is None or result == -1:
raise WinError(get_last_error())
return result
user32 = WinDLL('user32', use_last_error=True)
RegisterRawInputDevices = user32.RegisterRawInputDevices
RegisterRawInputDevices.argtypes = (RawInputDevice * 7), UINT, UINT
RegisterRawInputDevices.restype = BOOL
RegisterRawInputDevices.errcheck = errcheck
GetRawInputData = user32.GetRawInputData
GetRawInputData.argtypes = INT, UINT, LPVOID, PUINT, UINT
GetRawInputData.restype = UINT
GetRawInputData.errcheck = errcheck
def register_devices(hwnd_target=None):
page = 0x01
devices = (RawInputDevice * 7)(
RawInputDevice(page, 0x01, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x02, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x04, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x05, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x06, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x07, DW_FLAGS, hwnd_target),
RawInputDevice(page, 0x08, DW_FLAGS, hwnd_target),
)
RegisterRawInputDevices(devices, len(devices), sizeof(devices[0]))
def get_raw_input(handle):
dw_size = c_uint()
GetRawInputData(handle, RID_INPUT, None, byref(dw_size), sizeof(RawInputHeader))
lpb = LPBYTE(dw_size)
print(lpb.contents)
GetRawInputData(handle, RID_INPUT, lpb, byref(dw_size), sizeof(RawInputHeader))
print(lpb.contents)
return cast(lpb, POINTER(RawInput))
constants.py:
from ctypes.wintypes import *
from ctypes import c_int64, WINFUNCTYPE, c_void_p
LRESULT = c_int64
HCURSOR = c_void_p
USAGE_PAGE = 0x01
USAGE = 0x06
DW_FLAGS = 0
DW_TYPE = 2
WM_INPUT = 0x00FF
WM_PAINT = 0x000F
WM_DESTROY = 0x0002
WM_QUI = 0x0012
RIDI_DEVICENAME = 0x20000007
RIDI_DEVICEINFO = 0x2000000b
ERROR_INSUFFICIENT_BUFFER = 0x7A
WS_EX_CLIENTEDGE = 0x00000200
WS_BORDER = 0x00800000
CS_BYTEALIGNCLIENT = 0x1000
CS_HREDRAW = 2
CS_VREDRAW = 1
SW_NORMAL = 1
CW_USEDEFAULT = -2147483648
WS_OVERLAPPED = 0x00000000
WS_CAPTION = 0x00C00000
WS_SYSMENU = 0x00080000
WS_THICKFRAME = 0x00040000
WS_MINIMIZEBOX = 0x00020000
WS_MAXIMIZEBOX = 0x00010000
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
RID_INPUT = 0x10000003
PM_REMOVE = 0x0001
DT_SINGLELINE = 32
DT_CENTER = 1
DT_VCENTER = 4
IDI_APPLICATION = LPCWSTR(32512)
IDC_ARROW = LPCWSTR(32512)
WHITE_BRUSH = 0
WNDPROC = WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM)
structures.py:
from ctypes import Structure, windll, WINFUNCTYPE, c_int64, Union, c_byte, c_void_p
from ctypes.wintypes import *
from constants import *
HCURSOR = c_void_p
class RawInputDevice(Structure):
_fields_ = [
("usUsagePage", USHORT),
("usUsage", USHORT),
("dwFlags", DWORD),
("hwndTarget", HWND),
]
class RawInputDeviceList(Structure):
_fields_ = [
("hDevice", HANDLE),
("dwType", DWORD),
]
class RIDDeviceInfoHID(Structure):
_fields_ = [
("dwVendorId", DWORD),
("dwProductId", DWORD),
("dwVersionNumber", DWORD),
("usUsagePage", USHORT),
("usUsage", USHORT),
]
class RIDDeviceInfo(Structure):
_fields_ = [
("cbSize", DWORD),
("dwType", DWORD),
("hid", RIDDeviceInfoHID),
]
class WndClass(Structure):
_fields_ = [
("style", UINT),
("lpfnWndProc", WNDPROC),
("cbClsExtra", INT),
("cbWndExtra", INT),
("hInstance", HINSTANCE),
("hIcon", HICON),
("hCursor", HCURSOR),
("hbrBackground", HBRUSH),
("lpszMenuName", LPCWSTR),
("lpszClassName", LPCWSTR),
]
class PaintStruct(Structure):
_fields_ = [
("hdc", HDC),
("fErase", BOOL),
("rcPaint", RECT),
("fRestore", BOOL),
("fIncUpdate", BOOL),
("rgbReserved", BYTE * 32),
]
class RawInputHeader(Structure):
_fields_ = [
("dwType", DWORD),
("dwSize", DWORD),
("hDevice", HANDLE),
("wParam", WPARAM),
]
class RawHID(Structure):
_fields_ = [
("dwSizeHid", DWORD),
("dwCount", DWORD),
("bRawData", BYTE),
]
class MouseStruct(Structure):
_fields_ = [
("usButtonFlags", USHORT),
("usButtonData", USHORT)
]
class MouseUnion(Union):
_fields_ = [
("ulButtons", ULONG),
("data", MouseStruct)
]
class RawMouse(Structure):
_fields_ = [
("usFlags", USHORT),
("data", MouseUnion),
("ulRawButtons", ULONG),
("lLastX", LONG),
("lLastY", LONG),
("ulExtraInformation", ULONG),
]
class RawKeyboard(Structure):
_fields_ = [
("MakeCode", USHORT),
("Flags", USHORT),
("Reserved", USHORT),
("VKey", USHORT),
("Message", UINT),
("ExtraInformation", ULONG),
]
class RawUnion(Union):
_fields_ = [
("mouse", RawMouse),
("keyboard", RawKeyboard),
("hid", RawHID)
]
class RawInput(Structure):
_fields_ = [
("header", RawInputHeader),
("data", RawUnion),
]
清单[Python.Docs]: ctypes - A foreign function library for Python.
此(修复)已作为
问题是LPBYTE (POINTER(c_byte))初始化:
没有参数,包装一个NULL指针
使用参数(整数值),它将将该值存储在指向的区域(并且不使用它作为大小)。
更多,该区域将是 064bit 大 (通过实验发现)意味着尝试在其外部索引会触发 Undefined Behavior,即使程序没有崩溃(那是因为旁边的区域没有被认领由其他变量)
要分配一定大小的内存区域,使用create_string_buffer(或者一个数组——但是你会将其传递给需要指针的函数时必须 cast)。
>>> import ctypes as ct >>> import ctypes.wintypes as wt >>> >>> >>> pb0 = wt.LPBYTE() >>> bool(pb0) False >>> pb0.contents Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: NULL pointer access >>> >>> ll = ct.c_longlong(0x010203040506070809) # Will be truncated (head part - due to little endianness) >>> pb1 = wt.LPBYTE(ll) >>> bool(pb1) True >>> pb1.contents c_byte(9) >>> [pb1[e] for e in range(0, 10)] # @TODO - cfati: will genarate UB !!! [9, 8, 7, 6, 5, 4, 3, 2, 0, 0] >>> >>> buf = ct.create_string_buffer(12) >>> len(buf) 12 >>> buf[0] b'\x00' >>> buf[12] Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: invalid index