sync with trunk r49322
[reactos.git] / dll / win32 / browseui / toolsband.cpp
1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2009 Andrew Hill <ash77 at domain reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 Implements the toolbar band of a cabinet window
23 */
24 #include <windows.h>
25 #include <shlobj.h>
26 #include <shlobj_undoc.h>
27 #include <shlguid.h>
28 #include <shlguid_undoc.h>
29 #include <tchar.h>
30 #include <atlbase.h>
31 #include <atlcom.h>
32 #include <atlwin.h>
33
34 /*
35 TODO:
36 **Fix GetBandInfo to calculate size correctly
37 */
38 static const int gBackCommandID = 0xa121;
39 static const int gForwardCommandID = 0xa122;
40 static const int gUpLevelCommandID = 0xa022;
41 static const int gSearchCommandID = 1003;
42 static const int gFoldersCommandID = 1004;
43 static const int gMoveToCommandID = 0x701f;
44 static const int gCopyToCommandID = 0x701e;
45 static const int gDeleteCommandID = 0x7011;
46 static const int gUndoCommandID = 0x701b;
47 static const int gViewsCommandID = 0x7031;
48 static const int gStopCommandID = 1010;
49 static const int gRefreshCommandID = 0xa220;
50 static const int gHomeCommandID = 1012;
51 static const int gMapDriveCommandID = 41089;
52 static const int gDisconnectCommandID = 41090;
53 static const int gFavoritesCommandID = 1015;
54 static const int gHistoryCommandID = 1016;
55 static const int gFullScreenCommandID = 1017;
56 static const int gPropertiesCommandID = 0x7013;
57 static const int gCutCommandID = 0x7018;
58 static const int gCopyCommandID = 0x7019;
59 static const int gPasteCommandID = 0x701a;
60 static const int gFolderOptionsCommandID = 41251;
61
62 class CToolsBand :
63 public CWindowImpl<CToolsBand, CWindow, CControlWinTraits>,
64 public CComObjectRootEx<CComMultiThreadModelNoCS>,
65 public IDeskBand,
66 public IObjectWithSite,
67 public IInputObject,
68 public IPersistStream
69 {
70 private:
71 IDockingWindowSite *fDockSite;
72 GUID fExecCommandCategory;
73 CComPtr<IOleCommandTarget> fExecCommandTarget;
74 public:
75 CToolsBand();
76 ~CToolsBand();
77 public:
78 // *** IDeskBand methods ***
79 virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi);
80
81 // *** IObjectWithSite methods ***
82 virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown* pUnkSite);
83 virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
84
85 // *** IOleWindow methods ***
86 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
87 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
88
89 // *** IDockingWindow methods ***
90 virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved);
91 virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved);
92 virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow);
93
94 // *** IInputObject methods ***
95 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
96 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
97 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
98
99 // *** IPersist methods ***
100 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
101
102 // *** IPersistStream methods ***
103 virtual HRESULT STDMETHODCALLTYPE IsDirty();
104 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
105 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
106 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
107
108 // message handlers
109 LRESULT OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled);
110
111 BEGIN_MSG_MAP(CToolsBand)
112 // MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
113 // MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
114 NOTIFY_HANDLER(0, TBN_GETBUTTONINFOW, OnGetButtonInfo)
115 END_MSG_MAP()
116
117 BEGIN_COM_MAP(CToolsBand)
118 COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
119 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
120 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
121 COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
122 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
123 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
124 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
125 END_COM_MAP()
126 };
127
128 CToolsBand::CToolsBand()
129 {
130 fDockSite = NULL;
131 }
132
133 CToolsBand::~CToolsBand()
134 {
135 if (fDockSite)
136 fDockSite->Release();
137 }
138
139 HRESULT STDMETHODCALLTYPE CToolsBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
140 {
141 if (pdbi->dwMask & DBIM_MINSIZE)
142 {
143 pdbi->ptMinSize.x = 400;
144 pdbi->ptMinSize.y = 38;
145 }
146 if (pdbi->dwMask & DBIM_MAXSIZE)
147 {
148 pdbi->ptMaxSize.x = 0;
149 pdbi->ptMaxSize.y = 0;
150 }
151 if (pdbi->dwMask & DBIM_INTEGRAL)
152 {
153 pdbi->ptIntegral.x = 0;
154 pdbi->ptIntegral.y = 0;
155 }
156 if (pdbi->dwMask & DBIM_ACTUAL)
157 {
158 pdbi->ptActual.x = 400;
159 pdbi->ptActual.y = 38;
160 }
161 if (pdbi->dwMask & DBIM_TITLE)
162 wcscpy(pdbi->wszTitle, L"");
163 if (pdbi->dwMask & DBIM_MODEFLAGS)
164 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
165 if (pdbi->dwMask & DBIM_BKCOLOR)
166 pdbi->crBkgnd = 0;
167 return S_OK;
168 }
169
170 static const int backImageIndex = 0;
171 static const int forwardImageIndex = 1;
172 static const int favoritesImageIndex = 2;
173 // 3
174 // 4
175 static const int cutImageIndex = 5;
176 static const int copyImageIndex = 6;
177 static const int pasteImageIndex = 7;
178 static const int undoImageIndex = 8;
179 static const int redoImageIndex = 9;
180 static const int deleteImageIndex = 10;
181 // 11
182 // 12
183 // 13
184 // 14
185 static const int propertiesImageIndex = 15;
186 // 16
187 static const int searchImageIndex = 17;
188 // 18
189 // 19
190 // 20
191 // 21
192 static const int viewsImageIndex = 22;
193 // 23
194 // 24
195 // 25
196 // 26
197 // 27
198 static const int upImageIndex = 28;
199 static const int mapDriveImageIndex = 29;
200 static const int disconnectImageIndex = 30;
201 // 31
202 static const int viewsAltImageIndex = 32; // same image as viewsImageIndex
203 // 33
204 // 34
205 // 35
206 // 36
207 // 37
208 static const int viewsAlt2ImageIndex = 38; // same image as viewsAltImageIndex & viewsImageIndex
209 // 39
210 // 40
211 // 41
212 // 42
213 static const int foldersImageIndex = 43;
214 static const int moveToImageIndex = 44;
215 static const int copyToImageIndex = 45;
216 static const int folderOptionsImageIndex = 46;
217
218 const int numShownButtons = 13;
219 const int numHiddenButtons = 13;
220 TBBUTTON tbButtonsAdd[numShownButtons + numHiddenButtons] =
221 {
222 {backImageIndex, gBackCommandID, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Back")},
223 {forwardImageIndex, gForwardCommandID, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)_T("Forward")},
224 {upImageIndex, gUpLevelCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Up")},
225 {6, -1, TBSTATE_ENABLED, BTNS_SEP},
226 {searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Search")},
227 {foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Folders")},
228 {6, -1, TBSTATE_ENABLED, BTNS_SEP},
229 {moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Move To")},
230 {copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Copy To")},
231 {deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Delete")},
232 {undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Undo")},
233 {6, -1, TBSTATE_ENABLED, BTNS_SEP},
234 {viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0}, 0, (INT_PTR)_T("Views")},
235
236 {0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Stop")},
237 {0, gRefreshCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Refresh")},
238 {0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Home")},
239 {mapDriveImageIndex, gMapDriveCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Map Drive")},
240 {disconnectImageIndex, gDisconnectCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Disconnect")},
241 {favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Favorites")},
242 {0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("History")},
243 {0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Full Screen")},
244 {propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Properties")},
245 {cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Cut")},
246 {copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Copy")},
247 {pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Paste")},
248 {folderOptionsImageIndex, gFolderOptionsCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Folder Options")},
249 };
250
251 HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite)
252 {
253 HWND parentWindow;
254 IOleWindow *oleWindow;
255 HWND toolbar;
256 HRESULT hResult;
257
258 if (fDockSite != NULL)
259 fDockSite->Release();
260 if (pUnkSite == NULL)
261 return S_OK;
262 hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, (void **)&fDockSite);
263 if (FAILED(hResult))
264 return hResult;
265 parentWindow = NULL;
266 hResult = pUnkSite->QueryInterface(IID_IOleWindow, (void **)&oleWindow);
267 if (SUCCEEDED(hResult))
268 {
269 oleWindow->GetWindow(&parentWindow);
270 oleWindow->Release();
271 }
272 if (!::IsWindow(parentWindow))
273 return E_FAIL;
274
275 toolbar = CreateWindowEx(TBSTYLE_EX_DOUBLEBUFFER, TOOLBARCLASSNAMEW, _T(""), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
276 WS_CLIPCHILDREN | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
277 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP, 0, 0, 500, 20, parentWindow, NULL,
278 _AtlBaseModule.GetModuleInstance(), 0);
279 if (toolbar == NULL)
280 return E_FAIL;
281 SubclassWindow(toolbar);
282
283 SendMessage(WM_USER + 100, GetSystemMetrics(SM_CXEDGE) / 2, 0);
284 SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
285 SendMessage(TB_SETMAXTEXTROWS, 1, 0);
286 SendMessage(TB_SETEXTENDEDSTYLE, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
287
288 HINSTANCE shell32Instance = GetModuleHandle(_T("shell32.dll"));
289 HBITMAP imageBitmap = (HBITMAP)LoadImage(shell32Instance, MAKEINTRESOURCE(214), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
290
291 DIBSECTION bitmapInfo;
292 GetObjectW(imageBitmap, sizeof(bitmapInfo), &bitmapInfo);
293 HIMAGELIST imageList = ImageList_Create(bitmapInfo.dsBm.bmHeight, bitmapInfo.dsBm.bmHeight, ILC_COLOR32, 4, 4);
294
295 ImageList_Add(imageList, imageBitmap, NULL);
296 DeleteObject(imageBitmap);
297
298 SendMessage(TB_SETIMAGELIST, 0, (LPARAM)imageList);
299
300 SendMessage(TB_ADDBUTTONSW, numShownButtons, (LPARAM)&tbButtonsAdd);
301
302 return hResult;
303 }
304
305 HRESULT STDMETHODCALLTYPE CToolsBand::GetSite(REFIID riid, void **ppvSite)
306 {
307 if (fDockSite == NULL)
308 return E_FAIL;
309 return fDockSite->QueryInterface(riid, ppvSite);
310 }
311
312 HRESULT STDMETHODCALLTYPE CToolsBand::GetWindow(HWND *lphwnd)
313 {
314 if (lphwnd == NULL)
315 return E_POINTER;
316 *lphwnd = m_hWnd;
317 return S_OK;
318 }
319
320 HRESULT STDMETHODCALLTYPE CToolsBand::ContextSensitiveHelp(BOOL fEnterMode)
321 {
322
323 return E_NOTIMPL;
324 }
325
326 HRESULT STDMETHODCALLTYPE CToolsBand::CloseDW(DWORD dwReserved)
327 {
328 ShowDW(FALSE);
329
330 if (IsWindow())
331 DestroyWindow();
332
333 m_hWnd = NULL;
334
335 return S_OK;
336 }
337
338 HRESULT STDMETHODCALLTYPE CToolsBand::ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved)
339 {
340 return E_NOTIMPL;
341 }
342
343 HRESULT STDMETHODCALLTYPE CToolsBand::ShowDW(BOOL fShow)
344 {
345 if (m_hWnd)
346 {
347 if (fShow)
348 ShowWindow(SW_SHOW);
349 else
350 ShowWindow(SW_HIDE);
351 }
352 return S_OK;
353 }
354
355 HRESULT STDMETHODCALLTYPE CToolsBand::HasFocusIO()
356 {
357 return E_NOTIMPL;
358 }
359
360 HRESULT STDMETHODCALLTYPE CToolsBand::TranslateAcceleratorIO(LPMSG lpMsg)
361 {
362 return E_NOTIMPL;
363 }
364
365 HRESULT STDMETHODCALLTYPE CToolsBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
366 {
367 return E_NOTIMPL;
368 }
369
370 HRESULT STDMETHODCALLTYPE CToolsBand::GetClassID(CLSID *pClassID)
371 {
372 return E_NOTIMPL;
373 }
374
375 HRESULT STDMETHODCALLTYPE CToolsBand::IsDirty()
376 {
377 return E_NOTIMPL;
378 }
379
380 HRESULT STDMETHODCALLTYPE CToolsBand::Load(IStream *pStm)
381 {
382 return E_NOTIMPL;
383 }
384
385 HRESULT STDMETHODCALLTYPE CToolsBand::Save(IStream *pStm, BOOL fClearDirty)
386 {
387 return E_NOTIMPL;
388 }
389
390 HRESULT STDMETHODCALLTYPE CToolsBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
391 {
392 return E_NOTIMPL;
393 }
394
395 LRESULT CToolsBand::OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
396 {
397 TBNOTIFYW *pTBntf = (TBNOTIFYW *)pNMHDR;
398
399 if (pTBntf->iItem >= 0 && pTBntf->iItem < (numShownButtons + numHiddenButtons))
400 {
401 pTBntf->tbButton = tbButtonsAdd[pTBntf->iItem];
402 return TRUE;
403 }
404 else
405 return FALSE;
406 return 0;
407 }
408
409 HRESULT CreateToolsBar(REFIID riid, void **ppv)
410 {
411 CComObject<CToolsBand> *theMenuBar;
412 HRESULT hResult;
413
414 if (ppv == NULL)
415 return E_POINTER;
416 *ppv = NULL;
417 ATLTRY (theMenuBar = new CComObject<CToolsBand>);
418 if (theMenuBar == NULL)
419 return E_OUTOFMEMORY;
420 hResult = theMenuBar->QueryInterface (riid, (void **)ppv);
421 if (FAILED (hResult))
422 {
423 delete theMenuBar;
424 return hResult;
425 }
426 return S_OK;
427 }
428