[pywin32-checkins] pywin32/com/win32comext/shell/demos/servers shell_view.py, 1.6, 1.7
OLD project page for the Python extensions for Windows
Brought to you by:
mhammond
From: Mark H. <mha...@us...> - 2007-02-12 03:22:00
|
Update of /cvsroot/pywin32/pywin32/com/win32comext/shell/demos/servers In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv3691 Modified Files: shell_view.py Log Message: Upgrade the shell_view sample to include a list-control based view and also get more coverage for the shell.cpp functions and structure handling. Index: shell_view.py =================================================================== RCS file: /cvsroot/pywin32/pywin32/com/win32comext/shell/demos/servers/shell_view.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** shell_view.py 26 May 2004 09:39:11 -0000 1.6 --- shell_view.py 12 Feb 2007 03:21:56 -0000 1.7 *************** *** 51,55 **** import pyclbr import pythoncom ! import win32gui, win32api, win32con, winerror from win32com.shell import shell, shellcon from win32com.server.util import wrap, NewEnum --- 51,56 ---- import pyclbr import pythoncom ! import win32gui, win32gui_struct, win32api, win32con, winerror ! import commctrl from win32com.shell import shell, shellcon from win32com.server.util import wrap, NewEnum *************** *** 62,65 **** --- 63,70 ---- debug=0 + # markh is toying with an implementation that allows auto reload of a module + # if this attribute exists. + com_auto_reload = True + # Helper function to get a system IShellFolder interface, and the PIDL within # that folder for an existing file/directory. *************** *** 165,169 **** try: inout, ret = folder.GetUIObjectOf(hwndOwner, [child_pidl], iid, ! inout, pythoncom.IID_IUnknown) except pythoncom.com_error, (hr, desc, exc, arg): raise COMException(hresult=hr) --- 170,174 ---- try: inout, ret = folder.GetUIObjectOf(hwndOwner, [child_pidl], iid, ! inout, iid) except pythoncom.com_error, (hr, desc, exc, arg): raise COMException(hresult=hr) *************** *** 321,327 **** # by us - see the notes at the top of the file. #print "Initialize called with pidl", repr(pidl) ! pass def CreateViewObject(self, hwnd, iid): ! raise COMException(hresult=winerror.E_NOTIMPL) def EnumObjects(self, hwndOwner, flags): items = [ ["directory\0" + p] for p in sys.path if os.path.isdir(p)] --- 326,333 ---- # by us - see the notes at the top of the file. #print "Initialize called with pidl", repr(pidl) ! self.pidl = pidl def CreateViewObject(self, hwnd, iid): ! return wrap(FileSystemView(self, hwnd), useDispatcher=debug>0) ! def EnumObjects(self, hwndOwner, flags): items = [ ["directory\0" + p] for p in sys.path if os.path.isdir(p)] *************** *** 329,333 **** useDispatcher=(debug>0)) ! # A Simple shell view implementation # This uses scintilla to display a filename, and optionally jump to a line # number. --- 335,671 ---- useDispatcher=(debug>0)) ! # Simple shell view implementations ! ! # Uses a builtin listview control to display simple lists of directories ! # or filenames. ! class FileSystemView: ! _public_methods_ = IShellView_Methods ! _com_interfaces_ = [pythoncom.IID_IOleWindow, ! shell.IID_IShellView, ! ] ! def __init__(self, folder, hwnd): ! self.hwnd_parent = hwnd # provided by explorer. ! self.hwnd = None # intermediate window for catching command notifications. ! self.hwnd_child = None # our ListView ! self.activate_state = None ! self.hmenu = None ! self.browser = None ! self.folder = folder ! self.children = None ! ! # IOleWindow ! def GetWindow(self): ! return self.hwnd ! ! def ContextSensitiveHelp(self, enter_mode): ! raise COMException(hresult=winerror.E_NOTIMPL) ! ! # IShellView ! def CreateViewWindow(self, prev, settings, browser, rect): ! print "CreateViewWindow", prev, settings, browser, rect ! self.cur_foldersettings = settings ! self.browser = browser ! self._CreateMainWindow(prev, settings, browser, rect) ! self._CreateChildWindow(prev) ! ! def _CreateMainWindow(self, prev, settings, browser, rect): ! # Creates a parent window that hosts the view window. This window ! # gets the control notifications etc sent from the child. ! style = win32con.WS_CHILD | win32con.WS_VISIBLE # ! wclass_name = "EnfoldDesktop_DefView" ! # Register the Window class. ! wc = win32gui.WNDCLASS() ! wc.hInstance = win32gui.dllhandle ! wc.lpszClassName = wclass_name ! wc.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW ! try: ! win32gui.RegisterClass(wc) ! except win32gui.error, details: ! # Should only happen when this module is reloaded ! if details[0] != winerror.ERROR_CLASS_ALREADY_EXISTS: ! raise ! ! message_map = { ! win32con.WM_DESTROY: self.OnDestroy, ! win32con.WM_COMMAND: self.OnCommand, ! win32con.WM_NOTIFY: self.OnNotify, ! win32con.WM_CONTEXTMENU: self.OnContextMenu, ! } ! ! self.hwnd = win32gui.CreateWindow( wclass_name, "", style, \ ! rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1], ! self.hwnd_parent, 0, win32gui.dllhandle, None) ! win32gui.SetWindowLong(self.hwnd, win32con.GWL_WNDPROC, message_map) ! print "View 's hwnd is", self.hwnd ! ! def _CreateChildWindow(self, prev): ! # Creates the list view window. ! print "_CreateChildWindow" ! assert self.hwnd_child is None, "already have a window" ! assert self.cur_foldersettings is not None, "no settings" ! style = win32con.WS_CHILD | win32con.WS_VISIBLE | win32con.WS_BORDER | \ ! commctrl.LVS_SHAREIMAGELISTS | commctrl.LVS_EDITLABELS ! ! view_mode, view_flags = self.cur_foldersettings ! if view_mode==shellcon.FVM_ICON: ! style |= commctrl.LVS_ICON | commctrl.LVS_AUTOARRANGE ! elif view_mode==shellcon.FVM_SMALLICON: ! style |= commctrl.LVS_SMALLICON | commctrl.LVS_AUTOARRANGE ! elif view_mode==shellcon.FVM_LIST: ! style |= commctrl.LVS_LIST | commctrl.LVS_AUTOARRANGE ! elif view_mode==shellcon.FVM_DETAILS: ! style |= commctrl.LVS_REPORT | commctrl.LVS_AUTOARRANGE ! else: ! # XP 'thumbnails' etc ! view_mode = shellcon.FVM_DETAILS ! # Default to 'report' ! style |= commctrl.LVS_REPORT | commctrl.LVS_AUTOARRANGE ! ! for f_flag, l_flag in [ ! (shellcon.FWF_SINGLESEL, commctrl.LVS_SINGLESEL), ! (shellcon.FWF_ALIGNLEFT, commctrl.LVS_ALIGNLEFT), ! (shellcon.FWF_SHOWSELALWAYS, commctrl.LVS_SHOWSELALWAYS), ! ]: ! if view_flags & f_flag: ! style |= l_flag ! ! self.hwnd_child = win32gui.CreateWindowEx( ! win32con.WS_EX_CLIENTEDGE, ! "SysListView32", None, style, ! 0, 0, 0, 0, ! self.hwnd, 1000, 0, None) ! ! cr = win32gui.GetClientRect(self.hwnd) ! win32gui.MoveWindow(self.hwnd_child, ! 0, 0, cr[2]-cr[0], cr[3]-cr[1], ! True) ! ! # Setup the columns for the view. ! lvc, extras = win32gui_struct.PackLVCOLUMN(fmt=commctrl.LVCFMT_LEFT, ! subItem=1, ! text='Name', ! cx=300) ! win32gui.SendMessage(self.hwnd_child, commctrl.LVM_INSERTCOLUMN, ! 0, lvc) ! ! lvc, extras = win32gui_struct.PackLVCOLUMN(fmt=commctrl.LVCFMT_RIGHT, ! subItem=1, ! text='Exists', ! cx=50) ! win32gui.SendMessage(self.hwnd_child, commctrl.LVM_INSERTCOLUMN, ! 1, lvc) ! # and fill it with the content ! self.Refresh() ! ! def GetCurrentInfo(self): ! return self.cur_foldersettings ! ! def UIActivate(self, activate_state): ! print "OnActivate" ! ! def _OnActivate(self, activate_state): ! if self.activate_state == activate_state: ! return ! self._OnDeactivate() # restore menu's first, if necessary. ! if activate_state != shellcon.SVUIA_DEACTIVATE: ! assert self.hmenu is None, "Should have destroyed it!" ! self.hmenu = win32gui.CreateMenu() ! widths = 0,0,0,0,0,0 ! # Ask explorer to add its standard items. ! self.browser.InsertMenusSB(self.hmenu, widths) ! # Merge with these standard items ! self._MergeMenus(activate_state) ! self.browser.SetMenuSB(self.hmenu, 0, self.hwnd); ! self.activate_state = activate_state ! ! def _OnDeactivate(self): ! if self.browser is not None and self.hmenu is not None: ! self.browser.SetMenuSB(0, 0, 0) ! self.browser.RemoveMenusSB(self.hmenu) ! win32gui.DestroyMenu(self.hmenu) ! self.hmenu = None ! self.hsubmenus = None ! self.activate_state = shellcon.SVUIA_DEACTIVATE ! ! def _MergeMenus(self, activate_state): ! # Merge the operations we support into the top-level menus. ! # NOTE: This function it *not* called each time the selection changes. ! # SVUIA_ACTIVATE_FOCUS really means "have a selection?" ! have_sel = activate_state == shellcon.SVUIA_ACTIVATE_FOCUS ! # only do "file" menu here, and only 1 item on it! ! mid = shellcon.FCIDM_MENU_FILE ! # Get the hmenu for the menu ! buf, extras = win32gui_struct.EmptyMENUITEMINFO(win32con.MIIM_SUBMENU) ! win32gui.GetMenuItemInfo(self.hmenu, ! mid, ! False, ! buf) ! data = win32gui_struct.UnpackMENUITEMINFO(buf) ! submenu = data[3] ! print "Do someting with the file menu!" ! ! def Refresh(self): ! stateMask = commctrl.LVIS_SELECTED | commctrl.LVIS_DROPHILITED ! state = 0 ! self.children = [] ! # Enumerate and store the child PIDLs ! for cid in self.folder.EnumObjects(self.hwnd, 0): ! print "Have CID" ! self.children.append(cid) ! ! for row_index, data in enumerate(self.children): ! assert len(data)==1, "expecting just a child PIDL" ! typ, path = data[0].split('\0') ! desc = os.path.exists(path) and "Yes" or "No" ! prop_vals = (path, desc) ! # first col ! data, extras = win32gui_struct.PackLVITEM( ! item=row_index, ! subItem=0, ! text=prop_vals[0], ! state=state, ! stateMask=stateMask) ! win32gui.SendMessage(self.hwnd_child, ! commctrl.LVM_INSERTITEM, ! row_index, data) ! # rest of the cols. ! col_index = 1 ! for prop_val in prop_vals[1:]: ! data, extras = win32gui_struct.PackLVITEM( ! item=row_index, ! subItem=col_index, ! text=prop_val) ! ! win32gui.SendMessage(self.hwnd_child, ! commctrl.LVM_SETITEM, ! 0, data) ! col_index += 1 ! ! def SelectItem(self, pidl, flag): ! # For the sake of brevity, we don't implement this yet. ! # You would need to locate the index of the item in the shell-view ! # with that PIDL, then ask the list-view to select it. ! print "Please implement SelectItem for PIDL", pidl ! ! def GetItemObject(self, item_num, iid): ! raise COMException(hresult=winerror.E_NOTIMPL) ! ! def TranslateAccelerator(self, msg): ! return winerror.S_FALSE ! ! def DestroyViewWindow(self): ! win32gui.DestroyWindow(self.hwnd) ! self.hwnd = None ! print "Destroyed view window" ! ! # Message handlers. ! def OnDestroy(self, hwnd, msg, wparam, lparam): ! print "OnDestory" ! ! def OnCommand(self, hwnd, msg, wparam, lparam): ! print "OnCommand" ! ! def OnNotify(self, hwnd, msg, wparam, lparam): ! hwndFrom, idFrom, code = win32gui_struct.UnpackWMNOTIFY(lparam) ! print "OnNotify code=0x%x (0x%x, 0x%x)" % (code, wparam, lparam) ! if code == commctrl.NM_SETFOCUS: ! # Control got focus - Explorer may not know - tell it ! if self.browser is not None: ! self.browser.OnViewWindowActive(None) ! # And do our menu thang ! self._OnActivate(shellcon.SVUIA_ACTIVATE_FOCUS) ! elif code == commctrl.NM_KILLFOCUS: ! self._OnDeactivate() ! elif code == commctrl.NM_DBLCLK: ! # This DblClick implementation leaves a little to be desired :) ! # It demonstrates some useful concepts, such as asking the ! # folder for its context-menu and invoking a command from it. ! # However, as our folder delegates IContextMenu to the shell ! # itself, the end result is that the folder is opened in ! # its "normal" place in Windows explorer rather than inside ! # our shell-extension. ! # Determine the selected items. ! sel = [] ! n = -1 ! while 1: ! n = win32gui.SendMessage(self.hwnd_child, ! commctrl.LVM_GETNEXTITEM, ! n, ! commctrl.LVNI_SELECTED) ! if n==-1: ! break ! sel.append(self.children[n][-1:]) ! print "Selection is", sel ! # Get the IContextMenu for the items. ! inout, cm = self.folder.GetUIObjectOf(self.hwnd_parent, sel, ! shell.IID_IContextMenu, 0) ! hmenu = win32gui.CreateMenu() ! try: ! # As per 'Q179911', we need to determine if the default operation ! # should be 'open' or 'explore' ! flags = shellcon.CMF_DEFAULTONLY ! try: ! self.browser.GetControlWindow(shellcon.FCW_TREE) ! flags |= shellcon.CMF_EXPLORE ! except pythoncom.com_error: ! pass ! id_cmd_first = 1 # TrackPopupMenu makes it hard to use 0 ! cm.QueryContextMenu(hmenu, 0, id_cmd_first, -1, flags) ! # Find the default item in the returned menu. ! cmd = win32gui.GetMenuDefaultItem(hmenu, False, 0) ! if cmd == -1: ! print "Oops: _doDefaultActionFor found no default menu" ! else: ! ci = 0, self.hwnd_parent, cmd-id_cmd_first, None, None, 0, 0, 0 ! cm.InvokeCommand(ci) ! finally: ! win32gui.DestroyMenu(hmenu) ! ! def OnContextMenu(self, hwnd, msg, wparam, lparam): ! # Get the selected items. ! pidls = [] ! n = -1 ! while 1: ! n = win32gui.SendMessage(self.hwnd_child, ! commctrl.LVM_GETNEXTITEM, ! n, ! commctrl.LVNI_SELECTED) ! if n==-1: ! break ! pidls.append(self.children[n][-1:]) ! ! spt = win32api.GetCursorPos() ! if not pidls: ! print "Ignoring background click" ! return ! # Get the IContextMenu for the items. ! inout, cm = self.folder.GetUIObjectOf(self.hwnd_parent, pidls, shell.IID_IContextMenu, 0) ! hmenu = win32gui.CreatePopupMenu() ! sel = None ! # As per 'Q179911', we need to determine if the default operation ! # should be 'open' or 'explore' ! try: ! flags = 0 ! try: ! self.browser.GetControlWindow(shellcon.FCW_TREE) ! flags |= shellcon.CMF_EXPLORE ! except pythoncom.com_error: ! pass ! id_cmd_first = 1 # TrackPopupMenu makes it hard to use 0 ! cm.QueryContextMenu(hmenu, 0, id_cmd_first, -1, flags) ! tpm_flags = win32con.TPM_LEFTALIGN | win32con.TPM_RETURNCMD | \ ! win32con.TPM_RIGHTBUTTON ! sel = win32gui.TrackPopupMenu(hmenu, ! tpm_flags, ! spt[0], spt[1], ! 0, self.hwnd, None) ! print "TrackPopupMenu returned", sel ! finally: ! win32gui.DestroyMenu(hmenu) ! if sel: ! ci = 0, self.hwnd_parent, sel-id_cmd_first, None, None, 0, 0, 0 ! cm.InvokeCommand(ci) ! ! # This uses scintilla to display a filename, and optionally jump to a line # number. |