我正在尝试通过python和ctypes设置Win32窗口的所有者(而不是父)。
我打电话的时候:
GWL_HWNDPARENT = -8
ctypes.windll.user32.SetWindowLongW(hWndChild, GWL_HWNDPARENT, hWndParent)
失败,ctypes.GetLastError()
返回1413 - ERROR_INVALID_INDEX(link)。
hWndChild和hWndParent似乎都有效,因为我可以成功使用ctypes.windll.user32.SetParent
。
我很困惑。无效索引是指什么?
根据评论更新。
这需要两个记事本分别编辑OwnerWindow.txt
和NonOwnerWindow.txt
import ctypes
GWL_HWNDPARENT = -8
_FindWindow = ctypes.windll.user32.FindWindowW
_FindWindow.argtypes = [ctypes.c_wchar_p,ctypes.c_wchar_p]
_FindWindow.restype = ctypes.c_void_p
_SetWindowLong = ctypes.windll.user32.SetWindowLongW
_SetWindowLong.argtypes = [ctypes.c_long, ctypes.c_long, ctypes.c_long]
_SetWindowLong.restype = ctypes.c_void_p
oHWnd = _FindWindow('Notepad', 'OwnerWindow.txt - Notepad')
nHWnd = _FindWindow('Notepad', 'NonOwnerWindow.txt - Notepad')
print "Last Error: {0}".format(str(ctypes.GetLastError()))
_SetWindowLong(ctypes.c_int(nHWnd), ctypes.c_int(GWL_HWNDPARENT), ctypes.c_int(oHWnd))
print "Last Error: {0}".format(str(ctypes.GetLastError()))
答案 0 :(得分:1)
编辑:考虑到@eryksun的评论,我做了一些测试和(重新)阅读文档。
了解SetWindowLong失败或成功的唯一方法是在呼叫之前使用SetLastError(0)
,然后在呼叫之后使用GetLastError
,如果呼叫返回0。
如果函数成功,则返回值为之前的值 指定的32位整数。
如果函数失败,则返回值为零。要获得扩展错误 信息,调用GetLastError。
如果指定的32位整数的前一个值为零,则为 函数成功,返回值为零,但函数没有 清除最后的错误信息。这使得难以确定 成功与失败。要处理这个问题,你应该清除最后一个错误 通过在调用之前调用SetLastError为0来获取信息 SetWindowLong函数。然后,返回表示功能失败 值为零,GetLastError结果为非零值。
如果来自ctypes
的C / C ++代码在您的SetLastError
电话和最终SetWindowLong
电话之间进行插入 Win32 API调用,则您无法知道如果成功或失败。
ctypes use_last_error
示例:
from ctypes import *
from ctypes.wintypes import *
from ctypes import _SimpleCData
user32le = WinDLL('user32', use_last_error=True)
user32le.SetWindowLongW.restype = LONG
user32le.SetWindowLongW.argtypes = [HWND, c_int, LONG]
LONG_PTR = HWND # should be an integer, but a pointer is simpler
if sizeof(HWND) == sizeof(c_long): # WIN32
# WIN32: this is a macro in winuser.h
user32le.SetWindowLongPtrW = user32le.SetWindowLongW
elif sizeof(HWND) == sizeof(c_longlong): # WIN64
user32le.SetWindowLongPtrW.restype = LONG_PTR
user32le.SetWindowLongPtrW.argtypes = [HWND, c_int, LONG_PTR]
def SetWindowLongPtr(hWnd, nIndex, dwNewLong):
if isinstance(dwNewLong, _SimpleCData):
# avoid ArgumentError with LONG, etc
dwNewLong = dwNewLong.value
# set last_error to 0, and save the previous value
last_error = set_last_error(0)
try:
# ctypes calls GetLastError / SetLastError to swap
# LastError and last_error
result = user32le.SetWindowLongPtrW(hWnd, nIndex, dwNewLong)
# ctypes again swaps LastError and last_error
finally:
last_error = set_last_error(last_error)
if not result and last_error:
raise WinError(last_error)
return result