Cara Mengimplementasikan Antarmuka IContextMenu

IContextMenu adalah antarmuka yang paling kuat tetapi juga yang paling rumit untuk diimplementasikan. Kami sangat menyarankan Anda menerapkan kata kerja dengan menggunakan salah satu metode kata kerja statis. Untuk informasi selengkapnya, lihat Memilih Metode Menu Pintasan Statis atau Dinamis. IContextMenu memiliki tiga metode, GetCommandString, InvokeCommand, dan QueryContextMenu, yang dibahas di sini secara rinci.

Apa yang perlu Anda ketahui

Teknologi

  • C++

Prasyarat

  • Kata Kerja Statis
  • Menu Pintasan

Petunjuk

IContextMenu::GetCommandString Method

Metode IContextMenu::GetCommandString handler digunakan untuk mengembalikan nama kanonis untuk kata kerja. Metode ini bersifat opsional. Di Windows XP dan versi Windows yang lebih lama, ketika Windows Explorer memiliki bilah Status, metode ini digunakan untuk mengambil teks bantuan yang ditampilkan di bilah Status untuk item menu.

Parameter idCmd menyimpan offset pengidentifikasi dari perintah yang ditentukan ketika IContextMenu::QueryContextMenu dipanggil. Jika string bantuan diminta, uFlags akan diatur ke GCS_HELPTEXTW. Salin string bantuan ke buffer pszName , transmisikan ke PWSTR. String kata kerja diminta dengan mengatur uFlags ke GCS_VERBW. Salin string yang sesuai ke pszName, sama seperti string bantuan. Bendera GCS_VALIDATEA dan GCS_VALIDATEW tidak digunakan oleh penangan menu pintasan.

Contoh berikut menunjukkan implementasi sederhana GetCommandString yang sesuai dengan contoh QueryContextMenu yang diberikan di bagian Metode IContextMenu::QueryContextMenu dari topik ini. Karena handler hanya menambahkan satu item menu, hanya ada satu set string yang dapat dikembalikan. Metode menguji apakah idCmd valid dan, jika ya, mengembalikan string yang diminta.

Fungsi StringCchCopy digunakan untuk menyalin string yang diminta ke pszName untuk memastikan bahwa string yang disalin tidak melebihi ukuran buffer yang ditentukan oleh cchName. Contoh ini mengimplementasikan dukungan hanya untuk nilai Unicode uFlags, karena hanya yang telah digunakan di Windows Explorer sejak Windows 2000.

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 that is passed in
                // through idCommand.
                hr = StringCchCopyW(reinterpret_cast<PWSTR>(pszName), 
                                    cchName, 
                                    L"DisplayFileName");
                break; 
        }
    }
    return hr;
}

IContextMenu::InvokeCommand Method

Metode ini dipanggil ketika pengguna mengklik item menu untuk memberi tahu handler untuk menjalankan perintah terkait. Parameter pici menunjuk ke struktur yang berisi informasi yang diperlukan untuk menjalankan perintah.

Meskipun pici dinyatakan dalam Shlobj.h sebagai struktur CMINVOKECOMMANDINFO , dalam praktiknya sering menunjuk ke struktur CMINVOKECOMMANDINFOEX . Struktur ini adalah versi yang diperluas dari CMINVOKECOMMANDINFO dan memiliki beberapa anggota tambahan yang memungkinkan untuk meneruskan string Unicode.

Periksa anggota pici cbSize untuk menentukan struktur mana yang diteruskan. Jika itu adalah struktur CMINVOKECOMMANDINFOEX dan anggota fMask memiliki set bendera CMIC_MASK_UNICODE , transmisikan pici ke CMINVOKECOMMANDINFOEX. Ini memungkinkan aplikasi Anda untuk menggunakan informasi Unicode yang terkandung dalam lima anggota terakhir struktur.

Anggota lpVerb atau lpVerbW struktur digunakan untuk mengidentifikasi perintah yang akan dijalankan. Perintah diidentifikasi dengan salah satu dari dua cara berikut:

  • Menurut string kata kerja perintah
  • Dengan offset pengidentifikasi perintah

Untuk membedakan antara kedua kasus ini, periksa kata urutan tinggi lpVerb untuk kasus ANSI atau lpVerbW untuk kasus Unicode. Jika kata urutan tinggi bukan nol, lpVerb atau lpVerbW memegang string kata kerja. Jika kata urutan tinggi adalah nol, offset perintah berada dalam kata lpVerb urutan rendah.

Contoh berikut menunjukkan implementasi sederhana IContextMenu::InvokeCommand yang sesuai dengan contoh IContextMenu::QueryContextMenu dan IContextMenu::GetCommandString yang diberikan sebelum dan sesudah bagian ini. Metode pertama-tama menentukan struktur mana yang sedang diteruskan. Kemudian menentukan apakah perintah diidentifikasi oleh offset atau kata kerjanya. Jika lpVerb atau lpVerbW menyimpan kata kerja atau offset yang valid, metode akan menampilkan kotak pesan.

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;
}

Metode IContextMenu::QueryContextMenu

Shell memanggil IContextMenu::QueryContextMenu untuk mengaktifkan penangan menu pintasan untuk menambahkan item menunya ke menu. Ini melewati handel HMENU dalam parameter hmenu . Parameter indexMenu diatur ke indeks yang akan digunakan untuk item menu pertama yang akan ditambahkan.

Item menu apa pun yang ditambahkan oleh handler harus memiliki pengidentifikasi yang berada di antara nilai dalam parameter idCmdFirst dan idCmdLast . Biasanya, pengidentifikasi perintah pertama diatur ke idCmdFirst, yang bertambah satu (1) untuk setiap perintah tambahan. Praktik ini membantu Anda menghindari melebihi idCmdLast dan memaksimalkan jumlah pengidentifikasi yang tersedia jika Shell memanggil lebih dari satu handler.

Offset perintah pengidentifikasi item adalah perbedaan antara pengidentifikasi dan nilai di idCmdFirst. Simpan offset setiap item yang ditambahkan handler Anda ke menu pintasan, karena Shell mungkin menggunakan offset untuk mengidentifikasi item jika kemudian memanggil IContextMenu::GetCommandString atau IContextMenu::InvokeCommand.

Anda juga harus menetapkan kata kerja untuk setiap perintah yang Anda tambahkan. Kata kerja adalah string yang dapat digunakan alih-alih offset untuk mengidentifikasi perintah saat InvokeCommand dipanggil. Ini juga digunakan oleh fungsi seperti ShellExecuteEx untuk menjalankan perintah menu pintasan.

Ada tiga bendera yang dapat diteruskan melalui parameter uFlags yang relevan dengan penangan menu pintasan. File tersebut dijelaskan dalam tabel berikut.

Bendera Deskripsi
CMF_DEFAULTONLY Pengguna telah memilih perintah default, biasanya dengan mengklik dua kali objek. IContextMenu::QueryContextMenu harus mengembalikan kontrol ke Shell tanpa memodifikasi menu.
CMF_NODEFAULT Tidak ada item dalam menu yang harus menjadi item default. Metode harus menambahkan perintahnya ke menu.
CMF_NORMAL Menu pintasan akan ditampilkan secara normal. Metode harus menambahkan perintahnya ke menu.

 

Gunakan InsertMenu atau InsertMenuItem untuk menambahkan item menu ke daftar. Kemudian kembalikan nilai HRESULT dengan tingkat keparahan diatur ke SEVERITY_SUCCESS. Atur nilai kode ke offset pengidentifikasi perintah terbesar yang ditetapkan, ditambah satu (1). Misalnya, asumsikan bahwa idCmdFirst diatur ke 5 dan Anda menambahkan tiga item ke menu dengan pengidentifikasi perintah 5, 7, dan 8. Nilai yang dikembalikan harus MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 + 1).

Contoh berikut menunjukkan implementasi sederhana QueryContextMenu yang menyisipkan satu perintah. Offset pengidentifikasi untuk perintah IDM_DISPLAY, yang diatur ke nol. Variabel m_pszVerb dan m_pwszVerb adalah variabel privat yang digunakan untuk menyimpan string kata kerja independen bahasa terkait dalam format ANSI dan Unicode.

#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));}

Keterangan

Untuk tugas implementasi kata kerja lainnya, lihat Membuat Penangan Menu Pintasan.