Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2615|回复: 5
打印 上一主题 下一主题

windows 覆盖图标实现 角标

[复制链接]

1272

主题

2067

帖子

7960

积分

认证用户组

Rank: 5Rank: 5

积分
7960
跳转到指定楼层
楼主
发表于 2021-5-20 16:38:20 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Qter 于 2021-8-24 15:40 编辑

https://blog.csdn.net/lianjunming/article/details/102806525
文件文件夹图标 覆盖 实现
http://www.voidcn.com/article/p-hvrkzglq-tn.html
有两种开发方式,用C++ ATL开发需要手动在程序中编写相关的注册表,调试也有一些难度;用C#调SharpShell来实现会方便很多,且有相关的调试工具。
https://segmentfault.com/a/1190000009279826

https://blog.csdn.net/weixin_306 ... 1001.2101.3001.4242

注意点,前面多加空格  64位 32位分开
  1. ForceRemove ' MyOverlayIcon' = s '{81539FE6-33C7-4CE7-90C7-1C7B8F2F2D40}'
复制代码
https://github.com/TortoiseGit/TortoiseGit


CloudDiskCornerMarker


overlayicon_src
https://www.codeproject.com/Arti ... sting-shell-objects
X64 Release版本编译自动注册成功



https://www.cnblogs.com/mq0036/p/14926674.html


https://docs.microsoft.com/en-us ... dlers-windows-shell
The number of icon overlay handlers that the system can support is limited by the amount of available space for icon overlays in the system image list. There are currently 15 slots allotted for icon overlays, 4 of which are reserved by the system. When there are more than 11 icon overlay handlers registered in the system, only the first 11 icon overlays that are provided by icon overlay handlers are added to the system image list. The remaining icon overlay handlers aren't used.


回复

使用道具 举报

1272

主题

2067

帖子

7960

积分

认证用户组

Rank: 5Rank: 5

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

转载于:https://my.oschina.net/zhuhj/blog/336020
回复 支持 反对

使用道具 举报

1272

主题

2067

帖子

7960

积分

认证用户组

Rank: 5Rank: 5

积分
7960
板凳
 楼主| 发表于 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

回复 支持 反对

使用道具 举报

1272

主题

2067

帖子

7960

积分

认证用户组

Rank: 5Rank: 5

积分
7960
地板
 楼主| 发表于 2021-7-22 15:54:36 | 只看该作者
本帖最后由 Qter 于 2021-7-22 16:42 编辑

  1. STDMETHODIMP CShellExt::GetOverlayInfo(LPWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags)
  2. {
  3.         if (!pwszIconFile)
  4.                 return E_POINTER;
  5.         if (!pIndex)
  6.                 return E_POINTER;
  7.         if (!pdwFlags)
  8.                 return E_POINTER;
  9.         if(cchMax < 1)
  10.                 return E_INVALIDARG;

  11.         // Set "out parameters" since we return S_OK later.
  12.         *pwszIconFile = 0;
  13.         *pIndex = 0;
  14.         *pdwFlags = 0;

  15.         // Now here's where we can find out if due to lack of enough overlay
  16.         // slots some of our overlays won't be shown.
  17.         // To do that we have to mark every overlay handler that's successfully
  18.         // loaded, so we can later check if some are missing
  19.         switch (m_State)
  20.         {
  21.                 case FileStateVersioned                                : g_normalovlloaded = true; break;
  22.                 case FileStateModified                                : g_modifiedovlloaded = true; break;
  23.                 case FileStateConflict                                : g_conflictedovlloaded = true; break;
  24.                 case FileStateDeleted                                : g_deletedovlloaded = true; break;
  25.                 case FileStateReadOnly                                : g_readonlyovlloaded = true; break;
  26.                 case FileStateLockedOverlay                        : g_lockedovlloaded = true; break;
  27.                 case FileStateAddedOverlay                        : g_addedovlloaded = true; break;
  28.                 case FileStateIgnoredOverlay                : g_ignoredovlloaded = true; break;
  29.                 case FileStateUnversionedOverlay        : g_unversionedovlloaded = true; break;
  30.         }

  31.         // we don't have to set the icon file and/or the index here:
  32.         // the icons are handled by the TortoiseOverlays dll.
  33.         return S_OK;
  34. };
复制代码
TortoiseGit-master\ext\TortoiseOverlays\readme.txt
  1. The binary files in this directory are directly taken from the TortoiseSVN project.

  2. The source code and the original binary files are available in the TortoiseSVN Subversion repository:

  3. SourceForge Web-SVN-Browser: http://sourceforge.net/p/tortoisesvn/code/HEAD/tree/trunk/src/TortoiseOverlays/
  4. Official binaries: http://sourceforge.net/p/tortoisesvn/code/HEAD/tree/TortoiseOverlays/
复制代码
https://sourceforge.net/p/tortoisesvn/code/HEAD/tree/trunk/src/TortoiseOverlays/


C:\Program Files (x86)\Common Files\TortoiseOverlays\icons\

C:\Program Files\Common Files\TortoiseOverlays\icons

计算机\HKEY_LOCAL_MACHINE\SOFTWARE\TortoiseOverlays\


然后根据这个 {3035134E-7B7D-4FCC-81B4-1E394CA267EB},会找到其实现的动态库TortoiseShell


TortoiseShell里面会再实现GetOverlayInfo函数



回复 支持 反对

使用道具 举报

1272

主题

2067

帖子

7960

积分

认证用户组

Rank: 5Rank: 5

积分
7960
5#
 楼主| 发表于 2021-7-26 17:24:58 | 只看该作者
回复 支持 反对

使用道具 举报

1272

主题

2067

帖子

7960

积分

认证用户组

Rank: 5Rank: 5

积分
7960
6#
 楼主| 发表于 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')
复制代码


回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-11-23 12:29 , Processed in 0.075491 second(s), 21 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

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