Повідомлення про належність: Я автор програмного забезпечення, згаданого в цій відповіді.
По-перше, я дам вам знати, що я навчився C ++ та Win32 тільки для цього питання .
Я розробив 64-розрядне розширення оболонки, яке реєструється як обробник контекстного меню. Коли його викликають, він перекопує наявні пункти меню, шукаючи цікаві записи. Якщо він знайде його, він наклеїть на нього піктограму (яку, мабуть, було завантажено раніше). На даний момент він шукає Копіювати , Вирізати , Видалити , Вставити , Повторити , Надіслати та Скасувати . Ви можете додати свій власний, змінивши код; процедура цього описана нижче. (Вибачте, я недостатньо хороший на C ++, щоб зробити його налаштованим.)
Скріншот його в дії з найгіршими іконами, відомими людині:
Ви можете завантажити ці значки, якщо дуже хочете.
Налаштування його
Завантажте його (з мого Dropbox). Зверніть увагу : один сканер VirusTotal виявляє цей файл як певну форму зловмисного програмного забезпечення. Це зрозуміло, враховуючи вид речей, які він повинен зробити, щоб зірвати існуючі записи. Я даю вам своє слово, що це не завдає навмисної шкоди вашому комп'ютеру. Якщо ви підозріло та / або хочете змінити і розширити його, перегляньте код на GitHub !
Створіть папку в диску С: C:\shellicon
. Створення BMP файлів з наступними назвами: copy
, cut
, delete
, paste
, redo
, sendto
, undo
. (Сподіваємось, очевидно, хто з них робить щось.) Ці зображення, мабуть, мають бути 16 на 16 пікселів (або наскільки вони великі, якщо ваші налаштування DPI роблять межу поля), але я мав успіх і з більшими. Якщо ви хочете, щоб піктограми виглядали прозорими, вам доведеться просто зробити їх фоном такого ж кольору, як і контекстне меню. (Цей трюк використовується і в Dropbox.) Я створив свої жахливі іконки за допомогою MS Paint; інші програми можуть або не можуть зберігати спосіб, сумісний із LoadImageA
. 16 на 16 при 24-бітовій глибині кольорів у 96 пікселів на дюйм здається найнадійнішим набором властивостей зображення.
Помістіть DLL де-небудь доступною для всіх користувачів, що тільки що створена вами папка є хорошим вибором. Відкрийте запит адміністратора в папці, що містить DLL, і виконайте regsvr32 ContextIcons.dll
. Це створює реєстраційну інформацію для типів оболонок *
, Drive
, Directory
і Directory\Background
. Якщо ви хочете коли-небудь видалити розширення оболонки, зробіть це regsvr32 /u ContextIcons.dll
.
Відповідний код
В основному, розширення просто запитує текст кожного елемента контекстного меню GetMenuItemInfo
і, якщо це доречно, коригує піктограму SetMenuItemInfo
.
Visual Studio генерує багато магічного таємничого коду для проектів ATL, але це вміст IconInjector.cpp
, який реалізує обробник контекстного меню:
// 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;
}
Зауважте, що HBITMAP
s ніколи не прибираються, але це не має великого значення, враховуючи, що речі DLL зникнуть, коли Explorer вимкнеться. Ікони ледь не забирають жодної пам’яті.
Якщо ви компілюєте для 32-бітового, перший параметр до GetCommandString
- це лише UINT
замість а UINT_PTR
.
Якщо ви дійсно хочете , прозорі іконки, вам доведеться створити вікно з потрібною іконці , а потім встановити mii.hBmpItem
на HBMMENU_SYSTEM
і поставити ручку вікна в mii.dwItemData
, як описано в нижній частині статті MSDN поMENUITEMINFO
. Я не зміг зрозуміти, як створити вікна з розширень оболонок. LR_LOADTRANSPARENT
виглядає як прапор перспективного LoadImageA
, але у нього є свої підводні камені - зокрема, не працює, якщо ви не використовуєте 256-кольорові растрові карти.
Якщо у вас виникли проблеми із завантаженням зображення, спробуйте видалити LR_DEFAULTSIZE
прапор із LoadImageA
дзвінків.
Хтось із достатньо кваліфікованих C ++, можливо, міг би схопити ресурси з інших DLL та перетворити їх на HBITMAP
s, але це хтось не я.
Модифікація
Я написав це у Visual Studio, який вважаю найкращим редактором для Windows C ++.
Завантажте файл SLN в Visual Studio 2015 після встановлення інструментів C ++. В IconInjector.cpp
, ви можете додати HBITMAP
записи у верхній і LoadImageA
дзвінки в Initialize
додавати нові іконки. Внизу в else if
розділі використовуйте wcscmp
дзвінок, щоб шукати точну відповідність, або wcsstr
виклик, щоб шукати наявність підрядка. В обох випадках &
являє собою положення підкреслення / прискорювача при використанні Shift + F10. Встановіть для режиму Release та вашу архітектуру x64 та виконайте Build → Build Solution . Ви отримаєте помилку щодо невдалої реєстрації виводу, але не хвилюйтесь; ви хочете зробити це в будь-якому випадку вручну. Кінець Провідника, скопіюйте нову DLL ( \x64\Release\ContextIcons.dll
у папку з рішеннями) на місце, після чого виконайте regsvr32
танець.
Атрибути
Величезне спасибі письменникам MSDN та творцеві " Повного довідника про написання розширень оболонок ", на який я багато посилався.
Евлогія
Для багатьох екземплярів Explorer, які загинули при виробництві цього розширення оболонки: ви померли з великої причини, що деякі люди в Інтернеті можуть мати піктограми поруч зі своїми словами.