开始之前的基础知识
1. 获取软件列表
在Python的标准库中,_winreg可以操作Windows的注册表。
获取已经安装的软件列表一般是读去windows的注册表: SOFTWAREMicrosoftWindowsCurrentVersionUninstall
读取注册表循环出list
正则出 “DisplayIcon” 包含“exe” 或 “ico”
1 key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWAREMicrosoftWindowsCurrentVersionUninstall", 0, _winreg.KEY_ALL_ACCESS) 2 for i in xrange(0, _winreg.QueryInfoKey(key)[0]-1): 3 DisplayName = '' 4 DisplayIcon = '' 5 try: 6 key_name_list =_winreg.EnumKey(key, i) 7 each_key_path = "SOFTWAREMicrosoftWindowsCurrentVersionUninstall"+'\'+key_name_list 8 each_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, each_key_path, 0, _winreg.KEY_ALL_ACCESS) 9 DisplayName, REG_SZ = _winreg.QueryValueEx(each_key, "DisplayName") 10 DisplayName = DisplayName.encode('utf-8') 11 try: 12 DisplayIcon, REG_SZ = _winreg.QueryValueEx(each_key,"DisplayIcon") 13 DisplayIcon = DisplayIcon.encode('utf-8') 14 except WindowsError: 15 pass 16 #注册表中同时满足DisplayName 和 DisplayIcon 17 if DisplayName and DisplayIcon: 18 result = self.orderDict(str(i), DisplayName, DisplayIcon) 19 except WindowsError: 20 pass
2.从exe中获取Icon资源
获取到了软件的列表,现在要把列表展示出来,肯定要查看软件的Icon了,所以要从已有的“DisplayIcon” 包含“exe”中读取exe的Icon
通过win32ui,win32gui 来获取exe中的Icon资源
1 large, small = win32gui.ExtractIconEx(self.numreg[key]['exe'], 0) 2 self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]), 2) 3 def bitmapFromHIcon(self, hIcon): 4 hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0)) 5 hbmp = win32ui.CreateBitmap() 6 hbmp.CreateCompatibleBitmap(hdc, 32, 32) 7 hdc = hdc.CreateCompatibleDC() 8 hdc.SelectObject(hbmp) 9 hdc.DrawIcon((0, 0), hIcon) 10 hdc.DeleteDC() 11 return hbmp.GetHandle()
3.QListWidget的Icon模型,与获取item值
在QListWidget 中setViewMode 设置查看的模型中为IconMode ,才可以指定显示的Icon
1 self.contentsWidget = QtGui.QListWidget() 2 self.contentsWidget.setViewMode(QtGui.QListView.IconMode) 3 self.contentsWidget.setIconSize(QtCore.QSize(96, 84)) #Icon 大小 4 self.contentsWidget.setMovement(QtGui.QListView.Static) #Listview不让列表拖动 5 self.contentsWidget.setMaximumWidth(800) # 最大宽度 6 self.contentsWidget.setSpacing(15) # 间距大小
需要获取QListWidget中item。 首先要在定义QlistWidgetItem的时候setData 值
Atem=QtGui.QListWidgetItem(self.contentsWidget) exeMenu=‘data_string’ Atem.setData(QtCore.Qt.UserRole, exeMenu)
获取:
item = self.contentsWidget.currentItem() location = item.data(QtCore.Qt.UserRole) Obj= location.toPyObject() print(Obj)
4.打开exe文件或目录
打开文件和目录参考: http://www.cnblogs.com/dcb3688/p/4463670.html
if Obj and os.path.exists(Obj): #文件or 目录存在 if os.path.isfile(Obj): import win32process try: win32process.CreateProcess(str(Obj), '',None , None , 0 ,win32process. CREATE_NO_WINDOW , None , None ,win32process.STARTUPINFO()) except Exception, e: print(e) else: os.startfile(str(Obj)) else: # 不存在的目录 QtGui.QMessageBox.warning(self, (u'提示'),(u'无法打开不存在的目录!'),QtGui.QMessageBox.Yes)
完整代码如下:
1 # -*- coding: UTF8 -*- 2 from PyQt4 import QtCore, QtGui 3 import _winreg 4 import re, sys, os, rcc 5 import win32ui 6 import win32gui 7 reload(sys) 8 sys.setdefaultencoding("utf-8") 9 class ListDialog(QtGui.QDialog): 10 def __init__(self, parent=None): 11 super(ListDialog, self).__init__(parent) 12 13 self.contentsWidget = QtGui.QListWidget() 14 self.contentsWidget.setViewMode(QtGui.QListView.IconMode) 15 self.contentsWidget.setIconSize(QtCore.QSize(96, 84)) #Icon 大小 16 self.contentsWidget.setMovement(QtGui.QListView.Static) #Listview不让列表拖动 17 self.contentsWidget.setMaximumWidth(800) # 最大宽度 18 self.contentsWidget.setSpacing(15) # 间距大小 19 20 winrege= winregeditor() 21 self.numreg=winrege.getreg() 22 for key in self.numreg.keys(): 23 Atem=QtGui.QListWidgetItem(self.contentsWidget) 24 try: # ico 来自exe 25 large, small = win32gui.ExtractIconEx(self.numreg[key]['exe'], 0) 26 exeMenu=self.numreg[key]['exe'] 27 win32gui.DestroyIcon(small[0]) 28 self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]), 2) 29 except Exception,e: #ico 来自 icon 30 if self.numreg[key].has_key('icon') and os.path.isfile(self.numreg[key]['icon']): # 判断ico文件是否存在 31 self.pixmap = QtGui.QPixmap(self.numreg[key]['icon']) 32 iconMenu = self.numreg[key]['icon'] 33 split = iconMenu.split('\') 34 exeMenu ='\'.join(split[:-1]) 35 else: # 不存在ico文件给定默认图标 36 self.pixmap = ':default.png' 37 exeMenu = '' 38 39 Atem.setIcon(QtGui.QIcon(self.pixmap)) 40 Atem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) 41 Atem.setTextAlignment(QtCore.Qt.AlignHCenter) 42 Atem.setData(QtCore.Qt.UserRole, exeMenu) 43 DisplayName=self.numreg[key]['DisplayName'].encode('utf-8') 44 Atem.setToolTip(u""+DisplayName) # tip 显示 45 if len(DisplayName)>=6: 46 DisplayName=DisplayName.decode('utf8')[0:6].encode('utf8')+'…' 47 Atem.setText(u""+DisplayName) 48 49 50 horizontalLayout = QtGui.QHBoxLayout() 51 horizontalLayout.addWidget(self.contentsWidget) 52 mainLayout = QtGui.QVBoxLayout() 53 mainLayout.addLayout(horizontalLayout) 54 self.setLayout(mainLayout) 55 self.setWindowTitle(u'Pyqt 显示已安装软件列表') 56 self.setWindowIcon(QtGui.QIcon(':favicon.ico')) 57 self.resize(600, 300) 58 self.contentsWidget.itemDoubleClicked.connect(self.DoubleClicked) #双击事件 59 60 61 # 当窗体大小改变后重新绘制窗体 重新排列Icon效果 62 def paintEvent(self,event): 63 mw = self.geometry() 64 width=mw.width() # 获取窗体宽度 65 self.contentsWidget.setViewMode(QtGui.QListView.IconMode) 66 self.contentsWidget.setIconSize(QtCore.QSize(96, 84)) #Icon 大小 67 self.contentsWidget.setMaximumWidth(width) 68 self.contentsWidget.setSpacing(12) # 间距大小 69 # win32 获取exe 资源 70 def bitmapFromHIcon(self, hIcon): 71 hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0)) 72 hbmp = win32ui.CreateBitmap() 73 hbmp.CreateCompatibleBitmap(hdc, 32, 32) 74 hdc = hdc.CreateCompatibleDC() 75 hdc.SelectObject(hbmp) 76 hdc.DrawIcon((0, 0), hIcon) 77 hdc.DeleteDC() 78 return hbmp.GetHandle() 79 # 双击事件 80 def DoubleClicked(self): 81 item = self.contentsWidget.currentItem() # 获取当前item <PyQt4.QtGui.QListWidgetItem object at 0x01775E40> 82 location = item.data(QtCore.Qt.UserRole) # 获取item里面的data <PyQt4.QtCore.QVariant object at 0x018FD9B0> 83 Obj= location.toPyObject() 84 if Obj and os.path.exists(Obj): #文件or 目录存在 85 if os.path.isfile(Obj): 86 import win32process 87 try: 88 win32process.CreateProcess(str(Obj), '',None , None , 0 ,win32process. CREATE_NO_WINDOW , None , None ,win32process.STARTUPINFO()) 89 except Exception, e: 90 print(e) 91 else: 92 os.startfile(str(Obj)) 93 94 else: # 不存在的目录 95 QtGui.QMessageBox.warning(self, (u'提示'),(u'无法打开不存在的目录!'),QtGui.QMessageBox.Yes) 96 97 98 99 100 # 注册表操作 101 class winregeditor: 102 dicList = {} 103 104 def orderDict(self, numkey, DisplayName, DisplayIcon): 105 self.dicList[numkey] = {'DisplayName': DisplayName, 'DisplayIcon': DisplayIcon} 106 exeIcon = re.compile('.*exe') 107 match = exeIcon.match(DisplayIcon) 108 if match: #匹配到exe, 可直接打开 109 self.dicList[numkey]['exe'] = match.group() 110 else: # 没有exe,Icon可为ico 文件 111 self.dicList[numkey]['icon'] =DisplayIcon 112 return self.dicList 113 114 115 def getreg(self): 116 key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r"SOFTWAREMicrosoftWindowsCurrentVersionUninstall", 0, _winreg.KEY_ALL_ACCESS) 117 for i in xrange(0, _winreg.QueryInfoKey(key)[0]-1): 118 DisplayName = '' 119 DisplayIcon = '' 120 try: 121 key_name_list =_winreg.EnumKey(key, i) 122 each_key_path = "SOFTWAREMicrosoftWindowsCurrentVersionUninstall"+'\'+key_name_list 123 each_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, each_key_path, 0, _winreg.KEY_ALL_ACCESS) 124 DisplayName, REG_SZ = _winreg.QueryValueEx(each_key, "DisplayName") 125 DisplayName = DisplayName.encode('utf-8') 126 try: 127 DisplayIcon, REG_SZ = _winreg.QueryValueEx(each_key,"DisplayIcon") 128 DisplayIcon = DisplayIcon.encode('utf-8') 129 except WindowsError: 130 pass 131 #注册表中同时满足DisplayName 和 DisplayIcon 132 if DisplayName and DisplayIcon: 133 result = self.orderDict(str(i), DisplayName, DisplayIcon) 134 except WindowsError: 135 pass 136 137 return result 138 139 140 141 142 if __name__ == '__main__': 143 app = QtGui.QApplication(sys.argv) 144 dialog = ListDialog() 145 dialog.show() 146 sys.exit(app.exec_())
效果:
控制面板--软件删除:
QlistWidget软件列表效果: