Python 和 Ctypes - 放大 DLL
Python and Ctypes - Magnification DLL
我的目标是使用 Ctypes 在 Python 3.6 中从 Windows 运行 获得 magnification.dll。我可以缩放屏幕,但无法进行输入转换。
我希望有人知道如何解决这个问题,并能向我解释我做错了什么。谢谢。 ( Magnification API (Windows) )
P.s。您可能需要手动关闭 python 进程,因为缩放不会停止。 (至少在 Visual Studio 代码中)
magnification_api.py
import ctypes
class RECT(ctypes.Structure):
_fields_ = [("left", ctypes.c_long),
("top", ctypes.c_long),
("right", ctypes.c_long),
("bottom", ctypes.c_long)]
class Magnification:
def __init__(self):
self.dll = ctypes.CDLL("magnification.dll")
BOOL = ctypes.c_bool
FLOAT = ctypes.c_float
INT = ctypes.c_int
self.LPRECT = LPRECT = ctypes.POINTER(RECT)
self.PBOOL = PBOOL = ctypes.POINTER(ctypes.c_bool)
# MagInitialize
self.dll.MagInitialize.restype = BOOL
# MagUninitialize
self.dll.MagUninitialize.restype = BOOL
# MagSetFullscreenTransform
self.dll.MagSetFullscreenTransform.restype = BOOL
self.dll.MagSetFullscreenTransform.argtypes = (FLOAT, INT, INT)
# MagGetInputTransform
self.dll.MagGetInputTransform.restype = BOOL
self.dll.MagGetInputTransform.argtypes = (PBOOL, LPRECT, LPRECT)
def MagInitialize(self):
return self.dll.MagInitialize()
def MagUninitialize(self):
return self.dll.MagUninitialize()
def MagSetFullscreenTransform(self, magLevel, xOffset, yOffset):
return self.dll.MagSetFullscreenTransform(magLevel, xOffset, yOffset)
def MagGetInputTransform(self, pfEnabled, prcSource, prcDest):
return self.dll.MagGetInputTransform(pfEnabled, prcSource, prcDest)
zoomer.py
import ctypes
from magnification_api import Magnification
import time
class Main:
def __init__(self):
self.mag = Magnification()
def zoom(self, factor, x, y):
if factor > 1.0:
while True:
if self.mag.MagInitialize():
result = self.mag.MagSetFullscreenTransform(factor, 0, 0)
if result:
fInputTransformEnabled = self.mag.PBOOL()
rcInputTransformSource = self.mag.LPRECT()
rcInputTransformDest = self.mag.LPRECT()
if self.mag.MagGetInputTransform(fInputTransformEnabled, rcInputTransformSource, rcInputTransformDest):
# fails here
print("Success")
else:
print("Failed")
time.sleep(1)
if __name__ == "__main__":
m = Main()
m.zoom(1.05, 0, 0)
我想首先指出代码中不正确的其他内容(不一定与错误相关):
这里好像是在重新发明轮子。使用 wintypes 模块(仅在文档中提及),它具有此场景所需的一切:
>>> from ctypes import wintypes
>>> dir(wintypes)
['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'CHAR', 'COLORREF', 'DOUBLE', 'DWORD', 'FILETIME', 'FLOAT', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH', 'HCOLORSPACE', 'HDC', 'HDESK', 'HDWP', 'HENHMETAFILE', 'HFONT', 'HGDIOBJ', 'HGLOBAL', 'HHOOK', 'HICON', 'HINSTANCE', 'HKEY', 'HKL', 'HLOCAL', 'HMENU', 'HMETAFILE', 'HMODULE', 'HMONITOR', 'HPALETTE', 'HPEN', 'HRGN', 'HRSRC', 'HSTR', 'HTASK', 'HWINSTA', 'HWND', 'INT', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', 'LGRPID', 'LONG', 'LPARAM', 'LPBOOL', 'LPBYTE', 'LPCOLESTR', 'LPCOLORREF', 'LPCSTR', 'LPCVOID', 'LPCWSTR', 'LPDWORD', 'LPFILETIME', 'LPHANDLE', 'LPHKL', 'LPINT', 'LPLONG', 'LPMSG', 'LPOLESTR', 'LPPOINT', 'LPRECT', 'LPRECTL', 'LPSC_HANDLE', 'LPSIZE', 'LPSIZEL', 'LPSTR', 'LPUINT', 'LPVOID', 'LPWIN32_FIND_DATAA', 'LPWIN32_FIND_DATAW', 'LPWORD', 'LPWSTR', 'MAX_PATH', 'MSG', 'OLESTR', 'PBOOL', 'PBOOLEAN', 'PBYTE', 'PCHAR', 'PDWORD', 'PFILETIME', 'PFLOAT', 'PHANDLE', 'PHKEY', 'PINT', 'PLARGE_INTEGER', 'PLCID', 'PLONG', 'PMSG', 'POINT', 'POINTL', 'PPOINT', 'PPOINTL', 'PRECT', 'PRECTL', 'PSHORT', 'PSIZE', 'PSIZEL', 'PSMALL_RECT', 'PUINT', 'PULARGE_INTEGER', 'PULONG', 'PUSHORT', 'PWCHAR', 'PWIN32_FIND_DATAA', 'PWIN32_FIND_DATAW', 'PWORD', 'RECT', 'RECTL', 'RGB', 'SC_HANDLE', 'SERVICE_STATUS_HANDLE', 'SHORT', 'SIZE', 'SIZEL', 'SMALL_RECT', 'UINT', 'ULARGE_INTEGER', 'ULONG', 'USHORT', 'VARIANT_BOOL', 'WCHAR', 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', 'WORD', 'WPARAM', '_COORD', '_FILETIME', '_LARGE_INTEGER', '_POINTL', '_RECTL', '_SMALL_RECT', '_ULARGE_INTEGER', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'ctypes', 'tagMSG', 'tagPOINT', 'tagRECT', 'tagSIZE']
作为子注释,BOOL
的自定义定义与 Win 的自定义定义不匹配:
>>> ctypes.sizeof(ctypes.c_bool)
1
>>> ctypes.sizeof(wintypes.BOOL)
4
这是 访问冲突的候选者
- 像
self.LPRECT = LPRECT = ctypes.POINTER(RECT)
这样的东西看起来很奇怪。类型不应该是实例的成员
- 尽量关注[Python]: PEP 8 -- Style Guide for Python Code
- 其他不值得一提的小问题
回到错误:是ERROR_INVALID_PARAMETER,因为所有3个参数都传递给了MagGetInputTransform是 NULL 指针,如 [Python 3]: Pointers 状态:
Calling the pointer type without an argument creates a NULL
pointer.
要修复它(这只是一种方法 - 我觉得最直接)更改:
初始化3个变量:
fInputTransformEnabled = wintypes.BOOL()
rcInputTransformSource = wintypes.RECT()
rcInputTransformDest = wintypes.RECT()
它们传递给MagGetInputTransform的方式:
if self.mag.MagGetInputTransform(ctypes.byref(fInputTransformEnabled), ctypes.byref(rcInputTransformSource), ctypes.byref(rcInputTransformDest)):
一切都应该没问题(但是所有 3 个变量都已填充 0s)。
注意:当您在 Win 上遇到错误时,[MSDN]: GetLastError function 是您最好的朋友!
我的目标是使用 Ctypes 在 Python 3.6 中从 Windows 运行 获得 magnification.dll。我可以缩放屏幕,但无法进行输入转换。 我希望有人知道如何解决这个问题,并能向我解释我做错了什么。谢谢。 ( Magnification API (Windows) )
P.s。您可能需要手动关闭 python 进程,因为缩放不会停止。 (至少在 Visual Studio 代码中)
magnification_api.py
import ctypes
class RECT(ctypes.Structure):
_fields_ = [("left", ctypes.c_long),
("top", ctypes.c_long),
("right", ctypes.c_long),
("bottom", ctypes.c_long)]
class Magnification:
def __init__(self):
self.dll = ctypes.CDLL("magnification.dll")
BOOL = ctypes.c_bool
FLOAT = ctypes.c_float
INT = ctypes.c_int
self.LPRECT = LPRECT = ctypes.POINTER(RECT)
self.PBOOL = PBOOL = ctypes.POINTER(ctypes.c_bool)
# MagInitialize
self.dll.MagInitialize.restype = BOOL
# MagUninitialize
self.dll.MagUninitialize.restype = BOOL
# MagSetFullscreenTransform
self.dll.MagSetFullscreenTransform.restype = BOOL
self.dll.MagSetFullscreenTransform.argtypes = (FLOAT, INT, INT)
# MagGetInputTransform
self.dll.MagGetInputTransform.restype = BOOL
self.dll.MagGetInputTransform.argtypes = (PBOOL, LPRECT, LPRECT)
def MagInitialize(self):
return self.dll.MagInitialize()
def MagUninitialize(self):
return self.dll.MagUninitialize()
def MagSetFullscreenTransform(self, magLevel, xOffset, yOffset):
return self.dll.MagSetFullscreenTransform(magLevel, xOffset, yOffset)
def MagGetInputTransform(self, pfEnabled, prcSource, prcDest):
return self.dll.MagGetInputTransform(pfEnabled, prcSource, prcDest)
zoomer.py
import ctypes
from magnification_api import Magnification
import time
class Main:
def __init__(self):
self.mag = Magnification()
def zoom(self, factor, x, y):
if factor > 1.0:
while True:
if self.mag.MagInitialize():
result = self.mag.MagSetFullscreenTransform(factor, 0, 0)
if result:
fInputTransformEnabled = self.mag.PBOOL()
rcInputTransformSource = self.mag.LPRECT()
rcInputTransformDest = self.mag.LPRECT()
if self.mag.MagGetInputTransform(fInputTransformEnabled, rcInputTransformSource, rcInputTransformDest):
# fails here
print("Success")
else:
print("Failed")
time.sleep(1)
if __name__ == "__main__":
m = Main()
m.zoom(1.05, 0, 0)
我想首先指出代码中不正确的其他内容(不一定与错误相关):
这里好像是在重新发明轮子。使用 wintypes 模块(仅在文档中提及),它具有此场景所需的一切:
>>> from ctypes import wintypes >>> dir(wintypes) ['ATOM', 'BOOL', 'BOOLEAN', 'BYTE', 'CHAR', 'COLORREF', 'DOUBLE', 'DWORD', 'FILETIME', 'FLOAT', 'HACCEL', 'HANDLE', 'HBITMAP', 'HBRUSH', 'HCOLORSPACE', 'HDC', 'HDESK', 'HDWP', 'HENHMETAFILE', 'HFONT', 'HGDIOBJ', 'HGLOBAL', 'HHOOK', 'HICON', 'HINSTANCE', 'HKEY', 'HKL', 'HLOCAL', 'HMENU', 'HMETAFILE', 'HMODULE', 'HMONITOR', 'HPALETTE', 'HPEN', 'HRGN', 'HRSRC', 'HSTR', 'HTASK', 'HWINSTA', 'HWND', 'INT', 'LANGID', 'LARGE_INTEGER', 'LCID', 'LCTYPE', 'LGRPID', 'LONG', 'LPARAM', 'LPBOOL', 'LPBYTE', 'LPCOLESTR', 'LPCOLORREF', 'LPCSTR', 'LPCVOID', 'LPCWSTR', 'LPDWORD', 'LPFILETIME', 'LPHANDLE', 'LPHKL', 'LPINT', 'LPLONG', 'LPMSG', 'LPOLESTR', 'LPPOINT', 'LPRECT', 'LPRECTL', 'LPSC_HANDLE', 'LPSIZE', 'LPSIZEL', 'LPSTR', 'LPUINT', 'LPVOID', 'LPWIN32_FIND_DATAA', 'LPWIN32_FIND_DATAW', 'LPWORD', 'LPWSTR', 'MAX_PATH', 'MSG', 'OLESTR', 'PBOOL', 'PBOOLEAN', 'PBYTE', 'PCHAR', 'PDWORD', 'PFILETIME', 'PFLOAT', 'PHANDLE', 'PHKEY', 'PINT', 'PLARGE_INTEGER', 'PLCID', 'PLONG', 'PMSG', 'POINT', 'POINTL', 'PPOINT', 'PPOINTL', 'PRECT', 'PRECTL', 'PSHORT', 'PSIZE', 'PSIZEL', 'PSMALL_RECT', 'PUINT', 'PULARGE_INTEGER', 'PULONG', 'PUSHORT', 'PWCHAR', 'PWIN32_FIND_DATAA', 'PWIN32_FIND_DATAW', 'PWORD', 'RECT', 'RECTL', 'RGB', 'SC_HANDLE', 'SERVICE_STATUS_HANDLE', 'SHORT', 'SIZE', 'SIZEL', 'SMALL_RECT', 'UINT', 'ULARGE_INTEGER', 'ULONG', 'USHORT', 'VARIANT_BOOL', 'WCHAR', 'WIN32_FIND_DATAA', 'WIN32_FIND_DATAW', 'WORD', 'WPARAM', '_COORD', '_FILETIME', '_LARGE_INTEGER', '_POINTL', '_RECTL', '_SMALL_RECT', '_ULARGE_INTEGER', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'ctypes', 'tagMSG', 'tagPOINT', 'tagRECT', 'tagSIZE']
作为子注释,
BOOL
的自定义定义与 Win 的自定义定义不匹配:>>> ctypes.sizeof(ctypes.c_bool) 1 >>> ctypes.sizeof(wintypes.BOOL) 4
这是 访问冲突的候选者
- 像
self.LPRECT = LPRECT = ctypes.POINTER(RECT)
这样的东西看起来很奇怪。类型不应该是实例的成员 - 尽量关注[Python]: PEP 8 -- Style Guide for Python Code
- 其他不值得一提的小问题
回到错误:是ERROR_INVALID_PARAMETER,因为所有3个参数都传递给了MagGetInputTransform是 NULL 指针,如 [Python 3]: Pointers 状态:
Calling the pointer type without an argument creates a
NULL
pointer.
要修复它(这只是一种方法 - 我觉得最直接)更改:
初始化3个变量:
fInputTransformEnabled = wintypes.BOOL() rcInputTransformSource = wintypes.RECT() rcInputTransformDest = wintypes.RECT()
它们传递给MagGetInputTransform的方式:
if self.mag.MagGetInputTransform(ctypes.byref(fInputTransformEnabled), ctypes.byref(rcInputTransformSource), ctypes.byref(rcInputTransformDest)):
一切都应该没问题(但是所有 3 个变量都已填充 0s)。
注意:当您在 Win 上遇到错误时,[MSDN]: GetLastError function 是您最好的朋友!