Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz

windows 覆盖图标实现 角标

查看数: 1839 | 评论数: 5 | 收藏 0
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2021-5-20 16:38

正文摘要:

本帖最后由 Qter 于 2021-8-24 15:40 编辑 https://blog.csdn.net/lianjunming/article/details/102806525 文件文件夹图标 覆盖 实现 http://www.voidcn.com/article/p-hvrkzglq-tn.html 有两种开发方式,用C+ ...

回复

Qter 发表于 2021-7-27 15:23:27
https://www.programmersought.com/article/74726500719/
IconOverlay implemented by Python, providing dynamic icon switching and refresh support


Development Platform
  • windows10
  • python3.8
  • pywin32
background knowledge

Icon overlay concept:Controversy over IconOverlay in Windows
Widows implementation:How to overlay an icon over existing shell objects
Python implementation:Add my own icon overlays
SHChangeNotify:SHChangeNotify

Problems with existing articles

inAdd my own icon overlaysThe author provides the code to implement the icon overlay function under python, but there are two problems

  • Does not explain how to realize the judgment and reality of different overlay icons under different conditions when there are multiple icons
  • There is no illustration on how to dynamically implement icon overlay switching and refreshing. For example, the icon overlay status in the current file explorer is in synchronization, how to use application code to control the icon overlay to the synchronization completion, and actively refresh the icon display in the user file resource browser Without requiring the user to manually refresh
solutionMultiple icon overlays to realize condition judgment

Create multiple IconOverlay classes and register them at the same time, one IconOverlay class corresponds to one icon
Note that multiple IconOverlay classes must be differentreg_clsid Properties and thenGetOverlayInfo Different icons are returned in the method, and then inIsMemberOf The method returns whether to display the icon according to different conditions
My implementation is inIsMemberOf In the method, a file status table of the sqlite database is queried, and according to the file path in the table and the corresponding file status, it is determined which icon is displayed for the file

  1. import os
  2. import winreg
  3. import sqlite3
  4. import winerror
  5. import win32con
  6. // Pay attention to the import path here, the path of the old version of pywin32 is different
  7. from win32comext.shell import shell, shellcon


  8. class IconOverlayOk:
  9.     """
  10.          Icon overlay component
  11.          The IShellIconOverlayIdentifier interface under the windows shell is used to implement the icon overlay function
  12.          The following steps are required to implement functions in python
  13.          1. Use pywin32 to write python class to implement windows com components
  14.          2. Register the component to the windows system
  15.          3. Add the icon overlay component item in the registry
  16.          4. Restart explorer.exe

  17.          When the windows file explorer browses the file
  18.          1. Explorer will call the IsMemberOf method of IShellIconOverlayIdentifier for each file currently to be displayed to determine whether the file needs to be processed
  19.          2. If IsMemberOf returns winerror.S_OK, the system will continue to call the GetOverlayInfo method to obtain the icon file to be superimposed
  20.          3. The operating system is responsible for superimposing the icon returned by GetOverlayInfo onto the original icon of the file

  21.          _reg_remove_keys_: When uninstalling the component, the registry keys that need to be deleted at the same time. Here, add a space prefix to the last registry key name to ensure the priority of the icon overlay component and avoid other icon overlay programs such as oneDriver, Nut Cloud Unsuccessful competition causes the icon overlay to fail

  22.     """
  23.     _reg_clsid_ = '{EA258179-A91D-45F9-A237-FC92A5290423}'
  24.     _reg_progid_ = 'SUN.PythonPackagesOverlayHandlerOK'
  25.     _reg_desc_ = 'Icon Overlay Handler to indicate Python packages'
  26.     _public_methods_ = ['GetOverlayInfo', 'GetPriority', 'IsMemberOf']
  27.     _com_interfaces_ = [shell.IID_IShellIconOverlayIdentifier]
  28.     _reg_remove_keys_ = [(r'Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\     PyPackageOverlay1',
  29.         win32con.HKEY_LOCAL_MACHINE)]

  30.     def GetOverlayInfo(self):
  31.         """
  32.                  Get the location of the icon file to be superimposed
  33.                  Obtain the icon file path iconPath from the registry
  34.         :return:
  35.         """
  36.         key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Dachengyun')
  37.         iconPath, index = winreg.QueryValueEx(key, 'iconPath')
  38.         key.Close()
  39.         return os.path.join(iconPath, 'Ok.ico'), 0, shellcon.ISIOI_ICONFILE

  40.     def GetPriority(self):
  41.         return 1

  42.     def IsMemberOf(self, fname, attributes):
  43.         """
  44.                  Determine whether to overwrite the file icon

  45.                  Read the synchronization folder path syncPath, sqlite database file path dbPath from the registry
  46.                  If the current file is under syncPath, go to db to query the file synchronization status
  47.                  Determine whether icon overlay is needed according to the file synchronization status
  48.         :param fname:
  49.         :param attributes:
  50.         :return:
  51.         """
  52.         key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Dachengyun')
  53.         syncPath, index = winreg.QueryValueEx(key, 'syncPath')
  54.         dbPath, index = winreg.QueryValueEx(key, 'dbPath')
  55.         key.Close()
  56.         if fname.startswith(syncPath):
  57.             filePath = fname[len(os.path.dirname(syncPath)):]
  58.             conn = sqlite3.connect(dbPath)
  59.             c = conn.cursor()
  60.             c.execute('SELECT state FROM file_sync_state WHERE path=:filePath', {'filePath': filePath})
  61.             r = c.fetchone()
  62.             c.close()
  63.             conn.close()
  64.             if r is not None and r[0] == 1:
  65.                 return winerror.S_OK
  66.         return winerror.E_FAIL


  67. class IconOverlaySync:
  68.     _reg_clsid_ = '{EA258179-A92D-45F9-A237-FC92A5290423}'
  69.     _reg_progid_ = 'SUN.PythonPackagesOverlayHandlerSync'
  70.     _reg_desc_ = 'Icon Overlay Handler to indicate Python packages'
  71.     _public_methods_ = ['GetOverlayInfo', 'GetPriority', 'IsMemberOf']
  72.     _com_interfaces_ = [shell.IID_IShellIconOverlayIdentifier]
  73.     _reg_remove_keys_ = [(r'Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\     PyPackageOverlay2',
  74.         win32con.HKEY_LOCAL_MACHINE)]

  75.     def GetOverlayInfo(self):
  76.         key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Dachengyun')
  77.         iconPath, index = winreg.QueryValueEx(key, 'iconPath')
  78.         key.Close()
  79.         return os.path.join(iconPath, 'Sync.ico'), 0, shellcon.ISIOI_ICONFILE

  80.     def GetPriority(self):
  81.         return 2

  82.     def IsMemberOf(self, fname, attributes):

  83.         key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Dachengyun')
  84.         syncPath, index = winreg.QueryValueEx(key, 'syncPath')
  85.         dbPath, index = winreg.QueryValueEx(key, 'dbPath')
  86.         key.Close()
  87.         if fname.startswith(syncPath):
  88.             filePath = fname[len(os.path.dirname(syncPath)):]
  89.             conn = sqlite3.connect(dbPath)
  90.             c = conn.cursor()
  91.             c.execute('SELECT state FROM file_sync_state WHERE path=:filePath',
  92.                       {'filePath': filePath})
  93.             r = c.fetchone()
  94.             c.close()
  95.             conn.close()
  96.             if r is not None and r[0] == 2:
  97.                 return winerror.S_OK
  98.         return winerror.E_FAIL

复制代码

Dynamic icon switching and refresh

The dynamic switching of icons only needs to modify the file status table data in the sqlite database in the external application code.
But this can only achieve the switching of icon overlays, not dynamic refresh; that is, when the user browses the file in the file explorer, if the current icon overlay file is being displayed, even if we re If the file status is changed in the database, the icon overlay will not be dynamically refreshed. You must manually refresh the file explorer or exit the folder and re-enter to see the changed overlay icon
The solution is to useSHChangeNotify To notify the operating system that the file has changed, so that the operating system does an active refresh

  1. //  Pay attention to the introduction here, the introduction path of the old version of pywin32 seems to be different, which is prone to errors
  2. from win32comext.shell import shell, shellcon
  3. //  syncPath is the absolute path of the file to be refreshed
  4. shell.SHChangeNotify(shellcon.SHCNE_ATTRIBUTES,
  5.                      shellcon.SHCNF_PATH | shellcon.SHCNF_FLUSHNOWAIT,
  6.                      bytes(syncPath, 'gbk'), None)
复制代码

Component registration uninstallation and explorer.exe restart

After the IconOverlay class is written, it needs to be registered to the windows system. The code is as follows

  1. import os
  2. import win32api
  3. import win32con
  4. from win32com.server import register
  5. import iconOverlay
  6. //  Multiple icons need to copy the following code, and register multiple classes after modifying the class name
  7. register.UseCommandLine(iconOverlay.IconOverlayOk)
  8. win32api.RegSetValue(win32api.RegCreateKey(iconOverlay.IconOverlayOk._reg_remove_keys_[0][1],iconOverlay.IconOverlayOk._reg_remove_keys_[0][0]),
  9.                      None, win32con.REG_SZ,
  10.                      iconOverlay.IconOverlayOk._reg_clsid_)
  11. register.UseCommandLine(iconOverlay.IconOverlaySync)
  12. win32api.RegSetValue(win32api.RegCreateKey(iconOverlay.IconOverlaySync._reg_remove_keys_[0][1],iconOverlay.IconOverlaySync._reg_remove_keys_[0][0]),
  13.                      None, win32con.REG_SZ,
  14.                      iconOverlay.IconOverlaySync._reg_clsid_)
  15. //  Explorer needs to be restarted after component registration is complete.exe makes the component effective               
  16. os.system('taskkill /f /im explorer.exe & start explorer.exe')
复制代码
Component uninstall

  1. import win32com.server.register
  2. win32com.server.register.UnregisterClasses(iconOverlay.IconOverlayOk)
  3. win32com.server.register.UnregisterClasses(iconOverlay.IconOverlaySync)
  4. os.system('taskkill /f /im explorer.exe & start explorer.exe')
复制代码


Qter 发表于 2021-7-26 17:24:58
Qter 发表于 2021-7-22 14:40:26
使用ATL向导的话,会在resource中产生一个rgs的注册脚本文件放在"REGISTRY"目录中用来注册组件,会在程序中通过函数DECLARE_REGISTRY_RESOURCEID(IDR_OPCSERVER)使用,IDR_OPCSERVER就是向导产生的资源文件的ID,当服务器调用CComModule::RegisterServer()时,便会使用这些脚本来载入注册表的设置,并在调用CComModule::UnregisterServer()时移除它们。所有COM的注册键都放在HKEY_CLASSES_ROOT中。

https://blog.csdn.net/idiszerg/article/details/3875934

Qter 发表于 2021-5-21 10:31:41
一般是由于 安装其他的 状态图标叠加程序导致的, 比如 微软的onedriver 或者 金山快盘   之类的工具, 可以把
注册表里面HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers
里面的除了  TortoiseSVN 之类的有关的可以删掉。
然后重启你的桌面。 就可以解决了。

转载于:https://my.oschina.net/zhuhj/blog/336020

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-5-4 10:12 , Processed in 0.061829 second(s), 23 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表