Easy method to use Windows Explorer's ProgressDialog COM object to show progress of processing, uploads, downloads, etc.
| Python |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | import win32gui
class COMprogressDialog(object):
def __init__(self, title='Progress Dialog', animation_res=161):
'''
COMprogressDialog - Windows COM object that shows progress of task.
This dialog runs in a separate thread so it can be
run from virtually any program without adding
threading complexity to that program.
title - Dialog window title
animation_res - animation resource .AVI for interesting progress display
animation_res=160 (move)
animation_res=161 (copy)
COMprogressDialog.dialog class methods -
StartProgressDialog(hwndParent, lEnableModeless, dwFlags, pvReserved)
StopProgressDialog()
SetTitle(sTitle)
SetAnimation(hInstAnimation, idAnimation)
HasUserCancelled()
SetProgress(completed, total)
SetProgress64(completed64, total64)
SetLine(lineNum, sText, lCompactPath, pvReserved)
SetCancelMsg(sCancelMsg, pvReserved)
Timer() - Reset timer
Release() - Close dialog, release resources
Animation resource in shell32.dll that points to .AVIs
Written by: Larry Bates (with substantial help from Thomas Heller and
Tim Golden on COM interfacing to IProgressDialog),
February 2008
License: GPL
Requires: ctypes, comtypes, win32gui
'''
#
# Save title so I can update it with % completed as I progress
#
self.title = title
#
# Get a list of topWindows
#
topWindows = []
win32gui.EnumWindows(self._windowEnumerationHandler, topWindows)
#
# Isolate Program Manager window from all the other topWindows,
# this will be used as the parent window for the dialog.
#
hwndParent = [w[0] for w in topWindows if w[1] == 'Program Manager'][0]
import comtypes.client
try:
import comtypes.gen.VBProgressDialog
except ImportError:
#
# Create object from the progress tlb file for the COM Progress
# Dialog
#
comtypes.client.GetModule('progdlg.tlb')
vbpd = comtypes.gen.VBProgressDialog
#
# Create instance of progress dialog
#
self.dialog = comtypes.client.CreateObject(vbpd.ProgressDialog)
#
# Set the animation for the dialog (default=copy) from shell32.dll
#
import ctypes
#
# Pointer to shell32.dll
#
shell32 = ctypes.windll.shell32
#
# Get handle for this
#
m_hLibShell32 = shell32._handle
#
# Set the animation based on animation_res number (default animation
# is copy animation).
#
self.dialog.SetAnimation(m_hLibShell32, animation_res)
#
# Insert title into top of dialog if present
#
if title:
self.dialog.SetTitle(title)
#
# Start the dialog
#
self.dialog.StartProgressDialog(hwndParent, None, 0, 0)
def _windowEnumerationHandler(self, hwnd, resultList):
#
# Get a list of the top level windows so I can find Program Manager
#
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
def __del__(self):
self.dialog.Release()
del self.dialog
if __name__ == "__main__":
import time
compactPath = 1
total = 100
filenames=['C:/pagefile.sys',
'C:/Documents and Settings/All Users/Start Menu/' \
'Programs/Administrative Tools/Computer Management'
]
for i in xrange(3):
title="COMprogressDialot Unit Test %i" % (i+1)
#
# Create instance of the COMprogressDialog class
#
DLGobj = COMprogressDialog(title=title)
#
# Set the first line of the dialog to the filename
#
DLGobj.dialog.SetLine(1, filenames[0], compactPath, 0)
for j in xrange(total):
completed=int(100.0 / total * j)
completed="%s (%i%%)" % (title, completed)
#
# Update title to include (xx%) completed
#
DLGobj.dialog.SetTitle(completed)
#
# Update the progress gauge
#
DLGobj.dialog.SetProgress(j, total)
#
# Set second line to ##### of ##### bytes uploaded
#
line2="%i of %i bytes uploaded" % (j, total)
DLGobj.dialog.SetLine(2, line2, 0, 0)
#
# See if user pushed cancel button
#
if DLGobj.dialog.HasUserCancelled():
break
#
# Simulate uploading two equal sized files
#
if j == 50:
compactPath=1
DLGobj.dialog.SetLine(1, filenames[1], compactPath, 0)
time.sleep(0.1)
#
# Only necessary because of nested loops
#
if DLGobj.dialog.HasUserCancelled():
break
#
# Destroy the object (note: this is important!)
#
del DLGobj
|
Discussion
Launches ProgressDialog in a separate thread for showing progress on long running tasks.


Comments
I don't have progdlg.tlb anywhere, nor an VBProgressDialog object registered. Where do you get those?
Sign in to comment