开创上下文菜单项,创造Logo标志

创建上下文菜单项 

创建图标标记 Handlers (续)

 

 

1、新建一个ATL Project。

1、新建一个ATL Project。

图片 1

图片 2

2、建议将Project Property中Linker – General - “Register Output” 设为no,C/C - “Code Generation” - “Runtime Library” 设为 /MTd。

2、建议将 Project Property 中 Linker – General - “Register Output” 设为 no,C/C - “Code Generation” - “Runtime Library” 设为 /MTd。

 图片 3

图片 4

图片 5

图片 6

3、在Solution Explorer中右键Add Class,选择ATL Simple Object。并在弹出的对话框中为该Class命名。

3、在 Solution Explorer 中右键 Add Class,选择 ATL Simple Object。并在弹出的对话框中为该 Class 命名。

 图片 7

图片 8

图片 9

图片 10

4、添加完成后建议Build一下Project,MIDL compiler将根据 .idl文件生成IIDs and CLSIDs。

4、添加完成后建议 Build 一下 Project,MIDL compiler 将根据 .idl 文件生成 IIDs and CLSIDs。

 图片 11

图片 12

5、(可选)在Solution Explorer中右键Add Resource导入图标资源。

5、切换到新增 Class 的 .h 文件中,使其继承接口 IShellIconOverlayIdentifier。

 图片 13

图片 14

6、切换到新增Class的 .h文件中,使其继承接口IShellExtInit和IContextMenu。并在 .cpp文件中,参照MSDN给出实现。

图片 15

 图片 16

图片 17

图片 18

图片 19

图片 20

图片 21图片 22

图片 23

 1 // MyOverlay.h : Declaration of the CMyOverlay
 2 
 3 #pragma once
 4 #include "resource.h"       // main symbols
 5 
 6 
 7 
 8 #include "Example_i.h"
 9 #include <ShlObj.h>
10 
11 
12 
13 #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
14 #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
15 #endif
16 
17 using namespace ATL;
18 
19 
20 // CMyOverlay
21 
22 class ATL_NO_VTABLE CMyOverlay :
23     public CComObjectRootEx<CComSingleThreadModel>,
24     public CComCoClass<CMyOverlay, &CLSID_MyOverlay>,
25     public IDispatchImpl<IMyOverlay, &IID_IMyOverlay, &LIBID_ExampleLib, 
26     /*wMajor =*/ 1, /*wMinor =*/ 0>,
27     public IShellIconOverlayIdentifier
28 {
29 public:
30     CMyOverlay()
31     {
32     }
33 
34 DECLARE_REGISTRY_RESOURCEID(IDR_MYOVERLAY)
35 
36 
37 BEGIN_COM_MAP(CMyOverlay)
38     COM_INTERFACE_ENTRY(IMyOverlay)
39     COM_INTERFACE_ENTRY(IDispatch)
40     COM_INTERFACE_ENTRY(IShellIconOverlayIdentifier)
41 END_COM_MAP()
42 
43 
44 
45     DECLARE_PROTECT_FINAL_CONSTRUCT()
46 
47 
48     HRESULT FinalConstruct()
49     {
50         return S_OK;
51     }
52 
53     void FinalRelease()
54     {
55     }
56 
57 public:
58     STDMETHOD(IsMemberOf)(THIS_ _In_ PCWSTR pwszPath, DWORD dwAttrib);
59     STDMETHOD(GetOverlayInfo)(THIS_ _Out_writes_(cchMax) PWSTR pwszIconFile,
60         int cchMax, _Out_ int * pIndex, _Out_ DWORD * pdwFlags);
61     STDMETHOD(GetPriority)(THIS_ _Out_ int * pIPriority);
62 
63 };
64 
65 OBJECT_ENTRY_AUTO(__uuidof(MyOverlay), CMyOverlay)

图片 24图片 25

MyOverlay.h

 1 // MyContextMenu.h : Declaration of the CMyContextMenu
 2 
 3 #pragma once
 4 #include "resource.h"       // main symbols
 5 
 6 
 7 
 8 #include "ContextMenuExample_i.h"
 9 #include <Shlobj.h>
10 
11 
12 
13 #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
14 #error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
15 #endif
16 
17 using namespace ATL;
18 
19 
20 // CMyContextMenu
21 
22 class ATL_NO_VTABLE CMyContextMenu :
23     public CComObjectRootEx<CComSingleThreadModel>,
24     public CComCoClass<CMyContextMenu, &CLSID_MyContextMenu>,
25     public IDispatchImpl<IMyContextMenu, &IID_IMyContextMenu, 
26     &LIBID_ContextMenuExampleLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
27     public IShellExtInit,
28     public IContextMenu
29 {
30 public:
31     CMyContextMenu()
32     {
33     }
34 
35 DECLARE_REGISTRY_RESOURCEID(IDR_MYCONTEXTMENU)
36 
37 
38 BEGIN_COM_MAP(CMyContextMenu)
39     COM_INTERFACE_ENTRY(IMyContextMenu)
40     COM_INTERFACE_ENTRY(IDispatch)
41     COM_INTERFACE_ENTRY(IShellExtInit)
42     COM_INTERFACE_ENTRY(IContextMenu)
43 END_COM_MAP()
44 
45 
46 
47     DECLARE_PROTECT_FINAL_CONSTRUCT()
48 
49     HRESULT FinalConstruct();
50 
51     void FinalRelease();
52 
53 public:
54     // IShellExtInit Method
55     HRESULT STDMETHODCALLTYPE Initialize(
56         _In_opt_  PCIDLIST_ABSOLUTE pidlFolder,
57         _In_opt_  IDataObject *pdtobj,
58         _In_opt_  HKEY hkeyProgID);
59 
60     // IContextMenu Method
61     HRESULT STDMETHODCALLTYPE QueryContextMenu(
62         _In_  HMENU hmenu,    
63         _In_  UINT indexMenu,    
64         _In_  UINT idCmdFirst,
65         _In_  UINT idCmdLast,
66         _In_  UINT uFlags);
67 
68     HRESULT STDMETHODCALLTYPE InvokeCommand(
69         _In_  CMINVOKECOMMANDINFO *pici);
70 
71     HRESULT STDMETHODCALLTYPE GetCommandString(
72         _In_  UINT_PTR idCmd,
73         _In_  UINT uType,
74         _Reserved_  UINT *pReserved,
75         _Out_writes_bytes_((uType & GCS_UNICODE) ? (cchMax * sizeof(wchar_t)) : cchMax) _When_(!(uType & (GCS_VALIDATEA | GCS_VALIDATEW)), _Null_terminated_)  CHAR *pszName,
76         _In_  UINT cchMax);
77 
78 private:
79     HBITMAP MenuIcon1;
80     HBITMAP MenuIcon2;
81     HBITMAP MenuIcon3;
82     HBITMAP MenuIcon4;
83 
84 
85 };
86 
87 OBJECT_ENTRY_AUTO(__uuidof(MyContextMenu), CMyContextMenu)

6、根据 MSDN 实现该 Class。

MyContextMenu.h

图片 26

  1 // MyContextMenu.cpp : Implementation of CMyContextMenu
  2 
  3 #include "stdafx.h"
  4 #include "MyContextMenu.h"
  5 
  6 
  7 // CMyContextMenu
  8 
  9 HRESULT CMyContextMenu::FinalConstruct()
 10 {
 11     HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();
 12     MenuIcon1 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
 13     MenuIcon2 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
 14     MenuIcon3 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP3));
 15     MenuIcon4 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP4));
 16     
 17     return S_OK;
 18 }
 19 
 20 void CMyContextMenu::FinalRelease()
 21 {
 22     if (MenuIcon1 != NULL)
 23     {
 24         DeleteObject(MenuIcon1);
 25     }
 26     if (MenuIcon2 != NULL)
 27     {
 28         DeleteObject(MenuIcon2);
 29     }
 30     if (MenuIcon3 != NULL)
 31     {
 32         DeleteObject(MenuIcon3);
 33     }
 34     if (MenuIcon4 != NULL)
 35     {
 36         DeleteObject(MenuIcon4);
 37     }
 38 }
 39 
 40 HRESULT CMyContextMenu::Initialize(
 41     _In_opt_  PCIDLIST_ABSOLUTE pidlFolder,
 42     _In_opt_  IDataObject *pdtobj,
 43     _In_opt_  HKEY hkeyProgID) {
 44     HRESULT hr;
 45     UINT    nFileCount;
 46 
 47     FORMATETC fmt =
 48     {
 49         CF_HDROP,
 50         NULL,
 51         DVASPECT_CONTENT,
 52         -1,
 53         TYMED_HGLOBAL
 54     };
 55 
 56     STGMEDIUM sm =
 57     {
 58         TYMED_HGLOBAL
 59     };
 60 
 61     hr = pdtobj->GetData(&fmt, &sm);
 62 
 63     if (FAILED(hr))
 64     {
 65         return hr;
 66     }
 67 
 68     // query quantity of selected files
 69     nFileCount = DragQueryFile((HDROP)sm.hGlobal, 0xFFFFFFFF, NULL, 0);
 70 
 71     if (nFileCount == 1) // deal with only one file
 72     {
 73         // analyze selected file
 74 
 75     }
 76     else
 77     {
 78         hr = E_INVALIDARG;
 79     }
 80 
 81     ReleaseStgMedium(&sm);
 82 
 83     return hr;
 84 }
 85 
 86 // IContextMenu Method
 87 HRESULT CMyContextMenu::QueryContextMenu(
 88     _In_  HMENU hmenu,
 89     _In_  UINT indexMenu,
 90     _In_  UINT idCmdFirst,
 91     _In_  UINT idCmdLast,
 92     _In_  UINT uFlags) {
 93 
 94     UINT uCmdID = idCmdFirst;
 95     LPCWSTR text1 = TEXT("新增层叠菜单项1");
 96     LPCWSTR text2 = TEXT("新增菜单项2");
 97     LPCWSTR text3 = TEXT("新增菜单项3");
 98     LPCWSTR text4 = TEXT("新增菜单项4");
 99     // do nothing when flag includes CMF_DEFAULTONLY.
100     if (uFlags & CMF_DEFAULTONLY)
101     {
102         return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
103     }
104     InsertMenu(hmenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
105     indexMenu  ;
106     HMENU hSubMenu = CreateMenu();
107     if (hSubMenu)
108     {
109         InsertMenu(hSubMenu, 0, MF_STRING | MF_BYPOSITION, uCmdID  , text2);
110         SetMenuItemBitmaps(hSubMenu, 0, MF_BYPOSITION, MenuIcon2, MenuIcon2);
111         InsertMenu(hSubMenu, 1, MF_STRING | MF_BYPOSITION, uCmdID  , text3);
112         SetMenuItemBitmaps(hSubMenu, 1, MF_BYPOSITION, MenuIcon3, MenuIcon3);
113         InsertMenu(hSubMenu, 2, MF_STRING | MF_BYPOSITION, uCmdID  , text4);
114         SetMenuItemBitmaps(hSubMenu, 2, MF_BYPOSITION, MenuIcon4, MenuIcon4);
115         // InsertMenu(hSubMenu, 3, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);//插入分隔线
116     }
117     InsertMenu(hmenu, indexMenu, MF_STRING | MF_POPUP | MF_BYPOSITION, (UINT_PTR)hSubMenu, text1);
118     SetMenuItemBitmaps(hmenu, indexMenu, MF_BYPOSITION, MenuIcon1, MenuIcon1);
119     indexMenu  ;
120     InsertMenu(hmenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);
121     indexMenu  ;
122 
123     // inform the explorer how many menu item we have added
124     return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uCmdID - idCmdFirst);
125 }
126 
127 HRESULT CMyContextMenu::InvokeCommand(
128     _In_  CMINVOKECOMMANDINFO *pici) {
129     if (0 != HIWORD(pici->lpVerb))
130         return E_INVALIDARG;
131     // get index of added menu item
132     switch (LOWORD(pici->lpVerb))
133     {
134     case 0:
135     {
136         // 执行新增菜单项2触发的操作
137         STARTUPINFO si = { sizeof(si) };
138         PROCESS_INFORMATION pi;
139         TCHAR szCommandLine[] = TEXT("notepad");
140         BOOL bCreateRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
141 
142         break;
143     }
144     case 1:
145     {
146         // 执行新增菜单项3触发的操作
147         STARTUPINFO si = { sizeof(si) };
148         PROCESS_INFORMATION pi;
149         TCHAR szCommandLine[] = TEXT("write");
150         BOOL bCreateRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
151 
152         break;
153     }
154     case 2:
155     {
156         // 执行新增菜单项4触发的操作
157         STARTUPINFO si = { sizeof(si) };
158         PROCESS_INFORMATION pi;
159         TCHAR szCommandLine[] = TEXT("cmd");
160         BOOL bCreateRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
161 
162         break;
163     }
164     default:
165     {
166         return E_INVALIDARG;
167         break;
168     }
169     }
170     return S_OK;
171 }
172 
173 HRESULT CMyContextMenu::GetCommandString(
174     _In_  UINT_PTR idCmd,
175     _In_  UINT uType,
176     _Reserved_  UINT *pReserved,
177     _Out_writes_bytes_((uType & GCS_UNICODE) ? (cchMax * sizeof(wchar_t)) : cchMax) _When_(!(uType & (GCS_VALIDATEA | GCS_VALIDATEW)), _Null_terminated_)  CHAR *pszName,
178     _In_  UINT cchMax) {
179     USES_CONVERSION;
180     LPCTSTR szPrompt;
181     // copy help info to cache when explorer ask
182     if (uType & GCS_HELPTEXT)
183     {
184         switch (idCmd)
185         {
186         case 0:
187             szPrompt = _T("新增菜单项2说明文字");
188             break;
189         case 1:
190             szPrompt = _T("新增菜单项3说明文字");
191             break;
192         case 2:
193             szPrompt = _T("新增菜单项4说明文字");
194             break;
195         default:
196             //ATLASSERT(0);           // should never get here
197             return E_INVALIDARG;
198             break;
199         }
200         if (uType & GCS_UNICODE)
201         {
202             lstrcpynW((LPWSTR)pszName, T2CW(szPrompt), cchMax);
203         }
204         else
205         {
206             lstrcpynA(pszName, T2CA(szPrompt), cchMax);
207         }
208         return S_OK;
209     }
210     return E_INVALIDARG;
211 }

图片 27

7、在 .rgs文件中添加注册表信息,确保各GUID与 .idl文件中的一致。

图片 28

 1 HKCR
 2 {
 3     NoRemove CLSID
 4     {
 5         ForceRemove {9C50C98F-E1FF-41CF-BD54-E9A3BBDDDEF8} = s 'MyContextMenu Class'
 6         {
 7             ForceRemove Programmable
 8             InprocServer32 = s '%MODULE%'
 9             {
10                 val ThreadingModel = s 'Apartment'
11             }
12             TypeLib = s '{EB1C2F43-315D-4D8F-9A2A-70E67BE888E2}'
13             Version = s '1.0'
14         }
15     }
16 
17     NoRemove *
18     {
19         NoRemove ShellEx
20         {
21             NoRemove ContextMenuHandlers
22             {
23                 ForceRemove MyContextMenu = s '{9C50C98F-E1FF-41CF-BD54-E9A3BBDDDEF8}'
24             }
25         }
26     }
27 }

图片 29

8、Build Project 后打开cmd.exe,通过regsvr32命令注册或解注册生成的 .dll文件。

图片 30图片 31

 图片 32

 1 // MyOverlay.cpp : Implementation of CMyOverlay
 2 
 3 #include "stdafx.h"
 4 #include "MyOverlay.h"
 5 #include <WinBase.h>
 6 #pragma comment(lib, "Kernel32.lib")
 7 
 8 // CMyOverlay
 9 
10 STDMETHODIMP CMyOverlay::IsMemberOf(THIS_ _In_ PCWSTR pwszPath, DWORD dwAttrib)
11 {
12     if (_tcscmp(pwszPath, L"test") == 0)
13     {
14         return S_OK;
15     }
16     else
17     {
18         return S_FALSE;
19     }
20 }
21 
22 STDMETHODIMP CMyOverlay::GetOverlayInfo(
23     THIS_ _Out_writes_(cchMax) PWSTR pwszIconFile, 
24     int cchMax, 
25     _Out_ int * pIndex,
26     _Out_ DWORD * pdwFlags)
27 {
28     
29     GetModuleFileNameW(_AtlBaseModule.GetModuleInstance(), pwszIconFile, cchMax);
30 
31     *pIndex = 0;
32 
33     *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
34 
35     return S_OK;
36 }
37 
38 STDMETHODIMP CMyOverlay::GetPriority(THIS_ _Out_ int * pIPriority)
39 {
40     *pIPriority = 0;
41 
42     return S_OK;
43 }

10、查看效果如下图所示。

MyOverlay.cpp

 图片 33

7、在 .rgs 文件中添加注册表信息,确保各 GUID 与 .idl 文件中的一致。

 

 1 HKCR
 2 {
 3     NoRemove CLSID
 4     {
 5         ForceRemove {29913677-1662-46C5-8645-16F84DA6F438} = s 'MyOverlay Class'
 6         {
 7             ForceRemove Programmable
 8             InprocServer32 = s '%MODULE%'
 9             {
10                 val ThreadingModel = s 'Apartment'
11             }
12             TypeLib = s '{942F4DBB-4667-4767-A35B-52F32F623C63}'
13             Version = s '1.0'
14         }
15     }
16 }
17 
18 HKLM
19 {
20     NoRemove SOFTWARE
21     {
22         NoRemove Microsoft
23         {
24             NoRemove Windows
25             {
26                 NoRemove CurrentVersion
27                 {
28                     NoRemove Explorer
29                     {
30                         NoRemove ShellIconOverlayIdentifiers
31                         {
32                             ForceRemove '  MyOverlay' = s '{29913677-1662-46C5-8645-16F84DA6F438}'
33                             {
34                             }
35                         }
36                     }
37                 }
38             }
39         }
40     }
41 }

——————————————————

8、Build Project 后通过 cmd.exe 注册或解注册生成的 .dll 文件。重启 explorer.exe 后生效。

本文为本人原创,如需转载请注明出处。

图片 34

图片 35

图片 36

9、由于 slots 数量有限,检查在注册表中添加的子项是否在有效范围内(目前为前15个)。按下Win R键,通过运行对话框打开regedit.exe,按HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionExplorerShellIconOverlayIdentifiers的顺序依次展开或直接Ctrl F查找到MyOverlay项。可采用在.rgs文件中的子项名称前添加空格的方式将其位置提前。

图片 37

图片 38

10、查看效果如下图所示。

图片 39

 

参考网址:

—————————————————————————————————————

本文为本人原创,如需转载请注明出处。

 

本文由星彩网app下载发布于星彩网app下载,转载请注明出处:开创上下文菜单项,创造Logo标志

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。