[BROWSEUI]
[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
25 #include "precomp.h"
26
27 /* FIXME, I can't include windowsx because it conflicts with some #defines */
28 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
29 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
30
31 class CToolsBand :
32 public CWindowImpl<CToolsBand, CWindow, CControlWinTraits>,
33 public CComObjectRootEx<CComMultiThreadModelNoCS>,
34 public IDeskBand,
35 public IObjectWithSite,
36 public IInputObject,
37 public IPersistStream
38 {
39 private:
40 IDockingWindowSite *fDockSite;
41 GUID fExecCommandCategory;
42 CComPtr<IOleCommandTarget> fExecCommandTarget;
43 public:
44 CToolsBand();
45 ~CToolsBand();
46 public:
47 // *** IDeskBand methods ***
48 virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi);
49
50 // *** IObjectWithSite methods ***
51 virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown* pUnkSite);
52 virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
53
54 // *** IOleWindow methods ***
55 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
56 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
57
58 // *** IDockingWindow methods ***
59 virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved);
60 virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved);
61 virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow);
62
63 // *** IInputObject methods ***
64 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
65 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
66 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
67
68 // *** IPersist methods ***
69 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
70
71 // *** IPersistStream methods ***
72 virtual HRESULT STDMETHODCALLTYPE IsDirty();
73 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
74 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
75 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
76
77 // message handlers
78 LRESULT OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled);
79
80 BEGIN_MSG_MAP(CToolsBand)
81 // MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
82 // MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
83 NOTIFY_HANDLER(0, TBN_GETBUTTONINFOW, OnGetButtonInfo)
84 END_MSG_MAP()
85
86 BEGIN_COM_MAP(CToolsBand)
87 COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
88 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
89 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
90 COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
91 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
92 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
93 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
94 END_COM_MAP()
95 };
96
97 CToolsBand::CToolsBand()
98 {
99 fDockSite = NULL;
100 }
101
102 CToolsBand::~CToolsBand()
103 {
104 if (fDockSite)
105 fDockSite->Release();
106 }
107
108 HRESULT STDMETHODCALLTYPE CToolsBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
109 {
110 RECT actualRect;
111 POINTL actualSize;
112 POINTL idealSize;
113 POINTL maxSize;
114 POINTL itemSize;
115
116 ::GetWindowRect(m_hWnd, &actualRect);
117 actualSize.x = actualRect.right - actualRect.left;
118 actualSize.y = actualRect.bottom - actualRect.top;
119
120 /* Obtain the ideal size, to be used as min and max */
121 SendMessageW(m_hWnd, TB_AUTOSIZE, 0, 0);
122 SendMessageW(m_hWnd, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&maxSize));
123
124 idealSize = maxSize;
125 SendMessageW(m_hWnd, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&idealSize));
126
127 /* Obtain the button size, to be used as the integral size */
128 DWORD size = SendMessageW(m_hWnd, TB_GETBUTTONSIZE, 0, 0);
129 itemSize.x = GET_X_LPARAM(size);
130 itemSize.y = GET_Y_LPARAM(size);
131
132 if (pdbi->dwMask & DBIM_MINSIZE)
133 {
134 pdbi->ptMinSize = idealSize;
135 }
136 if (pdbi->dwMask & DBIM_MAXSIZE)
137 {
138 pdbi->ptMaxSize = maxSize;
139 }
140 if (pdbi->dwMask & DBIM_INTEGRAL)
141 {
142 pdbi->ptIntegral = itemSize;
143 }
144 if (pdbi->dwMask & DBIM_ACTUAL)
145 {
146 pdbi->ptActual = actualSize;
147 }
148 if (pdbi->dwMask & DBIM_TITLE)
149 wcscpy(pdbi->wszTitle, L"");
150 if (pdbi->dwMask & DBIM_MODEFLAGS)
151 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
152 if (pdbi->dwMask & DBIM_BKCOLOR)
153 pdbi->crBkgnd = 0;
154 return S_OK;
155 }
156
157 static const int backImageIndex = 0;
158 static const int forwardImageIndex = 1;
159 static const int favoritesImageIndex = 2;
160 // 3
161 // 4
162 static const int cutImageIndex = 5;
163 static const int copyImageIndex = 6;
164 static const int pasteImageIndex = 7;
165 static const int undoImageIndex = 8;
166 static const int redoImageIndex = 9;
167 static const int deleteImageIndex = 10;
168 // 11
169 // 12
170 // 13
171 // 14
172 static const int propertiesImageIndex = 15;
173 // 16
174 static const int searchImageIndex = 17;
175 // 18
176 // 19
177 // 20
178 // 21
179 static const int viewsImageIndex = 22;
180 // 23
181 // 24
182 // 25
183 // 26
184 // 27
185 static const int upImageIndex = 28;
186 static const int mapDriveImageIndex = 29;
187 static const int disconnectImageIndex = 30;
188 // 31
189 static const int viewsAltImageIndex = 32; // same image as viewsImageIndex
190 // 33
191 // 34
192 // 35
193 // 36
194 // 37
195 static const int viewsAlt2ImageIndex = 38; // same image as viewsAltImageIndex & viewsImageIndex
196 // 39
197 // 40
198 // 41
199 // 42
200 static const int foldersImageIndex = 43;
201 static const int moveToImageIndex = 44;
202 static const int copyToImageIndex = 45;
203 static const int folderOptionsImageIndex = 46;
204
205 const int numShownButtons = 13;
206 const int numHiddenButtons = 13;
207 TBBUTTON tbButtonsAdd[numShownButtons + numHiddenButtons] =
208 {
209 {backImageIndex, gBackCommandID, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Back")},
210 {forwardImageIndex, gForwardCommandID, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)_T("Forward")},
211 {upImageIndex, gUpLevelCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Up")},
212 {6, -1, TBSTATE_ENABLED, BTNS_SEP},
213 {searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Search")},
214 {foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Folders")},
215 {6, -1, TBSTATE_ENABLED, BTNS_SEP},
216 {moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Move To")},
217 {copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Copy To")},
218 {deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Delete")},
219 {undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Undo")},
220 {6, -1, TBSTATE_ENABLED, BTNS_SEP},
221 {viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0}, 0, (INT_PTR)_T("Views")},
222
223 {0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Stop")},
224 {0, gRefreshCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Refresh")},
225 {0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Home")},
226 {mapDriveImageIndex, gMapDriveCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Map Drive")},
227 {disconnectImageIndex, gDisconnectCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Disconnect")},
228 {favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Favorites")},
229 {0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("History")},
230 {0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Full Screen")},
231 {propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Properties")},
232 {cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Cut")},
233 {copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Copy")},
234 {pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Paste")},
235 {folderOptionsImageIndex, gFolderOptionsCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Folder Options")},
236 };
237
238 HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite)
239 {
240 HWND parentWindow;
241 IOleWindow *oleWindow;
242 HWND toolbar;
243 HRESULT hResult;
244
245 if (fDockSite != NULL)
246 fDockSite->Release();
247 if (pUnkSite == NULL)
248 return S_OK;
249 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fDockSite));
250 if (FAILED(hResult))
251 return hResult;
252 parentWindow = NULL;
253 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
254 if (SUCCEEDED(hResult))
255 {
256 oleWindow->GetWindow(&parentWindow);
257 oleWindow->Release();
258 }
259 if (!::IsWindow(parentWindow))
260 return E_FAIL;
261
262 toolbar = CreateWindowEx(TBSTYLE_EX_DOUBLEBUFFER, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
263 WS_CLIPCHILDREN | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
264 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP, 0, 0, 500, 20, parentWindow, NULL,
265 _AtlBaseModule.GetModuleInstance(), 0);
266 if (toolbar == NULL)
267 return E_FAIL;
268 SubclassWindow(toolbar);
269
270 SendMessage(WM_USER + 100, GetSystemMetrics(SM_CXEDGE) / 2, 0);
271 SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
272 SendMessage(TB_SETMAXTEXTROWS, 1, 0);
273 SendMessage(TB_SETEXTENDEDSTYLE, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS,
274 TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
275
276 HINSTANCE shell32Instance = GetModuleHandle(_T("shell32.dll"));
277 HBITMAP imgNormal = reinterpret_cast<HBITMAP>(
278 LoadImage(shell32Instance, MAKEINTRESOURCE(214),
279 IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION));
280
281 HBITMAP imgHot = reinterpret_cast<HBITMAP>(
282 LoadImage(shell32Instance, MAKEINTRESOURCE(215),
283 IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION));
284
285 if (imgNormal && imgHot)
286 {
287 BITMAP bitmapInfo;
288 GetObjectW(imgNormal, sizeof(bitmapInfo), &bitmapInfo);
289 HIMAGELIST himlNormal = ImageList_Create(bitmapInfo.bmHeight, bitmapInfo.bmHeight, ILC_COLOR32, 4, 4);
290
291 ImageList_Add(himlNormal, imgNormal, NULL);
292 DeleteObject(imgNormal);
293
294 GetObjectW(imgHot, sizeof(bitmapInfo), &bitmapInfo);
295 HIMAGELIST himlHot = ImageList_Create(bitmapInfo.bmHeight, bitmapInfo.bmHeight, ILC_COLOR32, 4, 4);
296
297 ImageList_Add(himlHot, imgHot, NULL);
298 DeleteObject(imgHot);
299
300 SendMessage(TB_SETIMAGELIST, 0, (LPARAM) himlNormal);
301 SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) himlHot);
302 }
303
304 SendMessage(TB_ADDBUTTONSW, numShownButtons, (LPARAM)&tbButtonsAdd);
305
306 return hResult;
307 }
308
309 HRESULT STDMETHODCALLTYPE CToolsBand::GetSite(REFIID riid, void **ppvSite)
310 {
311 if (fDockSite == NULL)
312 return E_FAIL;
313 return fDockSite->QueryInterface(riid, ppvSite);
314 }
315
316 HRESULT STDMETHODCALLTYPE CToolsBand::GetWindow(HWND *lphwnd)
317 {
318 if (lphwnd == NULL)
319 return E_POINTER;
320 *lphwnd = m_hWnd;
321 return S_OK;
322 }
323
324 HRESULT STDMETHODCALLTYPE CToolsBand::ContextSensitiveHelp(BOOL fEnterMode)
325 {
326
327 return E_NOTIMPL;
328 }
329
330 HRESULT STDMETHODCALLTYPE CToolsBand::CloseDW(DWORD dwReserved)
331 {
332 ShowDW(FALSE);
333
334 if (IsWindow())
335 DestroyWindow();
336
337 m_hWnd = NULL;
338
339 return S_OK;
340 }
341
342 HRESULT STDMETHODCALLTYPE CToolsBand::ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved)
343 {
344 return E_NOTIMPL;
345 }
346
347 HRESULT STDMETHODCALLTYPE CToolsBand::ShowDW(BOOL fShow)
348 {
349 if (m_hWnd)
350 {
351 if (fShow)
352 ShowWindow(SW_SHOW);
353 else
354 ShowWindow(SW_HIDE);
355 }
356 return S_OK;
357 }
358
359 HRESULT STDMETHODCALLTYPE CToolsBand::HasFocusIO()
360 {
361 return E_NOTIMPL;
362 }
363
364 HRESULT STDMETHODCALLTYPE CToolsBand::TranslateAcceleratorIO(LPMSG lpMsg)
365 {
366 return E_NOTIMPL;
367 }
368
369 HRESULT STDMETHODCALLTYPE CToolsBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
370 {
371 return E_NOTIMPL;
372 }
373
374 HRESULT STDMETHODCALLTYPE CToolsBand::GetClassID(CLSID *pClassID)
375 {
376 return E_NOTIMPL;
377 }
378
379 HRESULT STDMETHODCALLTYPE CToolsBand::IsDirty()
380 {
381 return E_NOTIMPL;
382 }
383
384 HRESULT STDMETHODCALLTYPE CToolsBand::Load(IStream *pStm)
385 {
386 return E_NOTIMPL;
387 }
388
389 HRESULT STDMETHODCALLTYPE CToolsBand::Save(IStream *pStm, BOOL fClearDirty)
390 {
391 return E_NOTIMPL;
392 }
393
394 HRESULT STDMETHODCALLTYPE CToolsBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
395 {
396 return E_NOTIMPL;
397 }
398
399 LRESULT CToolsBand::OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
400 {
401 TBNOTIFYW *pTBntf = reinterpret_cast<TBNOTIFYW *>(pNMHDR);
402
403 if (pTBntf->iItem >= 0 && pTBntf->iItem < (numShownButtons + numHiddenButtons))
404 {
405 pTBntf->tbButton = tbButtonsAdd[pTBntf->iItem];
406 return TRUE;
407 }
408 else
409 return FALSE;
410 return 0;
411 }
412
413 HRESULT CreateToolsBar(REFIID riid, void **ppv)
414 {
415 CComObject<CToolsBand> *theMenuBar;
416 HRESULT hResult;
417
418 if (ppv == NULL)
419 return E_POINTER;
420 *ppv = NULL;
421 ATLTRY (theMenuBar = new CComObject<CToolsBand>);
422 if (theMenuBar == NULL)
423 return E_OUTOFMEMORY;
424 hResult = theMenuBar->QueryInterface(riid, reinterpret_cast<void **>(ppv));
425 if (FAILED(hResult))
426 {
427 delete theMenuBar;
428 return hResult;
429 }
430 return S_OK;
431 }
432