You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
8.4 KiB
Python
259 lines
8.4 KiB
Python
from __future__ import division
|
|
from numpy import round
|
|
from threading import Thread
|
|
from time import sleep
|
|
from win32gui import (InitCommonControls, CallWindowProc, CreateWindowEx,
|
|
CreateWindow, SetWindowLong, SendMessage, ShowWindow,
|
|
PumpWaitingMessages, PostQuitMessage, DestroyWindow,
|
|
MessageBox, EnumWindows, GetClassName)
|
|
from win32api import GetModuleHandle, GetSystemMetrics # @UnresolvedImport
|
|
from win32api import SetWindowLong as api_SetWindowLong # @UnresolvedImport
|
|
from commctrl import (TOOLTIPS_CLASS, TTM_GETDELAYTIME, TTM_SETDELAYTIME,
|
|
TTDT_INITIAL, TTDT_AUTOPOP)
|
|
import win32con
|
|
|
|
WM_USER = win32con.WM_USER
|
|
PBM_SETRANGE = (WM_USER + 1)
|
|
PBM_SETPOS = (WM_USER + 2)
|
|
PBM_DELTAPOS = (WM_USER + 3)
|
|
PBM_SETSTEP = (WM_USER + 4)
|
|
PBM_STEPIT = (WM_USER + 5)
|
|
PBM_SETRANGE32 = (WM_USER + 6)
|
|
PBM_GETRANGE = (WM_USER + 7)
|
|
PBM_GETPOS = (WM_USER + 8)
|
|
PBM_SETBARCOLOR = (WM_USER + 9)
|
|
PBM_SETMARQUEE = (WM_USER + 10)
|
|
PBM_GETSTEP = (WM_USER + 13)
|
|
PBM_GETBKCOLOR = (WM_USER + 14)
|
|
PBM_GETBARCOLOR = (WM_USER + 15)
|
|
PBM_SETSTATE = (WM_USER + 16)
|
|
PBM_GETSTATE = (WM_USER + 17)
|
|
PBS_SMOOTH = 0x01
|
|
PBS_VERTICAL = 0x04
|
|
PBS_MARQUEE = 0x08
|
|
PBS_SMOOTHREVERSE = 0x10
|
|
PBST_NORMAL = 1
|
|
PBST_ERROR = 2
|
|
PBST_PAUSED = 3
|
|
WC_DIALOG = 32770
|
|
WM_SETTEXT = win32con.WM_SETTEXT
|
|
|
|
|
|
def MAKELPARAM(a, b):
|
|
return (a & 0xffff) | ((b & 0xffff) << 16)
|
|
|
|
|
|
def _get_tooltip_handles(hwnd, resultList):
|
|
'''
|
|
Adds a window handle to resultList if its class-name is 'tooltips_class32',
|
|
i.e. the window is a tooltip.
|
|
'''
|
|
if GetClassName(hwnd) == TOOLTIPS_CLASS:
|
|
resultList.append(hwnd)
|
|
|
|
|
|
def set_max_pop_delay_on_tooltip(tooltip):
|
|
'''
|
|
Sets maximum auto-pop delay (delay before hiding) on an instance of
|
|
wx.ToolTip.
|
|
NOTE: The tooltip's SetDelay method is used just to identify the correct
|
|
tooltip.
|
|
'''
|
|
test_value = 12345
|
|
# Set initial delay just to identify tooltip.
|
|
tooltip.SetDelay(test_value)
|
|
handles = []
|
|
EnumWindows(_get_tooltip_handles, handles)
|
|
for hwnd in handles:
|
|
if SendMessage(hwnd, TTM_GETDELAYTIME, TTDT_INITIAL) == test_value:
|
|
SendMessage(hwnd, TTM_SETDELAYTIME, TTDT_AUTOPOP, 32767)
|
|
tooltip.SetDelay(500) # Restore default value
|
|
|
|
|
|
class Waitbar(Thread):
|
|
|
|
def __init__(self, title='Waitbar', can_abort=True, max_val=100):
|
|
Thread.__init__(self) # Initialize thread
|
|
self.title = title
|
|
self.can_abort = can_abort
|
|
self.max_val = max_val
|
|
InitCommonControls()
|
|
self.hinst = GetModuleHandle(None)
|
|
self.started = False
|
|
self.position = 0
|
|
self.do_update = False
|
|
self.start() # Run the thread
|
|
while not self.started:
|
|
sleep(0.1) # Wait until the dialog is ready
|
|
|
|
def DlgProc(self, hwnd, uMsg, wParam, lParam):
|
|
if uMsg == win32con.WM_DESTROY:
|
|
api_SetWindowLong(self.dialog,
|
|
win32con.GWL_WNDPROC,
|
|
self.oldWndProc)
|
|
if uMsg == win32con.WM_CLOSE:
|
|
self.started = False
|
|
if uMsg == win32con.WM_COMMAND and self.can_abort:
|
|
self.started = False
|
|
return CallWindowProc(self.oldWndProc, hwnd, uMsg, wParam, lParam)
|
|
|
|
def BuildWindow(self):
|
|
width = 400
|
|
height = 100
|
|
self.dialog = CreateWindowEx(
|
|
win32con.WS_EX_TOPMOST,
|
|
WC_DIALOG,
|
|
self.title + ' (0%)',
|
|
win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW,
|
|
int(round(
|
|
GetSystemMetrics(win32con.SM_CXSCREEN) * .5 - width * .5)),
|
|
int(round(
|
|
GetSystemMetrics(win32con.SM_CYSCREEN) * .5 - height * .5)),
|
|
width,
|
|
height,
|
|
0,
|
|
0,
|
|
self.hinst,
|
|
None)
|
|
self.progbar = CreateWindow(
|
|
# win32con.WS_EX_DLGMODALFRAME,
|
|
'msctls_progress32',
|
|
'',
|
|
win32con.WS_VISIBLE | win32con.WS_CHILD,
|
|
10,
|
|
10,
|
|
width - 30,
|
|
20,
|
|
self.dialog,
|
|
0,
|
|
0,
|
|
None)
|
|
if self.can_abort:
|
|
self.button = CreateWindow(
|
|
# win32con.WS_EX_DLGMODALFRAME,
|
|
'BUTTON',
|
|
'Cancel',
|
|
win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.BS_PUSHBUTTON, # @IgnorePep8
|
|
int(width / 2.75),
|
|
40,
|
|
100,
|
|
20,
|
|
self.dialog,
|
|
0,
|
|
0,
|
|
None)
|
|
self.oldWndProc = SetWindowLong(
|
|
self.dialog,
|
|
win32con.GWL_WNDPROC,
|
|
self.DlgProc)
|
|
SendMessage(self.progbar, PBM_SETRANGE, 0, MAKELPARAM(0, self.max_val))
|
|
# win32gui.SendMessage(self.progbar, PBM_SETSTEP, 0, 10)
|
|
# win32gui.SendMessage(self.progbar, PBM_SETMARQUEE, 0, 0)
|
|
ShowWindow(self.progbar, win32con.SW_SHOW)
|
|
|
|
def run(self):
|
|
self.BuildWindow()
|
|
self.started = True
|
|
while self.started:
|
|
PumpWaitingMessages()
|
|
if self.do_update:
|
|
SendMessage(self.progbar, PBM_SETPOS,
|
|
int(self.position % self.max_val), 0)
|
|
percentage = int(round(100.0 * self.position / self.max_val))
|
|
SendMessage(self.dialog, WM_SETTEXT, 0,
|
|
self.title + ' (%d%%)' % percentage)
|
|
# SendMessage(self.progbar, PBM_STEPIT, 0, 0)
|
|
self.do_update = False
|
|
sleep(0.1)
|
|
PostQuitMessage(0)
|
|
DestroyWindow(self.dialog)
|
|
|
|
def update(self, pos):
|
|
if self.started:
|
|
if not self.do_update:
|
|
self.position = pos
|
|
self.do_update = True
|
|
return True
|
|
return False
|
|
|
|
def close(self):
|
|
self.started = False
|
|
|
|
|
|
# class Waitbar2(Dialog, Thread):
|
|
# def __init__(self, title='Waitbar'):
|
|
# template = [[title, (0, 0, 215, 36),
|
|
# (win32con.DS_MODALFRAME | win32con.WS_POPUP |
|
|
# win32con.WS_VISIBLE | win32con.WS_CAPTION |
|
|
# win32con.WS_SYSMENU | win32con.DS_SETFONT |
|
|
# win32con.WS_GROUP | win32con.WS_EX_TOPMOST),
|
|
# | win32con.DS_SYSMODAL),
|
|
# None, (8, "MS Sans Serif")], ]
|
|
# Dialog.__init__(self, id=template)
|
|
# Thread.__init__(self) # Initialize thread
|
|
# self.started = False
|
|
# self.start() # Run the thread
|
|
# while not self.started:
|
|
# sleep(0.1) # Wait until the dialog is ready
|
|
#
|
|
# def OnInitDialog(self):
|
|
# rc = Dialog.OnInitDialog(self)
|
|
# self.pbar = CreateProgressCtrl()
|
|
# self.pbar.CreateWindow (win32con.WS_CHILD | win32con.WS_VISIBLE,
|
|
# (10, 10, 310, 24), self, 1001)
|
|
# self.started = True
|
|
# return rc
|
|
#
|
|
# def run(self):
|
|
# self.DoModal()
|
|
#
|
|
# def update(self, pos):
|
|
# self.pbar.SetPos(int(pos))
|
|
#
|
|
# def close(self):
|
|
# self.OnCancel()
|
|
|
|
|
|
class WarnDlg(Thread):
|
|
|
|
def __init__(self, message='', title='Warning!'):
|
|
Thread.__init__(self) # Initialize thread
|
|
self.title = title
|
|
self.message = message
|
|
self.start() # Run the thread
|
|
|
|
def run(self):
|
|
# MessageBox(self.message, self.title, win32con.MB_ICONWARNING)
|
|
MessageBox(0, self.message, self.title,
|
|
win32con.MB_ICONWARNING | win32con.MB_SYSTEMMODAL)
|
|
|
|
|
|
class ErrorDlg(Thread):
|
|
|
|
def __init__(self, message='', title='Error!', blocking=False):
|
|
Thread.__init__(self) # Initialize thread
|
|
self.title = title
|
|
self.message = message
|
|
if blocking:
|
|
self.run() # Run without threading
|
|
else:
|
|
self.start() # Run in thread
|
|
|
|
def run(self):
|
|
# MessageBox(self.message, self.title, win32con.MB_ICONERROR)
|
|
MessageBox(0, self.message, self.title,
|
|
win32con.MB_ICONERROR | win32con.MB_SYSTEMMODAL)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
WarnDlg('This is an example of a warning', 'Warning!')
|
|
ErrorDlg('This is an example of an error message')
|
|
wb = Waitbar('Waitbar example')
|
|
# wb2 = Waitbar2('Waitbar example')
|
|
for i in xrange(20):
|
|
print(wb.update(i * 5))
|
|
# wb2.update(i)
|
|
sleep(0.1)
|
|
wb.close()
|
|
# wb2.close()
|