Spaces:
Sleeping
Sleeping
# toolmenu.py | |
import sys | |
import win32api | |
import win32con | |
import win32ui | |
from . import app | |
tools = {} | |
idPos = 100 | |
# The default items should no tools menu exist in the INI file. | |
defaultToolMenuItems = [ | |
("Browser", "win32ui.GetApp().OnViewBrowse(0,0)"), | |
( | |
"Browse PythonPath", | |
"from pywin.tools import browseProjects;browseProjects.Browse()", | |
), | |
("Edit Python Path", "from pywin.tools import regedit;regedit.EditRegistry()"), | |
("COM Makepy utility", "from win32com.client import makepy;makepy.main()"), | |
( | |
"COM Browser", | |
"from win32com.client import combrowse;combrowse.main(modal=False)", | |
), | |
( | |
"Trace Collector Debugging tool", | |
"from pywin.tools import TraceCollector;TraceCollector.MakeOutputWindow()", | |
), | |
] | |
def LoadToolMenuItems(): | |
# Load from the registry. | |
items = [] | |
lookNo = 1 | |
while 1: | |
menu = win32ui.GetProfileVal("Tools Menu\\%s" % lookNo, "", "") | |
if menu == "": | |
break | |
cmd = win32ui.GetProfileVal("Tools Menu\\%s" % lookNo, "Command", "") | |
items.append((menu, cmd)) | |
lookNo = lookNo + 1 | |
if len(items) == 0: | |
items = defaultToolMenuItems | |
return items | |
def WriteToolMenuItems(items): | |
# Items is a list of (menu, command) | |
# Delete the entire registry tree. | |
try: | |
mainKey = win32ui.GetAppRegistryKey() | |
toolKey = win32api.RegOpenKey(mainKey, "Tools Menu") | |
except win32ui.error: | |
toolKey = None | |
if toolKey is not None: | |
while 1: | |
try: | |
subkey = win32api.RegEnumKey(toolKey, 0) | |
except win32api.error: | |
break | |
win32api.RegDeleteKey(toolKey, subkey) | |
# Keys are now removed - write the new ones. | |
# But first check if we have the defaults - and if so, dont write anything! | |
if items == defaultToolMenuItems: | |
return | |
itemNo = 1 | |
for menu, cmd in items: | |
win32ui.WriteProfileVal("Tools Menu\\%s" % itemNo, "", menu) | |
win32ui.WriteProfileVal("Tools Menu\\%s" % itemNo, "Command", cmd) | |
itemNo = itemNo + 1 | |
def SetToolsMenu(menu, menuPos=None): | |
global tools | |
global idPos | |
# todo - check the menu does not already exist. | |
# Create the new menu | |
toolsMenu = win32ui.CreatePopupMenu() | |
# Load from the ini file. | |
items = LoadToolMenuItems() | |
for menuString, cmd in items: | |
tools[idPos] = (menuString, cmd, menuString) | |
toolsMenu.AppendMenu( | |
win32con.MF_ENABLED | win32con.MF_STRING, idPos, menuString | |
) | |
win32ui.GetMainFrame().HookCommand(HandleToolCommand, idPos) | |
idPos = idPos + 1 | |
# Find the correct spot to insert the new tools menu. | |
if menuPos is None: | |
menuPos = menu.GetMenuItemCount() - 2 | |
if menuPos < 0: | |
menuPos = 0 | |
menu.InsertMenu( | |
menuPos, | |
win32con.MF_BYPOSITION | |
| win32con.MF_ENABLED | |
| win32con.MF_STRING | |
| win32con.MF_POPUP, | |
toolsMenu.GetHandle(), | |
"&Tools", | |
) | |
def HandleToolCommand(cmd, code): | |
import re | |
import traceback | |
global tools | |
(menuString, pyCmd, desc) = tools[cmd] | |
win32ui.SetStatusText("Executing tool %s" % desc, 1) | |
pyCmd = re.sub("\\\\n", "\n", pyCmd) | |
win32ui.DoWaitCursor(1) | |
oldFlag = None | |
try: | |
oldFlag = sys.stdout.template.writeQueueing | |
sys.stdout.template.writeQueueing = 0 | |
except (NameError, AttributeError): | |
pass | |
try: | |
exec("%s\n" % pyCmd) | |
worked = 1 | |
except SystemExit: | |
# The program raised a SystemExit - ignore it. | |
worked = 1 | |
except: | |
print("Failed to execute command:\n%s" % pyCmd) | |
traceback.print_exc() | |
worked = 0 | |
if oldFlag is not None: | |
sys.stdout.template.writeQueueing = oldFlag | |
win32ui.DoWaitCursor(0) | |
if worked: | |
text = "Completed successfully." | |
else: | |
text = "Error executing %s." % desc | |
win32ui.SetStatusText(text, 1) | |
# The property page for maintaing the items on the Tools menu. | |
import commctrl | |
from pywin.mfc import dialog | |
if win32ui.UNICODE: | |
LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITW | |
else: | |
LVN_ENDLABELEDIT = commctrl.LVN_ENDLABELEDITA | |
class ToolMenuPropPage(dialog.PropertyPage): | |
def __init__(self): | |
self.bImChangingEditControls = 0 # Am I programatically changing the controls? | |
dialog.PropertyPage.__init__(self, win32ui.IDD_PP_TOOLMENU) | |
def OnInitDialog(self): | |
self.editMenuCommand = self.GetDlgItem(win32ui.IDC_EDIT2) | |
self.butNew = self.GetDlgItem(win32ui.IDC_BUTTON3) | |
# Now hook the change notification messages for the edit controls. | |
self.HookCommand(self.OnCommandEditControls, win32ui.IDC_EDIT1) | |
self.HookCommand(self.OnCommandEditControls, win32ui.IDC_EDIT2) | |
self.HookNotify(self.OnNotifyListControl, commctrl.LVN_ITEMCHANGED) | |
self.HookNotify(self.OnNotifyListControlEndLabelEdit, commctrl.LVN_ENDLABELEDIT) | |
# Hook the button clicks. | |
self.HookCommand(self.OnButtonNew, win32ui.IDC_BUTTON3) # New Item | |
self.HookCommand(self.OnButtonDelete, win32ui.IDC_BUTTON4) # Delete item | |
self.HookCommand(self.OnButtonMove, win32ui.IDC_BUTTON1) # Move up | |
self.HookCommand(self.OnButtonMove, win32ui.IDC_BUTTON2) # Move down | |
# Setup the columns in the list control | |
lc = self.GetDlgItem(win32ui.IDC_LIST1) | |
rect = lc.GetWindowRect() | |
cx = rect[2] - rect[0] | |
colSize = cx / 2 - win32api.GetSystemMetrics(win32con.SM_CXBORDER) - 1 | |
item = commctrl.LVCFMT_LEFT, colSize, "Menu Text" | |
lc.InsertColumn(0, item) | |
item = commctrl.LVCFMT_LEFT, colSize, "Python Command" | |
lc.InsertColumn(1, item) | |
# Insert the existing tools menu | |
itemNo = 0 | |
for desc, cmd in LoadToolMenuItems(): | |
lc.InsertItem(itemNo, desc) | |
lc.SetItemText(itemNo, 1, cmd) | |
itemNo = itemNo + 1 | |
self.listControl = lc | |
return dialog.PropertyPage.OnInitDialog(self) | |
def OnOK(self): | |
# Write the menu back to the registry. | |
items = [] | |
itemLook = 0 | |
while 1: | |
try: | |
text = self.listControl.GetItemText(itemLook, 0) | |
if not text: | |
break | |
items.append((text, self.listControl.GetItemText(itemLook, 1))) | |
except win32ui.error: | |
# no more items! | |
break | |
itemLook = itemLook + 1 | |
WriteToolMenuItems(items) | |
return self._obj_.OnOK() | |
def OnCommandEditControls(self, id, cmd): | |
# print "OnEditControls", id, cmd | |
if cmd == win32con.EN_CHANGE and not self.bImChangingEditControls: | |
itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) | |
newText = self.editMenuCommand.GetWindowText() | |
self.listControl.SetItemText(itemNo, 1, newText) | |
return 0 | |
def OnNotifyListControlEndLabelEdit(self, id, cmd): | |
newText = self.listControl.GetEditControl().GetWindowText() | |
itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) | |
self.listControl.SetItemText(itemNo, 0, newText) | |
def OnNotifyListControl(self, id, cmd): | |
# print id, cmd | |
try: | |
itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) | |
except win32ui.error: # No selection! | |
return | |
self.bImChangingEditControls = 1 | |
try: | |
item = self.listControl.GetItem(itemNo, 1) | |
self.editMenuCommand.SetWindowText(item[4]) | |
finally: | |
self.bImChangingEditControls = 0 | |
return 0 # we have handled this! | |
def OnButtonNew(self, id, cmd): | |
if cmd == win32con.BN_CLICKED: | |
newIndex = self.listControl.GetItemCount() | |
self.listControl.InsertItem(newIndex, "Click to edit the text") | |
self.listControl.EnsureVisible(newIndex, 0) | |
def OnButtonMove(self, id, cmd): | |
if cmd == win32con.BN_CLICKED: | |
try: | |
itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) | |
except win32ui.error: | |
return | |
menu = self.listControl.GetItemText(itemNo, 0) | |
cmd = self.listControl.GetItemText(itemNo, 1) | |
if id == win32ui.IDC_BUTTON1: | |
# Move up | |
if itemNo > 0: | |
self.listControl.DeleteItem(itemNo) | |
# reinsert it. | |
self.listControl.InsertItem(itemNo - 1, menu) | |
self.listControl.SetItemText(itemNo - 1, 1, cmd) | |
else: | |
# Move down. | |
if itemNo < self.listControl.GetItemCount() - 1: | |
self.listControl.DeleteItem(itemNo) | |
# reinsert it. | |
self.listControl.InsertItem(itemNo + 1, menu) | |
self.listControl.SetItemText(itemNo + 1, 1, cmd) | |
def OnButtonDelete(self, id, cmd): | |
if cmd == win32con.BN_CLICKED: | |
try: | |
itemNo = self.listControl.GetNextItem(-1, commctrl.LVNI_SELECTED) | |
except win32ui.error: # No selection! | |
return | |
self.listControl.DeleteItem(itemNo) | |