79307878

Date: 2024-12-25 15:36:35
Score: 0.5
Natty:
Report link

As mentioned above, I didn't manage to encapsulate desired icon files into my executable to later access them with relative paths from my script. However there seems to be a way around as PyInstaller has no issues in attaching icon to the executable file itself. Afterwards I just read and decode icon from the executable file. Thanks to this post: How to extract 32x32 icon bitmap data from EXE and convert it into a PIL Image object?

My final script looks next:

import sys

import win32api
import win32con
import win32gui
import win32ui
from PySide6.QtCore import Qt
from PySide6.QtGui import QImage, QPixmap
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel


def extract_icon_from_exe(exe_path):
    """Extracts the icon from an executable and converts it to a QPixmap with transparency."""
    # Get system icon size
    ico_x = win32api.GetSystemMetrics(win32con.SM_CXICON)
    ico_y = win32api.GetSystemMetrics(win32con.SM_CYICON)

    # Extract the large icon from the executable
    large, small = win32gui.ExtractIconEx(exe_path, 0)
    if not large:
        raise RuntimeError("Failed to extract icon.")
    hicon = large[0]  # Handle to the large icon

    # Create a compatible device context (DC) and bitmap
    hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
    mem_dc = hdc.CreateCompatibleDC()
    hbmp = win32ui.CreateBitmap()
    hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_y)
    mem_dc.SelectObject(hbmp)

    # Draw the icon onto the bitmap
    mem_dc.DrawIcon((0, 0), hicon)

    # Retrieve the bitmap info and bits
    bmpinfo = hbmp.GetInfo()
    bmpstr = hbmp.GetBitmapBits(True)

    # Convert to a QImage with transparency (ARGB format)
    image = QImage(bmpstr, bmpinfo["bmWidth"], bmpinfo["bmHeight"], QImage.Format_ARGB32)

    # Clean up resources
    win32gui.DestroyIcon(hicon)
    mem_dc.DeleteDC()
    hdc.DeleteDC()

    return QPixmap.fromImage(image)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Hello World Application")
        label = QLabel("Hello, World!", self)
        label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.setWindowIcon(extract_icon_from_exe(sys.executable))
        self.setCentralWidget(label)

if __name__ == "__main__":
    app = QApplication(sys.argv)

    window = MainWindow()
    window.resize(400, 300)
    window.show()

    sys.exit(app.exec())

TestApp.spec:

a = Analysis(
    ['test.py'],
    pathex=[],
    binaries=[],
    datas=[('my_u2net', 'my_u2net')],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='TestApp',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['app_icon.ico'],
)
Reasons:
  • Blacklisted phrase (0.5): Thanks
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: Call_me_Utka