Reactos
1/*
2 * PROJECT: ReactOS Explorer
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: AppBar implementation
5 * COPYRIGHT: Copyright 2008 Vincent Povirk for CodeWeavers
6 * Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
9#include "precomp.h"
10#include "appbar.h"
11
12CAppBarManager::CAppBarManager()
13 : m_hAppBarDPA(NULL)
14 , m_ahwndAutoHideBars { 0 }
15{
16}
17
18CAppBarManager::~CAppBarManager()
19{
20 DestroyAppBarDPA();
21}
22
23PAPPBAR CAppBarManager::FindAppBar(_In_ HWND hwndAppBar) const
24{
25 if (!m_hAppBarDPA)
26 return NULL;
27
28 INT nItems = DPA_GetPtrCount(m_hAppBarDPA);
29 while (--nItems >= 0)
30 {
31 PAPPBAR pAppBar = (PAPPBAR)DPA_GetPtr(m_hAppBarDPA, nItems);
32 if (pAppBar && hwndAppBar == pAppBar->hWnd)
33 return pAppBar;
34 }
35
36 return NULL;
37}
38
39void CAppBarManager::EliminateAppBar(_In_ INT iItem)
40{
41 LocalFree(DPA_GetPtr(m_hAppBarDPA, iItem));
42 DPA_DeletePtr(m_hAppBarDPA, iItem);
43}
44
45void CAppBarManager::DestroyAppBarDPA()
46{
47 if (!m_hAppBarDPA)
48 return;
49
50 INT nItems = DPA_GetPtrCount(m_hAppBarDPA);
51 while (--nItems >= 0)
52 {
53 ::LocalFree(DPA_GetPtr(m_hAppBarDPA, nItems));
54 }
55
56 DPA_Destroy(m_hAppBarDPA);
57 m_hAppBarDPA = NULL;
58}
59
60// ABM_NEW
61BOOL CAppBarManager::OnAppBarNew(_In_ const APPBAR_COMMAND *pData)
62{
63 HWND hWnd = (HWND)UlongToHandle(pData->abd.hWnd32);
64
65 if (m_hAppBarDPA)
66 {
67 if (FindAppBar(hWnd))
68 {
69 ERR("Already exists: %p\n", hWnd);
70 return FALSE;
71 }
72 }
73 else
74 {
75 const UINT c_nGrow = 4;
76 m_hAppBarDPA = DPA_Create(c_nGrow);
77 if (!m_hAppBarDPA)
78 {
79 ERR("Out of memory\n");
80 return FALSE;
81 }
82 }
83
84 PAPPBAR pAppBar = (PAPPBAR)::LocalAlloc(LPTR, sizeof(*pAppBar));
85 if (pAppBar)
86 {
87 pAppBar->hWnd = hWnd;
88 pAppBar->uEdge = UINT_MAX;
89 pAppBar->uCallbackMessage = pData->abd.uCallbackMessage;
90 if (DPA_InsertPtr(m_hAppBarDPA, INT_MAX, pAppBar) >= 0)
91 return TRUE; // Success!
92
93 ::LocalFree(pAppBar);
94 }
95
96 ERR("Out of memory\n");
97 return FALSE;
98}
99
100// ABM_REMOVE
101void CAppBarManager::OnAppBarRemove(_In_ const APPBAR_COMMAND *pData)
102{
103 if (!m_hAppBarDPA)
104 return;
105
106 HWND hWnd = (HWND)UlongToHandle(pData->abd.hWnd32);
107 INT nItems = DPA_GetPtrCount(m_hAppBarDPA);
108 while (--nItems >= 0)
109 {
110 PAPPBAR pAppBar = (PAPPBAR)DPA_GetPtr(m_hAppBarDPA, nItems);
111 if (!pAppBar)
112 continue;
113
114 if (pAppBar->hWnd == hWnd)
115 {
116 RECT rcOld = pAppBar->rc;
117 EliminateAppBar(nItems);
118 StuckAppChange(hWnd, &rcOld, NULL, FALSE);
119 }
120 }
121}
122
123// ABM_QUERYPOS
124void CAppBarManager::OnAppBarQueryPos(_Inout_ PAPPBAR_COMMAND pData)
125{
126 HWND hWnd = (HWND)UlongToHandle(pData->abd.hWnd32);
127 PAPPBAR pAppBar1 = FindAppBar(hWnd);
128 if (!pAppBar1)
129 {
130 ERR("Not found: %p\n", hWnd);
131 return;
132 }
133
134 PAPPBARDATAINTEROP pOutput = AppBar_LockOutput(pData);
135 if (!pOutput)
136 {
137 ERR("!pOutput: %d\n", pData->dwProcessId);
138 return;
139 }
140 pOutput->rc = pData->abd.rc;
141
142 if (::IsRectEmpty(&pOutput->rc))
143 ERR("IsRectEmpty\n");
144
145 HMONITOR hMon1 = ::MonitorFromRect(&pOutput->rc, MONITOR_DEFAULTTOPRIMARY);
146 ASSERT(hMon1 != NULL);
147
148 // Subtract tray rectangle from pOutput->rc if necessary
149 if (hMon1 == GetMonitor() && !IsAutoHideState())
150 {
151 APPBAR dummyAppBar;
152 dummyAppBar.uEdge = GetPosition();
153 GetDockedRect(&dummyAppBar.rc);
154 AppBarSubtractRect(&dummyAppBar, &pOutput->rc);
155 }
156
157 // Subtract area from pOutput->rc
158 UINT uEdge = pData->abd.uEdge;
159 INT nItems = DPA_GetPtrCount(m_hAppBarDPA);
160 while (--nItems >= 0)
161 {
162 PAPPBAR pAppBar2 = (PAPPBAR)DPA_GetPtr(m_hAppBarDPA, nItems);
163 if (!pAppBar2 || pAppBar1->hWnd == pAppBar2->hWnd)
164 continue;
165
166 if ((Edge_IsVertical(uEdge) || !Edge_IsVertical(pAppBar2->uEdge)) &&
167 (pAppBar1->uEdge != uEdge || !AppBarOutsideOf(pAppBar1, pAppBar2)))
168 {
169 if (pAppBar1->uEdge == uEdge || pAppBar2->uEdge != uEdge)
170 continue;
171 }
172
173 HMONITOR hMon2 = ::MonitorFromRect(&pAppBar2->rc, MONITOR_DEFAULTTONULL);
174 if (hMon1 == hMon2)
175 AppBarSubtractRect(pAppBar2, &pOutput->rc);
176 }
177
178 AppBar_UnLockOutput(pOutput);
179}
180
181// ABM_SETPOS
182void CAppBarManager::OnAppBarSetPos(_Inout_ PAPPBAR_COMMAND pData)
183{
184 HWND hWnd = (HWND)UlongToHandle(pData->abd.hWnd32);
185 PAPPBAR pAppBar = FindAppBar(hWnd);
186 if (!pAppBar)
187 return;
188
189 OnAppBarQueryPos(pData);
190
191 PAPPBARDATAINTEROP pOutput = AppBar_LockOutput(pData);
192 if (!pOutput)
193 return;
194
195 RECT rcOld = pAppBar->rc, rcNew = pData->abd.rc;
196 BOOL bChanged = !::EqualRect(&rcOld, &rcNew);
197
198 pAppBar->rc = rcNew;
199 pAppBar->uEdge = pData->abd.uEdge;
200
201 AppBar_UnLockOutput(pOutput);
202
203 if (bChanged)
204 StuckAppChange(hWnd, &rcOld, &rcNew, FALSE);
205}
206
207void CAppBarManager::OnAppBarNotifyAll(
208 _In_opt_ HMONITOR hMon,
209 _In_opt_ HWND hwndIgnore,
210 _In_ DWORD dwNotify,
211 _In_opt_ LPARAM lParam)
212{
213 TRACE("%p, %p, 0x%X, %p\n", hMon, hwndIgnore, dwNotify, lParam);
214
215 if (!m_hAppBarDPA)
216 return;
217
218 INT nItems = DPA_GetPtrCount(m_hAppBarDPA);
219 while (--nItems >= 0)
220 {
221 PAPPBAR pAppBar = (PAPPBAR)DPA_GetPtr(m_hAppBarDPA, nItems);
222 if (!pAppBar || pAppBar->hWnd == hwndIgnore)
223 continue;
224
225 HWND hwndAppBar = pAppBar->hWnd;
226 if (!::IsWindow(hwndAppBar))
227 {
228 EliminateAppBar(nItems);
229 continue;
230 }
231
232 if (!hMon || hMon == ::MonitorFromWindow(hwndAppBar, MONITOR_DEFAULTTONULL))
233 ::PostMessageW(hwndAppBar, pAppBar->uCallbackMessage, dwNotify, lParam);
234 }
235}
236
237/// @param pAppBar The target AppBar to subtract.
238/// @param prc The rectangle to be subtracted.
239void CAppBarManager::AppBarSubtractRect(_In_ PAPPBAR pAppBar, _Inout_ PRECT prc)
240{
241 switch (pAppBar->uEdge)
242 {
243 case ABE_LEFT: prc->left = max(prc->left, pAppBar->rc.right); break;
244 case ABE_TOP: prc->top = max(prc->top, pAppBar->rc.bottom); break;
245 case ABE_RIGHT: prc->right = min(prc->right, pAppBar->rc.left); break;
246 case ABE_BOTTOM: prc->bottom = min(prc->bottom, pAppBar->rc.top); break;
247 default:
248 ASSERT(FALSE);
249 break;
250 }
251}
252
253// Is pAppBar1 outside of pAppBar2?
254BOOL CAppBarManager::AppBarOutsideOf(
255 _In_ const APPBAR *pAppBar1,
256 _In_ const APPBAR *pAppBar2)
257{
258 if (pAppBar1->uEdge != pAppBar2->uEdge)
259 return FALSE;
260
261 switch (pAppBar2->uEdge)
262 {
263 case ABE_LEFT: return pAppBar1->rc.left >= pAppBar2->rc.left;
264 case ABE_TOP: return pAppBar1->rc.top >= pAppBar2->rc.top;
265 case ABE_RIGHT: return pAppBar1->rc.right <= pAppBar2->rc.right;
266 case ABE_BOTTOM: return pAppBar1->rc.bottom <= pAppBar2->rc.bottom;
267 default:
268 ASSERT(FALSE);
269 return FALSE;
270 }
271}
272
273/// Get rectangle of the tray window.
274/// @param prcDocked The pointer to the rectangle to be received.
275void CAppBarManager::GetDockedRect(_Out_ PRECT prcDocked)
276{
277 *prcDocked = *GetTrayRect();
278 if (IsAutoHideState() && IsHidingState())
279 ComputeHiddenRect(prcDocked, GetPosition());
280}
281
282/// Compute the position and size of the hidden TaskBar.
283/// @param prc The rectangle before hiding TaskBar.
284/// @param uSide The side of TaskBar (ABE_...).
285void CAppBarManager::ComputeHiddenRect(_Inout_ PRECT prc, _In_ UINT uSide)
286{
287 MONITORINFO mi = { sizeof(mi) };
288 HMONITOR hMonitor = ::MonitorFromRect(prc, MONITOR_DEFAULTTONULL);
289 if (!::GetMonitorInfoW(hMonitor, &mi))
290 return;
291 RECT rcMon = mi.rcMonitor;
292
293 INT cxy = Edge_IsVertical(uSide) ? (prc->bottom - prc->top) : (prc->right - prc->left);
294 switch (uSide)
295 {
296 case ABE_LEFT:
297 prc->right = rcMon.left + GetSystemMetrics(SM_CXFRAME) / 2;
298 prc->left = prc->right - cxy;
299 break;
300 case ABE_TOP:
301 prc->bottom = rcMon.top + GetSystemMetrics(SM_CYFRAME) / 2;
302 prc->top = prc->bottom - cxy;
303 break;
304 case ABE_RIGHT:
305 prc->left = rcMon.right - GetSystemMetrics(SM_CXFRAME) / 2;
306 prc->right = prc->left + cxy;
307 break;
308 case ABE_BOTTOM:
309 prc->top = rcMon.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
310 prc->bottom = prc->top + cxy;
311 break;
312 default:
313 ASSERT(FALSE);
314 break;
315 }
316}
317
318/// This function is called when AppBar and/or TaskBar is being moved, removed, and/or updated.
319/// @param hwndTarget The target window. Optional.
320/// @param prcOld The old position and size. Optional.
321/// @param prcNew The new position and size. Optional.
322/// @param bTray TRUE if the tray is being moved.
323void
324CAppBarManager::StuckAppChange(
325 _In_opt_ HWND hwndTarget,
326 _In_opt_ const RECT *prcOld,
327 _In_opt_ const RECT *prcNew,
328 _In_ BOOL bTray)
329{
330 RECT rcWorkArea1, rcWorkArea2;
331 HMONITOR hMon1 = NULL;
332 UINT flags = 0;
333 enum { SET_WORKAREA_1 = 1, SET_WORKAREA_2 = 2, NEED_SIZING = 4 }; // for flags
334
335 if (prcOld)
336 {
337 hMon1 = (bTray ? GetPreviousMonitor() : ::MonitorFromRect(prcOld, MONITOR_DEFAULTTONEAREST));
338 if (hMon1)
339 {
340 WORKAREA_TYPE type1 = RecomputeWorkArea(GetTrayRect(), hMon1, &rcWorkArea1);
341 if (type1 == WORKAREA_IS_NOT_MONITOR)
342 flags = SET_WORKAREA_1;
343 if (type1 == WORKAREA_SAME_AS_MONITOR)
344 flags = NEED_SIZING;
345 }
346 }
347
348 if (prcNew)
349 {
350 HMONITOR hMon2 = ::MonitorFromRect(prcNew, MONITOR_DEFAULTTONULL);
351 if (hMon2 && hMon2 != hMon1)
352 {
353 WORKAREA_TYPE type2 = RecomputeWorkArea(GetTrayRect(), hMon2, &rcWorkArea2);
354 if (type2 == WORKAREA_IS_NOT_MONITOR)
355 flags |= SET_WORKAREA_2;
356 else if (type2 == WORKAREA_SAME_AS_MONITOR && !flags)
357 flags = NEED_SIZING;
358 }
359 }
360
361 if (flags & SET_WORKAREA_1)
362 {
363 UINT fWinIni = ((flags == SET_WORKAREA_1 && GetDesktopWnd()) ? SPIF_SENDCHANGE : 0);
364 ::SystemParametersInfoW(SPI_SETWORKAREA, TRUE, &rcWorkArea1, fWinIni);
365 RedrawDesktop(GetDesktopWnd(), &rcWorkArea1);
366 }
367
368 if (flags & SET_WORKAREA_2)
369 {
370 UINT fWinIni = (GetDesktopWnd() ? SPIF_SENDCHANGE : 0);
371 ::SystemParametersInfoW(SPI_SETWORKAREA, TRUE, &rcWorkArea2, fWinIni);
372 RedrawDesktop(GetDesktopWnd(), &rcWorkArea2);
373 }
374
375 if (bTray || flags == NEED_SIZING)
376 ::SendMessageW(GetDesktopWnd(), WM_SIZE, 0, 0);
377
378 // Post ABN_POSCHANGED messages to AppBar windows
379 OnAppBarNotifyAll(NULL, hwndTarget, ABN_POSCHANGED, TRUE);
380}
381
382void CAppBarManager::RedrawDesktop(_In_ HWND hwndDesktop, _Inout_ PRECT prc)
383{
384 if (!hwndDesktop)
385 return;
386 ::MapWindowPoints(NULL, hwndDesktop, (POINT*)prc, sizeof(*prc) / sizeof(POINT));
387 ::RedrawWindow(hwndDesktop, prc, 0, RDW_ALLCHILDREN | RDW_ERASE | RDW_INVALIDATE);
388}
389
390/// Re-compute the work area.
391/// @param prcTray The position and size of the tray window
392/// @param hMonitor The monitor of the work area to re-compute.
393/// @param prcWorkArea The work area to be re-computed.
394WORKAREA_TYPE
395CAppBarManager::RecomputeWorkArea(
396 _In_ const RECT *prcTray,
397 _In_ HMONITOR hMonitor,
398 _Out_ PRECT prcWorkArea)
399{
400 MONITORINFO mi = { sizeof(mi) };
401 if (!::GetMonitorInfoW(hMonitor, &mi))
402 return WORKAREA_NO_TRAY_AREA;
403
404 if (IsAutoHideState())
405 *prcWorkArea = mi.rcMonitor;
406 else
407 ::SubtractRect(prcWorkArea, &mi.rcMonitor, prcTray);
408
409 if (m_hAppBarDPA)
410 {
411 INT nItems = DPA_GetPtrCount(m_hAppBarDPA);
412 while (--nItems >= 0)
413 {
414 PAPPBAR pAppBar = (PAPPBAR)DPA_GetPtr(m_hAppBarDPA, nItems);
415 if (pAppBar && hMonitor == ::MonitorFromRect(&pAppBar->rc, MONITOR_DEFAULTTONULL))
416 AppBarSubtractRect(pAppBar, prcWorkArea);
417 }
418 }
419
420 if (!::EqualRect(prcWorkArea, &mi.rcWork))
421 return WORKAREA_IS_NOT_MONITOR;
422
423 if (IsAutoHideState() || ::IsRectEmpty(prcTray))
424 return WORKAREA_NO_TRAY_AREA;
425
426 return WORKAREA_SAME_AS_MONITOR;
427}
428
429BOOL CALLBACK
430CAppBarManager::MonitorEnumProc(
431 _In_ HMONITOR hMonitor,
432 _In_ HDC hDC,
433 _In_ LPRECT prc,
434 _Inout_ LPARAM lParam)
435{
436 CAppBarManager *pThis = (CAppBarManager *)lParam;
437 UNREFERENCED_PARAMETER(hDC);
438
439 RECT rcWorkArea;
440 if (pThis->RecomputeWorkArea(prc, hMonitor, &rcWorkArea) != WORKAREA_IS_NOT_MONITOR)
441 return TRUE;
442
443 HWND hwndDesktop = pThis->GetDesktopWnd();
444 ::SystemParametersInfoW(SPI_SETWORKAREA, 0, &rcWorkArea, hwndDesktop ? SPIF_SENDCHANGE : 0);
445 pThis->RedrawDesktop(hwndDesktop, &rcWorkArea);
446 return TRUE;
447}
448
449void CAppBarManager::RecomputeAllWorkareas()
450{
451 ::EnumDisplayMonitors(NULL, NULL, CAppBarManager::MonitorEnumProc, (LPARAM)this);
452}
453
454BOOL CAppBarManager::SetAutoHideBar(_In_ HWND hwndTarget, _In_ BOOL bSetOrReset, _In_ UINT uSide)
455{
456 ATLASSERT(uSide < _countof(m_ahwndAutoHideBars));
457 HWND *phwndAutoHide = &m_ahwndAutoHideBars[uSide];
458 if (!IsWindow(*phwndAutoHide))
459 *phwndAutoHide = NULL;
460
461 if (bSetOrReset) // Set?
462 {
463 if (!*phwndAutoHide)
464 *phwndAutoHide = hwndTarget;
465 return *phwndAutoHide == hwndTarget;
466 }
467 else // Reset
468 {
469 if (*phwndAutoHide == hwndTarget)
470 *phwndAutoHide = NULL;
471 return TRUE;
472 }
473}
474
475void CAppBarManager::OnAppBarActivationChange2(_In_ HWND hwndNewAutoHide, _In_ UINT uSide)
476{
477 HWND hwndAutoHideBar = OnAppBarGetAutoHideBar(uSide);
478 if (hwndAutoHideBar && hwndAutoHideBar != hwndNewAutoHide)
479 ::PostMessageW(GetTrayWnd(), TWM_SETZORDER, (WPARAM)hwndAutoHideBar, uSide);
480}
481
482PAPPBAR_COMMAND
483CAppBarManager::GetAppBarMessage(_Inout_ PCOPYDATASTRUCT pCopyData)
484{
485 PAPPBAR_COMMAND pData = (PAPPBAR_COMMAND)pCopyData->lpData;
486
487 if (pCopyData->cbData != sizeof(*pData) || pData->abd.cbSize != sizeof(pData->abd))
488 {
489 ERR("Invalid AppBar message\n");
490 return NULL;
491 }
492
493 return pData;
494}
495
496// ABM_GETSTATE
497UINT CAppBarManager::OnAppBarGetState()
498{
499 return (IsAutoHideState() ? ABS_AUTOHIDE : 0) | (IsAlwaysOnTop() ? ABS_ALWAYSONTOP : 0);
500}
501
502// ABM_GETTASKBARPOS
503BOOL CAppBarManager::OnAppBarGetTaskbarPos(_Inout_ PAPPBAR_COMMAND pData)
504{
505 PAPPBARDATAINTEROP pOutput = AppBar_LockOutput(pData);
506 if (!pOutput)
507 {
508 ERR("!pOutput: %d\n", pData->dwProcessId);
509 return FALSE;
510 }
511
512 pOutput->rc = *GetTrayRect();
513 pOutput->uEdge = GetPosition();
514
515 AppBar_UnLockOutput(pOutput);
516 return TRUE;
517}
518
519// ABM_ACTIVATE, ABM_WINDOWPOSCHANGED
520void CAppBarManager::OnAppBarActivationChange(_In_ const APPBAR_COMMAND *pData)
521{
522 HWND hWnd = (HWND)UlongToHandle(pData->abd.hWnd32);
523 PAPPBAR pAppBar = FindAppBar(hWnd);
524 if (!pAppBar)
525 {
526 ERR("Not found: %p\n", hWnd);
527 return;
528 }
529
530 HWND hwndAppBar = pAppBar->hWnd;
531 for (UINT uSide = ABE_LEFT; uSide <= ABE_BOTTOM; ++uSide)
532 {
533 if (m_ahwndAutoHideBars[uSide] == hwndAppBar && uSide != pAppBar->uEdge)
534 return;
535 }
536
537 OnAppBarActivationChange2(hwndAppBar, pAppBar->uEdge);
538}
539
540// ABM_GETAUTOHIDEBAR
541HWND CAppBarManager::OnAppBarGetAutoHideBar(_In_ UINT uSide)
542{
543 if (uSide >= _countof(m_ahwndAutoHideBars))
544 return NULL;
545
546 if (!::IsWindow(m_ahwndAutoHideBars[uSide]))
547 m_ahwndAutoHideBars[uSide] = NULL;
548 return m_ahwndAutoHideBars[uSide];
549}
550
551// ABM_SETAUTOHIDEBAR
552BOOL CAppBarManager::OnAppBarSetAutoHideBar(_In_ const APPBAR_COMMAND *pData)
553{
554 if (pData->abd.uEdge >= _countof(m_ahwndAutoHideBars))
555 return FALSE;
556 HWND hwndTarget = (HWND)UlongToHandle(pData->abd.hWnd32);
557 return SetAutoHideBar(hwndTarget, (BOOL)pData->abd.lParam64, pData->abd.uEdge);
558}
559
560// ABM_SETSTATE
561void CAppBarManager::OnAppBarSetState(_In_ UINT uState)
562{
563 if ((uState & ~(ABS_AUTOHIDE | ABS_ALWAYSONTOP)))
564 return;
565
566 SetAutoHideState(!!(uState & ABS_AUTOHIDE));
567 UpdateAlwaysOnTop(!!(uState & ABS_ALWAYSONTOP));
568}
569
570// WM_COPYDATA TABDMC_APPBAR
571LRESULT CAppBarManager::OnAppBarMessage(_Inout_ PCOPYDATASTRUCT pCopyData)
572{
573 PAPPBAR_COMMAND pData = GetAppBarMessage(pCopyData);
574 if (!pData)
575 return 0;
576
577 switch (pData->dwMessage)
578 {
579 case ABM_NEW:
580 return OnAppBarNew(pData);
581 case ABM_REMOVE:
582 OnAppBarRemove(pData);
583 break;
584 case ABM_QUERYPOS:
585 OnAppBarQueryPos(pData);
586 break;
587 case ABM_SETPOS:
588 OnAppBarSetPos(pData);
589 break;
590 case ABM_GETSTATE:
591 return OnAppBarGetState();
592 case ABM_GETTASKBARPOS:
593 return OnAppBarGetTaskbarPos(pData);
594 case ABM_ACTIVATE:
595 case ABM_WINDOWPOSCHANGED:
596 OnAppBarActivationChange(pData);
597 break;
598 case ABM_GETAUTOHIDEBAR:
599 return (LRESULT)OnAppBarGetAutoHideBar(pData->abd.uEdge);
600 case ABM_SETAUTOHIDEBAR:
601 return OnAppBarSetAutoHideBar(pData);
602 case ABM_SETSTATE:
603 OnAppBarSetState((UINT)pData->abd.lParam64);
604 break;
605 default:
606 {
607 FIXME("0x%X\n", pData->dwMessage);
608 return FALSE;
609 }
610 }
611 return TRUE;
612}