2

我有一个带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
);

https://msdn.microsoft.com/en-us/library/windows/desktop/hh824802(v=vs.85).aspx

我正在 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())

我试图传递 qtWindow 的句柄,但收到一条错误消息..can't convert parameter 3..。该功能期望什么?窗户把手?我真的不知道,我不熟悉 C++。

顺便说一句:QProgressdialog 是一个带有 QProgress 和 QButton 的窗口。当我单击取消按钮时,我的def canceled(self):方法被发出,窗口将关闭一秒钟,然后继续进行。

编辑:
在 zett42 建议后,我想出了这个:

DISM_CANCEl_EVENT = CreateEvent(None, False, False, None)

和:

def canceled(self):
    print("canceled")
    SetEvent(dism_manager.DISM_CANCEl_EVENT)

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

我收到此错误消息: ctypes.ArgumentError: argument 3: <class 'TypeError'>: Don't know how to convert parameter 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_progress_callback 强制窗口再次弹出,尽管我调用self.progdialog.cancel()它关闭了窗口......希望你能关注我。你有什么建议我可以控制这个吗?


已解决:
我得到了最终解决方案:我之前调用self.progdialog.canceled.disconnect()self.progdialog.canceled.connect(self.dism_cancel_event)覆盖 cancelled() 信号并阻止调用 cancel()。

4

1 回答 1

0

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

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

于 2017-07-13T09:42:06.110 回答