Thông báo liên kết: Tôi là tác giả của phần mềm được đề cập trong câu trả lời này.
Trước tiên, tôi sẽ cho bạn biết rằng tôi đã học C ++ và Win32 chỉ cho câu hỏi này .
Tôi đã phát triển một phần mở rộng shell 64 bit được đăng ký như một trình xử lý menu ngữ cảnh. Khi được gọi, nó lục lọi các mục menu hiện có, tìm kiếm các mục thú vị. Nếu nó tìm thấy một cái, nó sẽ dán một biểu tượng trên đó (cái này phải được tải trước đó). Hiện tại, nó tìm kiếm Sao chép , Cắt , Xóa , Dán , Làm lại , Gửi đến và Hoàn tác . Bạn có thể thêm của riêng bạn bằng cách sửa đổi mã; thủ tục này được mô tả dưới đây. (Xin lỗi, tôi không đủ giỏi về C ++ để biến nó thành cấu hình.)
Một ảnh chụp màn hình của nó trong hành động, với các biểu tượng xấu nhất mà con người biết đến:
Bạn có thể tải xuống các biểu tượng này nếu bạn thực sự muốn.
Thiết lập nó
Tải xuống (từ Dropbox của tôi). Lưu ý : tệp này được phát hiện bởi một trình quét VirusTotal là một dạng phần mềm độc hại. Điều này là dễ hiểu, dựa trên những điều nó phải làm để đánh vào các mục hiện có. Tôi nói với bạn rằng nó không có hại cho máy tính của bạn. Nếu bạn nghi ngờ và / hoặc bạn muốn sửa đổi và mở rộng nó, hãy xem mã trên GitHub !
Tạo một thư mục trong ổ C của bạn : C:\shellicon
. Tạo file BMP với các chức danh sau: copy
, cut
, delete
, paste
, redo
, sendto
, undo
. (Hy vọng rằng rõ ràng cái nào sẽ làm cái gì.) Những hình ảnh này có thể phải là 16 x 16 pixel (hoặc lớn hơn là cài đặt DPI của bạn làm lề menu), nhưng tôi cũng đã thành công với những cái lớn hơn. Nếu bạn muốn các biểu tượng trông trong suốt, bạn sẽ chỉ cần làm cho nền của chúng có cùng màu với menu ngữ cảnh. (Thủ thuật này cũng được Dropbox sử dụng.) Tôi đã tạo các biểu tượng khủng khiếp của mình bằng MS Paint; các chương trình khác có thể hoặc không thể lưu theo cách tương thích với LoadImageA
. 16 x 16 ở độ sâu màu 24 bit ở 96 pixel mỗi inch dường như là tập hợp các thuộc tính hình ảnh đáng tin cậy nhất.
Đặt DLL ở đâu đó có thể truy cập được cho tất cả người dùng, thư mục bạn vừa thực hiện là một lựa chọn tốt. Mở một nhắc nhở quản trị trong thư mục chứa DLL và làm regsvr32 ContextIcons.dll
. Điều này tạo ra thông tin đăng ký cho các loại vỏ *
, Drive
, Directory
, và Directory\Background
. Nếu bạn muốn loại bỏ phần mở rộng shell, hãy làm regsvr32 /u ContextIcons.dll
.
Mã liên quan
Về cơ bản, tiện ích mở rộng chỉ truy vấn mọi văn bản của mục menu ngữ cảnh GetMenuItemInfo
và, nếu phù hợp, sẽ điều chỉnh biểu tượng với SetMenuItemInfo
.
Visual Studio tạo ra rất nhiều mã bí ẩn kỳ diệu cho các dự án ATL, nhưng đây là nội dung IconInjector.cpp
, trong đó thực hiện trình xử lý trình đơn ngữ cảnh:
// 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;
}
Lưu ý rằng các HBITMAP
s không bao giờ được dọn sạch, nhưng điều này không quá quan trọng khi các công cụ của DLL sẽ biến mất khi Explorer tắt. Các biểu tượng hầu như không có bất kỳ bộ nhớ nào.
Nếu bạn đang biên dịch cho 32 bit, tham số đầu tiên GetCommandString
chỉ là UINT
thay vì a UINT_PTR
.
Nếu bạn thực sự muốn các biểu tượng trong suốt, bạn sẽ phải tạo một cửa sổ với biểu tượng mong muốn, sau đó đặt mii.hBmpItem
thành HBMMENU_SYSTEM
và đặt tay cầm vào cửa sổ mii.dwItemData
, như được mô tả ở cuối bài viết MSDNMENUITEMINFO
. Tôi không thể tìm ra cách tạo cửa sổ từ tiện ích mở rộng. LR_LOADTRANSPARENT
Trông đầy hứa hẹn như một lá cờ của LoadImageA
nó, nhưng nó có những cạm bẫy riêng - đặc biệt, không hoạt động trừ khi bạn sử dụng bitmap 256 màu.
Nếu bạn gặp vấn đề với tải hình ảnh, hãy thử xóa LR_DEFAULTSIZE
cờ khỏi các LoadImageA
cuộc gọi.
Ai đó có đủ kỹ năng về C ++ có thể lấy tài nguyên từ các DLL khác và chuyển đổi chúng thành HBITMAP
s, nhưng ai đó không phải là tôi.
Sửa đổi nó
Tôi đã viết điều này trong Visual Studio, nơi tôi tin là trình chỉnh sửa tốt nhất cho Windows C ++.
Tải tệp SLN vào Visual Studio 2015 sau khi bạn cài đặt các công cụ C ++. Trong IconInjector.cpp
, bạn có thể thêm HBITMAP
các mục ở trên cùng và LoadImageA
gọi Initialize
để thêm biểu tượng mới. Trong else if
phần dưới, sử dụng một wcscmp
cuộc gọi để tìm kiếm một kết hợp chính xác hoặc một wcsstr
cuộc gọi để tìm kiếm sự hiện diện của một chuỗi con. Trong cả hai trường hợp, &
đại diện cho vị trí của gạch dưới / máy gia tốc khi sử dụng Shift + F10. Đặt chế độ của bạn thành Phát hành và kiến trúc của bạn thành x64 và thực hiện Build → Build Solution . Bạn sẽ gặp lỗi về việc không đăng ký đầu ra, nhưng đừng lo lắng; dù sao bạn cũng muốn làm điều này bằng tay. End Explorer, sao chép DLL mới ( \x64\Release\ContextIcons.dll
trong thư mục giải pháp) vào vị trí, sau đó thực hiện regsvr32
điệu nhảy.
Phân phối
Rất cám ơn các nhà văn MSDN, và người tạo ra " Hướng dẫn hoàn chỉnh của kẻ ngốc để viết phần mở rộng Shell ", mà tôi đã tham khảo rất nhiều.
Eulogy
Đối với nhiều phiên bản Explorer đã bị giết trong quá trình sản xuất tiện ích mở rộng này: bạn đã chết vì một lý do lớn, rằng một số người trên Internet có thể có các biểu tượng bên cạnh lời nói của họ.