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)