SetWindowLongW&错误1413

时间:2014-02-21 21:30:50

标签: python winapi ctypes

我正在尝试通过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.txtNonOwnerWindow.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()))

1 个答案:

答案 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