Windows python/pyqt-将CancelEvent传递给C++;功能

Windows python/pyqt-将CancelEvent传递给C++;功能,windows,winapi,events,pyqt,dism,Windows,Winapi,Events,Pyqt,Dism,我有一个带有CancelEvent参数的WinApi函数,但我不知道必须传递什么 HRESULT WINAPI DismUnmountImage( _In_ PCWSTR MountPath, _In_ DWORD Flags, _In_opt_ HANDLE CancelEvent, _In_opt_ DISM_PROGRESS_CALLBACK Progress,

我有一个带有
CancelEvent
参数的WinApi函数,但我不知道必须传递什么

HRESULT WINAPI DismUnmountImage(
  _In_     PCWSTR                 MountPath,
  _In_     DWORD                  Flags,
  _In_opt_ HANDLE                 CancelEvent,
  _In_opt_ DISM_PROGRESS_CALLBACK Progress,
  _In_opt_ PVOID                  UserData
);

我正在Windows 10上使用python 3.6。该函数工作正常,进度对话框也正常。我使用QProgressDialog小部件来显示进度状态,我只需要实现CancelEvent。 重新定义:

from ctypes import *
import win32con, win32api

def UnmountImage(self, MountPath, Flags=DISM_DISCARD_IMAGE, CancelEvent=None, Progress=None, UserData=None):
    self.hDism.DismUnmountImage.restype = HRESULT
    try:
        return self.hDism.DismUnmountImage(MountPath, Flags, CancelEvent, Progress, UserData)
    except OSError as e:
        print("DismUnmountImage failed: %s\nErrorCode: %s" % (e.strerror, e))
        return self.GetLastErrorMessage()
和pyqt部分:

def canceled(self):
    print("canceled")

@pyqtSlot(QVariant)
def unmount_image(self, json_data):
    dism_progress_callback = dism_manager.DISM_PROGRESS_CALLBACK(self.dism_progress_callback)
    data = json.loads(json_data)

    self.progdialog = QProgressDialog("", "Cancel", 0, 100, None)
    self.progdialog.setWindowTitle("Unmounting Image...")
    self.progdialog.setModal(True)
    self.progdialog.canceled.connect(self.canceled)
    self.progdialog.show()

    for image in data:
        dism_manager.UnmountImage(MountPath=image['MountPath'], Progress=dism_progress_callback, CancelEvent=self.progdialog.winId())
我试图传递QT窗口的句柄,但收到错误消息
。无法转换参数3..
。这个函数期望什么?窗户把手?我真的不知道,我不熟悉C++。 顺便说一句:QProgressdialog是一个带有QProgress和QButton的窗口。单击取消按钮时,将发出我的
def cancelled(self):
方法,窗口将关闭一秒钟,然后继续进行

编辑:
根据zett42的建议,我提出了以下建议:

DISM_CANCEl_EVENT = CreateEvent(None, False, False, None)
以及:

我收到以下错误消息:
ctypes.ArgumentError:参数3::不知道如何转换参数3

你知道我错过了什么吗

EDIT2:
我明白了:

def canceled(self):
    self.progdialog.cancel()
    SetEvent(self.cancel_event)

self.cancel_event = dism_manager.DISM_CANCEl_EVENT.Detach()

for image in data:
    dism_manager.UnmountImage(MountPath=image['MountPath'], Progress=dism_progress_callback, CancelEvent=self.cancel_event)
我唯一的问题是:cancelevent需要大约2秒钟才能执行,这样同时dism\u progress\u回调会强制窗口再次弹出,尽管我调用了
self.progdialog.cancel()
,关闭了窗口……希望您能跟我来。你对我如何控制这件事有什么建议吗


已解决:

我得到了一个最终的解决方案:我在
self.progliation.cancelled.connect(self.dism\u cancel\u event)
之前调用了
self.progliation.cancelled.disconnect()
,以覆盖cancel()信号并防止调用cancel()。

该函数需要使用C API创建的事件对象的句柄。在Python中,您可以调用


在函数
def cancelled(self)
中,应该调用传递为
hEvent
参数创建的事件对象的句柄。这将要求取消
UnmountImage()

非常感谢您的回答。我确实按照您的指示编辑了我的帖子,但是
CancelEvent
参数似乎仍然无效。也许你有什么想法?@FalloutBoy我知道你找到了解决方案,但是现在你有了内存泄漏,因为
Detach()
释放了所有权,所以句柄将不再关闭。相反,您应该使用
DISM\u CANCEl\u EVENT.handle
。不幸的是
DISM\u CANCEl\u EVENT.handle
具有相同的效果。当我点击Cancel时,窗口关闭,此时我的控制台是空的。2秒后,窗口再次弹出,进程继续。再过2秒钟,窗口再次关闭,在我的控制台中,我收到通知消息
…Progress get cancelled…
。你知道如何关闭进度窗口吗。。。如果这有帮助的话,我可以做一个视频?@FalloutBoy为什么要调用
self.progdialog.cancel()
?如果取消需要2秒钟,则进度对话框仍应可见,以便用户可以看到程序仍在忙。我会禁用“取消”按钮。只有当
dism_manager.UnmountImage()
返回时才关闭进度对话框,这样您就没有这些问题。很抱歉,您是对的,但我当前发现:
void QProgressDialog::cancelled()[signal]->单击取消按钮时会发出此信号。默认情况下,它连接到cancel()插槽
…因此,当我单击cancel按钮时,
self.progdialog.cancel()
将自动运行。我必须覆盖
Cancel
行为,或者添加一个QPushbutton,它看起来像Cancel按钮,但反应不象它。我测试了self.progdialog.setCancelButton(cancel_btn),但它显然具有相同的效果。有什么想法吗?请将您的解决方案作为以下答案发布,而不是将其包含在您的问题中。
def canceled(self):
    self.progdialog.cancel()
    SetEvent(self.cancel_event)

self.cancel_event = dism_manager.DISM_CANCEl_EVENT.Detach()

for image in data:
    dism_manager.UnmountImage(MountPath=image['MountPath'], Progress=dism_progress_callback, CancelEvent=self.cancel_event)