アイコンとサブメニューを備えたPythonを使用していくつかのシェル拡張機能を追加しようとしていますが、pywin32のデモよりもはるかに多くの機能を取得するのに苦労しています。グーグルで検索しても何も思いつかないようです。
右クリックしたファイル/フォルダの場所やファイルの種類などに応じてサブメニューのオプションを変更できるようにするには、comサーバーを登録する必要があると思います。
# 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)