[BROWSEUI] Don't leak the image lists created by CAddressBand and CToolsBand.
[reactos.git] / reactos / 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 CComPtr<IDockingWindowSite> fDockSite;
41 GUID fExecCommandCategory;
42 CComPtr<IOleCommandTarget> fExecCommandTarget;
43 HIMAGELIST m_himlNormal;
44 HIMAGELIST m_himlHot;
45 public:
46 CToolsBand();
47 virtual ~CToolsBand();
48 public:
49 // *** IDeskBand methods ***
50 virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi);
51
52 // *** IObjectWithSite methods ***
53 virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown* pUnkSite);
54 virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
55
56 // *** IOleWindow methods ***
57 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
58 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
59
60 // *** IDockingWindow methods ***
61 virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved);
62 virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved);
63 virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow);
64
65 // *** IInputObject methods ***
66 virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
67 virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
68 virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
69
70 // *** IPersist methods ***
71 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
72
73 // *** IPersistStream methods ***
74 virtual HRESULT STDMETHODCALLTYPE IsDirty();
75 virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
76 virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
77 virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
78
79 // message handlers
80 LRESULT OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled);
81
82 BEGIN_MSG_MAP(CToolsBand)
83 // MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
84 // MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
85 NOTIFY_HANDLER(0, TBN_GETBUTTONINFOW, OnGetButtonInfo)
86 END_MSG_MAP()
87
88 BEGIN_COM_MAP(CToolsBand)
89 COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
90 COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
91 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
92 COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
93 COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
94 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
95 COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
96 END_COM_MAP()
97 };
98
99 CToolsBand::CToolsBand()
100 : fDockSite(NULL)
101 {
102 }
103
104 CToolsBand::~CToolsBand()
105 {
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 enum StandardToolbarButtons {
206 BtnIdx_Back = 0,
207 BtnIdx_Forward,
208 BtnIdx_Up,
209 BtnIdx_Search,
210 BtnIdx_Folders,
211 BtnIdx_MoveTo,
212 BtnIdx_CopyTo,
213 BtnIdx_Delete,
214 BtnIdx_Undo,
215 BtnIdx_Views,
216 BtnIdx_Stop,
217 BtnIdx_Refresh,
218 BtnIdx_Home,
219 BtnIdx_MapDrive,
220 BtnIdx_Disconnect,
221 BtnIdx_Favorites,
222 BtnIdx_History,
223 BtnIdx_FullScreen,
224 BtnIdx_Properties,
225 BtnIdx_Cut,
226 BtnIdx_Copy,
227 BtnIdx_Paste,
228 BtnIdx_FolderOptions,
229 };
230
231 const int numShownButtons = 13;
232 const int numHiddenButtons = 13;
233 TBBUTTON tbButtonsAdd[numShownButtons + numHiddenButtons] =
234 {
235 { backImageIndex, IDM_GOTO_BACK, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Back },
236 { forwardImageIndex, IDM_GOTO_FORWARD, TBSTATE_ENABLED, BTNS_DROPDOWN, { 0 }, 0, BtnIdx_Forward },
237 { upImageIndex, IDM_GOTO_UPONELEVEL, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Up },
238 { 6, -1, TBSTATE_ENABLED, BTNS_SEP },
239 { searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Search },
240 { foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Folders },
241 { 6, -1, TBSTATE_ENABLED, BTNS_SEP },
242 { moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MoveTo },
243 { copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_CopyTo },
244 { deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Delete },
245 { undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Undo },
246 { 6, -1, TBSTATE_ENABLED, BTNS_SEP },
247 { viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, { 0 }, 0, BtnIdx_Views },
248
249 { 0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Stop },
250 { 0, IDM_VIEW_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Refresh },
251 { 0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Home },
252 { mapDriveImageIndex, IDM_TOOLS_MAPNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MapDrive },
253 { disconnectImageIndex, IDM_TOOLS_DISCONNECTNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Disconnect },
254 { favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Favorites },
255 { 0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_History },
256 { 0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FullScreen },
257 { propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Properties },
258 { cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Cut },
259 { copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Copy },
260 { pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Paste },
261 { folderOptionsImageIndex, IDM_TOOLS_FOLDEROPTIONS, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FolderOptions },
262 };
263
264 HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite){
265 HWND parentWindow;
266 HWND toolbar;
267 HRESULT hResult;
268
269 if(fDockSite) fDockSite.Release();
270
271 if (pUnkSite == NULL)
272 return S_OK;
273 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fDockSite));
274 if (FAILED_UNEXPECTEDLY(hResult))
275 return hResult;
276 parentWindow = NULL;
277 hResult = IUnknown_GetWindow(pUnkSite, &parentWindow);
278 if (FAILED(hResult) || !::IsWindow(parentWindow))
279 return E_FAIL;
280
281 toolbar = CreateWindowEx(
282 TBSTYLE_EX_DOUBLEBUFFER,
283 TOOLBARCLASSNAMEW, NULL,
284 WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
285 TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
286 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP,
287 0, 0, 500, 20, parentWindow, NULL, _AtlBaseModule.GetModuleInstance(), 0);
288 if (toolbar == NULL)
289 return E_FAIL;
290 SubclassWindow(toolbar);
291 SendMessage(TB_ADDSTRINGW, (WPARAM) GetModuleHandle(L"browseui.dll"), IDS_STANDARD_TOOLBAR);
292
293 SendMessage(WM_USER + 100, GetSystemMetrics(SM_CXEDGE) / 2, 0);
294 SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
295 SendMessage(TB_SETMAXTEXTROWS, 1, 0);
296 SendMessage(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
297
298 HINSTANCE shell32Instance = GetModuleHandle(_T("shell32.dll"));
299 m_himlNormal = ImageList_LoadImageW(shell32Instance, MAKEINTRESOURCE(214),
300 0, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
301
302 m_himlHot = ImageList_LoadImageW(shell32Instance, MAKEINTRESOURCE(215),
303 0, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
304
305 SendMessage(TB_SETIMAGELIST, 0, (LPARAM) m_himlNormal);
306 SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) m_himlHot);
307 SendMessage(TB_ADDBUTTONSW, numShownButtons, (LPARAM)&tbButtonsAdd);
308
309 return hResult;
310 }
311
312 HRESULT STDMETHODCALLTYPE CToolsBand::GetSite(REFIID riid, void **ppvSite)
313 {
314 if (fDockSite == NULL)
315 return E_FAIL;
316 return fDockSite->QueryInterface(riid, ppvSite);
317 }
318
319 HRESULT STDMETHODCALLTYPE CToolsBand::GetWindow(HWND *lphwnd)
320 {
321 if (lphwnd == NULL)
322 return E_POINTER;
323 *lphwnd = m_hWnd;
324 return S_OK;
325 }
326
327 HRESULT STDMETHODCALLTYPE CToolsBand::ContextSensitiveHelp(BOOL fEnterMode)
328 {
329 return E_NOTIMPL;
330 }
331
332 HRESULT STDMETHODCALLTYPE CToolsBand::CloseDW(DWORD dwReserved)
333 {
334 ShowDW(FALSE);
335
336 if (IsWindow())
337 DestroyWindow();
338
339 m_hWnd = NULL;
340
341 if (fDockSite)
342 fDockSite.Release();
343
344 if (m_himlNormal)
345 ImageList_Destroy(m_himlNormal);
346
347 if (m_himlHot)
348 ImageList_Destroy(m_himlHot);
349
350 return S_OK;
351 }
352
353 HRESULT STDMETHODCALLTYPE CToolsBand::ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved)
354 {
355 return E_NOTIMPL;
356 }
357
358 HRESULT STDMETHODCALLTYPE CToolsBand::ShowDW(BOOL fShow)
359 {
360 if (m_hWnd)
361 {
362 if (fShow)
363 ShowWindow(SW_SHOW);
364 else
365 ShowWindow(SW_HIDE);
366 }
367 return S_OK;
368 }
369
370 HRESULT STDMETHODCALLTYPE CToolsBand::HasFocusIO()
371 {
372 return S_FALSE;
373 }
374
375 HRESULT STDMETHODCALLTYPE CToolsBand::TranslateAcceleratorIO(LPMSG lpMsg)
376 {
377 return S_FALSE;
378 }
379
380 HRESULT STDMETHODCALLTYPE CToolsBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
381 {
382 return E_NOTIMPL;
383 }
384
385 HRESULT STDMETHODCALLTYPE CToolsBand::GetClassID(CLSID *pClassID)
386 {
387 return E_NOTIMPL;
388 }
389
390 HRESULT STDMETHODCALLTYPE CToolsBand::IsDirty()
391 {
392 return E_NOTIMPL;
393 }
394
395 HRESULT STDMETHODCALLTYPE CToolsBand::Load(IStream *pStm)
396 {
397 return E_NOTIMPL;
398 }
399
400 HRESULT STDMETHODCALLTYPE CToolsBand::Save(IStream *pStm, BOOL fClearDirty)
401 {
402 return E_NOTIMPL;
403 }
404
405 HRESULT STDMETHODCALLTYPE CToolsBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
406 {
407 return E_NOTIMPL;
408 }
409
410 LRESULT CToolsBand::OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
411 {
412 TBNOTIFYW *pTBntf = reinterpret_cast<TBNOTIFYW *>(pNMHDR);
413
414 if (pTBntf->iItem >= 0 && pTBntf->iItem < (numShownButtons + numHiddenButtons))
415 {
416 pTBntf->tbButton = tbButtonsAdd[pTBntf->iItem];
417 return TRUE;
418 }
419 else
420 return FALSE;
421 return 0;
422 }
423
424 HRESULT CToolsBand_CreateInstance(REFIID riid, void **ppv)
425 {
426 return ShellObjectCreator<CToolsBand>(riid, ppv);
427 }
428