[SHELL32]
[reactos.git] / dll / win32 / shell32 / CMenuBand.cpp
1 /*
2 * PROJECT: shell32
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/shell32/CMenuBand.c
5 * PURPOSE: menu band implementation
6 * PROGRAMMERS: Giannis Adamopoulos (gadamopoulos@reactos.org)
7 */
8
9 #include "precomp.h"
10
11 #include <windowsx.h>
12
13 WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
14
15
16 BOOL
17 AllocAndGetMenuString(HMENU hMenu, UINT ItemIDByPosition, WCHAR** String)
18 {
19 int Length;
20
21 Length = GetMenuStringW(hMenu, ItemIDByPosition, NULL, 0, MF_BYPOSITION);
22
23 if(!Length)
24 return FALSE;
25
26 /* Also allocate space for the terminating NULL character */
27 ++Length;
28 *String = (PWSTR)HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR));
29
30 GetMenuStringW(hMenu, ItemIDByPosition, *String, Length, MF_BYPOSITION);
31
32 return TRUE;
33 }
34
35 CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand)
36 {
37 m_menuBand = menuBand;
38
39
40 m_menuBand = NULL;
41 m_hwnd = NULL;
42 m_hmenu = NULL;
43 m_hwndOwner = NULL;
44 m_dwMenuFlags = NULL;
45 }
46
47 HRESULT CMenuStaticToolbar::GetMenu(
48 HMENU *phmenu,
49 HWND *phwnd,
50 DWORD *pdwFlags)
51 {
52 *phmenu = m_hmenu;
53 *phwnd = m_hwndOwner;
54 *pdwFlags = m_dwMenuFlags;
55
56 return S_OK;
57 }
58
59 HRESULT CMenuStaticToolbar::SetMenu(
60 HMENU hmenu,
61 HWND hwnd,
62 DWORD dwFlags)
63 {
64 if (!hwnd)
65 return E_FAIL;
66
67 m_hmenu = hmenu;
68 m_hwndOwner = hwnd;
69 m_dwMenuFlags = dwFlags;
70
71 return S_OK;
72 }
73
74 HRESULT CMenuStaticToolbar::ShowWindow(BOOL fShow)
75 {
76 ::ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
77
78 return S_OK;
79 }
80
81 HRESULT CMenuStaticToolbar::Close()
82 {
83 DestroyWindow(m_hwnd);
84 m_hwnd = NULL;
85 return S_OK;
86 }
87
88 HRESULT CMenuStaticToolbar::CreateToolbar(HWND hwndParent, DWORD dwFlags)
89 {
90 HWND hwndToolbar;
91 hwndToolbar = CreateWindowEx(TBSTYLE_EX_DOUBLEBUFFER, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
92 WS_CLIPCHILDREN | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
93 CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP, 0, 0, 500, 20, m_hwndOwner, NULL,
94 _AtlBaseModule.GetModuleInstance(), 0);
95 if (hwndToolbar == NULL)
96 return E_FAIL;
97
98 ::SetParent(hwndToolbar, hwndParent);
99
100 m_hwnd = hwndToolbar;
101
102 /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
103 SendMessageW(m_hwnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
104
105 if (dwFlags & SMINIT_TOPLEVEL)
106 {
107 /* Hide the placeholders for the button images */
108 SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
109 }
110
111 return S_OK;
112 }
113
114 HRESULT CMenuStaticToolbar::FillToolbar()
115 {
116 TBBUTTON tbb = {0};
117 int i;
118 PWSTR MenuString;
119
120 tbb.fsState = TBSTATE_ENABLED;
121 tbb.fsStyle = BTNS_DROPDOWN | BTNS_AUTOSIZE;
122
123 for(i = 0; i < GetMenuItemCount(m_hmenu); i++)
124 {
125 if(!AllocAndGetMenuString(m_hmenu, i, &MenuString))
126 return E_OUTOFMEMORY;
127
128 tbb.idCommand = i;
129 tbb.iString = (INT_PTR)MenuString;
130
131 SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, (LPARAM)(LPTBBUTTON)&tbb);
132 HeapFree(GetProcessHeap(), 0, MenuString);
133 }
134
135 return S_OK;
136 }
137
138 HRESULT CMenuStaticToolbar::GetWindow(HWND *phwnd)
139 {
140 if (!phwnd)
141 return E_FAIL;
142
143 *phwnd = m_hwnd;
144
145 return S_OK;
146 }
147
148 CMenuBand::CMenuBand()
149 {
150 m_site = NULL;
151 m_psmc = NULL;
152 m_staticToolbar = NULL;
153 }
154
155 CMenuBand::~CMenuBand()
156 {
157 if (m_site)
158 m_site->Release();
159
160 if (m_psmc)
161 m_psmc->Release();
162
163 if (m_staticToolbar)
164 delete m_staticToolbar;
165 }
166
167 HRESULT STDMETHODCALLTYPE CMenuBand::Initialize(
168 IShellMenuCallback *psmc,
169 UINT uId,
170 UINT uIdAncestor,
171 DWORD dwFlags)
172 {
173 if(m_psmc)
174 m_psmc->Release();
175
176 m_psmc = psmc;
177 m_uId = uId;
178 m_uIdAncestor = uIdAncestor;
179 m_dwFlags = dwFlags;
180
181 if (m_psmc)
182 m_psmc->AddRef();
183
184 return S_OK;
185 }
186
187 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenuInfo(
188 IShellMenuCallback **ppsmc,
189 UINT *puId,
190 UINT *puIdAncestor,
191 DWORD *pdwFlags)
192 {
193 *ppsmc = m_psmc;
194 *puId = m_uId;
195 *puIdAncestor = m_uIdAncestor;
196 *pdwFlags = m_dwFlags;
197
198 return S_OK;
199 }
200
201 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenu(
202 HMENU hmenu,
203 HWND hwnd,
204 DWORD dwFlags)
205 {
206 if (m_staticToolbar == NULL)
207 m_staticToolbar = new CMenuStaticToolbar(this);
208
209 HRESULT hResult = m_staticToolbar->SetMenu(hmenu, hwnd, dwFlags);
210 if (FAILED(hResult))
211 return hResult;
212
213 if (m_site)
214 {
215 HWND hwndParent;
216
217 hResult = m_site->GetWindow(&hwndParent);
218 if (FAILED(hResult))
219 return hResult;
220
221 hResult = m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
222 if (FAILED(hResult))
223 return hResult;
224
225 hResult = m_staticToolbar->FillToolbar();
226 }
227
228 return hResult;
229 }
230
231 HRESULT STDMETHODCALLTYPE CMenuBand::GetMenu(
232 HMENU *phmenu,
233 HWND *phwnd,
234 DWORD *pdwFlags)
235 {
236 if (m_staticToolbar == NULL)
237 return E_FAIL;
238
239 return m_staticToolbar->GetMenu(phmenu, phwnd, pdwFlags);
240 }
241
242 HRESULT STDMETHODCALLTYPE CMenuBand::SetSite(IUnknown *pUnkSite)
243 {
244 HWND hwndParent;
245 HRESULT hResult;
246
247 if (m_site != NULL)
248 m_site->Release();
249
250 if (pUnkSite == NULL)
251 return S_OK;
252
253 hwndParent = NULL;
254 hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
255 if (SUCCEEDED(hResult))
256 {
257 m_site->GetWindow(&hwndParent);
258 m_site->Release();
259 }
260 if (!::IsWindow(hwndParent))
261 return E_FAIL;
262
263 if (m_staticToolbar != NULL)
264 {
265 m_staticToolbar->CreateToolbar(hwndParent, m_dwFlags);
266 m_staticToolbar->FillToolbar();
267 }
268
269 return S_OK;
270 }
271
272 HRESULT STDMETHODCALLTYPE CMenuBand::GetSite(REFIID riid, PVOID *ppvSite)
273 {
274 if (m_site == NULL)
275 return E_FAIL;
276
277 return m_site->QueryInterface(riid, ppvSite);
278 }
279
280 HRESULT STDMETHODCALLTYPE CMenuBand::GetWindow(
281 HWND *phwnd)
282 {
283 if (m_staticToolbar != NULL)
284 return m_staticToolbar->GetWindow(phwnd);
285
286 return E_FAIL;
287 }
288
289 HRESULT STDMETHODCALLTYPE CMenuBand::GetBandInfo(
290 DWORD dwBandID,
291 DWORD dwViewMode,
292 DESKBANDINFO *pdbi)
293 {
294 SIZE size;
295 HWND hwnd;
296 HRESULT hResult;
297
298 /* FIXME */
299 if (m_staticToolbar == NULL)
300 return E_FAIL;
301 hResult = m_staticToolbar->GetWindow(&hwnd);
302 if (FAILED(hResult))
303 return hResult;
304 if (hwnd == NULL)
305 return E_FAIL;
306
307 if (pdbi->dwMask & DBIM_MINSIZE)
308 {
309 SendMessageW( hwnd, TB_GETIDEALSIZE, TRUE, (LPARAM)&size);
310
311 pdbi->ptMinSize.x = 0;
312 pdbi->ptMinSize.y = size.cy;
313 }
314 if (pdbi->dwMask & DBIM_MAXSIZE)
315 {
316 SendMessageW( hwnd, TB_GETMAXSIZE, 0, (LPARAM)&size);
317
318 pdbi->ptMaxSize.x = size.cx;
319 pdbi->ptMaxSize.y = size.cy;
320 }
321 if (pdbi->dwMask & DBIM_INTEGRAL)
322 {
323 pdbi->ptIntegral.x = 0;
324 pdbi->ptIntegral.y = 0;
325 }
326 if (pdbi->dwMask & DBIM_ACTUAL)
327 {
328 SendMessageW( hwnd, TB_GETIDEALSIZE, TRUE, (LPARAM)&size);
329 SendMessageW( hwnd, TB_GETIDEALSIZE, FALSE, (LPARAM)&size);
330
331 pdbi->ptActual.x = size.cx;
332 pdbi->ptActual.y = size.cy;
333 }
334 if (pdbi->dwMask & DBIM_TITLE)
335 wcscpy(pdbi->wszTitle, L"");
336 if (pdbi->dwMask & DBIM_MODEFLAGS)
337 pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
338 if (pdbi->dwMask & DBIM_BKCOLOR)
339 pdbi->crBkgnd = 0;
340 return S_OK;
341 }
342
343 /* IDockingWindow */
344 HRESULT STDMETHODCALLTYPE CMenuBand::ShowDW(BOOL fShow)
345 {
346 if (m_staticToolbar != NULL)
347 return m_staticToolbar->ShowWindow(fShow);
348
349 return E_FAIL;
350 }
351
352 HRESULT STDMETHODCALLTYPE CMenuBand::CloseDW(DWORD dwReserved)
353 {
354 ShowDW(FALSE);
355
356 if (m_staticToolbar != NULL)
357 return m_staticToolbar->Close();
358
359 return S_OK;
360 }
361 HRESULT STDMETHODCALLTYPE CMenuBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
362 {
363 UNIMPLEMENTED;
364 return S_OK;
365 }
366
367 HRESULT STDMETHODCALLTYPE CMenuBand::ContextSensitiveHelp(BOOL fEnterMode)
368 {
369 UNIMPLEMENTED;
370 return S_OK;
371 }
372
373 HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
374 {
375 UNIMPLEMENTED;
376 return S_OK;
377 }
378
379 HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
380 {
381 UNIMPLEMENTED;
382 return S_OK;
383 }
384
385 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateAcceleratorIO(LPMSG lpMsg)
386 {
387 UNIMPLEMENTED;
388 return S_OK;
389 }
390
391 HRESULT STDMETHODCALLTYPE CMenuBand::IsDirty()
392 {
393 UNIMPLEMENTED;
394 return S_OK;
395 }
396
397 HRESULT STDMETHODCALLTYPE CMenuBand::Load(IStream *pStm)
398 {
399 UNIMPLEMENTED;
400 return S_OK;
401 }
402
403 HRESULT STDMETHODCALLTYPE CMenuBand::Save(IStream *pStm, BOOL fClearDirty)
404 {
405 UNIMPLEMENTED;
406 return S_OK;
407 }
408
409 HRESULT STDMETHODCALLTYPE CMenuBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
410 {
411 UNIMPLEMENTED;
412 return S_OK;
413 }
414
415 HRESULT STDMETHODCALLTYPE CMenuBand::GetClassID(CLSID *pClassID)
416 {
417 UNIMPLEMENTED;
418 return S_OK;
419 }
420
421 HRESULT STDMETHODCALLTYPE CMenuBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText)
422 {
423 UNIMPLEMENTED;
424 return S_OK;
425 }
426
427 HRESULT STDMETHODCALLTYPE CMenuBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
428 {
429 UNIMPLEMENTED;
430 return S_OK;
431 }
432
433 HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
434 {
435 UNIMPLEMENTED;
436 return S_OK;
437 }
438
439 HRESULT STDMETHODCALLTYPE CMenuBand::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
440 {
441 UNIMPLEMENTED;
442 return S_OK;
443 }
444
445 HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
446 {
447 UNIMPLEMENTED;
448 return S_OK;
449 }
450
451 HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
452 {
453 UNIMPLEMENTED;
454 return S_OK;
455 }
456
457 HRESULT STDMETHODCALLTYPE CMenuBand::SetClient(IUnknown *punkClient)
458 {
459 UNIMPLEMENTED;
460 return S_OK;
461 }
462
463 HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
464 {
465 UNIMPLEMENTED;
466 return S_OK;
467 }
468
469 HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
470 {
471 UNIMPLEMENTED;
472 return S_OK;
473 }
474
475 HRESULT STDMETHODCALLTYPE CMenuBand::IsMenuMessage(MSG *pmsg)
476 {
477 UNIMPLEMENTED;
478 return S_OK;
479 }
480
481 HRESULT STDMETHODCALLTYPE CMenuBand::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet)
482 {
483 UNIMPLEMENTED;
484 return S_FALSE;
485 }
486
487 HRESULT STDMETHODCALLTYPE CMenuBand::SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags)
488 {
489 UNIMPLEMENTED;
490 return S_OK;
491 }
492
493 HRESULT STDMETHODCALLTYPE CMenuBand::GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv)
494 {
495 UNIMPLEMENTED;
496 return S_OK;
497 }
498
499 HRESULT STDMETHODCALLTYPE CMenuBand::InvalidateItem(LPSMDATA psmd, DWORD dwFlags)
500 {
501 UNIMPLEMENTED;
502 return S_OK;
503 }
504
505 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(LPSMDATA psmd)
506 {
507 UNIMPLEMENTED;
508 return S_OK;
509 }
510
511 HRESULT STDMETHODCALLTYPE CMenuBand::SetMenuToolbar(IUnknown *punk, DWORD dwFlags)
512 {
513 UNIMPLEMENTED;
514 return S_OK;
515 }
516
517 HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
518 {
519 UNIMPLEMENTED;
520 return S_OK;
521 }
522
523 HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
524 {
525 UNIMPLEMENTED;
526 return S_OK;
527 }
528
529 HRESULT STDMETHODCALLTYPE CMenuBand::GetSubMenu(THIS)
530 {
531 UNIMPLEMENTED;
532 return S_OK;
533 }
534
535 HRESULT STDMETHODCALLTYPE CMenuBand::SetToolbar(THIS)
536 {
537 UNIMPLEMENTED;
538 return S_OK;
539 }
540
541 HRESULT STDMETHODCALLTYPE CMenuBand::SetMinWidth(THIS)
542 {
543 UNIMPLEMENTED;
544 return S_OK;
545 }
546
547 HRESULT STDMETHODCALLTYPE CMenuBand::SetNoBorder(THIS)
548 {
549 UNIMPLEMENTED;
550 return S_OK;
551 }
552
553 HRESULT STDMETHODCALLTYPE CMenuBand::SetTheme(THIS)
554 {
555 UNIMPLEMENTED;
556 return S_OK;
557 }
558
559 HRESULT STDMETHODCALLTYPE CMenuBand::GetTop(THIS)
560 {
561 UNIMPLEMENTED;
562 return S_OK;
563 }
564
565 HRESULT STDMETHODCALLTYPE CMenuBand::GetBottom(THIS)
566 {
567 UNIMPLEMENTED;
568 return S_OK;
569 }
570
571 HRESULT STDMETHODCALLTYPE CMenuBand::GetTracked(THIS)
572 {
573 UNIMPLEMENTED;
574 return S_OK;
575 }
576
577 HRESULT STDMETHODCALLTYPE CMenuBand::GetParentSite(THIS)
578 {
579 UNIMPLEMENTED;
580 return S_OK;
581 }
582
583 HRESULT STDMETHODCALLTYPE CMenuBand::GetState(THIS)
584 {
585 UNIMPLEMENTED;
586 return S_OK;
587 }
588
589 HRESULT STDMETHODCALLTYPE CMenuBand::DoDefaultAction(THIS)
590 {
591 UNIMPLEMENTED;
592 return S_OK;
593 }
594
595 HRESULT STDMETHODCALLTYPE CMenuBand::IsEmpty(THIS)
596 {
597 UNIMPLEMENTED;
598 return S_OK;
599 }
600