Melhor maneira de extrair .ico de .exe e pintar com PyQt?
Pergunta
Eu estou procurando uma maneira de extrair um ícone de um arquivo .exe usando Python. Eu sei que você pode usar win32gui da função ExtractIconEx para pegar o ícone de um .exe, mas isso retorna um resource handle hIcon que não é bom, porque eu quero pintar o ícone usando PyQt.
Além disso, o único exemplo que tenho visto usando win32gui não tem qualquer transparência e os ícones não parecer suave.
Qual seria a melhor maneira de ir sobre como fazer isso usando Python e PyQt?
- Edit -
Graças à ajuda de Lukáš Lalinský esse problema foi resolvido, aqui está o código final é quem está a tentar fazer algo semelhante para mim:
import sys
import win32ui
import win32gui
from PyQt4 import QtCore
from PyQt4 import QtGui
class testWindow(QtGui.QMainWindow):
def __init__(self):
super(testWindow, self).__init__()
self.setGeometry(180.0, 130.0, 280.0, 400.0)
self.setMouseTracking(True)
large, small = win32gui.ExtractIconEx('C:\\Users\\Blank\\Apps\\Web Browsers\\Firefox\\Firefox.exe', 0)
win32gui.DestroyIcon(small[0])
self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]), 2)
def bitmapFromHIcon(self, hIcon):
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, 32, 32)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), hIcon)
hdc.DeleteDC()
return hbmp.GetHandle()
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(QtGui.QBrush(QtGui.QColor(255.0, 255.0, 255.0, 255.0), QtCore.Qt.SolidPattern))
painter.drawRect(QtCore.QRect(0.0, 0.0, 280.0, 400.0))
painter.drawPixmap(QtCore.QRect(0.0, 0.0, 32.0, 32.0), self.pixmap)
painter.end()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
mainWindow = testWindow()
mainWindow.show()
app.exec_()
Solução
Existe um método para criar QPixmap
de um HBITMAP
, de modo que o único problema é como converter HICON
para HBITMAP
. Isso pode ser feito usando GetIconInfo
.
icons = win32gui.ExtractIconEx('C:/Program Files/Internet Explorer/iexplore.exe', 0, 10)
info = win32gui.GetIconInfo(icons[0][0])
pixmap = QtGui.QPixmap.fromWinHBITMAP(info[4])
info[3].close()
info[4].close()
# call win32gui.DestroyIcon on all the icons returned by ExtractIconEx
EDIT: Este código não vai ajudar com antialiasing e alfa canal. Seu novo código é quase correto, mas você precisa dizer a Qt para carregar o canal alfa. Se você substituir:
self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]))
com:
self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]), 2)
ele vai fazer a coisa certa. A "mágica" número 2
devem ser tecnicamente QtGui.QPixmap.Alpha
mas por alguma razão Qt não fornece a constante.