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.
pywafo/wafo/win32_utils.py

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 range(20):
print(wb.update(i * 5))
# wb2.update(i)
sleep(0.1)
wb.close()
# wb2.close()