EDIT: I made some test and (re)read documentation, taking into account comments from @eryksun.
The only way to know if the SetWindowLong failed or succeeded is to use SetLastError(0)
just before the call, and then to use GetLastError
after the call, if the call returned 0.
If the function succeeds, the return value is the previous value of the specified 32-bit integer.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
If the previous value of the specified 32-bit integer is zero, and the function succeeds, the return value is zero, but the function does not clear the last error information. This makes it difficult to determine success or failure. To deal with this, you should clear the last error information by calling SetLastError with 0 before calling SetWindowLong. Then, function failure will be indicated by a return value of zero and a GetLastError result that is nonzero.
If the C/C++ code from ctypes
does insert Win32 APIs call beetween your SetLastError
call and the final SetWindowLong
call, you can't know if there is success or failure.
ctypes use_last_error
example:
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