从 .exe 中提取 .ico 并使用 PyQt 进行绘制的最佳方法?

发布于 2024-08-08 07:19:43 字数 1823 浏览 5 评论 0原文

我正在寻找一种使用 Python 从 .exe 文件中提取图标的方法。我知道您可以使用 win32gui 的 ExtractIconEx 函数来获取 .exe 的图标,但这会返回一个 HIcon 资源句柄,这不好,因为我想使用 PyQt 绘制图标。

另外,我见过的使用 win32gui 的唯一示例没有任何透明度,并且图标看起来不平滑。

使用 Python 和 Python 来完成此操作的最佳方法是什么? PyQt?

--编辑--

感谢 Lukáš Lalinský 的帮助,这个问题现在已经解决了,这是最终的代码,任何人都在寻求做与我类似的事情:

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_()

I am looking for a way to extract an icon from a .exe file using Python. I know that you can use win32gui's ExtractIconEx function to grab the icon of a .exe but this returns a HIcon resource handle which is no good because I want to paint the icon using PyQt.

Also the only example I have seen using win32gui does not have any transparency and the icons do not look smooth.

What would be the best way to go about doing this using Python & PyQt?

--Edit--

Thanks to help from Lukáš Lalinský this problem is now solved, here is the final code is anyone is seeking to do something similar to me:

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_()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟花易冷人易散 2024-08-15 07:19:43

有一种方法可以从 HBITMAP 创建 QPixmap,因此唯一的问题是如何将 HICON 转换为 HBITMAP 。这可以使用 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

编辑:此代码对抗锯齿和 Alpha 通道没有帮助。您的新代码几乎是正确的,但您需要告诉 Qt 加载 Alpha 通道。如果将: 替换

self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]))

为:

self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]), 2)

它将做正确的事情。 “神奇”数字2从技术上讲应该是QtGui.QPixmap.Alpha,但由于某种原因Qt没有提供该常量。

There is a method to create QPixmap from a HBITMAP, so the only problem is how to convert HICON to HBITMAP. This can be done using 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: This code will not help with antialiasing and alpha channel. Your new code is almost correct, but you need to tell Qt to load the alpha channel. If you replace:

self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]))

with:

self.pixmap = QtGui.QPixmap.fromWinHBITMAP(self.bitmapFromHIcon(large[0]), 2)

it will do the right thing. The "magic" number 2 should be technically QtGui.QPixmap.Alpha but for some reason Qt doesn't provide the constant.

偏闹i 2024-08-15 07:19:43

如果您无法访问 fromWinHBITMAP(例如在 PySide6 中),则可以使用 win32gui.DrawIconEx 创建图标。

import win32ui
import win32gui
from PySide6 import QtGui, QtCore, QtWidgets

# Get the icons
icons = win32gui.ExtractIconEx('C:/Program Files/Internet Explorer/iexplore.exe', 0)
icon = icons[0][0]
width = height = 32

# Create DC and bitmap and make them compatible.
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, width, height)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)

# Draw the icon.
win32gui.DrawIconEx(hdc.GetHandleOutput(), 0, 0, icon, width, height, 0, None, 0x0003)

# Get the icon's bits and convert to a QtGui.QImage.
bitmapbits = hbmp.GetBitmapBits(True)
image = QtGui.QImage(bitmapbits, width, height, QtGui.QImage.Format_ARGB32_Premultiplied)
    
# Write to and then load from a buffer to convert to PNG.
# This step is only necessary if you are displaying the image.
# QtWidgets.QLabel and similar have trouble displaying the current format.
buffer = QtCore.QBuffer()
buffer.SetOpenMode(QtCore.QIODevice.ReadWrite)
image.save(buffer, "PNG")
image.loadFromData(buffer.data(), "PNG")
    
# Create a QtGui.QPixmap from the QtGui.QImage.
pixmap = QtGui.Pixmap.fromImage(image)

# Destroy the icons.
for iconList in icons:
    for icon in iconList:
        win32gui.DestroyIcon(icon)

# Display the image.
display_label = QtWidgets.QLabel()
display_label.setPixmap(pixmap)
display_label.show()

If you don't have access to fromWinHBITMAP (such as in PySide6) then it is possible to create the icon using win32gui.DrawIconEx.

import win32ui
import win32gui
from PySide6 import QtGui, QtCore, QtWidgets

# Get the icons
icons = win32gui.ExtractIconEx('C:/Program Files/Internet Explorer/iexplore.exe', 0)
icon = icons[0][0]
width = height = 32

# Create DC and bitmap and make them compatible.
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, width, height)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)

# Draw the icon.
win32gui.DrawIconEx(hdc.GetHandleOutput(), 0, 0, icon, width, height, 0, None, 0x0003)

# Get the icon's bits and convert to a QtGui.QImage.
bitmapbits = hbmp.GetBitmapBits(True)
image = QtGui.QImage(bitmapbits, width, height, QtGui.QImage.Format_ARGB32_Premultiplied)
    
# Write to and then load from a buffer to convert to PNG.
# This step is only necessary if you are displaying the image.
# QtWidgets.QLabel and similar have trouble displaying the current format.
buffer = QtCore.QBuffer()
buffer.SetOpenMode(QtCore.QIODevice.ReadWrite)
image.save(buffer, "PNG")
image.loadFromData(buffer.data(), "PNG")
    
# Create a QtGui.QPixmap from the QtGui.QImage.
pixmap = QtGui.Pixmap.fromImage(image)

# Destroy the icons.
for iconList in icons:
    for icon in iconList:
        win32gui.DestroyIcon(icon)

# Display the image.
display_label = QtWidgets.QLabel()
display_label.setPixmap(pixmap)
display_label.show()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文