Lightningbeam/PyGUI-2.5.3/GUI/Win32/Component.py

264 lines
8.4 KiB
Python
Executable File

#--------------------------------------------------------------------
#
# PyGUI - Component - Win32
#
#--------------------------------------------------------------------
import win32con as wc, win32ui as ui, win32gui as gui, win32api as api
from GUI import export
from GUI.Geometry import sub_pt
from GUI import application
from GUI.WinUtils import win_none, win_event_messages
from GUI.WinEvents import win_message_to_event, win_prev_key_state
from GUI.Exceptions import Cancel
from GUI.GComponents import Component as GComponent, transform_coords
win_swp_flags = wc.SWP_NOACTIVATE | wc.SWP_NOZORDER
win_sws_flags = win_swp_flags | wc.SWP_NOMOVE
# Virtual key code to menu key char
win_menu_key_map = {
0xc0: '`',
0xbd: '-',
0xbb: '=',
0xdb: '[',
0xdd: ']',
0xba: ';',
0xde: "'",
0xbc: ',',
0xbe: '.',
0xbf: '/',
0xdc: '\\',
}
# Virtual key codes of modifier keys
win_virt_modifiers = (0x10, 0x11, 0x12, 0x14, 0x90)
# Translate virtual key code to menu key char
def win_translate_virtual_menu_key(virt):
if 0x41 <= virt <= 0x5a or 0x30 <= virt <= 0x39:
return chr(virt)
else:
return win_menu_key_map.get(virt)
#--------------------------------------------------------------------
class Component(GComponent):
_has_local_coords = True
_win_hooks_events = False
_win_transparent = False
_win_captures_mouse = False
_h_scroll_offset = 0
_v_scroll_offset = 0
_win_tracking_mouse = False
def __init__(self, _win, **kwds):
if self._win_transparent:
_win.ModifyStyleEx(0, wc.WS_EX_TRANSPARENT, 0)
self._win = _win
self._bounds = self._win_get_actual_bounds()
_win.AttachObject(self)
self._win_install_event_hooks()
GComponent.__init__(self, **kwds)
def destroy(self):
GComponent.destroy(self)
wo = self._win
if wo:
wo.AttachObject(None)
wo.ShowWindow(wc.SW_HIDE)
application()._win_recycle(wo)
#self._win = None
def _win_get_flag(self, flag):
return self._win.GetStyle() & flag != 0
def _win_set_flag(self, b, flag, swp_flags = 0):
if b:
state = flag
else:
state = 0
self._win.ModifyStyle(flag, state, swp_flags)
def _win_set_ex_flag(self, b, flag, swp_flags = 0):
if b:
state = flag
else:
state = 0
self._win.ModifyStyleEx(flag, state, swp_flags)
def _change_container(self, new_container):
GComponent._change_container(self, new_container)
if new_container:
win_new_parent = new_container._win
else:
win_new_parent = win_none
hwnd = self._win.GetSafeHwnd()
gui.SetParent(hwnd, win_new_parent.GetSafeHwnd())
if new_container:
self._win_move_window(self._bounds)
def _win_install_event_hooks(self):
def hook(message):
return self._win_event_message(message)
win = self._win
for msg in win_event_messages:
win.HookMessage(hook, msg)
win.HookMessage(self._win_wm_setfocus, wc.WM_SETFOCUS)
win.HookMessage(self._win_wm_killfocus, wc.WM_KILLFOCUS)
def _win_wm_setfocus(self, msg):
#print "Component._win_wm_setfocus:", self ###
self.targeted()
return True
def targeted(self):
pass
def _win_wm_killfocus(self, msg):
#print "Component._win_wm_killfocus:", self ###
self.untargeted()
return True
def untargeted(self):
pass
def _win_on_ctlcolor(self, dc, typ):
pass
# def OnCtlColor(self, dc, comp, typ):
# #print "Component.OnCtlColor" ###
# meth = getattr(comp, '_win_on_ctlcolor', None)
# if meth:
# return meth(dc, typ)
def get_bounds(self):
return self._bounds
def set_bounds(self, rect):
self._win_move_window(rect)
self._win_change_bounds(rect)
def _win_change_bounds(self, rect):
l0, t0, r0, b0 = self._bounds
l1, t1, r1, b1 = rect
w0 = r0 - l0
h0 = b0 - t0
w1 = r1 - l1
h1 = b1 - t1
self._bounds = rect
if w0 != w1 or h0 != h1:
self._resized((w1 - w0, h1 - h0))
def _win_move_window(self, bounds):
container = self.container
if container:
rect = container._win_adjust_bounds(bounds)
self._win.MoveWindow(rect)
def _win_adjust_bounds(self, bounds):
# Scrollable views override this to adjust for the scroll offset.
return bounds
def _win_get_actual_bounds(self):
win = self._win
parent = win.GetParent()
sbounds = win.GetWindowRect()
return parent._win.ScreenToClient(sbounds)
def become_target(self):
#print "Component.become_target:", self ###
window = self.window
if window:
if window._win_is_active():
#print "...setting focus" ###
self._win.SetFocus()
else:
#print "...saving focus in", window ###
window._win_saved_target = self
def invalidate_rect(self, r):
#print "Component.invalidate_rect:", self, r ###
self._invalidate_rect(r)
if self._win_transparent:
cont = self.container
if cont:
cont.invalidate_rect(self.local_to_container(r))
def _invalidate_rect(self, r):
self._win.InvalidateRect(r)
def local_to_global(self, p):
return self._win.ClientToScreen(p)
def global_to_local(self, p):
return self._win.ScreenToClient(p)
def container_to_local(self, p):
return transform_coords(self.container, self, p)
def local_to_container(self, p):
return transform_coords(self, self.container, p)
def _win_event_message(self, message):
try:
if 0:
from WinUtils import win_message_name ###
print "Component._win_event_message: %s 0x%08x 0x%08x" % ( ###
win_message_name(message[1]),
message[2] & 0xffffffff,
message[3] & 0xffffffff) ###
event = win_message_to_event(message, self)
kind = event.kind
if kind.startswith('key') and message[2] in win_virt_modifiers:
# Do not produce Events for modifier keys
return True
if kind == 'mouse_down' and self._win_captures_mouse:
self._win.SetCapture()
if self._win_tracking_mouse:
if 'mouse' in kind:
self._win_mouse_event = event
api.PostQuitMessage(0)
pass_message = False
else:
if kind == 'key_down' and event.control and event.char:
key = win_translate_virtual_menu_key(message[2])
top = self._win.GetTopLevelFrame()
if top._win_possible_menu_key(key, event.shift, event.option):
return False
pass_message = not self._event_custom_handled(event)
if kind == 'mouse_up' and self._win_captures_mouse:
self._win.ReleaseCapture()
# #<<<
# if kind.startswith('key'):
# if pass_message:
# print "Component._win_event_message: passing", event ###
# else:
# print "Component._win_event_message: absorbing", event ###
# #>>>
return pass_message
except Cancel:
pass
except:
application().report_error()
# print "Component._win_event_message: Posting quit message with 1" ###
# api.PostQuitMessage(1)
def _win_dump_flags(self):
from WinUtils import win_deconstruct_style, win_deconstruct_style_ex
print "%s.%s: style:" % (self.__class__.__module__, self.__class__.__name__)
win_deconstruct_style(self._win.GetStyle())
win_deconstruct_style_ex(self._win.GetExStyle())
# def PreTranslateMessage(self, message):
# print "Component.PreTranslateMessage:", self, \
# message[0], win_message_name(message[1]), \
# message[2]
#
#from WinUtils import win_message_name
export(Component)