def _notify(klass, hwnd, msg, wparam, lparam): self = klass._instance[hwnd] if lparam == win32con.WM_LBUTTONDBLCLK: menu = self.get_popup() wid = win32gui.GetMenuDefaultItem(menu, 0, 0) if 0 < wid: win32gui.PostMessage(hwnd, win32con.WM_COMMAND, wid, 0) elif lparam == win32con.WM_RBUTTONUP: menu = self.get_popup() pos = win32gui.GetCursorPos() win32gui.SetForegroundWindow(hwnd) win32gui.TrackPopupMenu(menu, win32con.TPM_LEFTALIGN, pos[0], pos[1], 0, hwnd, None) win32gui.PostMessage(hwnd, win32con.WM_NULL, 0, 0) elif lparam == win32con.WM_LBUTTONUP: pass return True
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) hmenu = win32gui.CreateMenu() try: # Get the IContextMenu for the items. inout, cm = self.folder.GetUIObjectOf(self.hwnd_parent, sel, shell.IID_IContextMenu, 0) # 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 # *sob* - delegating to the shell does work - but lands us # in the original location. Q179911 also shows that # ShellExecuteEx should work - but I can't make it work as # described (XP: function call succeeds, but another thread # shows a dialog with text of E_INVALID_PARAM, and new # Explorer window opens with desktop view. Vista: function # call succeeds, but no window created at all. # On Vista, I'd love to get an IExplorerBrowser interface # from the shell, but a QI fails, and although the # IShellBrowser does appear to support IServiceProvider, I # still can't get it if 0: 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) else: rv = shell.ShellExecuteEx(hwnd=self.hwnd_parent, nShow=win32con.SW_NORMAL, lpClass="folder", lpVerb="explore", lpIDList=sel[0]) print("ShellExecuteEx returned", rv) finally: win32gui.DestroyMenu(hmenu)