Dinamik Fiiller Kullanarak Kısayol Menüsünü Özelleştirme

Kısayol menüsü işleyicileri bağlam menüsü işleyicileri veya fiil işleyicileri olarak da bilinir. Kısayol menüsü işleyicisi, bir dosya türü işleyici türüdür.

Bu konu aşağıdaki gibi düzenlenmiştir:

Statik ve Dinamik Fiiller hakkında

Statik fiil yöntemlerinden birini kullanarak bir kısayol menüsü uygulamanızı kesinlikle öneririz. Bağlam Menüsü İşleyicileri Oluşturma "Statik Fiiller Kullanarak Kısayol Menüsünü Özelleştirme" bölümünde sağlanan yönergeleri izlemenizi öneririz. Windows 7 ve sonraki sürümlerde statik fiiller için dinamik davranış elde etmek için bağlam menüsü işleyicileri oluşturma 'de "Statik Fiiller için Dinamik Davranış Alma" bölümüne bakın. Statik fiil uygulaması ve kaçınılması gereken dinamik fiiller hakkında ayrıntılar için bkz. Kısayol Menünüz için Statik veya Dinamik Fiil Seçme.

Dosya türü için dinamik bir fiil kaydederek dosya türünün kısayol menüsünü genişletmeniz gerekiyorsa, bu konunun devamında verilen yönergeleri izleyin.

Not

32 bit uygulamalar bağlamında çalışan işleyicileri kaydederken 64 bit Windows için dikkat edilmesi gereken özel noktalar vardır: Kabuk fiilleri 32 bit uygulama bağlamında çağrıldığında WOW64 alt sistemi dosya sistemi erişimini bazı yollara yönlendirir. .exe işleyiciniz bu yollardan birinde depolanıyorsa, bu bağlamda erişilemez. Bu nedenle, geçici bir çözüm olarak, .exe'ınızı yeniden yönlendirilmeyen bir yolda depolayın veya gerçek sürümü başlatacak şekilde .exe için bir başlangıç sürümü depolayın.

 

Kısayol Menüsü İşleyicileri Dinamik Fiillerle Nasıl Çalışır?

IUnknownek olarak, kısayol menüsü işleyicileri, sahip tarafından çizilen menü öğelerini uygulamak için gereken mesajlaşmayı işlemek için aşağıdaki ek arabirimleri sağlar:

Sahip tarafından çizilen menü öğeleri hakkında daha fazla bilgi için, Owner-Drawn Menü Öğeleri Oluşturma bölümünde, Menüleri Kullanmakısmına bakın.

Shell, işleyiciyi başlatmak için IShellExtInitarabiriminikullanır. Shell, IShellExtInit::Initializeçağırdığında, nesnenin adını ve dosyayı içeren klasörün öğe tanımlayıcı listesinin (PIDL) işaretçisini içeren bir veri nesnesi geçirir. hkeyProgID parametresi, kısayol menü tanıtıcısının kayıtlı olduğu kayıt defteri konumudur. IShellExtInit::Initialize yöntemi, veri nesnesinden dosya adını ayıklamalı ve adı ve klasörün işaretçisini daha sonra kullanmak üzere bir öğe tanımlayıcı listesine (PIDL) depolamalıdır. İşleyici başlatma hakkında daha fazla bilgi için bkz. IShellExtInitUygulama Yöntemi.

Fiiller bir kısayol menüsünde sunulduğunda, önce bulunur, sonra kullanıcıya sunulur ve son olarak çağrılır. Aşağıdaki listede bu üç adım daha ayrıntılı olarak açıklanmaktadır:

  1. Shell, IContextMenu::QueryContextMenuçağırır. Bu, öğelerin veya sistemin durumuna bağlı olarak kullanılabilecek bir fiil kümesi döndürür.
  2. Sistem, yöntemin kısayol menüsüne öğe eklemek için kullanabileceği bir HMENU tanıtıcısını geçirir.
  3. Kullanıcı işleyicinin öğelerinden birine tıklarsa, Shell IContextMenu::InvokeCommandçağırır. İşleyici daha sonra uygun komutu yürütebilir.

Nitelenmemiş Fiil Adlarından Kaynaklanan Çakışmaları Önleme

Fiiller tür başına kaydedildiğinden, farklı öğelerdeki fiiller için aynı fiil adı kullanılabilir. Bunun yapılması, uygulamaların öğe türünden bağımsız olarak ortak fiillere başvurmasını sağlar. Bu işlev yararlı olsa da, nitelenmemiş adların kullanılması aynı fiil adını seçen birden çok bağımsız yazılım satıcısıyla (ISV) çakışmalara neden olabilir. Bunu önlemek için, fiilleri her zaman ISV adıyla aşağıdaki gibi önekleyin:

ISV_Name.verb

Her zaman uygulamaya özgü bir ProgID kullanın. ProgID sağlanan bir ISV'ye dosya adı uzantısını eşleme kuralının benimsenmesi olası çakışmaları önler. Bazı öğe türleri bu eşlemeyi kullanmadığı için satıcıya özgü adlara ihtiyaç duyulmaktadır. Zaten bu fiilin kayıtlı olabileceği mevcut bir ProgID'ye fiil eklerken, kendi fiilinizi eklemeden önce eski fiilin kayıt defteri anahtarını kaldırmanız gerekir. İki fiildeki fiil bilgilerinin birleştirilmemesi için bunu yapmanız gerekir. Bunun yapılmaması öngörülemeyen davranışlara neden olur.

Dinamik Fiil ile Kısayol Menü İşleyicisi Kaydetme

Kısayol menüsü işleyicileri bir dosya türü veya klasörle ilişkilendirilir. Dosya türleri için işleyici aşağıdaki alt anahtara kaydedilir.

HKEY_CLASSES_ROOT
   Program ID
      shellex
         ContextMenuHandlers

Bir kısayol menüsü işleyicisini dosya türü veya klasörle ilişkilendirmek için, önce ContextMenuHandlers alt anahtarı altında bir alt anahtar oluşturun. İşleyicinin alt anahtarını adlandırın ve alt anahtarın varsayılan değerini işleyicinin sınıf tanımlayıcısı (CLSID) GUID'sinin dize biçimine ayarlayın.

Ardından, bir kısayol menüsü işleyicisini farklı klasör türleriyle ilişkilendirmek için, işleyiciyi bir dosya türü için yaptığınız gibi kaydedin, ancak aşağıdaki örnekte gösterildiği gibi FolderType alt anahtarının altına kaydedin.

HKEY_CLASSES_ROOT
   FolderType
      shellex
         ContextMenuHandlers

İşleyicileri kaydedebileceğiniz klasör türleri hakkında daha fazla bilgi için bkz. Kabuk Uzantısı İşleyicilerini Kaydetme.

Dosya türüyle ilişkilendirilmiş bir kısayol menüsü varsa, nesneye çift tıklandığında normalde varsayılan komut başlatılır ve işleyicinin IContextMenu::QueryContextMenu yöntemi çağrılmaz. bir nesneye çift tıklandığında işleyicinin IContextMenu::QueryContextMenu yönteminin çağrılacağını belirtmek için, işleyicinin CLSID alt anahtarı altında aşağıda gösterildiği gibi bir alt anahtar oluşturun.

HKEY_CLASSES_ROOT
   CLSID
      {00000000-1111-2222-3333-444444444444}
         shellex
            MayChangeDefaultMenu

İşleyiciyle ilişkilendirilmiş bir nesneye çift tıklandığında, IContextMenu::QueryContextMenuuFlags parametresinde ayarlanmış CMF_DEFAULTONLY bayrağıyla çağrılır.

Kısayol menüsü işleyicileri, MayChangeDefaultMenu alt anahtarını yalnızca kısayol menüsünün varsayılan fiilini değiştirmeleri gerekebilecekse ayarlamalıdır. Bu alt anahtarın ayarlanması, ilişkili bir öğeye çift tıklandığında sistemi işleyicinin DLL'sini yüklemeye zorlar. İşleyiciniz varsayılan fiili değiştirmezse, bu alt anahtarı ayarlamamalısınız çünkü bunu yapmak sistemin DLL'nizi gereksiz yere yüklemesine neden olur.

Aşağıdaki örnekte, .myp dosya türü için kısayol menüsü işleyicisini etkinleştiren kayıt defteri girdileri gösterilmektedir. İşleyicinin CLSID alt anahtarı, kullanıcı ilgili bir nesneye çift tıkladığında işleyicinin çağrıldığını garanti etmek için bir MayChangeDefaultMenu alt anahtarı içerir.

HKEY_CLASSES_ROOT
   .myp
      (Default) = MyProgram.1
   CLSID
      {00000000-1111-2222-3333-444444444444}
         InProcServer32
            (Default) = C:\MyDir\MyCommand.dll
            ThreadingModel = Apartment
         shellex
            MayChangeDefaultMenu
   MyProgram.1
      (Default) = MyProgram Application
      shellex
         ContextMenuHandler
            MyCommand = {00000000-1111-2222-3333-444444444444}

IContextMenu Arabirimini Uygulama

IContextMenu, uygulanacak en güçlü ama aynı zamanda en karmaşık yöntemdir. Statik fiil yöntemlerinden birini kullanarak bir fiil uygulamanızı kesinlikle öneririz. Daha fazla bilgi için bkz. Kısayol Menünüz için Statik veya Dinamik Fiil Seçme. IContextMenu, GetCommandString , InvokeCommandve QueryContextMenuüç yöntemi vardır. Bu yöntemler burada ayrıntılı olarak ele alınmıştır.

IContextMenu::GetCommandString Yöntemi

İşleyicinin IContextMenu::GetCommandString yöntemi, fiilin kurallı adını döndürmek için kullanılır. Bu yöntem isteğe bağlıdır. Windows XP'de ve Windows'un önceki sürümlerinde, Windows Gezgini'nde Durum çubuğu olduğunda, bu yöntem bir menü öğesinin Durum çubuğunda görüntülenen yardım metnini almak için kullanılır.

idCmd parametresi, IContextMenu::QueryContextMenu çağrıldığında tanımlanan komutun tanımlayıcı uzaklığını tutar. Bir yardım dizesi istenirse uFlagsGCS_HELPTEXTWolarak ayarlanır. Yardım dizesini pszName arabelleğine kopyalayın ve bunu bir PWSTRolarak dönüştürün. Fiil dizesi, uFlagsGCS_VERBWolarak ayarlandığında istenir. Uygun dizeyi, tıpkı yardım dizesinde olduğu gibi, pszName'e kopyalayın. GCS_VALIDATEA ve GCS_VALIDATEW bayrakları kısayol menü işleyicileri tarafından kullanılmaz.

Aşağıdaki örnekte, bu konunun IContextMenu::QueryContextMenu Yöntemi bölümünde verilen IContextMenu::QueryContextMenu örneğine karşılık gelen IContextMenu::GetCommandString basit bir uygulaması gösterilmektedir. İşleyici yalnızca bir menü öğesi eklediğinden, döndürülebilecek yalnızca bir dize kümesi vardır. yöntemi idCmd geçerli olup olmadığını test eder ve geçerliyse istenen dizeyi döndürür.

StringCchCopy işlevi, kopyalanan dizenin cchNametarafından belirtilen arabellek boyutunu aşmadığından emin olmak için istenen dizeyi pszName kopyalamak için kullanılır. Bu örnek yalnızca Windows 2000'den bu yana Windows Gezgini'nde kullanıldığından uFlagsUnicode değerleri için destek uygular.

IFACEMETHODIMP CMenuExtension::GetCommandString(UINT idCommand, 
                                                UINT uFlags, 
                                                UINT *pReserved, 
                                                PSTR pszName, 
                                                UINT cchName)
{
    HRESULT hr = E_INVALIDARG;

    if (idCommand == IDM_DISPLAY)
    {
        switch (uFlags)
        {
            case GCS_HELPTEXTW:
                // Only useful for pre-Vista versions of Windows that 
                // have a Status bar.
                hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), 
                                    cchName, 
                                    L"Display File Name");
                break; 

            case GCS_VERBW:
                // GCS_VERBW is an optional feature that enables a caller
                // to discover the canonical name for the verb passed in
                // through idCommand.
                hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), 
                                    cchName, 
                                    L"DisplayFileName");
                break; 
        }
    }
    return hr;
}

IContextMenu::InvokeCommand Yöntemi

Bu yöntem, kullanıcı işleyiciye ilişkili komutu çalıştırmasını söylemek için bir menü öğesine tıkladığında çağrılır. pici parametresi, gerekli bilgileri içeren bir yapıyı gösterir.

pici Shlobj.h'de CMINVOKECOMMANDINFO yapısı olarak bildirilir, ancak uygulamada genellikle CMINVOKECOMMANDINFOEX yapısına işaret eder. Bu yapı, CMINVOKECOMMANDINFO genişletilmiş bir sürümüdür ve Unicode dizeleri geçirmeyi mümkün hale getiren birkaç ek üyesi vardır.

pici yapısına hangi verinin iletildiğini belirlemek için cbSize üyesini kontrol edin. bir CMINVOKECOMMANDINFOEX yapısıysa ve fMask üyesi CMIC_MASK_UNICODE bayrağına sahipse, pici'yi CMINVOKECOMMANDINFOEXolarak dönüştürün. Bu, uygulamanızın yapının son beş üyesinde yer alan Unicode bilgilerini kullanmasını sağlar.

Yürütülecek komutu tanımlamak için yapının lpVerb veya lpVerbW üyesi kullanılır. Komutlar aşağıdaki iki yöntemden biriyle tanımlanır:

  • Komutun fiil dizesine göre
  • Komutun tanımlayıcı uzaklığına göre

Bu iki durumu ayırt etmek için ANSI durumu için lpVerb üzerindeki yüksek dereceli kelimeyi veya Unicode durumu için lpVerbW üzerindeki yüksek dereceli kelimeyi denetleyin. Yüksek sıralı sözcük sıfır değilse lpVerb veya lpVerbW bir fiil dizesi tutar. Yüksek sıralı sözcük sıfırsa, komut uzaklığı lpVerbdüşük sıralı sözcüğündedir.

Aşağıdaki örnek, bu bölümden önce ve sonra verilen IContextMenu::QueryContextMenuveIContextMenu::GetCommandString,örneklerine karşılık gelen basit bir IContextMenu::InvokeCommand uygulamasını göstermektedir. Yöntem, önce hangi yapının geçirildiğini belirler. Ardından komutun uzaklığıyla mı yoksa fiiliyle mi tanımlanıp tanımlanmadığını belirler. lpVerb veya lpVerbW geçerli bir fiil veya ofset tutuyorsa, yöntem bir ileti kutusu görüntüler.

STDMETHODIMP CShellExtension::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
{
    BOOL fEx = FALSE;
    BOOL fUnicode = FALSE;

    if(lpcmi->cbSize == sizeof(CMINVOKECOMMANDINFOEX))
    {
        fEx = TRUE;
        if((lpcmi->fMask & CMIC_MASK_UNICODE))
        {
            fUnicode = TRUE;
        }
    }

    if( !fUnicode && HIWORD(lpcmi->lpVerb))
    {
        if(StrCmpIA(lpcmi->lpVerb, m_pszVerb))
        {
            return E_FAIL;
        }
    }

    else if( fUnicode && HIWORD(((CMINVOKECOMMANDINFOEX *) lpcmi)->lpVerbW))
    {
        if(StrCmpIW(((CMINVOKECOMMANDINFOEX *)lpcmi)->lpVerbW, m_pwszVerb))
        {
            return E_FAIL;
        }
    }

    else if(LOWORD(lpcmi->lpVerb) != IDM_DISPLAY)
    {
        return E_FAIL;
    }

    else
    {
        MessageBox(lpcmi->hwnd,
                   "The File Name",
                   "File Name",
                   MB_OK|MB_ICONINFORMATION);
    }

    return S_OK;
}

IContextMenu::QueryContextMenu Yöntemi

Kabuk IContextMenu::QueryContextMenu çağırarak kısayol menü işleyicisinin menü öğelerini menüye eklemesini sağlar. HMENU tutamacını hmenu parametresine aktarır. indexMenu parametresi, eklenecek ilk menü öğesi için kullanılacak dizine ayarlanır.

İşleyici tarafından eklenen tüm menü öğelerinin idCmdFirst ve idCmdLast parametrelerindeki değerler arasında kalan tanımlayıcıları olmalıdır. Genellikle, ilk komut tanımlayıcısı idCmdFirstolarak ayarlanır, ki bu da her ek komut için bir (1) artırılır. Bu uygulama, idCmdLast aşmaktan kaçınmanıza yardımcı olur ve Shell'in birden fazla işleyici çağırması durumunda kullanılabilir tanımlayıcı sayısını en üst düzeye çıkarır.

Öğe tanımlayıcısının komut uzaklığı, tanımlayıcı ile idCmdFirstiçindeki değer arasındaki farktır. İşleyicinizin kısayol menüsüne eklediği her öğenin konum ofsetini saklayın çünkü Kabuk, daha sonra IContextMenu::GetCommandString veya IContextMenu::InvokeCommandçağırdığında bu öğeyi tanımlamak için onu kullanabilir.

Ayrıca eklediğiniz her komuta bir fiili atamanız gerekir. Fiil, IContextMenu::InvokeCommand çağrıldığında komutu tanımlamak için uzaklık yerine kullanılabilecek bir dizedir. Ayrıca, kısayol menü komutlarını yürütmek için ShellExecuteEx gibi işlevler tarafından da kullanılır.

Kısayol menüsü işleyicileriyle ilgili üç bayrak, uFlags parametresi aracılığıyla geçirilebilir. Bunlar aşağıdaki tabloda açıklanmıştır.

Bayrak Açıklama
CMF_DEFAULTONLY Kullanıcı varsayılan komutu seçti, genellikle nesneye çift tıklayarak. IContextMenu::QueryContextMenu, menüyü değiştirmeden denetimi Shell'e döndürmelidir.
CMF_NODEFAULT Menüdeki hiçbir öğe varsayılan öğe olmamalıdır. yöntemi, komutlarını menüye eklemelidir.
CMF_NORMAL Kısayol menüsü normal şekilde görüntülenir. yöntemi, komutlarını menüye eklemelidir.

 

Listeye menü öğeleri eklemek için InsertMenuveya InsertMenuItemkullanın. Ardından önem derecesi SEVERITY_SUCCESSolarak ayarlanmış bir HRESULT değeri döndürür. Kod değerini atanan en büyük komut tanımlayıcısının uzaklığına, artı bir (1) olarak ayarlayın. Örneğin, idCmdFirst 5 olarak ayarlandığını ve menüye 5, 7 ve 8 komut tanımlayıcıları içeren üç öğe eklediğinizi varsayalım. Dönüş değeri MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 - 5 + 1)olmalıdır.

Aşağıdaki örnekte, tek bir komut ekleyen IContextMenu::QueryContextMenu basit bir uygulaması gösterilmektedir. Komutun tanımlayıcı uzaklığı sıfır olarak ayarlanmış IDM_DISPLAY. m_pszVerb ve m_pwszVerb değişkenleri, ilişkili dilden bağımsız fiil dizesini hem ANSI hem de Unicode biçimlerinde depolamak için kullanılan özel değişkenlerdir.

#define IDM_DISPLAY 0

STDMETHODIMP CMenuExtension::QueryContextMenu(HMENU hMenu,
                                              UINT indexMenu,
                                              UINT idCmdFirst,
                                              UINT idCmdLast,
                                              UINT uFlags)
{
    HRESULT hr;
    
    if(!(CMF_DEFAULTONLY & uFlags))
    {
        InsertMenu(hMenu, 
                   indexMenu, 
                   MF_STRING | MF_BYPOSITION, 
                   idCmdFirst + IDM_DISPLAY, 
                   "&Display File Name");

    
        
        hr = StringCbCopyA(m_pszVerb, sizeof(m_pszVerb), "display");
        hr = StringCbCopyW(m_pwszVerb, sizeof(m_pwszVerb), L"display");

        return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_DISPLAY + 1));
    }

    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}

Diğer fiil uygulama görevleri için bkz. Bağlam Menüsü İşleyicileri Oluşturma.

Kısayol (Bağlam) Menüleri ve Kısayol Menüsü İşleyicileri

Fiiller ve Dosya İlişkilendirmeleri

Kısayol Menünüz için Statik veya Dinamik Fiil Seçme

Kısayol Menüsü İşleyicileri ve Birden Çok Seçim Fiilleri için En İyi Yöntemler

Kısayol Menüsü İşleyicileri Oluşturma

Kısayol Menüsü Referansı