import win32gui
class COMprogressDialog(object):
_trace = False
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) [DEFAULT]
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
Updated February 2011 - Added close() method to gracefully
close the dialog.
License: GPL
Requires: ctypes, comtypes, win32gui
'''
LM = "COMprogressDialog.__init__"
if self._trace:
print "%s-Entering" % LM
#
# Save title so I can update it with % completed as I progress
#
self.title = title
#
# Get a list of topWindows
#
topWindows = list()
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
#
if self._trace:
print "%s-creating instance of progress dialog" % LM
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
#
self.dialog.SetTitle(title)
#
# Start the dialog
#
self.dialog.StartProgressDialog(hwndParent, None, 0, 0)
if self._trace:
print "%s-Leaving" % LM
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 close(self):
self.dialog.StopProgressDialog()
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
#
# Have the COM dialog close and release it's resources
#
DLGobj.close()
Diff to Previous Revision
--- revision 1 2009-06-27 21:13:04
+++ revision 2 2011-02-17 23:04:04
@@ -1,6 +1,7 @@
import win32gui
class COMprogressDialog(object):
+ _trace = False
def __init__(self, title='Progress Dialog', animation_res=161):
'''
COMprogressDialog - Windows COM object that shows progress of task.
@@ -9,9 +10,11 @@
threading complexity to that program.
title - Dialog window title
- animation_res - animation resource .AVI for interesting progress display
+ animation_res - animation resource .AVI for interesting
+ progress display
+
animation_res=160 (move)
- animation_res=161 (copy)
+ animation_res=161 (copy) [DEFAULT]
COMprogressDialog.dialog class methods -
@@ -33,9 +36,16 @@
Tim Golden on COM interfacing to IProgressDialog),
February 2008
+ Updated February 2011 - Added close() method to gracefully
+ close the dialog.
+
License: GPL
Requires: ctypes, comtypes, win32gui
'''
+ LM = "COMprogressDialog.__init__"
+ if self._trace:
+ print "%s-Entering" % LM
+
#
# Save title so I can update it with % completed as I progress
#
@@ -43,7 +53,7 @@
#
# Get a list of topWindows
#
- topWindows = []
+ topWindows = list()
win32gui.EnumWindows(self._windowEnumerationHandler, topWindows)
#
# Isolate Program Manager window from all the other topWindows,
@@ -65,6 +75,9 @@
#
# Create instance of progress dialog
#
+ if self._trace:
+ print "%s-creating instance of progress dialog" % LM
+
self.dialog = comtypes.client.CreateObject(vbpd.ProgressDialog)
#
# Set the animation for the dialog (default=copy) from shell32.dll
@@ -84,14 +97,15 @@
#
self.dialog.SetAnimation(m_hLibShell32, animation_res)
#
- # Insert title into top of dialog if present
+ # Insert title into top of dialog
#
- if title:
- self.dialog.SetTitle(title)
+ self.dialog.SetTitle(title)
#
# Start the dialog
#
self.dialog.StartProgressDialog(hwndParent, None, 0, 0)
+ if self._trace:
+ print "%s-Leaving" % LM
def _windowEnumerationHandler(self, hwnd, resultList):
#
@@ -99,21 +113,20 @@
#
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))
- def __del__(self):
- self.dialog.Release()
- del self.dialog
-
+ def close(self):
+ self.dialog.StopProgressDialog()
+
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'
- ]
+ 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)
+ title = "COMprogressDialot Unit Test %i" % (i+1)
#
# Create instance of the COMprogressDialog class
#
@@ -123,8 +136,8 @@
#
DLGobj.dialog.SetLine(1, filenames[0], compactPath, 0)
for j in xrange(total):
- completed=int(100.0 / total * j)
- completed="%s (%i%%)" % (title, completed)
+ completed = int(100.0 / total * j)
+ completed = "%s (%i%%)" % (title, completed)
#
# Update title to include (xx%) completed
#
@@ -136,7 +149,7 @@
#
# Set second line to ##### of ##### bytes uploaded
#
- line2="%i of %i bytes uploaded" % (j, total)
+ line2 = "%i of %i bytes uploaded" % (j, total)
DLGobj.dialog.SetLine(2, line2, 0, 0)
#
# See if user pushed cancel button
@@ -148,17 +161,17 @@
# Simulate uploading two equal sized files
#
if j == 50:
- compactPath=1
+ 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
#
- # Only necessary because of nested loops
+ # Have the COM dialog close and release it's resources
#
- if DLGobj.dialog.HasUserCancelled():
- break
- #
- # Destroy the object (note: this is important!)
- #
- del DLGobj
+ DLGobj.close()