在 Python 中使用 TaskDialogIndirect
Using TaskDialogIndirect in Python
我想从 Python 调用 Windows TaskDialogIndirect 函数。
它需要 TaskDialogConfig(相当大)结构作为指针传递。
这是我准备 运行 的例子。它给了我“-2147024809”(参数不正确),我不知道出了什么问题。
Python 3.7.4 x32,Windows 7 x64
import ctypes
from ctypes.wintypes import *
TDF_ALLOW_DIALOG_CANCELLATION = 8
TDCBF_OK_BUTTON = 1
class TaskDialogConfig(ctypes.Structure):
class DUMMYUNIONNAME(ctypes.Union):
_fields_ = [
('hMainIcon', HICON)
, ('pszMainIcon', LPCWSTR)
]
class DUMMYUNIONNAME2(ctypes.Union):
_fields_ = [
('hFooterIcon', HICON)
, ('sFooterIcon', LPCWSTR)
]
class _TASKDIALOG_BUTTON(ctypes.Structure):
_fields_ = [
('nButtonID', INT)
, ('pszButtonText', LPCWSTR)
]
_fields_ = [
('cbSize', UINT)
, ('hwndParent', HWND)
, ('hInstance', HINSTANCE)
, ('dwFlags', UINT)
, ('dwCommonButtons', UINT)
, ('pszWindowTitle', LPCWSTR)
, ('DUMMYUNIONNAME', DUMMYUNIONNAME)
, ('pszMainInstruction', LPCWSTR)
, ('pszContent', LPCWSTR)
, ('cButtons', UINT)
, ('pButtons', _TASKDIALOG_BUTTON)
, ('nDefaultButton', INT)
, ('cRadioButtons', UINT)
, ('pRadioButtons', _TASKDIALOG_BUTTON)
, ('nDefaultRadioButton', INT)
, ('pszVerificationText', LPCWSTR)
, ('pszExpandedInformation', LPCWSTR)
, ('pszExpandedControlText', LPCWSTR)
, ('pszCollapsedControlText', LPCWSTR)
, ('DUMMYUNIONNAME2', DUMMYUNIONNAME2)
, ('pszFooter', LPCWSTR)
, ('pfCallBack', ctypes.POINTER(None))
, ('lpCallbackData', LPLONG)
, ('cxWidth', UINT)
]
def __init__(s):
s.cbSize = ctypes.sizeof(s)
tdi = ctypes.WinDLL('comctl32.dll').TaskDialogIndirect
tdc = TaskDialogConfig()
tdc.hwndParent = None
tdc.hInstance = None
tdc.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION
tdc.dwCommonButtons = TDCBF_OK_BUTTON
tdc.pszWindowTitle = ctypes.c_wchar_p('Title')
tdc.pszMainInstruction = ctypes.c_wchar_p('Main instruction')
tdc.pszContent = ctypes.c_wchar_p('Content')
print( tdi(ctypes.byref(tdc), None, None, None) )
两个问题。
- CommCtrl.hheader使用1字节打包。在所有结构中的
_fields_
定义之前添加 _pack_ = 1
。
- 两个
_TASKDIALOG_BUTTON
字段的类型应为 ctypes.POINTER(_TASKDIALOG_BUTTON)
.
我通过使用 C 程序打印结构的大小和一些字段的偏移量来跟踪这些信息,并在 Python:
中打印相同的信息
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%zu\n",sizeof(TASKDIALOGCONFIG));
printf("%zu\n",offsetof(TASKDIALOGCONFIG,pszWindowTitle));
printf("%zu\n",offsetof(TASKDIALOGCONFIG,pszMainInstruction));
printf("%zu\n",offsetof(TASKDIALOGCONFIG,pszFooter));
}
tdc = TaskDialogConfig()
print(tdc.cbSize)
print(TaskDialogConfig.pszWindowTitle)
print(TaskDialogConfig.pszMainInstruction)
print(TaskDialogConfig.pszFooter)
我想从 Python 调用 Windows TaskDialogIndirect 函数。 它需要 TaskDialogConfig(相当大)结构作为指针传递。
这是我准备 运行 的例子。它给了我“-2147024809”(参数不正确),我不知道出了什么问题。
Python 3.7.4 x32,Windows 7 x64
import ctypes
from ctypes.wintypes import *
TDF_ALLOW_DIALOG_CANCELLATION = 8
TDCBF_OK_BUTTON = 1
class TaskDialogConfig(ctypes.Structure):
class DUMMYUNIONNAME(ctypes.Union):
_fields_ = [
('hMainIcon', HICON)
, ('pszMainIcon', LPCWSTR)
]
class DUMMYUNIONNAME2(ctypes.Union):
_fields_ = [
('hFooterIcon', HICON)
, ('sFooterIcon', LPCWSTR)
]
class _TASKDIALOG_BUTTON(ctypes.Structure):
_fields_ = [
('nButtonID', INT)
, ('pszButtonText', LPCWSTR)
]
_fields_ = [
('cbSize', UINT)
, ('hwndParent', HWND)
, ('hInstance', HINSTANCE)
, ('dwFlags', UINT)
, ('dwCommonButtons', UINT)
, ('pszWindowTitle', LPCWSTR)
, ('DUMMYUNIONNAME', DUMMYUNIONNAME)
, ('pszMainInstruction', LPCWSTR)
, ('pszContent', LPCWSTR)
, ('cButtons', UINT)
, ('pButtons', _TASKDIALOG_BUTTON)
, ('nDefaultButton', INT)
, ('cRadioButtons', UINT)
, ('pRadioButtons', _TASKDIALOG_BUTTON)
, ('nDefaultRadioButton', INT)
, ('pszVerificationText', LPCWSTR)
, ('pszExpandedInformation', LPCWSTR)
, ('pszExpandedControlText', LPCWSTR)
, ('pszCollapsedControlText', LPCWSTR)
, ('DUMMYUNIONNAME2', DUMMYUNIONNAME2)
, ('pszFooter', LPCWSTR)
, ('pfCallBack', ctypes.POINTER(None))
, ('lpCallbackData', LPLONG)
, ('cxWidth', UINT)
]
def __init__(s):
s.cbSize = ctypes.sizeof(s)
tdi = ctypes.WinDLL('comctl32.dll').TaskDialogIndirect
tdc = TaskDialogConfig()
tdc.hwndParent = None
tdc.hInstance = None
tdc.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION
tdc.dwCommonButtons = TDCBF_OK_BUTTON
tdc.pszWindowTitle = ctypes.c_wchar_p('Title')
tdc.pszMainInstruction = ctypes.c_wchar_p('Main instruction')
tdc.pszContent = ctypes.c_wchar_p('Content')
print( tdi(ctypes.byref(tdc), None, None, None) )
两个问题。
- CommCtrl.hheader使用1字节打包。在所有结构中的
_fields_
定义之前添加_pack_ = 1
。 - 两个
_TASKDIALOG_BUTTON
字段的类型应为ctypes.POINTER(_TASKDIALOG_BUTTON)
.
我通过使用 C 程序打印结构的大小和一些字段的偏移量来跟踪这些信息,并在 Python:
中打印相同的信息#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%zu\n",sizeof(TASKDIALOGCONFIG));
printf("%zu\n",offsetof(TASKDIALOGCONFIG,pszWindowTitle));
printf("%zu\n",offsetof(TASKDIALOGCONFIG,pszMainInstruction));
printf("%zu\n",offsetof(TASKDIALOGCONFIG,pszFooter));
}
tdc = TaskDialogConfig()
print(tdc.cbSize)
print(TaskDialogConfig.pszWindowTitle)
print(TaskDialogConfig.pszMainInstruction)
print(TaskDialogConfig.pszFooter)