#-------------------------------------------------------------------- # # 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)