Python叠加层调用SetWindowDisplayAffinity无效问题求助
解决方案
1. 修复C++ DLL的实现问题
错误码998(内存访问无效)大概率是DLL函数的调用约定或参数类型不匹配导致的内存读写错误,以下是正确的DLL代码示例:
#include <windows.h> // 使用__stdcall调用约定,匹配Python ctypes默认调用规则 extern "C" __declspec(dllexport) BOOL __stdcall SetWindowDisplayAffinityWrapper(HWND hWnd, DWORD dwAffinity) { return SetWindowDisplayAffinity(hWnd, dwAffinity); } extern "C" __declspec(dllexport) BOOL __stdcall GetWindowDisplayAffinityWrapper(HWND hWnd, LPDWORD pdwAffinity) { if (pdwAffinity == nullptr) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } return GetWindowDisplayAffinity(hWnd, pdwAffinity); }
编译注意事项:
- 选择与Python版本匹配的架构编译(32位Python对应32位DLL,64位对应64位)
- 确保链接user32.lib(多数编译器会自动处理,若报错需手动添加)
2. Python端的正确调用方式
用ctypes调用DLL,确保HWND传递和参数类型完全匹配:
import tkinter as tk import ctypes from ctypes import wintypes # 加载编译好的DLL,替换为你的DLL路径 display_affinity_dll = ctypes.WinDLL("DisplayAffinity.dll") # 声明函数参数与返回值类型,避免类型不匹配 display_affinity_dll.SetWindowDisplayAffinityWrapper.argtypes = [wintypes.HWND, wintypes.DWORD] display_affinity_dll.SetWindowDisplayAffinityWrapper.restype = wintypes.BOOL display_affinity_dll.GetWindowDisplayAffinityWrapper.argtypes = [wintypes.HWND, ctypes.POINTER(wintypes.DWORD)] display_affinity_dll.GetWindowDisplayAffinityWrapper.restype = wintypes.BOOL # 定义Windows API常量 WDA_EXCLUDEFROMCAPTURE = 0x00000011 WDA_MONITOR = 0x00000022 WDA_NONE = 0x00000000 root = tk.Tk() root.title("防截图窗口") root.geometry("400x300") # 获取正确的顶层窗口HWND:winfo_id()直接返回有效句柄,无需额外转换 hwnd = root.winfo_id() # 设置窗口捕获属性 set_result = display_affinity_dll.SetWindowDisplayAffinityWrapper(hwnd, WDA_EXCLUDEFROMCAPTURE) print(f"Set调用结果:{'成功' if set_result else f'失败,错误码{ctypes.GetLastError()}'}") # 验证设置结果 affinity = wintypes.DWORD() get_result = display_affinity_dll.GetWindowDisplayAffinityWrapper(hwnd, ctypes.byref(affinity)) if get_result: print(f"当前窗口捕获属性:{hex(affinity.value)}") else: print(f"Get调用失败,错误码:{ctypes.GetLastError()}") root.mainloop()
3. 关键排查点
- 系统版本限制:
SetWindowDisplayAffinity仅支持Windows 10 1809(10.0.17763)及以上版本,低版本系统调用会直接失败。 - HWND正确性:tkinter的
root.frame()返回的是内部框架句柄,不是顶层窗口的HWND,必须用winfo_id()获取。 - DLL架构匹配:DLL和Python必须同为32位或64位,否则会出现参数传递混乱或加载失败。
- 截图工具测试:OBS需选择“窗口捕获”模式,Discord用默认截图功能,若设置成功,窗口会显示为黑色或无法被捕获。
内容的提问来源于stack exchange,提问作者user26876988
相关产品推荐
相关产品推荐

