Qter 发表于 2021-5-20 16:38:20

windows 覆盖图标实现 角标

本帖最后由 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位分开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/troubleshoot/windows/win32/icon-overlay-handlers-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.


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

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-7-22 15:54:36

本帖最后由 Qter 于 2021-7-22 16:42 编辑


STDMETHODIMP CShellExt::GetOverlayInfo(LPWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags)
{
      if (!pwszIconFile)
                return E_POINTER;
      if (!pIndex)
                return E_POINTER;
      if (!pdwFlags)
                return E_POINTER;
      if(cchMax < 1)
                return E_INVALIDARG;

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

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

      // we don't have to set the icon file and/or the index here:
      // the icons are handled by the TortoiseOverlays dll.
      return S_OK;
};TortoiseGit-master\ext\TortoiseOverlays\readme.txtThe binary files in this directory are directly taken from the TortoiseSVN project.

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

SourceForge Web-SVN-Browser: http://sourceforge.net/p/tortoisesvn/code/HEAD/tree/trunk/src/TortoiseOverlays/
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函数



Qter 发表于 2021-7-26 17:24:58

https://stackoverflow.com/questions/19929278/can-we-enforce-shell-extension-to-call-ishelliconoverlayidentifiergetoverlayin

https://stackoverflow.com/questions/29790640/multiple-icon-overlay-handlers-in-one-dll/29791270#29791270



https://github.com/MicrosoftDocs/win32/blob/docs/desktop-src/shell/how-to-implement-icon-overlay-handlers.md


https://www.programmersought.com/article/74726500719/

https://www.codeproject.com/Articles/7484/How-to-overlay-an-icon-over-existing-shell-objects


https://www.codeproject.com/Articles/441/The-Complete-Idiot-s-Guide-to-Writing-Shell-Extens

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 knowledgeIcon 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:SHChangeNotifyProblems with existing articlesinAdd 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 judgmentCreate 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 fileimport os
import winreg
import sqlite3
import winerror
import win32con
// Pay attention to the import path here, the path of the old version of pywin32 is different
from win32comext.shell import shell, shellcon


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

         When the windows file explorer browses the file
         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
         2. If IsMemberOf returns winerror.S_OK, the system will continue to call the GetOverlayInfo method to obtain the icon file to be superimposed
         3. The operating system is responsible for superimposing the icon returned by GetOverlayInfo onto the original icon of the file

         _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

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

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

    def GetPriority(self):
      return 1

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

               Read the synchronization folder path syncPath, sqlite database file path dbPath from the registry
               If the current file is under syncPath, go to db to query the file synchronization status
               Determine whether icon overlay is needed according to the file synchronization status
      :param fname:
      :param attributes:
      :return:
      """
      key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Dachengyun')
      syncPath, index = winreg.QueryValueEx(key, 'syncPath')
      dbPath, index = winreg.QueryValueEx(key, 'dbPath')
      key.Close()
      if fname.startswith(syncPath):
            filePath = fname
            conn = sqlite3.connect(dbPath)
            c = conn.cursor()
            c.execute('SELECT state FROM file_sync_state WHERE path=:filePath', {'filePath': filePath})
            r = c.fetchone()
            c.close()
            conn.close()
            if r is not None and r == 1:
                return winerror.S_OK
      return winerror.E_FAIL


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

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

    def GetPriority(self):
      return 2

    def IsMemberOf(self, fname, attributes):

      key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'Software\Dachengyun')
      syncPath, index = winreg.QueryValueEx(key, 'syncPath')
      dbPath, index = winreg.QueryValueEx(key, 'dbPath')
      key.Close()
      if fname.startswith(syncPath):
            filePath = fname
            conn = sqlite3.connect(dbPath)
            c = conn.cursor()
            c.execute('SELECT state FROM file_sync_state WHERE path=:filePath',
                      {'filePath': filePath})
            r = c.fetchone()
            c.close()
            conn.close()
            if r is not None and r == 2:
                return winerror.S_OK
      return winerror.E_FAIL

Dynamic icon switching and refreshThe 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//Pay attention to the introduction here, the introduction path of the old version of pywin32 seems to be different, which is prone to errors
from win32comext.shell import shell, shellcon
//syncPath is the absolute path of the file to be refreshed
shell.SHChangeNotify(shellcon.SHCNE_ATTRIBUTES,
                     shellcon.SHCNF_PATH | shellcon.SHCNF_FLUSHNOWAIT,
                     bytes(syncPath, 'gbk'), None)
Component registration uninstallation and explorer.exe restartAfter the IconOverlay class is written, it needs to be registered to the windows system. The code is as followsimport os
import win32api
import win32con
from win32com.server import register
import iconOverlay
//Multiple icons need to copy the following code, and register multiple classes after modifying the class name
register.UseCommandLine(iconOverlay.IconOverlayOk)
win32api.RegSetValue(win32api.RegCreateKey(iconOverlay.IconOverlayOk._reg_remove_keys_,iconOverlay.IconOverlayOk._reg_remove_keys_),
                     None, win32con.REG_SZ,
                     iconOverlay.IconOverlayOk._reg_clsid_)
register.UseCommandLine(iconOverlay.IconOverlaySync)
win32api.RegSetValue(win32api.RegCreateKey(iconOverlay.IconOverlaySync._reg_remove_keys_,iconOverlay.IconOverlaySync._reg_remove_keys_),
                     None, win32con.REG_SZ,
                     iconOverlay.IconOverlaySync._reg_clsid_)
//Explorer needs to be restarted after component registration is complete.exe makes the component effective               
os.system('taskkill /f /im explorer.exe & start explorer.exe')
Component uninstallimport win32com.server.register
win32com.server.register.UnregisterClasses(iconOverlay.IconOverlayOk)
win32com.server.register.UnregisterClasses(iconOverlay.IconOverlaySync)
os.system('taskkill /f /im explorer.exe & start explorer.exe')

页: [1]
查看完整版本: windows 覆盖图标实现 角标