Üyelik bildirimi: Bu cevapta bahsedilen yazılımın yazarıyım.
Öncelikle, sadece bu soru için C ++ ve Win32 öğrendiğimi bileceğim .
Bağlam menüsü işleyicisi olarak kaydedilen 64 bit kabuk uzantısı geliştirdim. Çağrıldığında, ilginç menüleri arayarak mevcut menü öğeleri arasında dolaşır. Birini bulursa, üzerine bir simge yapıştırır (daha önce yüklenmiş olması gerekir). Şu anda Kopyala , Kes , Sil , Yapıştır , Yinele , Gönder ve Geri Al öğesini arar . Kodu değiştirerek kendinizinkini ekleyebilirsiniz; bunun için prosedür aşağıda açıklanmaktadır. (Maalesef, yapılandırılabilir hale getirmek için C ++ 'da yeterince iyi değilim.)
Eylemde, insanoğlunun bildiği en çirkin simgeleri olan bir ekran görüntüsü:
Sen olabilir bu simgeleri indirmek gerçekten istiyorsan.
Kurulum
İndirin (Dropbox'ımdan). Uyarı : Bu dosya bir VirusTotal tarayıcısı tarafından bir tür kötü amaçlı yazılım olarak algılanır . Bu, mevcut girişleri yok etmek için yapması gereken şeyler göz önüne alındığında anlaşılabilir. Bilgisayarınıza kasıtlı olarak zarar vermediğini söylüyorum. Şüpheniz varsa ve / veya değiştirmek ve genişletmek istiyorsanız, GitHub !
C sürücüsüne bir klasör oluşturun: C:\shellicon
. Aşağıdaki başlıklarla BMP dosyaları oluşturun: copy
, cut
, delete
, paste
, redo
, sendto
, undo
. (Umarım hangisinin hangi şeyi yaptığı açıktır.) Bu görüntüler muhtemelen 16 x 16 piksel olmalıdır (veya DPI ayarlarınızın büyük olması menü kenar boşluğunu oluşturur), ancak daha büyük olanlarla da başarılı oldum. Simgelerin şeffaf görünmesini istiyorsanız, arka planlarını içerik menüsüyle aynı renkte yapmanız gerekir. (Bu numara Dropbox tarafından da kullanılıyor.) Korkunç ikonlarımı MS Paint ile yaptım; diğer programlar uyumlu bir şekilde kaydedilebilir veya kaydedilmeyebilir LoadImageA
. 24 bit renk derinliğinde 16 x 16 inç, 96 piksel / inç en güvenilir görüntü özellikleri kümesi gibi görünüyor.
DLL dosyasını tüm kullanıcılar için erişilebilir bir yere koyun, yeni yaptığınız klasör iyi bir seçimdir. DLL içeren klasörde bir yönetici istemi açın ve do regsvr32 ContextIcons.dll
. Bu kabuk türleri için kayıt bilgilerini oluşturur *
, Drive
, Directory
, ve Directory\Background
. Kabuk uzantısını kaldırmak istiyorsanız, yapın regsvr32 /u ContextIcons.dll
.
İlgili kod
Temel olarak, uzantı her bağlam menüsü öğesinin metnini sorgular GetMenuItemInfo
ve uygunsa simgeyi ile ayarlar SetMenuItemInfo
.
Visual Studio , ATL projeleri için çok sayıda sihirli gizemli kod üretir , ancak içeriği, IconInjector.cpp
işleyici bağlam işleyicisi uygular:
// 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;
}
O Not HBITMAP
ler temizlediğini asla, ama bu konu çok fazla zaman Explorer kapanır aşağı DLL şeyler gideceğini verilen gelmez. Simgeler zar zor bellek alıyor.
32 bit için derliyorsanız, ilk parametresi GetCommandString
a UINT
yerine sadece bir parametredir UINT_PTR
.
Gerçekten şeffaf simgeler isterseniz, istenilen simgeli bir pencere oluşturmak ve daha sonra ayarlamak gerekir mii.hBmpItem
etmek HBMMENU_SYSTEM
ve tanıtıcı penceresine koymak mii.dwItemData
altındaki açıklandığı gibi, MSDN makalesindeMENUITEMINFO
. Kabuk uzantılarından pencerelerin nasıl oluşturulacağını anlayamadım. LR_LOADTRANSPARENT
bir bayrak gibi umut verici görünüyor LoadImageA
, ancak kendi tuzakları var - özellikle, 256 renkli bitmapler kullanmazsanız çalışmıyor.
Görüntü yükleme ile ilgili sorunlar yaşıyorsanız, LR_DEFAULTSIZE
bayrağı LoadImageA
aramalardan kaldırmayı deneyin .
C ++ konusunda yeteri kadar yetenekli biri muhtemelen diğer DLL dosyalarından kaynakları alıp HBITMAP
s'ye dönüştürebilir , ancak bu ben değilim.
Değiştirmek
Bunu Windows C ++ için en iyi editör olduğuna inandığım Visual Studio'da yazdım.
C ++ araçlarını yükledikten sonra SLN dosyasını Visual Studio 2015'e yükleyin. Gelen IconInjector.cpp
, ekleyebilir HBITMAP
üstündeki girişlerini ve LoadImageA
içinde çağrılar Initialize
yeni simgeler ekleyin. Aşağı else if
bölümde, bir kullanmak wcscmp
tam bir eşleşme veya için bakmak için çağrı wcsstr
bir alt dize varlığı için görünüm çağrısı. Her iki durumda da, &
Shift + F10 kullanırken alt çizgi / hızlandırıcının konumunu temsil eder. Modunuzu Release ve mimarinizi x64 olarak ayarlayın ve Build → Build Solution yapın . Çıktı kaydedilemediğinde bir hata alırsınız, ancak endişelenmeyin; yine de bunu manuel olarak yapmak istersiniz. Explorer'ı sonlandırın, yeni DLL'yi ( \x64\Release\ContextIcons.dll
çözüm klasöründe) yere kopyalayın, ardından regsvr32
dansı yapın.
Atıflar
MSDN yazarlarına ve " Komple Idiot'un Kabuk Uzantıları Yazma Kılavuzu " nun yaratıcısına çok teşekkür ederim .
methiye
Bu kabuk uzantısının üretiminde öldürülen birçok Explorer örneğine: büyük bir nedenden ötürü öldün, İnternet'teki bazı insanların kelimelerinin yanında ikonlar olabilir.