Hinweis zur Zugehörigkeit: Ich bin der Autor der in dieser Antwort genannten Software.
Zunächst möchte ich Ihnen mitteilen, dass ich C ++ und Win32 nur für diese Frage gelernt habe .
Ich habe eine 64-Bit-Shell-Erweiterung entwickelt, die als Kontextmenü-Handler registriert wird. Wenn es aufgerufen wird, durchsucht es die vorhandenen Menüelemente nach interessanten Einträgen. Wenn es eines findet, klebt es ein Symbol darauf (das zuvor geladen worden sein muss). Im Moment sucht es nach Kopieren , Ausschneiden , Löschen , Einfügen , Wiederholen , Senden an und Rückgängig . Sie können Ihren eigenen Code hinzufügen, indem Sie den Code ändern. Die Vorgehensweise hierfür wird im Folgenden beschrieben. (Sorry, ich bin nicht gut genug in C ++, um es konfigurierbar zu machen.)
Ein Screenshot davon in Aktion mit den hässlichsten Symbolen, die der Mensch kennt:
Sie können diese Symbole herunterladen, wenn Sie wirklich möchten.
Einrichten
Laden Sie es herunter (von meiner Dropbox). Hinweis : Diese Datei wird von einem VirusTotal-Scanner als Malware erkannt . Dies ist verständlich, wenn man bedenkt, wie viel man tun muss, um die vorhandenen Einträge zu schlagen. Ich versichere Ihnen, dass es Ihrem Computer keinen absichtlichen Schaden zufügt. Wenn Sie misstrauisch sind und / oder es ändern und erweitern möchten, lesen Sie den Code auf GitHub !
Erstellen Sie einen Ordner in Ihrem Laufwerk C: C:\shellicon
. Erstellen Sie BMP - Dateien mit den folgenden Titeln: copy
, cut
, delete
, paste
, redo
, sendto
, undo
. (Hoffentlich ist klar, wer was macht.) Diese Bilder sollten wahrscheinlich 16 mal 16 Pixel groß sein (oder wie groß Ihre DPI-Einstellungen auch sein mögen), aber ich hatte auch Erfolg mit größeren. Wenn Sie möchten, dass die Symbole transparent aussehen, müssen Sie lediglich den Hintergrund in der gleichen Farbe wie das Kontextmenü anzeigen. (Dieser Trick wird auch von Dropbox angewendet.) Ich habe meine schrecklichen Symbole mit MS Paint erstellt. Andere Programme werden möglicherweise auf eine Weise gespeichert, die mit kompatibel ist LoadImageA
. 16 x 16 bei 24-Bit-Farbtiefe bei 96 Pixel pro Zoll scheint der zuverlässigste Satz von Bildeigenschaften zu sein.
Platzieren Sie die DLL an einem Ort, auf den alle Benutzer zugreifen können. Der Ordner, den Sie gerade erstellt haben, ist eine gute Wahl. Öffnen Sie eine Admin-Eingabeaufforderung in dem Ordner, der die DLL enthält, und führen Sie dies aus regsvr32 ContextIcons.dll
. Dies schafft Registrierungsinformationen für den Shell - Typen *
, Drive
, Directory
, und Directory\Background
. Wenn Sie jemals die Shell-Erweiterung entfernen möchten, tun Sie dies regsvr32 /u ContextIcons.dll
.
Relevanter Code
Grundsätzlich fragt die Erweiterung nur den Text jedes Kontextmenüeintrags mit ab GetMenuItemInfo
und passt gegebenenfalls das Symbol mit an SetMenuItemInfo
.
Visual Studio generiert eine Menge mysteriösen Code für ATL-Projekte, aber dies ist der Inhalt von IconInjector.cpp
, der den Kontextmenü-Handler implementiert:
// IconInjector.cpp : Implementation of CIconInjector
#include "stdafx.h"
#include "IconInjector.h"
#include <string>
// CIconInjector
HBITMAP bmpCopy = NULL;
HBITMAP bmpCut = NULL;
HBITMAP bmpUndo = NULL;
HBITMAP bmpRedo = NULL;
HBITMAP bmpSendto = NULL;
HBITMAP bmpDel = NULL;
HBITMAP bmpPaste = NULL;
STDMETHODIMP CIconInjector::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID) {
// Load the images
bmpCopy = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\copy.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
bmpCut = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\cut.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
bmpUndo = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\undo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
bmpRedo = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\redo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
bmpSendto = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\sendto.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
bmpDel = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\delete.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
bmpPaste = (HBITMAP)LoadImageA(NULL, "C:\\shellicon\\paste.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
int err = GetLastError();
return S_OK;
}
STDMETHODIMP CIconInjector::QueryContextMenu(HMENU hmenu, UINT uMenuIndex, UINT uidFirst, UINT uidLast, UINT flags) {
using namespace std;
if (flags & CMF_DEFAULTONLY) return S_OK; // Don't do anything if it's just a double-click
int itemsCount = GetMenuItemCount(hmenu);
for (int i = 0; i < itemsCount; i++) { // Iterate over the menu items
MENUITEMINFO mii;
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_FTYPE | MIIM_STRING;
mii.dwTypeData = NULL;
BOOL ok = GetMenuItemInfo(hmenu, i, TRUE, &mii); // Get the string length
if (mii.fType != MFT_STRING) continue;
UINT size = (mii.cch + 1) * 2; // Allocate enough space
LPWSTR menuTitle = (LPWSTR)malloc(size);
mii.cch = size;
mii.fMask = MIIM_TYPE;
mii.dwTypeData = menuTitle;
ok = GetMenuItemInfo(hmenu, i, TRUE, &mii); // Get the actual string data
mii.fMask = MIIM_BITMAP;
bool chIcon = true;
if (wcscmp(menuTitle, L"&Copy") == 0) {
mii.hbmpItem = bmpCopy;
}
else if (wcscmp(menuTitle, L"Cu&t") == 0) {
mii.hbmpItem = bmpCut;
}
else if (wcscmp(menuTitle, L"&Paste") == 0) {
mii.hbmpItem = bmpPaste;
}
else if (wcscmp(menuTitle, L"Se&nd to") == 0) {
mii.hbmpItem = bmpSendto;
}
else if (wcsstr(menuTitle, L"&Undo") != NULL) {
mii.hbmpItem = bmpUndo;
}
else if (wcsstr(menuTitle, L"&Redo") != NULL) {
mii.hbmpItem = bmpRedo;
}
else if (wcscmp(menuTitle, L"&Delete") == 0) {
mii.hbmpItem = bmpDel;
}
else {
chIcon = false;
}
if (chIcon) SetMenuItemInfo(hmenu, i, TRUE, &mii);
free(menuTitle);
}
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); // Same as S_OK (= 0) but is The Right Thing To Do [TM]
}
STDMETHODIMP CIconInjector::InvokeCommand(LPCMINVOKECOMMANDINFO info) {
return S_OK;
}
STDMETHODIMP CIconInjector::GetCommandString(UINT_PTR, UINT, UINT*, LPSTR, UINT) {
return S_OK;
}
Beachten Sie, dass die HBITMAP
s nie bereinigt werden, dies ist jedoch nicht allzu wichtig, da die DLL-Dateien beim Herunterfahren des Explorers nicht mehr angezeigt werden. Die Icons nehmen sowieso kaum Speicherplatz in Anspruch.
Wenn Sie für 32-Bit kompilieren, ist der erste Parameter GetCommandString
nur a UINT
anstelle von a UINT_PTR
.
Wenn Sie wirklich transparente Symbole wollen, müssen Sie zunächst ein Fenster mit dem gewünschten Symbol und setzen Sie erstellen müssen , um mii.hBmpItem
zu HBMMENU_SYSTEM
und legen den Griff in die Fenster in mii.dwItemData
, wie im unteren Teil des beschriebenen auf den MSDN - ArtikelMENUITEMINFO
. Ich konnte nicht herausfinden, wie Fenster aus Shell-Erweiterungen erstellt werden. LR_LOADTRANSPARENT
sieht vielversprechend aus als Flagge von LoadImageA
, hat aber seine eigenen Fallstricke - und funktioniert nur, wenn Sie Bitmaps mit 256 Farben verwenden.
Wenn beim Laden von Bildern Probleme auftreten, entfernen Sie das LR_DEFAULTSIZE
Flag aus den LoadImageA
Aufrufen.
Jemand, der über ausreichende Kenntnisse in C ++ verfügt, könnte wahrscheinlich Ressourcen aus anderen DLLs entnehmen und in HBITMAP
s konvertieren , aber das bin nicht ich.
Ändern Sie es
Ich habe dies in Visual Studio geschrieben, das meiner Meinung nach der beste Editor für Windows C ++ ist.
Laden Sie die SLN-Datei in Visual Studio 2015, nachdem Sie die C ++ - Tools installiert haben. In IconInjector.cpp
können Sie HBITMAP
oben Einträge hinzufügen und LoadImageA
anrufen Initialize
, um neue Symbole hinzuzufügen. else if
Verwenden Sie unten im Abschnitt einen wcscmp
Aufruf, um nach einer genauen Übereinstimmung wcsstr
zu suchen , oder einen Aufruf, um nach der Anwesenheit einer Teilzeichenfolge zu suchen. In beiden Fällen steht das &
für die Position der Unterstreichung / Beschleunigung bei Verwendung von Umschalt + F10. Stellen Sie Ihren Modus auf Release und Ihre Architektur auf x64 ein und führen Sie Build → Build Solution aus . Es wird eine Fehlermeldung angezeigt, dass die Ausgabe nicht registriert werden konnte, aber keine Sorge. Sie möchten dies sowieso manuell tun. Beenden Sie den Explorer, kopieren Sie die neue DLL ( \x64\Release\ContextIcons.dll
im Lösungsordner) an den gewünschten Ort und regsvr32
tanzen Sie dann.
Zuschreibungen
Vielen Dank an die MSDN-Autoren und an den Schöpfer von " The Complete Idiot's Guide to Writing Shell Extensions ", auf das ich stark verwiesen habe.
Lobrede
Zu den vielen Explorer-Instanzen, die bei der Produktion dieser Shell-Erweiterung getötet wurden: Sie sind für eine große Sache gestorben, dass einige Leute im Internet Symbole neben ihren Worten haben können.