xref: /reactos/dll/win32/browseui/toolsband.cpp (revision d09998df)
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     HIMAGELIST m_himlNormal;
42     HIMAGELIST m_himlHot;
43 public:
44     CToolsBand();
45     virtual ~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     : fDockSite(NULL)
99 {
100 }
101 
102 CToolsBand::~CToolsBand()
103 {
104 }
105 
106 HRESULT STDMETHODCALLTYPE CToolsBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
107 {
108     RECT actualRect;
109     POINTL actualSize;
110     POINTL idealSize;
111     POINTL maxSize;
112     POINTL itemSize;
113 
114     ::GetWindowRect(m_hWnd, &actualRect);
115     actualSize.x = actualRect.right - actualRect.left;
116     actualSize.y = actualRect.bottom - actualRect.top;
117 
118     /* Obtain the ideal size, to be used as min and max */
119     SendMessageW(m_hWnd, TB_AUTOSIZE, 0, 0);
120     SendMessageW(m_hWnd, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&maxSize));
121 
122     idealSize = maxSize;
123     SendMessageW(m_hWnd, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&idealSize));
124 
125     /* Obtain the button size, to be used as the integral size */
126     DWORD size = SendMessageW(m_hWnd, TB_GETBUTTONSIZE, 0, 0);
127     itemSize.x = GET_X_LPARAM(size);
128     itemSize.y = GET_Y_LPARAM(size);
129 
130     if (pdbi->dwMask & DBIM_MINSIZE)
131     {
132         pdbi->ptMinSize = idealSize;
133     }
134     if (pdbi->dwMask & DBIM_MAXSIZE)
135     {
136         pdbi->ptMaxSize = maxSize;
137     }
138     if (pdbi->dwMask & DBIM_INTEGRAL)
139     {
140         pdbi->ptIntegral = itemSize;
141     }
142     if (pdbi->dwMask & DBIM_ACTUAL)
143     {
144         pdbi->ptActual = actualSize;
145     }
146     if (pdbi->dwMask & DBIM_TITLE)
147         wcscpy(pdbi->wszTitle, L"");
148     if (pdbi->dwMask & DBIM_MODEFLAGS)
149         pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
150     if (pdbi->dwMask & DBIM_BKCOLOR)
151         pdbi->crBkgnd = 0;
152     return S_OK;
153 }
154 
155 static const int backImageIndex = 0;
156 static const int forwardImageIndex = 1;
157 static const int favoritesImageIndex = 2;
158 // 3
159 // 4
160 static const int cutImageIndex = 5;
161 static const int copyImageIndex = 6;
162 static const int pasteImageIndex = 7;
163 static const int undoImageIndex = 8;
164 //static const int redoImageIndex = 9;
165 static const int deleteImageIndex = 10;
166 // 11
167 // 12
168 // 13
169 // 14
170 static const int propertiesImageIndex = 15;
171 // 16
172 static const int searchImageIndex = 17;
173 // 18
174 // 19
175 // 20
176 // 21
177 static const int viewsImageIndex = 22;
178 // 23
179 // 24
180 // 25
181 // 26
182 // 27
183 static const int upImageIndex = 28;
184 static const int mapDriveImageIndex = 29;
185 static const int disconnectImageIndex = 30;
186 // 31
187 //static const int viewsAltImageIndex = 32;       // same image as viewsImageIndex
188 // 33
189 // 34
190 // 35
191 // 36
192 // 37
193 //static const int viewsAlt2ImageIndex = 38;      // same image as viewsAltImageIndex & viewsImageIndex
194 // 39
195 // 40
196 // 41
197 // 42
198 static const int foldersImageIndex = 43;
199 static const int moveToImageIndex = 44;
200 static const int copyToImageIndex = 45;
201 static const int folderOptionsImageIndex = 46;
202 
203 enum StandardToolbarButtons {
204     BtnIdx_Back = 0,
205     BtnIdx_Forward,
206     BtnIdx_Up,
207     BtnIdx_Search,
208     BtnIdx_Folders,
209     BtnIdx_MoveTo,
210     BtnIdx_CopyTo,
211     BtnIdx_Delete,
212     BtnIdx_Undo,
213     BtnIdx_Views,
214     BtnIdx_Stop,
215     BtnIdx_Refresh,
216     BtnIdx_Home,
217     BtnIdx_MapDrive,
218     BtnIdx_Disconnect,
219     BtnIdx_Favorites,
220     BtnIdx_History,
221     BtnIdx_FullScreen,
222     BtnIdx_Properties,
223     BtnIdx_Cut,
224     BtnIdx_Copy,
225     BtnIdx_Paste,
226     BtnIdx_FolderOptions,
227 };
228 
229 const int numShownButtons = 13;
230 const int numHiddenButtons = 13;
231 TBBUTTON tbButtonsAdd[numShownButtons + numHiddenButtons] =
232 {
233     { backImageIndex, IDM_GOTO_BACK, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Back },
234     { forwardImageIndex, IDM_GOTO_FORWARD, TBSTATE_ENABLED, BTNS_DROPDOWN, { 0 }, 0,          BtnIdx_Forward },
235     { upImageIndex, IDM_GOTO_UPONELEVEL, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0,                 BtnIdx_Up },
236     { 6, -1, TBSTATE_ENABLED, BTNS_SEP },
237     { searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Search },
238     { foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Folders },
239     { 6, -1, TBSTATE_ENABLED, BTNS_SEP },
240     { moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MoveTo },
241     { copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_CopyTo },
242     { deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Delete },
243     { undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Undo },
244     { 6, -1, TBSTATE_ENABLED, BTNS_SEP },
245     { viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, { 0 }, 0, BtnIdx_Views },
246 
247     { 0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Stop },
248     { 0, IDM_VIEW_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Refresh },
249     { 0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Home },
250     { mapDriveImageIndex, IDM_TOOLS_MAPNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MapDrive },
251     { disconnectImageIndex, IDM_TOOLS_DISCONNECTNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Disconnect },
252     { favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Favorites },
253     { 0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_History },
254     { 0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FullScreen },
255     { propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Properties },
256     { cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Cut },
257     { copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Copy },
258     { pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Paste },
259     { folderOptionsImageIndex, IDM_TOOLS_FOLDEROPTIONS, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FolderOptions },
260 };
261 
262 HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite){
263     HWND                    parentWindow;
264     HWND                    toolbar;
265     HRESULT                 hResult;
266 
267     if(fDockSite) fDockSite.Release();
268 
269     if (pUnkSite == NULL)
270         return S_OK;
271     hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fDockSite));
272     if (FAILED_UNEXPECTEDLY(hResult))
273         return hResult;
274     parentWindow = NULL;
275     hResult = IUnknown_GetWindow(pUnkSite, &parentWindow);
276     if (FAILED(hResult) || !::IsWindow(parentWindow))
277         return E_FAIL;
278 
279     toolbar = CreateWindowEx(
280                     TBSTYLE_EX_DOUBLEBUFFER,
281                     TOOLBARCLASSNAMEW, NULL,
282                     WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
283                     TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
284                     CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP,
285                     0, 0, 500, 20, parentWindow, NULL, _AtlBaseModule.GetModuleInstance(), 0);
286     if (toolbar == NULL)
287         return E_FAIL;
288     SubclassWindow(toolbar);
289     SendMessage(TB_ADDSTRINGW, (WPARAM) GetModuleHandle(L"browseui.dll"), IDS_STANDARD_TOOLBAR);
290 
291     SendMessage(WM_USER + 100, GetSystemMetrics(SM_CXEDGE) / 2, 0);
292     SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
293     SendMessage(TB_SETMAXTEXTROWS, 1, 0);
294     SendMessage(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
295 
296     m_himlNormal = ImageList_LoadImageW(_AtlBaseModule.GetResourceInstance(),
297                                         MAKEINTRESOURCE(IDB_SHELL_EXPLORER_LG),
298                                         0, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
299 
300     m_himlHot = ImageList_LoadImageW(_AtlBaseModule.GetResourceInstance(),
301                                      MAKEINTRESOURCE(IDB_SHELL_EXPLORER_LG_HOT),
302                                      0, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
303 
304     SendMessage(TB_SETIMAGELIST, 0, (LPARAM) m_himlNormal);
305     SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) m_himlHot);
306     SendMessage(TB_ADDBUTTONSW, numShownButtons, (LPARAM)&tbButtonsAdd);
307 
308     return hResult;
309 }
310 
311 HRESULT STDMETHODCALLTYPE CToolsBand::GetSite(REFIID riid, void **ppvSite)
312 {
313     if (fDockSite == NULL)
314         return E_FAIL;
315     return fDockSite->QueryInterface(riid, ppvSite);
316 }
317 
318 HRESULT STDMETHODCALLTYPE CToolsBand::GetWindow(HWND *lphwnd)
319 {
320     if (lphwnd == NULL)
321         return E_POINTER;
322     *lphwnd = m_hWnd;
323     return S_OK;
324 }
325 
326 HRESULT STDMETHODCALLTYPE CToolsBand::ContextSensitiveHelp(BOOL fEnterMode)
327 {
328     return E_NOTIMPL;
329 }
330 
331 HRESULT STDMETHODCALLTYPE CToolsBand::CloseDW(DWORD dwReserved)
332 {
333     ShowDW(FALSE);
334 
335     if (IsWindow())
336         DestroyWindow();
337 
338     m_hWnd = NULL;
339 
340     if (fDockSite)
341         fDockSite.Release();
342 
343     if (m_himlNormal)
344         ImageList_Destroy(m_himlNormal);
345 
346     if (m_himlHot)
347         ImageList_Destroy(m_himlHot);
348 
349     return S_OK;
350 }
351 
352 HRESULT STDMETHODCALLTYPE CToolsBand::ResizeBorderDW(const RECT* prcBorder, IUnknown* punkToolbarSite, BOOL fReserved)
353 {
354     return E_NOTIMPL;
355 }
356 
357 HRESULT STDMETHODCALLTYPE CToolsBand::ShowDW(BOOL fShow)
358 {
359     if (m_hWnd)
360     {
361         if (fShow)
362             ShowWindow(SW_SHOW);
363         else
364             ShowWindow(SW_HIDE);
365     }
366     return S_OK;
367 }
368 
369 HRESULT STDMETHODCALLTYPE CToolsBand::HasFocusIO()
370 {
371     return S_FALSE;
372 }
373 
374 HRESULT STDMETHODCALLTYPE CToolsBand::TranslateAcceleratorIO(LPMSG lpMsg)
375 {
376     return S_FALSE;
377 }
378 
379 HRESULT STDMETHODCALLTYPE CToolsBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
380 {
381     return E_NOTIMPL;
382 }
383 
384 HRESULT STDMETHODCALLTYPE CToolsBand::GetClassID(CLSID *pClassID)
385 {
386     return E_NOTIMPL;
387 }
388 
389 HRESULT STDMETHODCALLTYPE CToolsBand::IsDirty()
390 {
391     return E_NOTIMPL;
392 }
393 
394 HRESULT STDMETHODCALLTYPE CToolsBand::Load(IStream *pStm)
395 {
396     return E_NOTIMPL;
397 }
398 
399 HRESULT STDMETHODCALLTYPE CToolsBand::Save(IStream *pStm, BOOL fClearDirty)
400 {
401     return E_NOTIMPL;
402 }
403 
404 HRESULT STDMETHODCALLTYPE CToolsBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
405 {
406     return E_NOTIMPL;
407 }
408 
409 LRESULT CToolsBand::OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled)
410 {
411     TBNOTIFYW *pTBntf = reinterpret_cast<TBNOTIFYW *>(pNMHDR);
412 
413     if (pTBntf->iItem >= 0 && pTBntf->iItem < (numShownButtons + numHiddenButtons))
414     {
415         pTBntf->tbButton = tbButtonsAdd[pTBntf->iItem];
416         return TRUE;
417     }
418     else
419         return FALSE;
420     return 0;
421 }
422 
423 HRESULT CToolsBand_CreateInstance(REFIID riid, void **ppv)
424 {
425     return ShellObjectCreator<CToolsBand>(riid, ppv);
426 }
427 
428