context_menu.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. # A sample context menu handler.
  2. # Adds a 'Hello from Python' menu entry to .py files. When clicked, a
  3. # simple message box is displayed.
  4. #
  5. # To demostrate:
  6. # * Execute this script to register the context menu.
  7. # * Open Windows Explorer, and browse to a directory with a .py file.
  8. # * Right-Click on a .py file - locate and click on 'Hello from Python' on
  9. # the context menu.
  10. import pythoncom
  11. from win32com.shell import shell, shellcon
  12. import win32gui
  13. import win32con
  14. class ShellExtension:
  15. _reg_progid_ = "Python.ShellExtension.ContextMenu"
  16. _reg_desc_ = "Python Sample Shell Extension (context menu)"
  17. _reg_clsid_ = "{CED0336C-C9EE-4a7f-8D7F-C660393C381F}"
  18. _com_interfaces_ = [shell.IID_IShellExtInit, shell.IID_IContextMenu]
  19. _public_methods_ = shellcon.IContextMenu_Methods + shellcon.IShellExtInit_Methods
  20. def Initialize(self, folder, dataobj, hkey):
  21. print "Init", folder, dataobj, hkey
  22. self.dataobj = dataobj
  23. def QueryContextMenu(self, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags):
  24. print "QCM", hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags
  25. # Query the items clicked on
  26. format_etc = win32con.CF_HDROP, None, 1, -1, pythoncom.TYMED_HGLOBAL
  27. sm = self.dataobj.GetData(format_etc)
  28. num_files = shell.DragQueryFile(sm.data_handle, -1)
  29. if num_files>1:
  30. msg = "&Hello from Python (with %d files selected)" % num_files
  31. else:
  32. fname = shell.DragQueryFile(sm.data_handle, 0)
  33. msg = "&Hello from Python (with '%s' selected)" % fname
  34. idCmd = idCmdFirst
  35. items = ['First Python content menu item']
  36. if (uFlags & 0x000F) == shellcon.CMF_NORMAL: # Check == here, since CMF_NORMAL=0
  37. print "CMF_NORMAL..."
  38. items.append(msg)
  39. elif uFlags & shellcon.CMF_VERBSONLY:
  40. print "CMF_VERBSONLY..."
  41. items.append(msg + " - shortcut")
  42. elif uFlags & shellcon.CMF_EXPLORE:
  43. print "CMF_EXPLORE..."
  44. items.append(msg + " - normal file, right-click in Explorer")
  45. elif uFlags & CMF_DEFAULTONLY:
  46. print "CMF_DEFAULTONLY...\r\n"
  47. else:
  48. print "** unknown flags", uFlags
  49. win32gui.InsertMenu(hMenu, indexMenu,
  50. win32con.MF_SEPARATOR|win32con.MF_BYPOSITION,
  51. 0, None)
  52. indexMenu += 1
  53. for item in items:
  54. win32gui.InsertMenu(hMenu, indexMenu,
  55. win32con.MF_STRING|win32con.MF_BYPOSITION,
  56. idCmd, item)
  57. indexMenu += 1
  58. idCmd += 1
  59. win32gui.InsertMenu(hMenu, indexMenu,
  60. win32con.MF_SEPARATOR|win32con.MF_BYPOSITION,
  61. 0, None)
  62. indexMenu += 1
  63. return idCmd-idCmdFirst # Must return number of menu items we added.
  64. def InvokeCommand(self, ci):
  65. mask, hwnd, verb, params, dir, nShow, hotkey, hicon = ci
  66. win32gui.MessageBox(hwnd, "Hello", "Wow", win32con.MB_OK)
  67. def GetCommandString(self, cmd, typ):
  68. # If GetCommandString returns the same string for all items then
  69. # the shell seems to ignore all but one. This is even true in
  70. # Win7 etc where there is no status bar (and hence this string seems
  71. # ignored)
  72. return "Hello from Python (cmd=%d)!!" % (cmd,)
  73. def DllRegisterServer():
  74. import _winreg
  75. key = _winreg.CreateKey(_winreg.HKEY_CLASSES_ROOT,
  76. "Python.File\\shellex")
  77. subkey = _winreg.CreateKey(key, "ContextMenuHandlers")
  78. subkey2 = _winreg.CreateKey(subkey, "PythonSample")
  79. _winreg.SetValueEx(subkey2, None, 0, _winreg.REG_SZ, ShellExtension._reg_clsid_)
  80. print ShellExtension._reg_desc_, "registration complete."
  81. def DllUnregisterServer():
  82. import _winreg
  83. try:
  84. key = _winreg.DeleteKey(_winreg.HKEY_CLASSES_ROOT,
  85. "Python.File\\shellex\\ContextMenuHandlers\\PythonSample")
  86. except WindowsError, details:
  87. import errno
  88. if details.errno != errno.ENOENT:
  89. raise
  90. print ShellExtension._reg_desc_, "unregistration complete."
  91. if __name__=='__main__':
  92. from win32com.server import register
  93. register.UseCommandLine(ShellExtension,
  94. finalize_register = DllRegisterServer,
  95. finalize_unregister = DllUnregisterServer)