Fix build.
[reactos.git] / reactos / dll / win32 / shell32 / CDefViewBckgrndMenu.cpp
1 /*
2 * PROJECT: shell32
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/shell32/CDefViewBckgrndMenu.cpp
5 * PURPOSE: background context menu of the CDefView
6 * PROGRAMMERS: Giannis Adamopoulos
7 */
8
9 #include <precomp.h>
10
11 WINE_DEFAULT_DEBUG_CHANNEL(shell);
12
13 class CDefViewBckgrndMenu :
14 public CComObjectRootEx<CComMultiThreadModelNoCS>,
15 public IContextMenu3,
16 public IObjectWithSite
17 {
18 private:
19 CComPtr<IUnknown> m_site;
20 CComPtr<IShellFolder> m_psf;
21 CComPtr<IContextMenu> m_folderCM;
22
23 BOOL _bIsDesktopBrowserMenu();
24 BOOL _bCanPaste();
25 public:
26 CDefViewBckgrndMenu();
27 ~CDefViewBckgrndMenu();
28 HRESULT Initialize(IShellFolder* psf);
29
30 // IContextMenu
31 virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
32 virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi);
33 virtual HRESULT WINAPI GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen);
34
35 // IContextMenu2
36 virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
37
38 // IContextMenu3
39 virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
40
41 // IObjectWithSite
42 virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
43 virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
44
45 BEGIN_COM_MAP(CDefViewBckgrndMenu)
46 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
47 COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
48 COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
49 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
50 END_COM_MAP()
51 };
52
53 CDefViewBckgrndMenu::CDefViewBckgrndMenu()
54 {
55 }
56
57 CDefViewBckgrndMenu::~CDefViewBckgrndMenu()
58 {
59 }
60
61 BOOL CDefViewBckgrndMenu::_bIsDesktopBrowserMenu()
62 {
63 if (!m_site)
64 return FALSE;
65
66 /* Get a pointer to the shell browser */
67 CComPtr<IShellView> psv;
68 HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
69 if (FAILED_UNEXPECTEDLY(hr))
70 return FALSE;
71
72 FOLDERSETTINGS FolderSettings;
73 hr = psv->GetCurrentInfo(&FolderSettings);
74 if (FAILED_UNEXPECTEDLY(hr))
75 return FALSE;
76
77 return ((FolderSettings.fFlags & FWF_DESKTOP) == FWF_DESKTOP);
78 }
79
80 BOOL CDefViewBckgrndMenu::_bCanPaste()
81 {
82 /* If the folder doesn't have a drop target we can't paste */
83 CComPtr<IDropTarget> pdt;
84 HRESULT hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdt));
85 if (FAILED(hr))
86 return FALSE;
87
88 /* We can only paste if CFSTR_SHELLIDLIST is present in the clipboard */
89 CComPtr<IDataObject> pDataObj;
90 hr = OleGetClipboard(&pDataObj);
91 if (FAILED(hr))
92 return FALSE;
93
94 STGMEDIUM medium;
95 FORMATETC formatetc;
96
97 /* Set the FORMATETC structure*/
98 InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
99 hr = pDataObj->GetData(&formatetc, &medium);
100 if (FAILED(hr))
101 return FALSE;
102
103 ReleaseStgMedium(&medium);
104 return TRUE;
105 }
106
107 HRESULT
108 CDefViewBckgrndMenu::Initialize(IShellFolder* psf)
109 {
110 m_psf = psf;
111 return S_OK;
112 }
113
114 HRESULT
115 WINAPI
116 CDefViewBckgrndMenu::SetSite(IUnknown *pUnkSite)
117 {
118 m_site = pUnkSite;
119 return S_OK;
120 }
121
122 HRESULT
123 WINAPI
124 CDefViewBckgrndMenu::GetSite(REFIID riid, void **ppvSite)
125 {
126 if (!m_site)
127 return E_FAIL;
128
129 return m_site->QueryInterface(riid, ppvSite);
130 }
131
132 HRESULT
133 WINAPI
134 CDefViewBckgrndMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
135 {
136 HRESULT hr;
137 HMENU hMenuPart;
138
139 /* Load the default part of the background context menu */
140 hMenuPart = LoadMenuW(shell32_hInstance, L"MENU_002");
141 if (hMenuPart)
142 {
143 /* Don't show the view submenu for the desktop */
144 if (_bIsDesktopBrowserMenu())
145 {
146 DeleteMenu(hMenuPart, FCIDM_SHVIEW_VIEW, MF_BYCOMMAND);
147 }
148
149 /* Disable the paste options if it is not possible */
150 if (!_bCanPaste())
151 {
152 EnableMenuItem(hMenuPart, FCIDM_SHVIEW_INSERT, MF_BYCOMMAND | MF_GRAYED);
153 EnableMenuItem(hMenuPart, FCIDM_SHVIEW_INSERTLINK, MF_BYCOMMAND | MF_GRAYED);
154 }
155
156 /* merge general background context menu in */
157 Shell_MergeMenus(hMenu, GetSubMenu(hMenuPart, 0), indexMenu, 0, 0xFFFF, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
158 indexMenu += GetMenuItemCount(GetSubMenu(hMenuPart, 0));
159 DestroyMenu(hMenuPart);
160 }
161 else
162 {
163 ERR("Failed to load menu from resource!\n");
164 }
165
166 /* Query the shell folder to add any items it wants to add in the background context menu */
167 hMenuPart = CreatePopupMenu();
168 if (hMenuPart)
169 {
170 hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IContextMenu, &m_folderCM));
171 if (SUCCEEDED(hr))
172 {
173 InsertMenuA(hMenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
174 UINT SeparatorIndex = indexMenu;
175 int count = GetMenuItemCount(hMenu);
176
177 hr = m_folderCM->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
178 if (SUCCEEDED(hr))
179 {
180 //Shell_MergeMenus(hMenu, hMenuPart, indexMenu, 0, UINT_MAX, MM_ADDSEPARATOR| MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
181 //DestroyMenu(hMenuPart);
182 }
183 else
184 {
185 WARN("QueryContextMenu failed!\n");
186 }
187
188 /* If no item was added after the separator, remove it */
189 if (count == GetMenuItemCount(hMenu))
190 DeleteMenu(hMenu, SeparatorIndex, MF_BYPOSITION);
191
192 }
193 else
194 {
195 WARN("GetUIObjectOf didn't give any context menu!\n");
196 }
197 }
198 else
199 {
200 ERR("CreatePopupMenu failed!\n");
201 }
202
203 return S_OK;
204 }
205
206 HRESULT
207 WINAPI
208 CDefViewBckgrndMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
209 {
210 /* The commands that are handled by the def view are forwarded to it */
211 switch (LOWORD(lpcmi->lpVerb))
212 {
213 case FCIDM_SHVIEW_BIGICON:
214 case FCIDM_SHVIEW_SMALLICON:
215 case FCIDM_SHVIEW_LISTVIEW:
216 case FCIDM_SHVIEW_REPORTVIEW:
217 case 0x30: /* FIX IDS in resource files */
218 case 0x31:
219 case 0x32:
220 case 0x33:
221 case FCIDM_SHVIEW_AUTOARRANGE:
222 case FCIDM_SHVIEW_SNAPTOGRID:
223 case FCIDM_SHVIEW_REFRESH:
224 if (!m_site)
225 return E_FAIL;
226
227 /* Get a pointer to the shell browser */
228 CComPtr<IShellView> psv;
229 HRESULT hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
230 if (FAILED_UNEXPECTEDLY(hr))
231 return hr;
232
233 HWND hwndSV = NULL;
234 if (SUCCEEDED(psv->GetWindow(&hwndSV)))
235 SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
236 return S_OK;
237 }
238
239 /* Unknown commands are added by the folder context menu so forward the invocation */
240 return m_folderCM->InvokeCommand(lpcmi);
241
242 }
243
244 HRESULT
245 WINAPI
246 CDefViewBckgrndMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
247 {
248 if (m_folderCM)
249 {
250 return m_folderCM->GetCommandString(idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
251 }
252
253 return E_NOTIMPL;
254 }
255
256 HRESULT
257 WINAPI
258 CDefViewBckgrndMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
259 {
260 if(m_folderCM)
261 {
262 CComPtr<IContextMenu2> pfolderCM2;
263 HRESULT hr = m_folderCM->QueryInterface(IID_PPV_ARG(IContextMenu2, &pfolderCM2));
264 if (FAILED_UNEXPECTEDLY(hr))
265 return hr;
266
267 return pfolderCM2->HandleMenuMsg(uMsg, wParam, lParam);
268 }
269
270 return E_NOTIMPL;
271 }
272
273 HRESULT
274 WINAPI
275 CDefViewBckgrndMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
276 {
277 if(m_folderCM)
278 {
279 CComPtr<IContextMenu3> pfolderCM3;
280 HRESULT hr = m_folderCM->QueryInterface(IID_PPV_ARG(IContextMenu3, &pfolderCM3));
281 if (FAILED_UNEXPECTEDLY(hr))
282 return hr;
283
284 return pfolderCM3->HandleMenuMsg2(uMsg, wParam, lParam, plResult);
285 }
286
287 return E_NOTIMPL;
288 }
289
290
291 HRESULT
292 CDefViewBckgrndMenu_CreateInstance(IShellFolder* psf, REFIID riid, void **ppv)
293 {
294 return ShellObjectCreatorInit<CDefViewBckgrndMenu>(psf, riid, ppv);
295 }