如何在Windows 7中设置应用程序的任务栏图标

时间:2022-05-25 00:20:47

How do I set an application's taskbar icon in PyQt4?

如何在PyQt4中设置应用程序的任务栏图标?

I have tried setWindowIcon, and it successfully sets the icon in the top-left of the main window, but it does not affect the icon shown in the Windows 7 taskbar -- the taskbar icon remains the default Python pyw icon. Here is my code:

我尝试过setWindowIcon,它成功地在主窗口的左上角设置了图标,但它不会影响Windows 7任务栏中显示的图标 - 任务栏图标仍然是默认的Python pyw图标。这是我的代码:

from PyQt4 import QtGui

app = QtGui.QApplication([])
mainwindow = QtGui.QMainWindow()
mainwindow.show()

app.setWindowIcon(QtGui.QIcon('chalk.ico'))
mainwindow.setWindowIcon(QtGui.QIcon('chalk.ico'))
app.exec_()

[update] I've tried placing the setWindowIcon() before the show(). I've tried it with other images, ico and png. Nothing helps.

[更新]我尝试在show()之前放置setWindowIcon()。我已经尝试过其他图像,ico和png。什么都没有帮助。

3 个解决方案

#1


85  

I've found the answer, after some digging.

经过一番挖掘,我找到了答案。

In Windows 7, the taskbar is not for "Application Windows" per se, it's for "Application User Models". For example, if you have several different instances of your application running, and each instance has its own icon, then they will all be grouped under a single taskbar icon. Windows uses various heuristics to decide whether different instances should be grouped or not, and in this case it decided that everything hosted by Pythonw.exe should be grouped under the icon for Pythonw.exe.

在Windows 7中,任务栏本身不适用于“应用程序Windows”,它适用于“应用程序用户模型”。例如,如果您运行了多个不同的应用程序实例,并且每个实例都有自己的图标,那么它们将全部分组到一个任务栏图标下。 Windows使用各种启发式方法来决定是否应该对不同的实例进行分组,在这种情况下,它决定将Pythonw.exe托管的所有内容分组到Pythonw.exe的图标下。

The correct solution is for Pythonw.exe to tell Windows that it is merely hosting other applications. Perhaps a future release of Python will do this. Alternatively, you can add a registry key to tell Windows that Pythonw.exe is just a host rather than an application in its own right. See MSDN documentation for AppUserModelIDs.

正确的解决方案是让Pythonw.exe告诉Windows它只是托管其他应用程序。也许未来的Python版本会这样做。或者,您可以添加一个注册表项来告诉Windows,Pythonw.exe本身只是一个主机而不是一个应用程序。请参阅AppUserModelIDs的MSDN文档。

Alternatively, you can use a Windows call from Python, to explicitly tell Windows what the correct AppUserModelID is for this process:

或者,您可以使用Python的Windows调用,明确告诉Windows此进程的正确AppUserModelID:

import ctypes
myappid = 'mycompany.myproduct.subproduct.version' # arbitrary string
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

EDIT: Please see Ronan's answer: the myappid string should be unicode.

编辑:请参阅Ronan的回答:myappid字符串应该是unicode。

#2


6  

@DamonJW's answer will work, but there is a minor catch: myappid should be unicode (argument type is PCWSTR).

@ DamonJW的答案会有效,但有一个小问题:myappid应该是unicode(参数类型是PCWSTR)。

import ctypes
myappid = u'mycompany.myproduct.subproduct.version' # arbitrary string
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

Otherwise getting the AppUserModelID will get wrong unicode characters (祭潣灭湡⹹祭牰摯捵⹴畳灢潲畤瑣瘮牥楳湯):

否则,获取AppUserModelID会得到错误的unicode字符(祭潣灭湡⹹祭牰挚楳楳楳琐琐琐琐琐楳汤):

import ctypes
from ctypes import wintypes
lpBuffer = wintypes.LPWSTR()
AppUserModelID = ctypes.windll.shell32.GetCurrentProcessExplicitAppUserModelID
AppUserModelID(ctypes.cast(ctypes.byref(lpBuffer), wintypes.LPWSTR))
appid = lpBuffer.value
ctypes.windll.kernel32.LocalFree(lpBuffer)
if appid is not None:
    print(appid)

That said, it is a minor thing, since Windows will still recognize the unicode string as "another process" and switch the icon accordingly.

也就是说,这是一个小问题,因为Windows仍然会将unicode字符串识别为“另一个进程”并相应地切换图标。

#3


4  

You must set the AppUserModelID before your app shows any GUI. If you need to access other Windows 7 features you can have a look at Q7Goodies which is a Qt add-on for Windows 7 with a PyQt bindings.

您必须在应用程序显示任何GUI之前设置AppUserModelID。如果您需要访问其他Windows 7功能,可以查看Q7Goodies,它是带有PyQt绑定的Windows 7的Qt插件。

#1


85  

I've found the answer, after some digging.

经过一番挖掘,我找到了答案。

In Windows 7, the taskbar is not for "Application Windows" per se, it's for "Application User Models". For example, if you have several different instances of your application running, and each instance has its own icon, then they will all be grouped under a single taskbar icon. Windows uses various heuristics to decide whether different instances should be grouped or not, and in this case it decided that everything hosted by Pythonw.exe should be grouped under the icon for Pythonw.exe.

在Windows 7中,任务栏本身不适用于“应用程序Windows”,它适用于“应用程序用户模型”。例如,如果您运行了多个不同的应用程序实例,并且每个实例都有自己的图标,那么它们将全部分组到一个任务栏图标下。 Windows使用各种启发式方法来决定是否应该对不同的实例进行分组,在这种情况下,它决定将Pythonw.exe托管的所有内容分组到Pythonw.exe的图标下。

The correct solution is for Pythonw.exe to tell Windows that it is merely hosting other applications. Perhaps a future release of Python will do this. Alternatively, you can add a registry key to tell Windows that Pythonw.exe is just a host rather than an application in its own right. See MSDN documentation for AppUserModelIDs.

正确的解决方案是让Pythonw.exe告诉Windows它只是托管其他应用程序。也许未来的Python版本会这样做。或者,您可以添加一个注册表项来告诉Windows,Pythonw.exe本身只是一个主机而不是一个应用程序。请参阅AppUserModelIDs的MSDN文档。

Alternatively, you can use a Windows call from Python, to explicitly tell Windows what the correct AppUserModelID is for this process:

或者,您可以使用Python的Windows调用,明确告诉Windows此进程的正确AppUserModelID:

import ctypes
myappid = 'mycompany.myproduct.subproduct.version' # arbitrary string
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

EDIT: Please see Ronan's answer: the myappid string should be unicode.

编辑:请参阅Ronan的回答:myappid字符串应该是unicode。

#2


6  

@DamonJW's answer will work, but there is a minor catch: myappid should be unicode (argument type is PCWSTR).

@ DamonJW的答案会有效,但有一个小问题:myappid应该是unicode(参数类型是PCWSTR)。

import ctypes
myappid = u'mycompany.myproduct.subproduct.version' # arbitrary string
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)

Otherwise getting the AppUserModelID will get wrong unicode characters (祭潣灭湡⹹祭牰摯捵⹴畳灢潲畤瑣瘮牥楳湯):

否则,获取AppUserModelID会得到错误的unicode字符(祭潣灭湡⹹祭牰挚楳楳楳琐琐琐琐琐楳汤):

import ctypes
from ctypes import wintypes
lpBuffer = wintypes.LPWSTR()
AppUserModelID = ctypes.windll.shell32.GetCurrentProcessExplicitAppUserModelID
AppUserModelID(ctypes.cast(ctypes.byref(lpBuffer), wintypes.LPWSTR))
appid = lpBuffer.value
ctypes.windll.kernel32.LocalFree(lpBuffer)
if appid is not None:
    print(appid)

That said, it is a minor thing, since Windows will still recognize the unicode string as "another process" and switch the icon accordingly.

也就是说,这是一个小问题,因为Windows仍然会将unicode字符串识别为“另一个进程”并相应地切换图标。

#3


4  

You must set the AppUserModelID before your app shows any GUI. If you need to access other Windows 7 features you can have a look at Q7Goodies which is a Qt add-on for Windows 7 with a PyQt bindings.

您必须在应用程序显示任何GUI之前设置AppUserModelID。如果您需要访问其他Windows 7功能,可以查看Q7Goodies,它是带有PyQt绑定的Windows 7的Qt插件。