python/pyqt - передает CancelEvent в функцию C++
У меня есть функция WinApi с CancelEvent
параметр, но я не знаю, что я должен передать там?
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
Я работаю с Python 3.6 на Windows 10. Функция работает правильно, диалог прогресса тоже. Я использовал виджет 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)
Единственная проблема, которая у меня есть: для отмены события требуется около 2 секунд, чтобы dism_progress_callback заставлял окно снова всплывать, хотя я и вызвал self.progdialog.cancel()
который закрывает окно... надеюсь, вы можете следовать за мной. Есть ли у вас какие-либо предложения, как я могу это контролировать?
Решено:
Я получил окончательное решение: я позвонил self.progdialog.canceled.disconnect()
до self.progdialog.canceled.connect(self.dism_cancel_event)
перезаписать сигнал отменен () и предотвратить вызов отмены ().
1 ответ
Функция ожидает дескриптор объекта события, который может быть создан с помощью CreateEvent()
C API. В Python вы можете позвонить win32event.CreateEvent()
,
В вашей функции def canceled(self)
ты должен позвонить win32event.SetEvent(hEvent)
передавая дескриптор объекта события, который вы создали для hEvent
параметр. Это будет запрашивать отмену UnmountImage()
,