Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

regedit.py 13KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. # Regedit - a Registry Editor for Python
  2. import commctrl
  3. import regutil
  4. import win32api
  5. import win32con
  6. import win32ui
  7. from pywin.mfc import dialog, docview, window
  8. from . import hierlist
  9. def SafeApply(fn, args, err_desc=""):
  10. try:
  11. fn(*args)
  12. return 1
  13. except win32api.error as exc:
  14. msg = "Error " + err_desc + "\r\n\r\n" + exc.strerror
  15. win32ui.MessageBox(msg)
  16. return 0
  17. class SplitterFrame(window.MDIChildWnd):
  18. def __init__(self):
  19. # call base CreateFrame
  20. self.images = None
  21. window.MDIChildWnd.__init__(self)
  22. def OnCreateClient(self, cp, context):
  23. splitter = win32ui.CreateSplitter()
  24. doc = context.doc
  25. frame_rect = self.GetWindowRect()
  26. size = ((frame_rect[2] - frame_rect[0]), (frame_rect[3] - frame_rect[1]) // 2)
  27. sub_size = (size[0] // 3, size[1])
  28. splitter.CreateStatic(self, 1, 2)
  29. # CTreeControl view
  30. self.keysview = RegistryTreeView(doc)
  31. # CListControl view
  32. self.valuesview = RegistryValueView(doc)
  33. splitter.CreatePane(self.keysview, 0, 0, (sub_size))
  34. splitter.CreatePane(self.valuesview, 0, 1, (0, 0)) # size ignored.
  35. splitter.SetRowInfo(0, size[1], 0)
  36. # Setup items in the imagelist
  37. return 1
  38. def OnItemDoubleClick(self, info, extra):
  39. (hwndFrom, idFrom, code) = info
  40. if idFrom == win32ui.AFX_IDW_PANE_FIRST:
  41. # Tree control
  42. return None
  43. elif idFrom == win32ui.AFX_IDW_PANE_FIRST + 1:
  44. item = self.keysview.SelectedItem()
  45. self.valuesview.EditValue(item)
  46. return 0
  47. # List control
  48. else:
  49. return None # Pass it on
  50. def PerformItemSelected(self, item):
  51. return self.valuesview.UpdateForRegItem(item)
  52. def OnDestroy(self, msg):
  53. window.MDIChildWnd.OnDestroy(self, msg)
  54. if self.images:
  55. self.images.DeleteImageList()
  56. self.images = None
  57. class RegistryTreeView(docview.TreeView):
  58. def OnInitialUpdate(self):
  59. rc = self._obj_.OnInitialUpdate()
  60. self.frame = self.GetParent().GetParent()
  61. self.hierList = hierlist.HierListWithItems(
  62. self.GetHLIRoot(), win32ui.IDB_HIERFOLDERS, win32ui.AFX_IDW_PANE_FIRST
  63. )
  64. self.hierList.HierInit(self.frame, self.GetTreeCtrl())
  65. self.hierList.SetStyle(
  66. commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS
  67. )
  68. self.hierList.PerformItemSelected = self.PerformItemSelected
  69. self.frame.HookNotify(self.frame.OnItemDoubleClick, commctrl.NM_DBLCLK)
  70. self.frame.HookNotify(self.OnItemRightClick, commctrl.NM_RCLICK)
  71. # self.HookMessage(self.OnItemRightClick, win32con.WM_RBUTTONUP)
  72. def GetHLIRoot(self):
  73. doc = self.GetDocument()
  74. regroot = doc.root
  75. subkey = doc.subkey
  76. return HLIRegistryKey(regroot, subkey, "Root")
  77. def OnItemRightClick(self, notify_data, extra):
  78. # First select the item we right-clicked on.
  79. pt = self.ScreenToClient(win32api.GetCursorPos())
  80. flags, hItem = self.HitTest(pt)
  81. if hItem == 0 or commctrl.TVHT_ONITEM & flags == 0:
  82. return None
  83. self.Select(hItem, commctrl.TVGN_CARET)
  84. menu = win32ui.CreatePopupMenu()
  85. menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1000, "Add Key")
  86. menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1001, "Add Value")
  87. menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1002, "Delete Key")
  88. self.HookCommand(self.OnAddKey, 1000)
  89. self.HookCommand(self.OnAddValue, 1001)
  90. self.HookCommand(self.OnDeleteKey, 1002)
  91. menu.TrackPopupMenu(win32api.GetCursorPos()) # track at mouse position.
  92. return None
  93. def OnDeleteKey(self, command, code):
  94. hitem = self.hierList.GetSelectedItem()
  95. item = self.hierList.ItemFromHandle(hitem)
  96. msg = "Are you sure you wish to delete the key '%s'?" % (item.keyName,)
  97. id = win32ui.MessageBox(msg, None, win32con.MB_YESNO)
  98. if id != win32con.IDYES:
  99. return
  100. if SafeApply(
  101. win32api.RegDeleteKey, (item.keyRoot, item.keyName), "deleting registry key"
  102. ):
  103. # Get the items parent.
  104. try:
  105. hparent = self.GetParentItem(hitem)
  106. except win32ui.error:
  107. hparent = None
  108. self.hierList.Refresh(hparent)
  109. def OnAddKey(self, command, code):
  110. from pywin.mfc import dialog
  111. val = dialog.GetSimpleInput("New key name", "", "Add new key")
  112. if val is None:
  113. return # cancelled.
  114. hitem = self.hierList.GetSelectedItem()
  115. item = self.hierList.ItemFromHandle(hitem)
  116. if SafeApply(win32api.RegCreateKey, (item.keyRoot, item.keyName + "\\" + val)):
  117. self.hierList.Refresh(hitem)
  118. def OnAddValue(self, command, code):
  119. from pywin.mfc import dialog
  120. val = dialog.GetSimpleInput("New value", "", "Add new value")
  121. if val is None:
  122. return # cancelled.
  123. hitem = self.hierList.GetSelectedItem()
  124. item = self.hierList.ItemFromHandle(hitem)
  125. if SafeApply(
  126. win32api.RegSetValue, (item.keyRoot, item.keyName, win32con.REG_SZ, val)
  127. ):
  128. # Simply re-select the current item to refresh the right spitter.
  129. self.PerformItemSelected(item)
  130. # self.Select(hitem, commctrl.TVGN_CARET)
  131. def PerformItemSelected(self, item):
  132. return self.frame.PerformItemSelected(item)
  133. def SelectedItem(self):
  134. return self.hierList.ItemFromHandle(self.hierList.GetSelectedItem())
  135. def SearchSelectedItem(self):
  136. handle = self.hierList.GetChildItem(0)
  137. while 1:
  138. # print "State is", self.hierList.GetItemState(handle, -1)
  139. if self.hierList.GetItemState(handle, commctrl.TVIS_SELECTED):
  140. # print "Item is ", self.hierList.ItemFromHandle(handle)
  141. return self.hierList.ItemFromHandle(handle)
  142. handle = self.hierList.GetNextSiblingItem(handle)
  143. class RegistryValueView(docview.ListView):
  144. def OnInitialUpdate(self):
  145. hwnd = self._obj_.GetSafeHwnd()
  146. style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
  147. win32api.SetWindowLong(
  148. hwnd,
  149. win32con.GWL_STYLE,
  150. (style & ~commctrl.LVS_TYPEMASK) | commctrl.LVS_REPORT,
  151. )
  152. itemDetails = (commctrl.LVCFMT_LEFT, 100, "Name", 0)
  153. self.InsertColumn(0, itemDetails)
  154. itemDetails = (commctrl.LVCFMT_LEFT, 500, "Data", 0)
  155. self.InsertColumn(1, itemDetails)
  156. def UpdateForRegItem(self, item):
  157. self.DeleteAllItems()
  158. hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)
  159. try:
  160. valNum = 0
  161. ret = []
  162. while 1:
  163. try:
  164. res = win32api.RegEnumValue(hkey, valNum)
  165. except win32api.error:
  166. break
  167. name = res[0]
  168. if not name:
  169. name = "(Default)"
  170. self.InsertItem(valNum, name)
  171. self.SetItemText(valNum, 1, str(res[1]))
  172. valNum = valNum + 1
  173. finally:
  174. win32api.RegCloseKey(hkey)
  175. def EditValue(self, item):
  176. # Edit the current value
  177. class EditDialog(dialog.Dialog):
  178. def __init__(self, item):
  179. self.item = item
  180. dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT)
  181. def OnInitDialog(self):
  182. self.SetWindowText("Enter new value")
  183. self.GetDlgItem(win32con.IDCANCEL).ShowWindow(win32con.SW_SHOW)
  184. self.edit = self.GetDlgItem(win32ui.IDC_EDIT1)
  185. # Modify the edit windows style
  186. style = win32api.GetWindowLong(
  187. self.edit.GetSafeHwnd(), win32con.GWL_STYLE
  188. )
  189. style = style & (~win32con.ES_WANTRETURN)
  190. win32api.SetWindowLong(
  191. self.edit.GetSafeHwnd(), win32con.GWL_STYLE, style
  192. )
  193. self.edit.SetWindowText(str(self.item))
  194. self.edit.SetSel(-1)
  195. return dialog.Dialog.OnInitDialog(self)
  196. def OnDestroy(self, msg):
  197. self.newvalue = self.edit.GetWindowText()
  198. try:
  199. index = self.GetNextItem(-1, commctrl.LVNI_SELECTED)
  200. except win32ui.error:
  201. return # No item selected.
  202. if index == 0:
  203. keyVal = ""
  204. else:
  205. keyVal = self.GetItemText(index, 0)
  206. # Query for a new value.
  207. try:
  208. newVal = self.GetItemsCurrentValue(item, keyVal)
  209. except TypeError as details:
  210. win32ui.MessageBox(details)
  211. return
  212. d = EditDialog(newVal)
  213. if d.DoModal() == win32con.IDOK:
  214. try:
  215. self.SetItemsCurrentValue(item, keyVal, d.newvalue)
  216. except win32api.error as exc:
  217. win32ui.MessageBox("Error setting value\r\n\n%s" % exc.strerror)
  218. self.UpdateForRegItem(item)
  219. def GetItemsCurrentValue(self, item, valueName):
  220. hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)
  221. try:
  222. val, type = win32api.RegQueryValueEx(hkey, valueName)
  223. if type != win32con.REG_SZ:
  224. raise TypeError("Only strings can be edited")
  225. return val
  226. finally:
  227. win32api.RegCloseKey(hkey)
  228. def SetItemsCurrentValue(self, item, valueName, value):
  229. # ** Assumes already checked is a string.
  230. hkey = win32api.RegOpenKey(
  231. item.keyRoot, item.keyName, 0, win32con.KEY_SET_VALUE
  232. )
  233. try:
  234. win32api.RegSetValueEx(hkey, valueName, 0, win32con.REG_SZ, value)
  235. finally:
  236. win32api.RegCloseKey(hkey)
  237. class RegTemplate(docview.DocTemplate):
  238. def __init__(self):
  239. docview.DocTemplate.__init__(
  240. self, win32ui.IDR_PYTHONTYPE, None, SplitterFrame, None
  241. )
  242. # def InitialUpdateFrame(self, frame, doc, makeVisible=1):
  243. # self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler.
  244. # frame.InitialUpdateFrame(doc, makeVisible)
  245. def OpenRegistryKey(
  246. self, root=None, subkey=None
  247. ): # Use this instead of OpenDocumentFile.
  248. # Look for existing open document
  249. if root is None:
  250. root = regutil.GetRootKey()
  251. if subkey is None:
  252. subkey = regutil.BuildDefaultPythonKey()
  253. for doc in self.GetDocumentList():
  254. if doc.root == root and doc.subkey == subkey:
  255. doc.GetFirstView().ActivateFrame()
  256. return doc
  257. # not found - new one.
  258. doc = RegDocument(self, root, subkey)
  259. frame = self.CreateNewFrame(doc)
  260. doc.OnNewDocument()
  261. self.InitialUpdateFrame(frame, doc, 1)
  262. return doc
  263. class RegDocument(docview.Document):
  264. def __init__(self, template, root, subkey):
  265. docview.Document.__init__(self, template)
  266. self.root = root
  267. self.subkey = subkey
  268. self.SetTitle("Registry Editor: " + subkey)
  269. def OnOpenDocument(self, name):
  270. raise TypeError("This template can not open files")
  271. return 0
  272. class HLIRegistryKey(hierlist.HierListItem):
  273. def __init__(self, keyRoot, keyName, userName):
  274. self.keyRoot = keyRoot
  275. self.keyName = keyName
  276. self.userName = userName
  277. hierlist.HierListItem.__init__(self)
  278. def __lt__(self, other):
  279. return self.name < other.name
  280. def __eq__(self, other):
  281. return (
  282. self.keyRoot == other.keyRoot
  283. and self.keyName == other.keyName
  284. and self.userName == other.userName
  285. )
  286. def __repr__(self):
  287. return "<%s with root=%s, key=%s>" % (
  288. self.__class__.__name__,
  289. self.keyRoot,
  290. self.keyName,
  291. )
  292. def GetText(self):
  293. return self.userName
  294. def IsExpandable(self):
  295. # All keys are expandable, even if they currently have zero children.
  296. return 1
  297. ## hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)
  298. ## try:
  299. ## keys, vals, dt = win32api.RegQueryInfoKey(hkey)
  300. ## return (keys>0)
  301. ## finally:
  302. ## win32api.RegCloseKey(hkey)
  303. def GetSubList(self):
  304. hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)
  305. win32ui.DoWaitCursor(1)
  306. try:
  307. keyNum = 0
  308. ret = []
  309. while 1:
  310. try:
  311. key = win32api.RegEnumKey(hkey, keyNum)
  312. except win32api.error:
  313. break
  314. ret.append(HLIRegistryKey(self.keyRoot, self.keyName + "\\" + key, key))
  315. keyNum = keyNum + 1
  316. finally:
  317. win32api.RegCloseKey(hkey)
  318. win32ui.DoWaitCursor(0)
  319. return ret
  320. template = RegTemplate()
  321. def EditRegistry(root=None, key=None):
  322. doc = template.OpenRegistryKey(root, key)
  323. if __name__ == "__main__":
  324. EditRegistry()