“Kopyala / Kes / Yapıştır / Sil” Windows varsayılan içerik menüsü öğeleri için bir simge nasıl atanır?


12

Windows 8 / 8.1 x64 altında, varsayılan olarak herhangi bir simgeye sahip olan Kopyala , Kes , Yapıştır , Sil , Geri Al , Yinele ve Gönder öğeleri gibi varsayılan Windows bağlam menüsü öğeleri için özel bir simge atamak istiyorum :

resim açıklamasını buraya girin

Nerede bu bağlam menü öğeleri kayıt defterinde "başvuru" bulabilirsiniz sonra onlar için bir "simge" kayıt defteri değeri ekleyebilirsiniz?

Başka bir deyişle, SendTo shellex gibi bir kabuk uzantısı menüsüne nasıl simge atanır ?.

Araştırma


@ Sk8erPeter tarafından yorumlandığı gibi:

" IconDize değerini farklı bağlam menüsü işleyicilerine eklemek, örneğin gibi özel bir öğeye eklenirken çalışmaz HKEY_CLASSES_ROOT\*\shell\MYCUSTOMKEY"


Hangi simgeye atıfta bulunuyorsunuz? Ekran görüntünüz var mı?
Raystafarian

@Raystafarian Soruyu bir resimle güncelledim.
ElektroStudios

1
@Raystafarian: Soru gibi varolan temel bağlam menü öğeleri için özel bir simge eklemek için nasıl "Kes" , "Kopyala" , "Sil" , "Rename" Bir eklerken BTW vb yeni özel öğe içerik menüsüne, bunu çok kolaydır, çünkü IconDize Değerini gibi bir tuşa eklemeniz yeterlidir HKEY_CLASSES_ROOT\*\shell\MYCUSTOMITEM(ve değeri Iconörneğin %SystemRoot%\System32\shell32.dll,-133veya sg. else gibi olacaktır ). AMA Icondize değerini farklı bağlam menüsü işleyicilerine eklemek, bu özel öğelere eklendiğinde çalışmaz .
Sk8erPeter

Netleştirmek için başka bir ekran görüntüsü (ilginç kısım kırmızı sınırlarda): i.imgur.com/fmewg6L.png . Gördüğünüz gibi BTW, bağlam menüsünde özel simgelerle ( "Notepad ++ ile Aç" gibi) bazı özel öğelerim var - bu tam olarak mevcut sistem bağlam menü öğeleri ile elde etmek istediğimiz şey!
Sk8erPeter

1
@ Sk8erPeter Şu anki en iyi ipucum SetMenuItemInfo, yanıt olarak kullanılan bir kabuk bağlam menüsü işleyicisi oluşturma olasılığı QueryContextMenu.
Ben N

Yanıtlar:


10

Ü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ü:

eylemde

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 GetMenuItemInfove uygunsa simgeyi ile ayarlar SetMenuItemInfo.

Visual Studio , ATL projeleri için çok sayıda sihirli gizemli kod üretir , ancak içeriği, IconInjector.cppiş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 HBITMAPler 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 GetCommandStringa UINTyerine sadece bir parametredir UINT_PTR.

Gerçekten şeffaf simgeler isterseniz, istenilen simgeli bir pencere oluşturmak ve daha sonra ayarlamak gerekir mii.hBmpItemetmek HBMMENU_SYSTEMve tanıtıcı penceresine koymak mii.dwItemDataaltındaki açıklandığı gibi, MSDN makalesindeMENUITEMINFO . Kabuk uzantılarından pencerelerin nasıl oluşturulacağını anlayamadım. LR_LOADTRANSPARENTbir 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_DEFAULTSIZEbayrağı LoadImageAaramalardan kaldırmayı deneyin .

C ++ konusunda yeteri kadar yetenekli biri muhtemelen diğer DLL dosyalarından kaynakları alıp HBITMAPs'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 LoadImageAiçinde çağrılar Initializeyeni simgeler ekleyin. Aşağı else ifbölümde, bir kullanmak wcscmptam bir eşleşme veya için bakmak için çağrı wcsstrbir 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 BuildBuild 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 regsvr32dansı 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.


Vaov! Çabalarınızı gerçekten takdir ediyorum, çok teşekkür ederim! (+1) Elimden geleni yaptım ama derlenmiş sürümü Windows 10'da (Build 10240) çalıştıramadım. Sorunun ne olduğunu bilmiyorum, tüm bmp görüntüleri doğru yolda var ( C:\shellicon\copy.bmp, vb - bunlar BMP formatında 20x20 piksel simgeler) ve dll ile regsvr32 ContextIcons.dllbaşarılı bir şekilde komut isteminde yönetici olarak kaydettim , ancak Bağlam menüsünde değişiklik görmüyorum. Hatta bilgisayarı yeniden başlattım, kayıtsız kaldım ve dll'yi tekrar kaydettim, ancak değişiklik yok. VS2015 kaynak derlemeye çalışıyorum!
Sk8erPeter

@ Sk8erPeter MSDN, simgelerin 16x16 olması gerektiğini söyledi, ancak 20x20 benim için çalışıyor. Belki Windows 10 16x16 gerektirir? Değişikliklerin etkili olması için Explorer'ı yeniden başlatmanız gerektiğini unutmayın.
Ben N

2
@ Sk8erPeter Kesinlikle, işte böyle . Kodu GitHub'a koymayı göreceğim. Windows 10'u şimdi indirmeye
Ben N

2
Buna inanmayacaksınız ... Görüntülerinizle ÇALIŞIR! : D: D Bu, Windows'un işleyemediği bazı nedenlerim var, neden bilmiyorum (daha sonra da kontrol edeceğim). Her neyse, çok teşekkür ederim, kodunuz gerçekten sorunu çözdü! :)
Sk8erPeter

1
@BenN: Tamam, teşekkürler! :) Biraz daha uygun olurdu. Bu arada BTW, daha önce çalışmayan görüntülerimi efsanevi Paint'te açarsam ve "Farklı kaydet"> "24 bit Bitmap (.bmp; .dip)" (yani bir BMP dosyasına kaydedersem) fark ettim. tekrar), ve ben bu yeni dosyayı kaynak görüntü olarak kullanmak, ÇALIŞIR. Tabii ki, bitmap'in boyutu tam olarak 16x16 piksel olmalıdır. Böylece Paint, piksel başına 24 bit (16,7 milyon renk), 96x96 DPI ve 16x16 piksel boyutunda beklenen bitmap biçimini oluşturur. Daha önce IrfanView'deki .png dosyalarını .bmp dosyalarına dönüştürdüm ve yeniden boyutlandırdım, bu simgeler işe yaramadı.
Sk8erPeter

1

Yorum bırakmak için yeterli temsilcisi yok ama bu bilgi shell32.dll içinde yer alıyor gibi görünüyor. Dosyalar derlendi, böylece içinde hangi işlevlerin olduğunu görmek zor, ancak bu gibi görünüyor.

İlgilenilenler (kayıt defteri ihracatı):

Hkey_classes_root \ CLSID {3ad05575-8857-4850-9277-11b85bdb8e09}

(Varsayılan) REG_SZ Nesneyi Kopyala / Taşı / Yeniden Adlandır / Sil / Bağla

Appıd REG_SZ {3ad05575-8857-4850-9277-11b85bdb8e09}

LocalizedString REG_EXPAND_SZ @% SystemRoot% \ system32 \ shell32.dll, -50176

InProcServer32 anahtarı altında shell32.dll başvurur. İlgili sondaj isimleri olan birkaç tane daha var. Muhtemelen ilgi ilgi windows.storage.dll


1
İlginç bilgi. Ancak, bir cevaptan ziyade bir yorum gibi görünüyor. Artık her yere yorum yapmak için yeterli temsilciniz var :)
Ben N
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.