On Thu, Apr 6, 2017 at 7:38 PM, Kurt Eilander <web...@totalrewind.com> wrote: > Hey all, > > I'm trying to get system modal functionality like the UAC dialog. > > According to http://developex.com/blog/system-modal-back/ the thing to do is > to create and switch to a new desktop. > > Therefore, I'm doing: > > hDeskOld=win32service.GetThreadDesktop(win32api.GetCurrentThreadId())
SwitchDesktop affects which desktop has input focus. SetThreadDesktop affects which desktop is used by the current thread. You need to open a handle to the current input desktop to switch back to it at the end. I'm far from a Tk expert. I don't know how to close out the resources it uses to be able to call SetThreadDesktop. I'm not going to bother figuring this out to get this working on the main thread. I'll just create a new thread; pass it the handle for the new desktop; save the existing input desktop; set the thread desktop; and switch the input desktop. Then on teardown switch back to the original input desktop and close the desktop handles. Since I can't reliably call SetThreadDesktop to restore the worker thread's desktop before the thread exits, there's some asynchronous overlap when the thread and its resources haven't been destroyed yet. To address the potential for getting ERROR_BUSY when calling CloseDesktop from the main thread, I'm adding a retry loop that defaults to 10 attempts, with a delay of 0.1s. It shouldn't need more than 2 attempts. import sys import time import tkinter import threading import winerror import win32con import win32api import win32service def close_desktop(hDesk, numtries=10): for i in range(numtries): try: return hDesk.CloseDesktop() except win32service.error as e: if e.winerror != winerror.ERROR_BUSY or i == numtries - 1: raise time.sleep(0.1) def dialog(hDesk, title='SysModalDialog', message='', img=None): hDeskInputOld = win32service.OpenInputDesktop(0, False, win32con.DESKTOP_SWITCHDESKTOP) try: hDesk.SetThreadDesktop() hDesk.SwitchDesktop() try: root = tkinter.Tk() #root.mainloop() app = SysmodalDialog(root, title, message, img) app.mainloop() finally: hDeskInputOld.SwitchDesktop() finally: close_desktop(hDeskInputOld) def main(): hDesk = win32service.CreateDesktop("SysModalDesktop", 0, win32con.GENERIC_ALL, None) try: t = threading.Thread(target=dialog, args=(hDesk,)) t.start() t.join() finally: close_desktop(hDesk) return 0 if __name__ == '__main__': sys.exit(main()) _______________________________________________ python-win32 mailing list python-win32@python.org https://mail.python.org/mailman/listinfo/python-win32