2012-05-31 19 views
15

का उपयोग कर उप-मेन्यू के साथ विंडोज एक्सप्लोरर संदर्भ मेनू मैं आइकन और उप मेनू के साथ पायथन का उपयोग करके कुछ खोल एक्सटेंशन जोड़ने की कोशिश कर रहा हूं लेकिन मैं pywin32 में डेमो से कहीं अधिक पाने के लिए संघर्ष कर रहा हूं। मैं Google को खोजकर कुछ भी नहीं आ सकता, या तो।pywin32

मेरा मानना ​​है कि मैं एक कॉम सर्वर रजिस्टर करने के लिए पर जहां सही क्लिक किया फ़ाइल के आधार सबमेनू में विकल्प को बदलने में सक्षम होने की जरूरत है/फ़ोल्डर है और आदि

# A sample context menu handler. 
# Adds a 'Hello from Python' menu entry to .py files. When clicked, a 
# simple message box is displayed. 
# 
# To demostrate: 
# * Execute this script to register the context menu. 
# * Open Windows Explorer, and browse to a directory with a .py file. 
# * Right-Click on a .py file - locate and click on 'Hello from Python' on 
# the context menu. 

import pythoncom 
from win32com.shell import shell, shellcon 
import win32gui 
import win32con 

class ShellExtension: 
    _reg_progid_ = "Python.ShellExtension.ContextMenu" 
    _reg_desc_ = "Python Sample Shell Extension (context menu)" 
    _reg_clsid_ = "{CED0336C-C9EE-4a7f-8D7F-C660393C381F}" 
    _com_interfaces_ = [shell.IID_IShellExtInit, shell.IID_IContextMenu] 
    _public_methods_ = shellcon.IContextMenu_Methods + shellcon.IShellExtInit_Methods 

    def Initialize(self, folder, dataobj, hkey): 
     print "Init", folder, dataobj, hkey 
     self.dataobj = dataobj 

    def QueryContextMenu(self, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags): 
     print "QCM", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags 
     # Query the items clicked on 
     format_etc = win32con.CF_HDROP, None, 1, -1, pythoncom.TYMED_HGLOBAL 
     sm = self.dataobj.GetData(format_etc) 
     num_files = shell.DragQueryFile(sm.data_handle, -1) 
     if num_files>1: 
      msg = "&Hello from Python (with %d files selected)" % num_files 
     else: 
      fname = shell.DragQueryFile(sm.data_handle, 0) 
      msg = "&Hello from Python (with '%s' selected)" % fname 
     idCmd = idCmdFirst 
     items = ['First Python content menu item!'] 
     if (uFlags & 0x000F) == shellcon.CMF_NORMAL: # Check == here, since CMF_NORMAL=0 
      print "CMF_NORMAL..." 
      items.append(msg) 
     elif uFlags & shellcon.CMF_VERBSONLY: 
      print "CMF_VERBSONLY..." 
      items.append(msg + " - shortcut") 
     elif uFlags & shellcon.CMF_EXPLORE: 
      print "CMF_EXPLORE..." 
      items.append(msg + " - normal file, right-click in Explorer") 
     elif uFlags & CMF_DEFAULTONLY: 
      print "CMF_DEFAULTONLY...\r\n" 
     else: 
      print "** unknown flags", uFlags 
     win32gui.InsertMenu(hMenu, indexMenu, 
          win32con.MF_SEPARATOR|win32con.MF_BYPOSITION, 
          0, None) 
     indexMenu += 1 
     for item in items: 
      win32gui.InsertMenu(hMenu, indexMenu, 
           win32con.MF_STRING|win32con.MF_BYPOSITION, 
           idCmd, item) 
      indexMenu += 1 
      idCmd += 1 

     win32gui.InsertMenu(hMenu, indexMenu, 
          win32con.MF_SEPARATOR|win32con.MF_BYPOSITION, 
          0, None) 
     indexMenu += 1 
     return idCmd-idCmdFirst # Must return number of menu items we added. 

    def InvokeCommand(self, ci): 
     mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci 
     win32gui.MessageBox(hwnd, "Hello", "Wow", win32con.MB_OK) 

    def GetCommandString(self, cmd, typ): 
     # If GetCommandString returns the same string for all items then 
     # the shell seems to ignore all but one. This is even true in 
     # Win7 etc where there is no status bar (and hence this string seems 
     # ignored) 
     return "Hello from Python (cmd=%d)!!" % (cmd,) 

def DllRegisterServer(): 
    import _winreg 
    folder_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 
    "Folder\\shellex") 
    folder_subkey = _winreg.CreateKey(folder_key, "ContextMenuHandlers") 
    folder_subkey2 = _winreg.CreateKey(folder_subkey, "PythonSample") 
    _winreg.SetValueEx(folder_subkey2, None, 0, _winreg.REG_SZ, 
    ShellExtension._reg_clsid_) 

    file_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 
    "*\\shellex") 
    file_subkey = _winreg.CreateKey(file_key, "ContextMenuHandlers") 
    file_subkey2 = _winreg.CreateKey(file_subkey, "PythonSample") 
    _winreg.SetValueEx(file_subkey2, None, 0, _winreg.REG_SZ, 
    ShellExtension._reg_clsid_) 

    print ShellExtension._reg_desc_, "registration complete." 

def DllUnregisterServer(): 
    import _winreg 
    try: 
     folder_key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT, 

     "Folder\\shellex\\ContextMenuHandlers\\PythonSample") 
     file_key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT, 

     "*\\shellex\\ContextMenuHandlers\\PythonSample ") 
    except WindowsError, details: 
     import errno 
     if details.errno != errno.ENOENT: 
      raise 
    print ShellExtension._reg_desc_, "unregistration complete." 

if __name__=='__main__': 
    from win32com.server import register 
    register.UseCommandLine(ShellExtension, 
        finalize_register = DllRegisterServer, 
        finalize_unregister = DllUnregisterServer) 
+0

हाय GP89। यदि आपको कोई समाधान मिलता है तो यहां पोस्ट करें। मैं एक साधारण संदर्भ मेनू जोड़ने की कोशिश कर रहा हूं जो केवल एक विशेष फ़ोल्डर के लिए दिखाई देता है लेकिन मुझे Win32 प्रोग्रामिंग के बारे में कोई जानकारी नहीं है। –

+0

अरे, इसमें काफी समय लगा लेकिन मैं अब इसके साथ लगभग हूं। मुझे डीबग करने या नेट पर वास्तव में किसी भी उदाहरण के लिए कोई रास्ता नहीं मिला। मैं इसे अगले दिन या दो में पोस्ट करूंगा :) – GP89

+0

मैंने नीचे दिए गए उत्तर को दिया है, अगर आप पंजीकरण में फ़ाइल बिट लेते हैं और विधियों को अनधिकृत करते हैं और क्वेरी विधि से 'वापसी 0'' करते हैं, यदि आप अंदर नहीं हैं जिस फ़ोल्डर में आप रुचि रखते हैं उसे प्राप्त करने में सक्षम होना चाहिए जो आप काफी आसानी से प्राप्त करना चाहते हैं – GP89

उत्तर

14

मुझे पता चला फ़ाइल के प्रकार कैसे बहुत सारे परीक्षण और त्रुटि और googling के बाद ऐसा करने के लिए।

नीचे दिया गया उदाहरण उपमेनू और आइकन के साथ एक मेनू दिखाता है।

# A sample context menu handler. 
# Adds a menu item with sub menu to all files and folders, different options inside specified folder. 
# When clicked a list of selected items is displayed. 
# 
# To demostrate: 
# * Execute this script to register the context menu. `python context_menu.py --register` 
# * Restart explorer.exe- in the task manager end process on explorer.exe. Then file > new task, then type explorer.exe 
# * Open Windows Explorer, and browse to a file/directory. 
# * Right-Click file/folder - locate and click on an option under 'Menu options'. 

import os 
import pythoncom 
from win32com.shell import shell, shellcon 
import win32gui 
import win32con 
import win32api 

class ShellExtension: 
    _reg_progid_ = "Python.ShellExtension.ContextMenu" 
    _reg_desc_ = "Python Sample Shell Extension (context menu)" 
    _reg_clsid_ = "{CED0336C-C9EE-4a7f-8D7F-C660393C381F}" 
    _com_interfaces_ = [shell.IID_IShellExtInit, shell.IID_IContextMenu] 
    _public_methods_ = shellcon.IContextMenu_Methods + shellcon.IShellExtInit_Methods 

    def Initialize(self, folder, dataobj, hkey): 
     print "Init", folder, dataobj, hkey 
     win32gui.InitCommonControls() 
     self.brand= "Menu options" 
     self.folder= "C:\\Users\\Paul\\" 
     self.dataobj = dataobj 
     self.hicon= self.prep_menu_icon(r"C:\path\to\icon.ico") 


    def QueryContextMenu(self, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags): 
     print "QCM", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags 

     # Query the items clicked on 
     files= self.getFilesSelected() 

     fname = files[0] 
     idCmd = idCmdFirst 

     isdir= os.path.isdir(fname) 
     in_folder= all([f_path.startswith(self.folder) for f_path in files]) 

     win32gui.InsertMenu(hMenu, indexMenu, 
      win32con.MF_SEPARATOR|win32con.MF_BYPOSITION, 
      0, None) 
     indexMenu += 1 

     menu= win32gui.CreatePopupMenu() 
     win32gui.InsertMenu(hMenu,indexMenu,win32con.MF_STRING|win32con.MF_BYPOSITION|win32con.MF_POPUP,menu,self.brand) 
     win32gui.SetMenuItemBitmaps(hMenu,menu,0,self.hicon,self.hicon) 
#  idCmd+=1 
     indexMenu+=1 

     if in_folder: 
      if len(files) == 1: 
       if isdir: 
        win32gui.InsertMenu(menu,0,win32con.MF_STRING,idCmd,"Item 1"); idCmd+=1 
       else: 
        win32gui.InsertMenu(menu,0,win32con.MF_STRING,idCmd,"Item 2") 
        win32gui.SetMenuItemBitmaps(menu,idCmd,0,self.hicon,self.hicon) 
        idCmd+=1 
     else: 
      win32gui.InsertMenu(menu,0,win32con.MF_STRING,idCmd,"Item 3") 
      win32gui.SetMenuItemBitmaps(menu,idCmd,0,self.hicon,self.hicon) 
      idCmd+=1 

     if idCmd > idCmdFirst: 
      win32gui.InsertMenu(menu,1,win32con.MF_SEPARATOR,0,None) 

     win32gui.InsertMenu(menu,2,win32con.MF_STRING,idCmd,"Item 4") 
     win32gui.SetMenuItemBitmaps(menu,idCmd,0,self.hicon,self.hicon) 
     idCmd+=1 
     win32gui.InsertMenu(menu,3,win32con.MF_STRING,idCmd,"Item 5") 
     win32gui.SetMenuItemBitmaps(menu,idCmd,0,self.hicon,self.hicon) 
     idCmd+=1 

     win32gui.InsertMenu(menu,4,win32con.MF_SEPARATOR,0,None) 

     win32gui.InsertMenu(menu,5,win32con.MF_STRING|win32con.MF_DISABLED,idCmd,"Item 6") 
     win32gui.SetMenuItemBitmaps(menu,idCmd,0,self.hicon,self.hicon) 
     idCmd+=1 

     win32gui.InsertMenu(hMenu, indexMenu, 
          win32con.MF_SEPARATOR|win32con.MF_BYPOSITION, 
          0, None) 
     indexMenu += 1 
     return idCmd-idCmdFirst # Must return number of menu items we added. 

    def getFilesSelected(self): 
     format_etc = win32con.CF_HDROP, None, 1, -1, pythoncom.TYMED_HGLOBAL 
     sm = self.dataobj.GetData(format_etc) 
     num_files = shell.DragQueryFile(sm.data_handle, -1) 
     files= [] 
     for i in xrange(num_files): 
      fpath= shell.DragQueryFile(sm.data_handle,i) 
      files.append(fpath) 
     return files 

    def prep_menu_icon(self, icon): #Couldn't get this to work with pngs, only ico 
     # First load the icon. 
     ico_x = win32api.GetSystemMetrics(win32con.SM_CXSMICON) 
     ico_y = win32api.GetSystemMetrics(win32con.SM_CYSMICON) 
     hicon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, ico_x, ico_y, win32con.LR_LOADFROMFILE) 

     hdcBitmap = win32gui.CreateCompatibleDC(0) 
     hdcScreen = win32gui.GetDC(0) 
     hbm = win32gui.CreateCompatibleBitmap(hdcScreen, ico_x, ico_y) 
     hbmOld = win32gui.SelectObject(hdcBitmap, hbm) 
     # Fill the background. 
     brush = win32gui.GetSysColorBrush(win32con.COLOR_MENU) 
     win32gui.FillRect(hdcBitmap, (0, 0, 16, 16), brush) 
     # unclear if brush needs to be feed. Best clue I can find is: 
     # "GetSysColorBrush returns a cached brush instead of allocating a new 
     # one." - implies no DeleteObject 
     # draw the icon 
     win32gui.DrawIconEx(hdcBitmap, 0, 0, hicon, ico_x, ico_y, 0, 0, win32con.DI_NORMAL) 
     win32gui.SelectObject(hdcBitmap, hbmOld) 
     win32gui.DeleteDC(hdcBitmap) 

     return hbm 

    def InvokeCommand(self, ci): 
     mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci 
     win32gui.MessageBox(hwnd, str(self.getFilesSelected()), "Wow", win32con.MB_OK) 

    def GetCommandString(self, cmd, typ): 
     # If GetCommandString returns the same string for all items then 
     # the shell seems to ignore all but one. This is even true in 
     # Win7 etc where there is no status bar (and hence this string seems 
     # ignored) 
     return "Hello from Python (cmd=%d)!!" % (cmd,) 

def DllRegisterServer(): 
    import _winreg 
    folder_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 
    "Folder\\shellex") 
    folder_subkey = _winreg.CreateKey(folder_key, "ContextMenuHandlers") 
    folder_subkey2 = _winreg.CreateKey(folder_subkey, "PythonSample") 
    _winreg.SetValueEx(folder_subkey2, None, 0, _winreg.REG_SZ, 
    ShellExtension._reg_clsid_) 

    file_key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT, 
    "*\\shellex") 
    file_subkey = _winreg.CreateKey(file_key, "ContextMenuHandlers") 
    file_subkey2 = _winreg.CreateKey(file_subkey, "PythonSample") 
    _winreg.SetValueEx(file_subkey2, None, 0, _winreg.REG_SZ, 
    ShellExtension._reg_clsid_) 

    print ShellExtension._reg_desc_, "registration complete." 

def DllUnregisterServer(): 
    import _winreg 
    try: 
     folder_key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT, 

     "Folder\\shellex\\ContextMenuHandlers\\PythonSample") 
     file_key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT, 

     "*\\shellex\\ContextMenuHandlers\\PythonSample") 
    except WindowsError, details: 
     import errno 
     if details.errno != errno.ENOENT: 
      raise 
    print ShellExtension._reg_desc_, "unregistration complete." 

if __name__=='__main__': 
    from win32com.server import register 
    register.UseCommandLine(ShellExtension, 
        finalize_register = DllRegisterServer, 
        finalize_unregister = DllUnregisterServer) 
+0

क्या यह विंडोज 10 पर काम करता है? मुझे इसके साथ बहुत भाग्य नहीं है? – Dynite

+0

@Dynite मुझे यकीन नहीं है, मैंने कुछ वर्षों में विंडोज सिस्टम का उपयोग नहीं किया है। विंडोज 7 के साथ काम कर रहा था जब मैं यह कर रहा था – GP89

+0

कुछ विकल्प https://msdn.microsoft.com/en-gb/library/windows/desktop/cc144171(v=vs.85).aspx#cascade_subcommands और कुछ टिप्पणियां मिलीं उस पृष्ठ (जैसा कि इसमें त्रुटियां हैं) यहां, https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/3ee4702a-f75a-4790-9332-e50f241efd6f/unable-to-create-extended-cascaded- मेनू का उपयोग कर-extendedsubcommandskey? मंच = windowsuidevelopment – Dynite

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^