Aviso de afiliación: soy el autor del software mencionado en esta respuesta.
Primero, quiero que sepa que aprendí C ++ y Win32 solo por esta pregunta .
He desarrollado una extensión de shell de 64 bits que se registra como un controlador de menú contextual. Cuando se invoca, revisa los elementos de menú existentes, buscando entradas interesantes. Si encuentra uno, le pega un ícono (que debe haberse cargado antes). Por el momento, busca Copiar , Cortar , Eliminar , Pegar , Rehacer , Enviar a y Deshacer . Puede agregar el suyo modificando el código; El procedimiento para esto se describe a continuación. (Lo siento, no soy lo suficientemente bueno en C ++ para hacerlo configurable).
Una captura de pantalla en acción, con los iconos más feos conocidos por el hombre:
Puede descargar estos iconos si realmente lo desea.
Configurarlo
Descárgalo (desde mi Dropbox). Aviso : un escáner de VirusTotal detecta este archivo como una forma de malware. Esto es comprensible, dado el tipo de cosas que tiene que hacer para bloquear las entradas existentes. Te doy mi palabra de que no hace daño intencional a tu computadora. Si sospecha y / o quiere modificarlo y extenderlo, ¡vea el código en GitHub !
Crear una carpeta en la unidad C: C:\shellicon
. Crear archivos BMP con los siguientes títulos: copy
, cut
, delete
, paste
, redo
, sendto
, undo
. (Espero que sea obvio cuál hace qué.) Estas imágenes probablemente deberían ser de 16 por 16 píxeles (o por grande que sea su configuración de DPI que haga el margen del menú), pero también he tenido éxito con las más grandes. Si desea que los iconos se vean transparentes, deberá hacer que su fondo sea del mismo color que el menú contextual. (Este truco también lo emplea Dropbox). Hice mis terribles iconos con MS Paint; otros programas pueden o no guardar de una manera compatible con LoadImageA
. 16 por 16 a una profundidad de color de 24 bits a 96 píxeles por pulgada parece ser el conjunto más confiable de propiedades de imagen.
Ponga la DLL en un lugar accesible para todos los usuarios, esa carpeta que acaba de hacer es una buena opción. Abra un indicador de administrador en la carpeta que contiene la DLL y haga regsvr32 ContextIcons.dll
. Esto crea la información de registro para los tipos de concha *
, Drive
, Directory
, y Directory\Background
. Si alguna vez desea eliminar la extensión de shell, hágalo regsvr32 /u ContextIcons.dll
.
Código relevante
Básicamente, la extensión solo consulta el texto de cada elemento del menú contextual GetMenuItemInfo
y, si corresponde, ajusta el icono con SetMenuItemInfo
.
Visual Studio genera una gran cantidad de código misterioso mágico para proyectos ATL, pero este es el contenido de IconInjector.cpp
, que implementa el controlador del menú contextual:
// 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;
}
Tenga en cuenta que los HBITMAP
s nunca se limpian, pero esto no importa demasiado dado que las cosas de la DLL desaparecerán cuando Explorer se apague. Los íconos apenas toman memoria de todos modos.
Si está compilando para 32 bits, el primer parámetro para GetCommandString
es solo a en UINT
lugar de a UINT_PTR
.
Si realmente quiere iconos transparentes, que tendrá que crear una ventana con el icono deseado y luego fijar mii.hBmpItem
a HBMMENU_SYSTEM
y poner el identificador de la ventana en mii.dwItemData
, como se describe en la parte inferior de del artículo de MSDN sobreMENUITEMINFO
. No pude descubrir cómo crear ventanas a partir de extensiones de shell. LR_LOADTRANSPARENT
parece prometedor como una bandera de LoadImageA
, pero tiene sus propios riesgos, específicamente, no funciona a menos que use mapas de bits de 256 colores.
Si tiene problemas con la carga de imágenes, intente eliminar el LR_DEFAULTSIZE
indicador de las LoadImageA
llamadas.
Alguien suficientemente capacitado en C ++ probablemente podría tomar recursos de otras DLL y convertirlos a HBITMAP
s, pero ese alguien no soy yo.
Modificándolo
Escribí esto en Visual Studio, que creo que es el mejor editor para Windows C ++.
Cargue el archivo SLN en Visual Studio 2015 después de instalar las herramientas de C ++. En IconInjector.cpp
, puede agregar HBITMAP
entradas en la parte superior y LoadImageA
llamadas Initialize
para agregar nuevos íconos. Abajo en la else if
sección, use una wcscmp
llamada para buscar una coincidencia exacta o una wcsstr
llamada para buscar la presencia de una subcadena. En ambos casos, &
representa la posición del subrayado / acelerador cuando se usa Shift + F10. Establezca su modo en Release y su arquitectura en x64, y haga Build → Build Solution . Obtendrá un error acerca de no registrar la salida, pero no se preocupe; de todas formas querrás hacer esto manualmente. Finalice Explorer, copie la nueva DLL ( \x64\Release\ContextIcons.dll
en la carpeta de la solución) en el lugar, luego haga elregsvr32
baile.
Atribuciones
Muchas gracias a los escritores de MSDN y al creador de " The Complete Idiot's Guide to Writing Shell Extensions". ", a la que hice referencia en gran medida.
Elogio
Para las muchas instancias de Explorer que murieron en la producción de esta extensión de shell: usted murió por una gran causa, que algunas personas en Internet pueden tener iconos al lado de sus palabras.