ReactOS 0.4.15-dev-6056-gb29b268
traywnd.cpp
Go to the documentation of this file.
1/*
2 * ReactOS Explorer
3 *
4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5 * Copyright 2018-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 *
7 * this library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * this library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "precomp.h"
23#include <commoncontrols.h>
24
25HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
27void appbar_notify_all(HMONITOR hMon, UINT uMsg, HWND hwndExclude, LPARAM lParam);
28
29#define WM_APP_TRAYDESTROY (WM_APP + 0x100)
30
31#define TIMER_ID_AUTOHIDE 1
32#define TIMER_ID_MOUSETRACK 2
33#define MOUSETRACK_INTERVAL 100
34#define AUTOHIDE_DELAY_HIDE 2000
35#define AUTOHIDE_DELAY_SHOW 50
36#define AUTOHIDE_INTERVAL_ANIMATING 10
37
38#define AUTOHIDE_SPEED_SHOW 10
39#define AUTOHIDE_SPEED_HIDE 1
40
41#define AUTOHIDE_HIDDEN 0
42#define AUTOHIDE_SHOWING 1
43#define AUTOHIDE_SHOWN 2
44#define AUTOHIDE_HIDING 3
45
46#define IDHK_RUN 0x1f4
47#define IDHK_MINIMIZE_ALL 0x1f5
48#define IDHK_RESTORE_ALL 0x1f6
49#define IDHK_HELP 0x1f7
50#define IDHK_EXPLORE 0x1f8
51#define IDHK_FIND 0x1f9
52#define IDHK_FIND_COMPUTER 0x1fa
53#define IDHK_NEXT_TASK 0x1fb
54#define IDHK_PREV_TASK 0x1fc
55#define IDHK_SYS_PROPERTIES 0x1fd
56#define IDHK_DESKTOP 0x1fe
57#define IDHK_PAGER 0x1ff
58
59static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
60
62
64{
67};
69
71{
72 WINDOWPOSBACKUPDATA wposdata;
73 HWND hDesk = GetDesktopWindow();
74 if (IsWindowVisible(hwnd) && !IsIconic(hwnd) && (hwnd != hDesk))
75 {
76 wposdata.hwnd = hwnd;
77 wposdata.wplt.length = sizeof(wposdata.wplt);
78 GetWindowPlacement(hwnd, &(wposdata.wplt));
79 g_WindowPosBackup.Add(wposdata);
80 }
81
82 return TRUE;
83}
84
86{
88}
89
91{
93
94 for (INT i = g_WindowPosBackup.GetSize() - 1; i >= 0; --i)
95 {
97 }
98
99 g_WindowPosBackup.RemoveAll();
100}
101
103{
109};
110
111static BOOL CALLBACK
113{
115
117 return TRUE; // continue
118
119 if (pei->hTrayWnd == hwnd || pei->hwndDesktop == hwnd ||
120 pei->hwndProgman == hwnd)
121 {
122 return TRUE; // continue
123 }
124
125 if (pei->bMustBeInMonitor)
126 {
127 // is the window in the nearest monitor?
128 HMONITOR hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
129 if (hMon)
130 {
132 ZeroMemory(&info, sizeof(info));
133 info.cbSize = sizeof(info);
134 if (GetMonitorInfoW(hMon, &info))
135 {
136 RECT rcWindow, rcMonitor, rcIntersect;
137 rcMonitor = info.rcMonitor;
138
139 GetWindowRect(hwnd, &rcWindow);
140
141 if (!IntersectRect(&rcIntersect, &rcMonitor, &rcWindow))
142 return TRUE; // continue
143 }
144 }
145 }
146
147 pei->hwndFound = hwnd;
148 return FALSE; // stop if found
149}
150
151static BOOL
153{
155 ei.hwndFound = NULL;
157 ei.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
158 ei.hwndProgman = FindWindowW(L"Progman", NULL);
159 ei.bMustBeInMonitor = bMustBeInMonitor;
160
162 if (ei.hwndFound && FALSE)
163 {
164 WCHAR szClass[64], szText[64];
165 GetClassNameW(ei.hwndFound, szClass, _countof(szClass));
166 GetWindowTextW(ei.hwndFound, szText, _countof(szText));
167 MessageBoxW(NULL, szText, szClass, 0);
168 }
169 return ei.hwndFound != NULL;
170}
171
172/* Minimized window position info */
174{
177};
179
180/*
181 * ITrayWindow
182 */
183
184const GUID IID_IShellDesktopTray = { 0x213e2df9, 0x9a14, 0x4328, { 0x99, 0xb1, 0x69, 0x61, 0xf9, 0x14, 0x3c, 0xe9 } };
185
187 : public CWindowImpl<CStartButton>
188{
192
193public:
195 : m_ImageList(NULL),
196 m_Font(NULL)
197 {
198 m_Size.cx = 0;
199 m_Size.cy = 0;
200 }
201
203 {
204 if (m_ImageList != NULL)
206
207 if (m_Font != NULL)
209 }
210
212 {
213 return m_Size;
214 }
215
217 {
218 SIZE Size = { 0, 0 };
219
220 if (m_ImageList == NULL ||
222 {
224 }
225
227
228 /* Save the size of the start button */
229 m_Size = Size;
230 }
231
233 {
234 /* Get the system fonts, we use the caption font, always bold, though. */
235 NONCLIENTMETRICS ncm = {sizeof(ncm)};
236 if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
237 return;
238
239 if (m_Font)
241
242 ncm.lfCaptionFont.lfWeight = FW_BOLD;
243 m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
244
246 }
247
249 {
250 // HACK & FIXME: CORE-18016
251 HWND hWnd = m_hWnd;
252 m_hWnd = NULL;
254
255 SetWindowTheme(m_hWnd, L"Start", NULL);
256
259 0, 0, 0,
262
265 UpdateSize();
266 }
267
269 {
270 WCHAR szStartCaption[32];
272 IDS_START,
273 szStartCaption,
274 _countof(szStartCaption)))
275 {
276 wcscpy(szStartCaption, L"Start");
277 }
278
280
281 // HACK & FIXME: CORE-18016
283 0,
284 WC_BUTTON,
285 szStartCaption,
286 dwStyle,
287 0, 0, 0, 0,
291 NULL);
292
293 if (m_hWnd)
294 Initialize();
295
296 return m_hWnd;
297 }
298
300 {
301 if (uMsg == WM_KEYUP && wParam != VK_SPACE)
302 return 0;
303
305 return 0;
306 }
307
311
312};
313
314// This window class name is CONFIRMED on Win10 by WinHier.
315static const WCHAR szTrayShowDesktopButton[] = L"TrayShowDesktopButtonWClass";
316
317// The 'Show Desktop' button at edge of taskbar
319 public CWindowImpl<CTrayShowDesktopButton, CWindow, CControlWinTraits>
320{
324
325public:
327
329 {
330 }
331
333 {
334#define SHOW_DESKTOP_MINIMUM_WIDTH 3
336 return max(cxy, SHOW_DESKTOP_MINIMUM_WIDTH);
337 }
338
340 {
343 if (!m_hWnd)
344 return E_FAIL;
345
346 ::SetWindowTheme(m_hWnd, L"TaskBar", NULL);
347 return S_OK;
348 }
349
351 {
352 // The actual action can be delayed as an expected behaviour.
353 // But a too late action is an unexpected behaviour.
354 LONG nTime0 = m_nClickedTime;
355 LONG nTime1 = ::GetMessageTime();
356 if (nTime1 - nTime0 >= 600) // Ignore after 0.6 sec
357 return 0;
358
359 // Show/Hide Desktop
361 return 0;
362 }
363
364#define TSDB_CLICK (WM_USER + 100)
365
366 // This function is called from OnLButtonDown and parent.
368 {
369 // The actual action can be delayed as an expected behaviour.
371 PostMessage(TSDB_CLICK, 0, 0);
372 }
373
375 {
376 Click(); // Left-click
377 return 0;
378 }
379
381 {
382 if (m_hTheme)
384
385 m_hTheme = ::OpenThemeData(m_hWnd, L"TaskBar");
387 return 0;
388 }
389
390 // This function is called from OnPaint and parent.
392
394 {
395 RECT rc;
396 GetClientRect(&rc);
397
398 PAINTSTRUCT ps;
399 HDC hdc = BeginPaint(&ps);
400 OnDraw(hdc, &rc);
401 EndPaint(&ps);
402 return 0;
403 }
404
406 {
407 if (!IsWindow())
408 return FALSE;
409 RECT rc;
410 GetWindowRect(&rc);
412 ::InflateRect(&rc, max(cxEdge, 1), max(cyEdge, 1));
413 return ::PtInRect(&rc, pt);
414 }
415
416#define SHOW_DESKTOP_TIMER_ID 999
417#define SHOW_DESKTOP_TIMER_INTERVAL 200
418
420 {
421 if (m_bHovering)
422 return;
423
428 }
429
431 {
433 return 0;
434 }
435
437 {
439 return 0;
440
441 POINT pt;
443 if (!PtInButton(pt)) // The end of hovering?
444 {
449 }
450
451 return 0;
452 }
453
455 {
456 if (m_hTheme)
457 {
459 m_hTheme = NULL;
460 }
461 return 0;
462 }
463
467 MESSAGE_HANDLER(WM_THEMECHANGED, OnSettingChanged)
474};
475
477{
478 if (m_hTheme)
479 {
480 if (m_bHovering) // Draw a hot button
481 {
482 HTHEME hButtonTheme = ::OpenThemeData(m_hWnd, L"Button");
484 ::CloseThemeData(hButtonTheme);
485 }
486 else // Draw a taskbar background
487 {
489 }
490 }
491 else
492 {
493 RECT rc = *prc;
494 if (m_bHovering) // Draw a hot button
495 {
497 HBRUSH hbrHot = ::CreateSolidBrush(RGB(255, 255, 191));
498 ::FillRect(hdc, &rc, hbrHot);
499 ::DeleteObject(hbrHot);
500 }
501 else // Draw a flattish button
502 {
504 ::InflateRect(&rc, -1, -1);
506 }
507 }
508}
509
511 public CComCoClass<CTrayWindow>,
512 public CComObjectRootEx<CComMultiThreadModelNoCS>,
513 public CWindowImpl < CTrayWindow, CWindow, CControlWinTraits >,
514 public ITrayWindow,
515 public IShellDesktopTray,
516 public IOleWindow,
517 public IContextMenu
518{
521
524
528
530
535
537
543
546
549
553
555
556public:
558
559 union
560 {
562 struct
563 {
564 /* UI Status */
569 };
570 };
571
572public:
576 m_Theme(NULL),
577 m_Font(NULL),
579 m_Rebar(NULL),
582 m_Position(0),
591 Flags(0)
592 {
598 }
599
600 virtual ~CTrayWindow()
601 {
602 if (m_ShellServices != NULL)
603 {
606 }
607
608 if (m_Font != NULL)
609 {
611 m_Font = NULL;
612 }
613
614 if (m_Theme)
615 {
617 m_Theme = NULL;
618 }
619
621 }
622
623
624
625
626
627 /**********************************************************
628 * ##### command handling #####
629 */
630
632 {
633 WCHAR szCommand[256];
634 WCHAR *pszParameters;
635
637 id,
638 szCommand,
639 _countof(szCommand)))
640 {
641 return E_FAIL;
642 }
643
644 pszParameters = wcschr(szCommand, L'>');
645 if (pszParameters)
646 {
647 *pszParameters = 0;
648 pszParameters++;
649 }
650
651 ShellExecuteW(m_hWnd, NULL, szCommand, pszParameters, NULL, SW_SHOWNORMAL);
652 return S_OK;
653 }
654
656 {
657 /* Display the ReactOS Shutdown Dialog */
659
660 /*
661 * If the user presses CTRL+ALT+SHIFT while exiting
662 * the shutdown dialog, exit the shell cleanly.
663 */
664 if ((GetKeyState(VK_CONTROL) & 0x8000) &&
665 (GetKeyState(VK_SHIFT) & 0x8000) &&
666 (GetKeyState(VK_MENU) & 0x8000))
667 {
668 PostMessage(WM_QUIT, 0, 0);
669 }
670 return 0;
671 }
672
674 {
675 HWND hwnd;
676 RECT posRect;
677
679
681 WC_STATIC,
682 NULL,
684 posRect.left,
685 posRect.top,
686 posRect.right - posRect.left,
687 posRect.bottom - posRect.top,
688 NULL,
689 NULL,
690 NULL,
691 NULL);
692
694
695 // build the default directory from two environment variables
696 CStringW strDefaultDir, strHomePath;
697 strDefaultDir.GetEnvironmentVariable(L"HOMEDRIVE");
698 strHomePath.GetEnvironmentVariable(L"HOMEPATH");
699 strDefaultDir += strHomePath;
700
702
705
706 return 0;
707 }
708
710 {
711 CTrayWindow * This = (CTrayWindow*) pParam;
712 return This->RunFileDlgThread();
713 }
714
716 {
717 HWND hRunDlg;
719 {
721 if (hRunDlg != NULL &&
722 hRunDlg != m_RunFileDlgOwner)
723 {
724 SetForegroundWindow(hRunDlg);
725 return;
726 }
727 }
728
730 }
731
733 {
734 HWND hwnd;
735 RECT posRect;
736
739 WC_STATIC,
740 NULL,
742 posRect.left,
743 posRect.top,
744 posRect.right - posRect.left,
745 posRect.bottom - posRect.top,
746 NULL,
747 NULL,
748 NULL,
749 NULL);
750
752
754
757
758 return 0;
759 }
760
762 {
763 CTrayWindow *This = (CTrayWindow*) pParam;
764
765 return This->TrayPropertiesThread();
766 }
767
769 {
770 HWND hTrayProp;
771
773 {
775 if (hTrayProp != NULL &&
776 hTrayProp != m_TrayPropertiesOwner)
777 {
778 SetForegroundWindow(hTrayProp);
779 return NULL;
780 }
781 }
782
784 return NULL;
785 }
786
788 {
789 WCHAR szDir[MAX_PATH];
790
791 if (SHGetSpecialFolderPath(hWndOwner,
792 szDir,
794 FALSE))
795 {
796 ShellExecute(hWndOwner,
797 lpOperation,
798 szDir,
799 NULL,
800 NULL,
802 }
803 }
804
806 {
807 ShellExecute(hWndOwner,
808 TEXT("open"),
809 TEXT("taskmgr.exe"),
810 NULL,
811 NULL,
813 }
814
816 {
818 {
819 ShowDesktop();
820 }
821 else
822 {
823 RestoreAll();
824 }
825 }
826
828 {
829 switch (uiCmd)
830 {
833 break;
834
837 TEXT("open"));
838 break;
839
842 TEXT("explore"));
843 break;
844
845 case ID_LOCKTASKBAR:
847 {
849 }
850 break;
851
854 break;
855
858 break;
859
861 ShowDesktop();
862 break;
863
866 if (g_Arrangement == NONE)
867 {
869 }
873 break;
874
877 if (g_Arrangement == NONE)
878 {
880 }
884 break;
885
888 if (g_Arrangement == NONE)
889 {
891 }
895 break;
896
899 break;
900
902 //FIXME: Use SHRunControlPanel
903 ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
904 break;
905
907 RestoreAll();
908 break;
909
910 default:
911 TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
912 return FALSE;
913 }
914
915 return TRUE;
916 }
917
919 {
920 m_StartMenuPopup->OnSelect(MPOS_CANCELLEVEL);
921 }
922
924 {
925 switch (id)
926 {
927 case IDHK_RUN:
930 break;
931 case IDHK_HELP:
933 break;
934 case IDHK_EXPLORE:
935 //FIXME: We don't support this yet:
936 //ShellExecuteW(0, L"explore", NULL, NULL, NULL, 1);
937 ShellExecuteW(0, NULL, L"explorer.exe", L"/e ,", NULL, 1);
938 break;
939 case IDHK_FIND:
941 break;
944 break;
946 //FIXME: Use SHRunControlPanel
947 ShellExecuteW(m_hWnd, NULL, L"sysdm.cpl", NULL, NULL, SW_NORMAL);
948 break;
949 case IDHK_NEXT_TASK:
950 break;
951 case IDHK_PREV_TASK:
952 break;
954 MinimizeAll();
955 break;
956 case IDHK_RESTORE_ALL:
957 RestoreAll();
958 break;
959 case IDHK_DESKTOP:
961 break;
962 case IDHK_PAGER:
963 break;
964 }
965
966 return 0;
967 }
968
970 {
971 switch (uCommand)
972 {
974 // TODO:
975 break;
979 break;
981 LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as DoExitWindows?
982 break;
983 case TRAYCMD_CASCADE:
985 break;
986 case TRAYCMD_TILE_H:
988 break;
989 case TRAYCMD_TILE_V:
991 break;
994 break;
996 ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
997 break;
1000 break;
1002 MinimizeAll();
1003 break;
1005 RestoreAll();
1006 break;
1008 ShowDesktop();
1009 break;
1012 break;
1014 break;
1017 {
1019 }
1020 break;
1023 break;
1025 // TODO:
1026 break;
1028 DoExitWindows();
1029 break;
1031 // TODO:
1032 break;
1034 // TODO:
1035 break;
1037 // TODO:
1038 break;
1039 case IDM_SEARCH:
1042 break;
1045 break;
1046
1047 default:
1048 break;
1049 }
1050
1051 return FALSE;
1052 }
1053
1054
1056 IN HMENU hMenu,
1057 IN POINT *ppt OPTIONAL,
1058 IN HWND hwndExclude OPTIONAL,
1059 IN BOOL TrackUp,
1060 IN BOOL IsContextMenu)
1061 {
1062 TPMPARAMS tmp, *ptmp = NULL;
1063 POINT pt;
1064 UINT cmdId;
1065 UINT fuFlags;
1066
1067 if (hwndExclude != NULL)
1068 {
1069 /* Get the client rectangle and map it to screen coordinates */
1070 if (::GetClientRect(hwndExclude,
1071 &tmp.rcExclude) &&
1072 ::MapWindowPoints(hwndExclude,
1073 NULL,
1074 (LPPOINT) &tmp.rcExclude,
1075 2) != 0)
1076 {
1077 ptmp = &tmp;
1078 }
1079 }
1080
1081 if (ppt == NULL)
1082 {
1083 if (ptmp == NULL &&
1084 GetClientRect(&tmp.rcExclude) &&
1086 NULL,
1087 (LPPOINT) &tmp.rcExclude,
1088 2) != 0)
1089 {
1090 ptmp = &tmp;
1091 }
1092
1093 if (ptmp != NULL)
1094 {
1095 /* NOTE: TrackPopupMenuEx will eventually align the track position
1096 for us, no need to take care of it here as long as the
1097 coordinates are somewhere within the exclusion rectangle */
1098 pt.x = ptmp->rcExclude.left;
1099 pt.y = ptmp->rcExclude.top;
1100 }
1101 else
1102 pt.x = pt.y = 0;
1103 }
1104 else
1105 pt = *ppt;
1106
1107 tmp.cbSize = sizeof(tmp);
1108
1109 fuFlags = TPM_RETURNCMD | TPM_VERTICAL;
1110 fuFlags |= (TrackUp ? TPM_BOTTOMALIGN : TPM_TOPALIGN);
1111 if (IsContextMenu)
1112 fuFlags |= TPM_RIGHTBUTTON;
1113 else
1114 fuFlags |= (TrackUp ? TPM_VERNEGANIMATION : TPM_VERPOSANIMATION);
1115
1116 cmdId = TrackPopupMenuEx(hMenu,
1117 fuFlags,
1118 pt.x,
1119 pt.y,
1120 m_hWnd,
1121 ptmp);
1122
1123 return cmdId;
1124 }
1125
1127 IN IContextMenu * contextMenu,
1128 IN POINT *ppt OPTIONAL,
1129 IN HWND hwndExclude OPTIONAL,
1130 IN BOOL TrackUp,
1132 {
1133 POINT pt;
1135 RECT rc;
1136 HRESULT hr;
1137 UINT uCommand;
1138 HMENU popup = CreatePopupMenu();
1139
1140 if (popup == NULL)
1141 return E_FAIL;
1142
1143 if (ppt)
1144 {
1145 pt = *ppt;
1146 }
1147 else
1148 {
1149 ::GetWindowRect(m_hWnd, &rc);
1150 pt.x = rc.left;
1151 pt.y = rc.top;
1152 }
1153
1154 TRACE("Before Query\n");
1155 hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
1157 {
1158 TRACE("Query failed\n");
1159 DestroyMenu(popup);
1160 return hr;
1161 }
1162
1163 TRACE("Before Tracking\n");
1165 if (hwndExclude)
1166 {
1167 ::GetWindowRect(hwndExclude, &rc);
1168 ZeroMemory(&params, sizeof(params));
1169 params.cbSize = sizeof(params);
1170 params.rcExclude = rc;
1171 uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, pt.x, pt.y, m_hWnd, &params);
1172 }
1173 else
1174 {
1175 uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, pt.x, pt.y, m_hWnd, NULL);
1176 }
1178
1179 if (uCommand != 0)
1180 {
1181 TRACE("Before InvokeCommand\n");
1182 CMINVOKECOMMANDINFO cmi = { 0 };
1183 cmi.cbSize = sizeof(cmi);
1184 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1185 cmi.hwnd = m_hWnd;
1186 hr = contextMenu->InvokeCommand(&cmi);
1187 }
1188 else
1189 {
1190 TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
1191 hr = S_FALSE;
1192 }
1193
1194 DestroyMenu(popup);
1195 return hr;
1196 }
1197
1198
1199
1200
1201
1202 /**********************************************************
1203 * ##### moving and sizing handling #####
1204 */
1205
1207 {
1208 /* There is nothing to do if themes are enabled */
1209 if (m_Theme)
1210 return;
1211
1213
1214 NONCLIENTMETRICS ncm = {sizeof(ncm)};
1215 if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
1216 {
1217 ERR("SPI_GETNONCLIENTMETRICS failed\n");
1218 return;
1219 }
1220
1221 if (m_Font != NULL)
1223
1224 ncm.lfCaptionFont.lfWeight = FW_NORMAL;
1225 m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
1226 if (!m_Font)
1227 {
1228 ERR("CreateFontIndirect failed\n");
1229 return;
1230 }
1231
1235 }
1236
1238 IN OUT RECT *pRect,
1240 {
1242 HMONITOR hMon;
1243
1244 mi.cbSize = sizeof(mi);
1245 hMon = MonitorFromRect(pRect, dwFlags);
1246 if (hMon != NULL &&
1247 GetMonitorInfo(hMon, &mi))
1248 {
1249 *pRect = mi.rcMonitor;
1250 }
1251 else
1252 {
1253 pRect->left = 0;
1254 pRect->top = 0;
1255 pRect->right = GetSystemMetrics(SM_CXSCREEN);
1256 pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1257
1258 hMon = NULL;
1259 }
1260
1261 return hMon;
1262 }
1263
1265 IN const RECT *pRect)
1266 {
1267 HMONITOR hMon;
1268
1269 /* In case the monitor sizes or saved sizes differ a bit (probably
1270 not a lot, only so the tray window overlaps into another monitor
1271 now), minimize the risk that we determine a wrong monitor by
1272 using the center point of the tray window if we can't determine
1273 it using the rectangle. */
1274 hMon = MonitorFromRect(pRect, MONITOR_DEFAULTTONULL);
1275 if (hMon == NULL)
1276 {
1277 POINT pt;
1278
1279 pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
1280 pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
1281
1282 /* be less error-prone, find the nearest monitor */
1283 hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
1284 }
1285
1286 return hMon;
1287 }
1288
1290 IN HMONITOR hMonitor,
1291 IN OUT RECT *pRect)
1292 {
1293 HMONITOR hMon = NULL;
1294
1295 if (hMonitor != NULL)
1296 {
1298
1299 mi.cbSize = sizeof(mi);
1300 if (!GetMonitorInfo(hMonitor, &mi))
1301 {
1302 /* Hm, the monitor is gone? Try to find a monitor where it
1303 could be located now */
1304 hMon = GetMonitorFromRect(pRect);
1305 if (hMon == NULL ||
1306 !GetMonitorInfo(hMon, &mi))
1307 {
1308 hMon = NULL;
1309 goto GetPrimaryRect;
1310 }
1311 }
1312
1313 *pRect = mi.rcMonitor;
1314 }
1315 else
1316 {
1317GetPrimaryRect:
1318 pRect->left = 0;
1319 pRect->top = 0;
1320 pRect->right = GetSystemMetrics(SM_CXSCREEN);
1321 pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1322 }
1323
1324 return hMon;
1325 }
1326
1328 {
1330 SIZE size;
1331
1332 if (pos > ABE_BOTTOM)
1333 pos = ABE_BOTTOM;
1334
1335 HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[pos], 0, NULL, TS_TRUE, &size);
1337 return;
1338
1339 switch (pos)
1340 {
1341 case ABE_TOP:
1342 rc->bottom -= size.cy;
1343 break;
1344 case ABE_BOTTOM:
1345 rc->top += size.cy;
1346 break;
1347 case ABE_LEFT:
1348 rc->right -= size.cx;
1349 break;
1350 case ABE_RIGHT:
1351 rc->left += size.cx;
1352 break;
1353 }
1354 }
1355
1357 IN const SIZE *pTraySize,
1358 IN OUT RECT *pRect)
1359 {
1360 switch (Position)
1361 {
1362 case ABE_LEFT:
1363 pRect->right = pRect->left + pTraySize->cx;
1364 break;
1365
1366 case ABE_TOP:
1367 pRect->bottom = pRect->top + pTraySize->cy;
1368 break;
1369
1370 case ABE_RIGHT:
1371 pRect->left = pRect->right - pTraySize->cx;
1372 break;
1373
1374 case ABE_BOTTOM:
1375 default:
1376 pRect->top = pRect->bottom - pTraySize->cy;
1377 break;
1378 }
1379 }
1380
1382 IN const RECT *pScreen,
1383 IN const SIZE *pTraySize OPTIONAL,
1384 OUT RECT *pRect)
1385 {
1386 if (pTraySize == NULL)
1387 pTraySize = &m_TraySize;
1388
1389 *pRect = *pScreen;
1390
1391 if(!m_Theme)
1392 {
1393 /* Move the border outside of the screen */
1394 InflateRect(pRect,
1397 }
1398
1399 MakeTrayRectWithSize(Position, pTraySize, pRect);
1400 }
1401
1403 {
1404 return m_Position == ABE_TOP || m_Position == ABE_BOTTOM;
1405 }
1406
1409 IN OUT RECT *pRect)
1410 {
1411 RECT rcScreen;
1412 //BOOL Horizontal;
1413 HMONITOR hMon;
1414 SIZE szMax, szWnd;
1415
1416 //Horizontal = IsPosHorizontal();
1417
1418 szWnd.cx = pRect->right - pRect->left;
1419 szWnd.cy = pRect->bottom - pRect->top;
1420
1421 rcScreen = *pRect;
1422 hMon = GetScreenRectFromRect(
1423 &rcScreen,
1424 MONITOR_DEFAULTTONEAREST);
1425
1426 /* Calculate the maximum size of the tray window and limit the window
1427 size to half of the screen's size. */
1428 szMax.cx = (rcScreen.right - rcScreen.left) / 2;
1429 szMax.cy = (rcScreen.bottom - rcScreen.top) / 2;
1430 if (szWnd.cx > szMax.cx)
1431 szWnd.cx = szMax.cx;
1432 if (szWnd.cy > szMax.cy)
1433 szWnd.cy = szMax.cy;
1434
1435 /* FIXME - calculate */
1436
1438 &rcScreen,
1439 &szWnd,
1440 pRect);
1441
1442 return hMon;
1443 }
1444
1445#if 0
1446 VOID
1447 GetMinimumWindowSize(
1448 OUT RECT *pRect)
1449 {
1450 RECT rcMin = {0};
1451
1452 AdjustWindowRectEx(&rcMin,
1454 GWL_STYLE),
1455 FALSE,
1457 GWL_EXSTYLE));
1458
1459 *pRect = rcMin;
1460 }
1461#endif
1462
1463
1465 IN POINT pt,
1466 OUT RECT *pRect,
1467 OUT HMONITOR *phMonitor)
1468 {
1469 HMONITOR hMon, hMonNew;
1470 DWORD PosH, PosV, Pos;
1471 SIZE DeltaPt, ScreenOffset;
1472 RECT rcScreen;
1473
1474 rcScreen.left = 0;
1475 rcScreen.top = 0;
1476
1477 /* Determine the screen rectangle */
1478 hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
1479 if (hMon != NULL)
1480 {
1482
1483 mi.cbSize = sizeof(mi);
1484 if (!GetMonitorInfo(hMon, &mi))
1485 {
1486 hMon = NULL;
1487 goto GetPrimaryScreenRect;
1488 }
1489
1490 /* make left top corner of the screen zero based to
1491 make calculations easier */
1492 pt.x -= mi.rcMonitor.left;
1493 pt.y -= mi.rcMonitor.top;
1494
1495 ScreenOffset.cx = mi.rcMonitor.left;
1496 ScreenOffset.cy = mi.rcMonitor.top;
1497 rcScreen.right = mi.rcMonitor.right - mi.rcMonitor.left;
1498 rcScreen.bottom = mi.rcMonitor.bottom - mi.rcMonitor.top;
1499 }
1500 else
1501 {
1502GetPrimaryScreenRect:
1503 ScreenOffset.cx = 0;
1504 ScreenOffset.cy = 0;
1507 }
1508
1509 /* Calculate the nearest screen border */
1510 if (pt.x < rcScreen.right / 2)
1511 {
1512 DeltaPt.cx = pt.x;
1513 PosH = ABE_LEFT;
1514 }
1515 else
1516 {
1517 DeltaPt.cx = rcScreen.right - pt.x;
1518 PosH = ABE_RIGHT;
1519 }
1520
1521 if (pt.y < rcScreen.bottom / 2)
1522 {
1523 DeltaPt.cy = pt.y;
1524 PosV = ABE_TOP;
1525 }
1526 else
1527 {
1528 DeltaPt.cy = rcScreen.bottom - pt.y;
1529 PosV = ABE_BOTTOM;
1530 }
1531
1532 Pos = (DeltaPt.cx * rcScreen.bottom < DeltaPt.cy * rcScreen.right) ? PosH : PosV;
1533
1534 /* Fix the screen origin to be relative to the primary monitor again */
1535 OffsetRect(&rcScreen,
1536 ScreenOffset.cx,
1537 ScreenOffset.cy);
1538
1539 RECT rcPos = m_TrayRects[Pos];
1540
1541 hMonNew = GetMonitorFromRect(&rcPos);
1542 if (hMon != hMonNew)
1543 {
1544 SIZE szTray;
1545
1546 /* Recalculate the rectangle, we're dragging to another monitor.
1547 We don't need to recalculate the rect on single monitor systems. */
1548 szTray.cx = rcPos.right - rcPos.left;
1549 szTray.cy = rcPos.bottom - rcPos.top;
1550
1551 GetTrayRectFromScreenRect(Pos, &rcScreen, &szTray, pRect);
1552 hMon = hMonNew;
1553 }
1554 else
1555 {
1556 /* The user is dragging the tray window on the same monitor. We don't need
1557 to recalculate the rectangle */
1558 *pRect = rcPos;
1559 }
1560
1561 *phMonitor = hMon;
1562
1563 return Pos;
1564 }
1565
1567 IN OUT RECT *pRect,
1568 OUT HMONITOR *phMonitor)
1569 {
1570 POINT pt;
1571
1572 /* Calculate the center of the rectangle. We call
1573 GetDraggingRectFromPt to calculate a valid
1574 dragging rectangle */
1575 pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
1576 pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
1577
1578 return GetDraggingRectFromPt(
1579 pt,
1580 pRect,
1581 phMonitor);
1582 }
1583
1585 {
1586 RECT rcTray;
1587
1588 if (IsDragging)
1589 {
1590 rcTray.left = pwp->x;
1591 rcTray.top = pwp->y;
1592 rcTray.right = rcTray.left + pwp->cx;
1593 rcTray.bottom = rcTray.top + pwp->cy;
1594
1595 if (!EqualRect(&rcTray,
1597 {
1598 /* Recalculate the rectangle, the user dragged the tray
1599 window to another monitor or the window was somehow else
1600 moved or resized */
1602 &rcTray,
1604 //m_TrayRects[DraggingPosition] = rcTray;
1605 }
1606
1607 //Monitor = CalculateValidSize(DraggingPosition,
1608 // &rcTray);
1609
1612 IsDragging = FALSE;
1613
1614 m_TrayRects[m_Position] = rcTray;
1615 goto ChangePos;
1616 }
1617 else if (GetWindowRect(&rcTray))
1618 {
1619 if (InSizeMove)
1620 {
1621 if (!(pwp->flags & SWP_NOMOVE))
1622 {
1623 rcTray.left = pwp->x;
1624 rcTray.top = pwp->y;
1625 }
1626
1627 if (!(pwp->flags & SWP_NOSIZE))
1628 {
1629 rcTray.right = rcTray.left + pwp->cx;
1630 rcTray.bottom = rcTray.top + pwp->cy;
1631 }
1632
1634
1635 if (!(pwp->flags & (SWP_NOMOVE | SWP_NOSIZE)))
1636 {
1637 SIZE szWnd;
1638
1639 szWnd.cx = pwp->cx;
1640 szWnd.cy = pwp->cy;
1641
1642 MakeTrayRectWithSize(m_Position, &szWnd, &rcTray);
1643 }
1644
1645 m_TrayRects[m_Position] = rcTray;
1646 }
1647 else if (m_Position != (DWORD)-1)
1648 {
1649 /* If the user isn't resizing the tray window we need to make sure the
1650 new size or position is valid. this is to prevent changes to the window
1651 without user interaction. */
1652 rcTray = m_TrayRects[m_Position];
1653
1655 {
1656 rcTray.left += m_AutoHideOffset.cx;
1657 rcTray.right += m_AutoHideOffset.cx;
1658 rcTray.top += m_AutoHideOffset.cy;
1659 rcTray.bottom += m_AutoHideOffset.cy;
1660 }
1661
1662 }
1663
1664ChangePos:
1665 m_TraySize.cx = rcTray.right - rcTray.left;
1666 m_TraySize.cy = rcTray.bottom - rcTray.top;
1667
1668 pwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
1669 pwp->x = rcTray.left;
1670 pwp->y = rcTray.top;
1671 pwp->cx = m_TraySize.cx;
1672 pwp->cy = m_TraySize.cy;
1673 }
1674 }
1675
1677 {
1678 RECT rcClip, rcWindow;
1679 HRGN hClipRgn;
1680
1681 if (GetWindowRect(&rcWindow))
1682 {
1683 /* Disable clipping on systems with only one monitor */
1685 Clip = FALSE;
1686
1687 if (Clip)
1688 {
1689 rcClip = rcWindow;
1690
1691 GetScreenRect(m_Monitor, &rcClip);
1692
1693 if (!IntersectRect(&rcClip, &rcClip, &rcWindow))
1694 {
1695 rcClip = rcWindow;
1696 }
1697
1698 OffsetRect(&rcClip,
1699 -rcWindow.left,
1700 -rcWindow.top);
1701
1702 hClipRgn = CreateRectRgnIndirect(&rcClip);
1703 }
1704 else
1705 hClipRgn = NULL;
1706
1707 /* Set the clipping region or make sure the window isn't clipped
1708 by disabling it explicitly. */
1709 SetWindowRgn(hClipRgn, TRUE);
1710 }
1711 }
1712
1714 {
1715#if !WIN7_DEBUG_MODE
1716 RECT rcTray, rcWorkArea;
1717
1718 /* If monitor has changed then fix the previous monitors work area */
1720 {
1721 GetScreenRect(m_PreviousMonitor, &rcWorkArea);
1722 SystemParametersInfoW(SPI_SETWORKAREA,
1723 1,
1724 &rcWorkArea,
1726 }
1727
1728 rcTray = m_TrayRects[m_Position];
1729
1730 GetScreenRect(m_Monitor, &rcWorkArea);
1732
1733 /* If AutoHide is false then change the workarea to exclude
1734 the area that the taskbar covers. */
1736 {
1737 switch (m_Position)
1738 {
1739 case ABE_TOP:
1740 rcWorkArea.top = rcTray.bottom;
1741 break;
1742 case ABE_LEFT:
1743 rcWorkArea.left = rcTray.right;
1744 break;
1745 case ABE_RIGHT:
1746 rcWorkArea.right = rcTray.left;
1747 break;
1748 case ABE_BOTTOM:
1749 rcWorkArea.bottom = rcTray.top;
1750 break;
1751 }
1752 }
1753
1754 /*
1755 * Resize the current monitor work area. Win32k will also send
1756 * a WM_SIZE message to automatically resize the desktop.
1757 */
1758 SystemParametersInfoW(SPI_SETWORKAREA,
1759 1,
1760 &rcWorkArea,
1762#endif
1763 }
1764
1766 {
1767 /* Force the rebar bands to resize */
1769 IID_IDeskBand,
1771 0,
1772 NULL,
1773 NULL);
1774
1775 /* Calculate the size of the taskbar based on the rebar */
1777
1778 /* Move the tray window */
1779 /* The handler of WM_WINDOWPOSCHANGING will override whatever size
1780 * and position we use here with m_TrayRects */
1784 }
1785
1787 {
1788 DWORD Pos;
1789 RECT rcScreen;
1790 SIZE WndSize, EdgeSize, DlgFrameSize;
1791 SIZE StartBtnSize = m_StartButton.GetSize();
1792
1793 EdgeSize.cx = GetSystemMetrics(SM_CXEDGE);
1794 EdgeSize.cy = GetSystemMetrics(SM_CYEDGE);
1795 DlgFrameSize.cx = GetSystemMetrics(SM_CXDLGFRAME);
1796 DlgFrameSize.cy = GetSystemMetrics(SM_CYDLGFRAME);
1797
1799 rcScreen = g_TaskbarSettings.sr.Rect;
1800 GetScreenRectFromRect(&rcScreen, MONITOR_DEFAULTTONEAREST);
1801
1803 {
1804 /* Use the minimum size of the taskbar, we'll use the start
1805 button as a minimum for now. Make sure we calculate the
1806 entire window size, not just the client size. However, we
1807 use a thinner border than a standard thick border, so that
1808 the start button and bands are not stuck to the screen border. */
1809 if(!m_Theme)
1810 {
1811 g_TaskbarSettings.sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
1812 g_TaskbarSettings.sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
1813 }
1814 else
1815 {
1816 g_TaskbarSettings.sr.Size.cx = StartBtnSize.cx - EdgeSize.cx;
1817 g_TaskbarSettings.sr.Size.cy = StartBtnSize.cy - EdgeSize.cy;
1820 }
1821 }
1822 /* Determine a minimum tray window rectangle. The "client" height is
1823 zero here since we cannot determine an optimal minimum width when
1824 loaded as a vertical tray window. We just need to make sure the values
1825 loaded from the registry are at least. The windows explorer behaves
1826 the same way, it allows the user to save a zero width vertical tray
1827 window, but not a zero height horizontal tray window. */
1828 if(!m_Theme)
1829 {
1830 WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
1831 WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
1832 }
1833 else
1834 {
1835 WndSize.cx = StartBtnSize.cx;
1836 WndSize.cy = StartBtnSize.cy - EdgeSize.cy;
1837 }
1838
1839 if (WndSize.cx < g_TaskbarSettings.sr.Size.cx)
1840 WndSize.cx = g_TaskbarSettings.sr.Size.cx;
1841 if (WndSize.cy < g_TaskbarSettings.sr.Size.cy)
1842 WndSize.cy = g_TaskbarSettings.sr.Size.cy;
1843
1844 /* Save the calculated size */
1845 m_TraySize = WndSize;
1846
1847 /* Calculate all docking rectangles. We need to do this here so they're
1848 initialized and dragging the tray window to another position gives
1849 usable results */
1850 for (Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
1851 {
1853 &rcScreen,
1854 &m_TraySize,
1855 &m_TrayRects[Pos]);
1856 // TRACE("m_TrayRects[%d(%d)]: %d,%d,%d,%d\n", Pos, Position, m_TrayRects[Pos].left, m_TrayRects[Pos].top, m_TrayRects[Pos].right, m_TrayRects[Pos].bottom);
1857 }
1858
1859 /* Determine which monitor we are on. It shouldn't matter which docked
1860 position rectangle we use */
1862 }
1863
1865 {
1866 RECT rcClient;
1867 SIZE TraySize, StartSize;
1868 POINT ptTrayNotify = { 0, 0 };
1869 BOOL Horizontal;
1870 HDWP dwp;
1871
1873 if (prcClient != NULL)
1874 {
1875 rcClient = *prcClient;
1876 }
1877 else
1878 {
1879 if (!GetClientRect(&rcClient))
1880 {
1881 ERR("Could not get client rect lastErr=%d\n", GetLastError());
1882 return;
1883 }
1884 }
1885
1886 Horizontal = IsPosHorizontal();
1887
1888 /* We're about to resize/move the start button, the rebar control and
1889 the tray notification control */
1890 dwp = BeginDeferWindowPos(4);
1891 if (dwp == NULL)
1892 {
1893 ERR("BeginDeferWindowPos failed. lastErr=%d\n", GetLastError());
1894 return;
1895 }
1896
1897 /* Limit the Start button width to the client width, if necessary */
1898 StartSize = m_StartButton.GetSize();
1899 if (StartSize.cx > rcClient.right)
1900 StartSize.cx = rcClient.right;
1901
1902 HWND hwndTaskToolbar = ::GetWindow(m_TaskSwitch, GW_CHILD);
1903 if (hwndTaskToolbar)
1904 {
1905 DWORD size = SendMessageW(hwndTaskToolbar, TB_GETBUTTONSIZE, 0, 0);
1906
1907 /* Themed button covers Edge area as well */
1908 StartSize.cy = HIWORD(size) + (m_Theme ? GetSystemMetrics(SM_CYEDGE) : 0);
1909 }
1910
1911 if (m_StartButton.m_hWnd != NULL)
1912 {
1913 /* Resize and reposition the button */
1914 dwp = m_StartButton.DeferWindowPos(dwp,
1915 NULL,
1916 0,
1917 0,
1918 StartSize.cx,
1919 StartSize.cy,
1921 if (dwp == NULL)
1922 {
1923 ERR("DeferWindowPos for start button failed. lastErr=%d\n", GetLastError());
1924 return;
1925 }
1926 }
1927
1929 {
1930 // Get rectangle from rcClient
1931 RECT rc = rcClient;
1932 INT cxyShowDesktop = m_ShowDesktopButton.WidthOrHeight();
1933 if (Horizontal)
1934 {
1935 rc.left = rc.right - cxyShowDesktop;
1936 rc.right += 5; // excessive
1937 }
1938 else
1939 {
1940 rc.top = rc.bottom - cxyShowDesktop;
1941 rc.bottom += 5; // excessive
1942 }
1943
1944 /* Resize and reposition the button */
1946 rc.left, rc.top,
1947 rc.right - rc.left, rc.bottom - rc.top,
1949
1950 // Adjust rcClient
1951 if (Horizontal)
1952 rcClient.right -= cxyShowDesktop + ::GetSystemMetrics(SM_CXEDGE);
1953 else
1954 rcClient.bottom -= cxyShowDesktop + ::GetSystemMetrics(SM_CYEDGE);
1955 }
1956
1957 /* Determine the size that the tray notification window needs */
1958 if (Horizontal)
1959 {
1960 TraySize.cx = 0;
1961 TraySize.cy = rcClient.bottom;
1962 }
1963 else
1964 {
1965 TraySize.cx = rcClient.right;
1966 TraySize.cy = 0;
1967 }
1968
1969 if (m_TrayNotify != NULL &&
1972 (WPARAM)Horizontal,
1973 (LPARAM)&TraySize))
1974 {
1975 /* Move the tray notification window to the desired location */
1976 if (Horizontal)
1977 ptTrayNotify.x = rcClient.right - TraySize.cx;
1978 else
1979 ptTrayNotify.y = rcClient.bottom - TraySize.cy;
1980
1981 dwp = ::DeferWindowPos(dwp,
1983 NULL,
1984 ptTrayNotify.x,
1985 ptTrayNotify.y,
1986 TraySize.cx,
1987 TraySize.cy,
1989 if (dwp == NULL)
1990 {
1991 ERR("DeferWindowPos for notification area failed. lastErr=%d\n", GetLastError());
1992 return;
1993 }
1994 }
1995
1996 /* Resize/Move the rebar control */
1997 if (m_Rebar != NULL)
1998 {
1999 POINT ptRebar = { 0, 0 };
2000 SIZE szRebar;
2001
2002 SetWindowStyle(m_Rebar, CCS_VERT, Horizontal ? 0 : CCS_VERT);
2003
2004 if (Horizontal)
2005 {
2006 ptRebar.x = StartSize.cx + GetSystemMetrics(SM_CXSIZEFRAME);
2007 szRebar.cx = ptTrayNotify.x - ptRebar.x;
2008 szRebar.cy = rcClient.bottom;
2009 }
2010 else
2011 {
2012 ptRebar.y = StartSize.cy + GetSystemMetrics(SM_CYSIZEFRAME);
2013 szRebar.cx = rcClient.right;
2014 szRebar.cy = ptTrayNotify.y - ptRebar.y;
2015 }
2016
2017 dwp = ::DeferWindowPos(dwp,
2018 m_Rebar,
2019 NULL,
2020 ptRebar.x,
2021 ptRebar.y,
2022 szRebar.cx,
2023 szRebar.cy,
2025 }
2026
2027 if (dwp != NULL)
2028 EndDeferWindowPos(dwp);
2029
2030 if (m_TaskSwitch != NULL)
2031 {
2032 /* Update the task switch window configuration */
2034 }
2035 }
2036
2037 void FitToRebar(PRECT pRect)
2038 {
2039 /* Get the rect of the rebar */
2040 RECT rebarRect, taskbarRect, clientRect;
2041 ::GetWindowRect(m_Rebar, &rebarRect);
2042 ::GetWindowRect(m_hWnd, &taskbarRect);
2043 ::GetClientRect(m_hWnd, &clientRect);
2044 OffsetRect(&rebarRect, -taskbarRect.left, -taskbarRect.top);
2045
2046 /* Calculate the difference of size of the taskbar and the rebar */
2047 SIZE margins;
2048 margins.cx = taskbarRect.right - taskbarRect.left - clientRect.right + clientRect.left;
2049 margins.cy = taskbarRect.bottom - taskbarRect.top - clientRect.bottom + clientRect.top;
2050
2051 /* Calculate the new size of the rebar and make it resize, then change the new taskbar size */
2052 switch (m_Position)
2053 {
2054 case ABE_TOP:
2055 rebarRect.bottom = rebarRect.top + pRect->bottom - pRect->top - margins.cy;
2057 pRect->bottom = pRect->top + rebarRect.bottom - rebarRect.top + margins.cy;
2058 break;
2059 case ABE_BOTTOM:
2060 rebarRect.top = rebarRect.bottom - (pRect->bottom - pRect->top - margins.cy);
2062 pRect->top = pRect->bottom - (rebarRect.bottom - rebarRect.top + margins.cy);
2063 break;
2064 case ABE_LEFT:
2065 rebarRect.right = rebarRect.left + (pRect->right - pRect->left - margins.cx);
2067 pRect->right = pRect->left + (rebarRect.right - rebarRect.left + margins.cx);
2068 break;
2069 case ABE_RIGHT:
2070 rebarRect.left = rebarRect.right - (pRect->right - pRect->left - margins.cx);
2072 pRect->left = pRect->right - (rebarRect.right - rebarRect.left + margins.cx);
2073 break;
2074 }
2075
2077 }
2078
2080 {
2081 if (m_StartMenuPopup != NULL)
2082 {
2083 POINTL pt;
2084 RECTL rcExclude;
2085 DWORD dwFlags = 0;
2086
2087 if (m_StartButton.GetWindowRect((RECT*) &rcExclude))
2088 {
2089 switch (m_Position)
2090 {
2091 case ABE_BOTTOM:
2092 pt.x = rcExclude.left;
2093 pt.y = rcExclude.top;
2094 dwFlags |= MPPF_TOP;
2095 break;
2096 case ABE_TOP:
2097 pt.x = rcExclude.left;
2098 pt.y = rcExclude.bottom;
2099 dwFlags |= MPPF_BOTTOM;
2100 break;
2101 case ABE_LEFT:
2102 pt.x = rcExclude.right;
2103 pt.y = rcExclude.top;
2104 dwFlags |= MPPF_RIGHT;
2105 break;
2106 case ABE_RIGHT:
2107 pt.x = rcExclude.left;
2108 pt.y = rcExclude.top;
2109 dwFlags |= MPPF_LEFT;
2110 break;
2111 }
2112
2113 m_StartMenuPopup->Popup(&pt, &rcExclude, dwFlags);
2114
2115 m_StartButton.SendMessageW(BM_SETSTATE, TRUE, 0);
2116 }
2117 }
2118 }
2119
2121 {
2122 RECT rcCurrent;
2123 POINT pt;
2124 BOOL over;
2126
2127 GetCursorPos(&pt);
2128 GetWindowRect(&rcCurrent);
2129 over = PtInRect(&rcCurrent, pt);
2130
2132 {
2133 over = TRUE;
2134 }
2135
2136 if (over)
2137 {
2138 if (state == AUTOHIDE_HIDING)
2139 {
2140 TRACE("AutoHide cancelling hide.\n");
2143 }
2144 else if (state == AUTOHIDE_HIDDEN)
2145 {
2146 TRACE("AutoHide starting show.\n");
2149 }
2150 }
2151 else
2152 {
2153 if (state == AUTOHIDE_SHOWING)
2154 {
2155 TRACE("AutoHide cancelling show.\n");
2158 }
2159 else if (state == AUTOHIDE_SHOWN)
2160 {
2161 TRACE("AutoHide starting hide.\n");
2164 }
2165
2167 }
2168 }
2169
2171 {
2174
2175 switch (m_AutoHideState)
2176 {
2177 case AUTOHIDE_HIDING:
2178 switch (m_Position)
2179 {
2180 case ABE_LEFT:
2181 m_AutoHideOffset.cy = 0;
2183 if (m_AutoHideOffset.cx < -w)
2185 break;
2186 case ABE_TOP:
2187 m_AutoHideOffset.cx = 0;
2189 if (m_AutoHideOffset.cy < -h)
2191 break;
2192 case ABE_RIGHT:
2193 m_AutoHideOffset.cy = 0;
2195 if (m_AutoHideOffset.cx > w)
2197 break;
2198 case ABE_BOTTOM:
2199 m_AutoHideOffset.cx = 0;
2201 if (m_AutoHideOffset.cy > h)
2203 break;
2204 }
2205
2207 {
2209 break;
2210 }
2211
2212 /* fallthrough */
2213 case AUTOHIDE_HIDDEN:
2214
2215 switch (m_Position)
2216 {
2217 case ABE_LEFT:
2219 m_AutoHideOffset.cy = 0;
2220 break;
2221 case ABE_TOP:
2222 m_AutoHideOffset.cx = 0;
2224 break;
2225 case ABE_RIGHT:
2227 m_AutoHideOffset.cy = 0;
2228 break;
2229 case ABE_BOTTOM:
2230 m_AutoHideOffset.cx = 0;
2232 break;
2233 }
2234
2237 break;
2238
2239 case AUTOHIDE_SHOWING:
2241 {
2243 }
2245 {
2247 }
2248 else
2249 {
2250 m_AutoHideOffset.cx = 0;
2251 }
2252
2254 {
2256 }
2258 {
2260 }
2261 else
2262 {
2263 m_AutoHideOffset.cy = 0;
2264 }
2265
2266 if (m_AutoHideOffset.cx != 0 || m_AutoHideOffset.cy != 0)
2267 {
2269 break;
2270 }
2271
2272 /* fallthrough */
2273 case AUTOHIDE_SHOWN:
2274
2277 break;
2278 }
2279
2281 }
2282
2283
2284
2285
2286
2287 /**********************************************************
2288 * ##### taskbar drawing #####
2289 */
2290
2292 {
2293 RECT rect;
2295
2297
2298 if (m_Theme)
2299 {
2301 DrawThemeBackground(m_Theme, hdc, iSBkgndPart[m_Position], 0, &rect, 0);
2302 }
2303
2304 return 0;
2305 }
2306
2308 {
2309 HDC hdc;
2310 RECT rect;
2312 SIZE size;
2313
2315
2318 return 0;
2319
2321 OffsetRect(&rect, -rect.left, -rect.top);
2322
2323 hdc = GetWindowDC();
2324
2325 switch (m_Position)
2326 {
2327 case ABE_LEFT:
2328 rect.left = rect.right - size.cx;
2329 break;
2330 case ABE_TOP:
2331 rect.top = rect.bottom - size.cy;
2332 break;
2333 case ABE_RIGHT:
2334 rect.right = rect.left + size.cx;
2335 break;
2336 case ABE_BOTTOM:
2337 default:
2338 rect.bottom = rect.top + size.cy;
2339 break;
2340 }
2341
2342 DrawThemeBackground(m_Theme, hdc, iSizerPart[m_Position], 0, &rect, 0);
2343
2344 ReleaseDC(hdc);
2345 return 0;
2346 }
2347
2348
2349
2350
2351
2352 /*
2353 * ITrayWindow
2354 */
2356 {
2357 RECT rcWnd;
2358
2359 /* Check if there's already a window created and try to show it.
2360 If it was somehow destroyed just create a new tray window. */
2361 if (m_hWnd != NULL && IsWindow())
2362 {
2363 return S_OK;
2364 }
2365
2368 dwExStyle |= WS_EX_TOPMOST;
2369
2371 if(!m_Theme)
2372 {
2373 dwStyle |= WS_THICKFRAME | WS_BORDER;
2374 }
2375
2376 ZeroMemory(&rcWnd, sizeof(rcWnd));
2377 if (m_Position != (DWORD) -1)
2378 rcWnd = m_TrayRects[m_Position];
2379
2380 if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
2381 return E_FAIL;
2382
2383 /* Align all controls on the tray window */
2385
2386 /* Move the tray window to the right position and resize it if necessary */
2388
2389 return S_OK;
2390 }
2391
2393 {
2394 if (m_hWnd != NULL)
2395 {
2398 0,
2399 0);
2400 }
2401
2402 return S_OK;
2403 }
2404
2406 {
2407 return m_hWnd;
2408 }
2409
2411 {
2412 return (m_hWnd == hWnd ||
2414 }
2415
2417 {
2418 return IsPosHorizontal();
2419 }
2420
2422 {
2423 BOOL bPrevLock = g_TaskbarSettings.bLock;
2424
2425 if (g_TaskbarSettings.bLock != bLock)
2426 {
2427 g_TaskbarSettings.bLock = bLock;
2428
2429 if (m_TrayBandSite != NULL)
2430 {
2431 if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
2432 {
2433 /* Reset?? */
2434 g_TaskbarSettings.bLock = bPrevLock;
2435 return bPrevLock;
2436 }
2437 }
2438
2439 if (m_Theme)
2440 {
2441 /* Update cached tray sizes */
2442 for(DWORD Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
2443 {
2444 RECT rcGripper = {0};
2445 AdjustSizerRect(&rcGripper, Pos);
2446
2448 {
2449 m_TrayRects[Pos].top += rcGripper.top;
2450 m_TrayRects[Pos].left += rcGripper.left;
2451 m_TrayRects[Pos].bottom += rcGripper.bottom;
2452 m_TrayRects[Pos].right += rcGripper.right;
2453 }
2454 else
2455 {
2456 m_TrayRects[Pos].top -= rcGripper.top;
2457 m_TrayRects[Pos].left -= rcGripper.left;
2458 m_TrayRects[Pos].bottom -= rcGripper.bottom;
2459 m_TrayRects[Pos].right -= rcGripper.right;
2460 }
2461 }
2462 }
2466 }
2467
2468 return bPrevLock;
2469 }
2470
2471 /* The task window is visible and non-WS_EX_TOOLWINDOW and
2472 { has WS_EX_APPWINDOW style or has no owner } and is none of explorer's
2473 special windows (such as the desktop or the tray window) */
2475 {
2477 {
2479 if (((exStyle & WS_EX_APPWINDOW) || ::GetWindow(hWnd, GW_OWNER) == NULL) &&
2480 !(exStyle & WS_EX_TOOLWINDOW))
2481 {
2482 return TRUE;
2483 }
2484 }
2485 return FALSE;
2486 }
2487
2488 /*
2489 * IContextMenu
2490 */
2492 UINT indexMenu,
2493 UINT idCmdFirst,
2494 UINT idCmdLast,
2495 UINT uFlags)
2496 {
2497 if (!m_ContextMenu)
2498 {
2501 return hr;
2502 }
2503
2504 return m_ContextMenu->QueryContextMenu(hPopup, indexMenu, idCmdFirst, idCmdLast, uFlags);
2505 }
2506
2508 {
2509 if (!m_ContextMenu)
2510 return E_INVALIDARG;
2511
2512 return m_ContextMenu->InvokeCommand(lpici);
2513 }
2514
2516 UINT uType,
2517 UINT *pwReserved,
2518 LPSTR pszName,
2519 UINT cchMax)
2520 {
2521 if (!m_ContextMenu)
2522 return E_INVALIDARG;
2523
2524 return m_ContextMenu->GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);
2525 }
2526
2527 BOOL IsShowDesktopButtonNeeded() // Read the registry value
2528 {
2529 return SHRegGetBoolUSValueW(
2530 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
2531 L"TaskbarSd",
2532 FALSE,
2533 TRUE);
2534 }
2535
2536 /**********************************************************
2537 * ##### message handling #####
2538 */
2539
2541 {
2542 HRESULT hRet;
2543
2544 ((ITrayWindow*)this)->AddRef();
2545
2546 SetWindowTheme(m_hWnd, L"TaskBar", NULL);
2547
2548 /* Create the Start button */
2550
2551 /* Create the 'Show Desktop' button if necessary */
2554
2555 /* Load the saved tray window settings */
2557
2558 /* Create and initialize the start menu */
2560 m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
2561
2562 /* Create the task band */
2564 if (FAILED_UNEXPECTEDLY(hRet))
2565 return FALSE;
2566
2567 /* Create the rebar band site. This actually creates the rebar and the tasks toolbar. */
2569 if (FAILED_UNEXPECTEDLY(hRet))
2570 return FALSE;
2571
2572 /* Create the tray notification window */
2574 if (FAILED_UNEXPECTEDLY(hRet))
2575 return FALSE;
2576
2577 /* Get the hwnd of the rebar */
2579 if (FAILED_UNEXPECTEDLY(hRet))
2580 return FALSE;
2581
2582 /* Get the hwnd of the tasks toolbar */
2584 if (FAILED_UNEXPECTEDLY(hRet))
2585 return FALSE;
2586
2587 /* Get the hwnd of the tray notification window */
2589 if (FAILED_UNEXPECTEDLY(hRet))
2590 return FALSE;
2591
2592 SetWindowTheme(m_Rebar, L"TaskBar", NULL);
2593
2594 UpdateFonts();
2595
2597
2599 {
2602 }
2603
2604 /* Set the initial lock state in the band site */
2606
2619
2620 return TRUE;
2621 }
2622
2623#define TIMER_ID_IGNOREPULSERESET 888
2624#define TIMER_IGNOREPULSERESET_TIMEOUT 200
2625
2627 {
2629 return 0;
2630 }
2631
2633 {
2634 if (m_Theme)
2636
2637 m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
2638
2639 if (m_Theme)
2640 {
2642 }
2643 else
2644 {
2646 }
2648
2649 return TRUE;
2650 }
2651
2653 {
2654 if (wParam == SPI_SETNONCLIENTMETRICS)
2655 {
2658 UpdateFonts();
2661 }
2662
2663 return 0;
2664 }
2665
2667 {
2668 HDC hdc = (HDC) wParam;
2669
2670 if (!m_Theme)
2671 {
2672 bHandled = FALSE;
2673 return 0;
2674 }
2675
2677 }
2678
2680 {
2681 /* Load the saved tray window settings */
2683
2684 /* Move the tray window to the right position and resize it if necessary */
2686
2687 return TRUE;
2688 }
2689
2691 {
2692 COPYDATASTRUCT *pCopyData = reinterpret_cast<COPYDATASTRUCT *>(lParam);
2693 switch (pCopyData->dwData)
2694 {
2695 case TABDMC_APPBAR:
2696 return appbar_message(pCopyData);
2697 case TABDMC_NOTIFY:
2698 case TABDMC_LOADINPROC:
2699 return ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
2700 }
2701 return FALSE;
2702 }
2703
2704 // We have to draw non-client area because the 'Show Desktop' button is beyond client area.
2706 {
2708 return;
2709 // Get the rectangle in window coordinates
2710 RECT rcButton, rcWnd;
2711 GetWindowRect(&rcWnd);
2713 ::OffsetRect(&rcButton, -rcWnd.left, -rcWnd.top);
2714
2716 m_ShowDesktopButton.OnDraw(hdc, &rcButton); // Draw the button
2717 ReleaseDC(hdc);
2718 }
2719
2721 {
2722 DefWindowProc(uMsg, wParam, lParam);
2723 bHandled = TRUE;
2724
2726 {
2727 DrawShowDesktopButton(); // We have to draw non-client area
2728 return 0;
2729 }
2730
2731 DrawSizerWithTheme((HRGN) wParam);
2732 DrawShowDesktopButton(); // We have to draw non-client area
2733 return 0;
2734 }
2735
2737 {
2740 }
2741
2743 {
2744 RECT rcClient;
2745 POINT pt;
2746
2748 {
2749 /* The user may not be able to resize the tray window.
2750 Pretend like the window is not sizeable when the user
2751 clicks on the border. */
2752 return HTBORDER;
2753 }
2754
2756 if (GetClientRect(&rcClient) &&
2757 (MapWindowPoints(NULL, (LPPOINT) &rcClient, 2) != 0 || GetLastError() == ERROR_SUCCESS))
2758 {
2759 pt.x = (SHORT) LOWORD(lParam);
2760 pt.y = (SHORT) HIWORD(lParam);
2761
2762 if (PtInRect(&rcClient, pt))
2763 {
2764 /* The user is trying to drag the tray window */
2765 return HTCAPTION;
2766 }
2767
2768 /* Depending on the position of the tray window, allow only
2769 changing the border next to the monitor working area */
2770 switch (m_Position)
2771 {
2772 case ABE_TOP:
2773 if (pt.y > rcClient.bottom)
2774 return HTBOTTOM;
2775 break;
2776 case ABE_LEFT:
2777 if (pt.x > rcClient.right)
2778 return HTRIGHT;
2779 break;
2780 case ABE_RIGHT:
2781 if (pt.x < rcClient.left)
2782 return HTLEFT;
2783 break;
2784 case ABE_BOTTOM:
2785 default:
2786 if (pt.y < rcClient.top)
2787 return HTTOP;
2788 break;
2789 }
2790 }
2791 return HTBORDER;
2792 }
2793
2795 {
2796 POINT ptCursor;
2797 PRECT pRect = (PRECT) lParam;
2798
2799 /* We need to ensure that an application can not accidently
2800 move the tray window (using SetWindowPos). However, we still
2801 need to be able to move the window in case the user wants to
2802 drag the tray window to another position or in case the user
2803 wants to resize the tray window. */
2804 if (!g_TaskbarSettings.bLock && GetCursorPos(&ptCursor))
2805 {
2806 IsDragging = TRUE;
2808 }
2809 else
2810 {
2811 *pRect = m_TrayRects[m_Position];
2812 }
2813 return TRUE;
2814 }
2815
2817 {
2818 PRECT pRect = (PRECT) lParam;
2819
2821 {
2822 FitToRebar(pRect);
2823 }
2824 else
2825 {
2826 *pRect = m_TrayRects[m_Position];
2827 }
2828 return TRUE;
2829 }
2830
2832 {
2834 return TRUE;
2835 }
2836
2838 {
2839 RECT rcClient;
2840 if (wParam == SIZE_RESTORED && lParam == 0)
2841 {
2843 /* Clip the tray window on multi monitor systems so the edges can't
2844 overlap into another monitor */
2846
2847 if (!GetClientRect(&rcClient))
2848 {
2849 return FALSE;
2850 }
2851 }
2852 else
2853 {
2854 rcClient.left = rcClient.top = 0;
2855 rcClient.right = LOWORD(lParam);
2856 rcClient.bottom = HIWORD(lParam);
2857 }
2858
2859 AlignControls(&rcClient);
2860 return TRUE;
2861 }
2862
2864 {
2865 InSizeMove = TRUE;
2866 IsDragging = FALSE;
2868 {
2869 /* Remove the clipping on multi monitor systems while dragging around */
2871 }
2872 return TRUE;
2873 }
2874
2876 {
2877 InSizeMove = FALSE;
2879 {
2881
2882 /* Apply clipping */
2884 }
2885 return TRUE;
2886 }
2887
2889 {
2890 switch (wParam)
2891 {
2892 case TEXT(' '):
2893 {
2894 /* The user pressed Alt+Space, this usually brings up the system menu of a window.
2895 The tray window needs to handle this specially, since it normally doesn't have
2896 a system menu. */
2897
2898 static const UINT uidDisableItem [] = {
2899 SC_RESTORE,
2900 SC_MOVE,
2901 SC_SIZE,
2904 };
2905 HMENU hSysMenu;
2906 UINT i, uId;
2907
2908 /* temporarily enable the system menu */
2910
2911 hSysMenu = GetSystemMenu(FALSE);
2912 if (hSysMenu != NULL)
2913 {
2914 /* Disable all items that are not relevant */
2915 for (i = 0; i < _countof(uidDisableItem); i++)
2916 {
2917 EnableMenuItem(hSysMenu,
2918 uidDisableItem[i],
2920 }
2921
2922 EnableMenuItem(hSysMenu,
2923 SC_CLOSE,
2924 MF_BYCOMMAND |
2926
2927 /* Display the system menu */
2928 uId = TrackMenu(
2929 hSysMenu,
2930 NULL,
2933 FALSE);
2934 if (uId != 0)
2935 {
2937 }
2938 }
2939
2940 /* revert the system menu window style */
2942 break;
2943 }
2944
2945 default:
2946 bHandled = FALSE;
2947 }
2948 return TRUE;
2949 }
2950
2952 {
2953 /* This handler implements the trick that makes the start button to
2954 get pressed when the user clicked left or below the button */
2955
2957 WINDOWINFO wi = {sizeof(WINDOWINFO)};
2958
2959 bHandled = FALSE;
2960
2961 RECT rcStartBtn;
2962 m_StartButton.GetWindowRect(&rcStartBtn);
2963
2964 GetWindowInfo(m_hWnd, &wi);
2965
2966 switch (m_Position)
2967 {
2968 case ABE_TOP:
2969 case ABE_LEFT:
2970 {
2971 if (pt.x > rcStartBtn.right || pt.y > rcStartBtn.bottom)
2972 return 0;
2973 break;
2974 }
2975 case ABE_RIGHT:
2976 {
2977 if (pt.x < rcStartBtn.left || pt.y > rcStartBtn.bottom)
2978 return 0;
2979
2980 if (rcStartBtn.right + (int)wi.cxWindowBorders * 2 + 1 < wi.rcWindow.right &&
2981 pt.x > rcStartBtn.right)
2982 {
2983 return 0;
2984 }
2985 break;
2986 }
2987 case ABE_BOTTOM:
2988 {
2989 if (pt.x > rcStartBtn.right || pt.y < rcStartBtn.top)
2990 return 0;
2991
2992 if (rcStartBtn.bottom + (int)wi.cyWindowBorders * 2 + 1 < wi.rcWindow.bottom &&
2993 pt.y > rcStartBtn.bottom)
2994 {
2995 return 0;
2996 }
2997
2998 break;
2999 }
3000 }
3001
3002 bHandled = TRUE;
3004 return 0;
3005 }
3006
3008 {
3009 /* We want the user to be able to get a context menu even on the nonclient
3010 area (including the sizing border)! */
3011 uMsg = WM_CONTEXTMENU;
3012 wParam = (WPARAM) m_hWnd;
3013
3014 return OnContextMenu(uMsg, wParam, lParam, bHandled);
3015 }
3016
3018 {
3019 LRESULT Ret = FALSE;
3020 POINT pt, *ppt = NULL;
3021 HWND hWndExclude = NULL;
3022
3023 /* Check if the administrator has forbidden access to context menus */
3025 return FALSE;
3026
3027 pt.x = (SHORT) LOWORD(lParam);
3028 pt.y = (SHORT) HIWORD(lParam);
3029
3030 if (pt.x != -1 || pt.y != -1)
3031 ppt = &pt;
3032 else
3033 hWndExclude = m_StartButton.m_hWnd;
3034
3036 {
3037 /* Make sure we can't track the context menu if the start
3038 menu is currently being shown */
3040 {
3041 CComPtr<IContextMenu> ctxMenu;
3043 TrackCtxMenu(ctxMenu, ppt, hWndExclude, m_Position == ABE_BOTTOM, this);
3044 }
3045 }
3046 else
3047 {
3048 /* See if the context menu should be handled by the task band site */
3049 if (ppt != NULL && m_TrayBandSite != NULL)
3050 {
3051 HWND hWndAtPt;
3052 POINT ptClient = *ppt;
3053
3054 /* Convert the coordinates to client-coordinates */
3055 ::MapWindowPoints(NULL, m_hWnd, &ptClient, 1);
3056
3057 hWndAtPt = ChildWindowFromPoint(ptClient);
3058 if (hWndAtPt != NULL &&
3059 (hWndAtPt == m_Rebar || ::IsChild(m_Rebar, hWndAtPt)))
3060 {
3061 /* Check if the user clicked on the task switch window */
3062 ptClient = *ppt;
3063 ::MapWindowPoints(NULL, m_Rebar, &ptClient, 1);
3064
3066 if (hWndAtPt == m_TaskSwitch)
3067 goto HandleTrayContextMenu;
3068
3069 /* Forward the message to the task band site */
3070 m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret);
3071 }
3072 else
3073 goto HandleTrayContextMenu;
3074 }
3075 else
3076 {
3077HandleTrayContextMenu:
3078 /* Tray the default tray window context menu */
3079 TrackCtxMenu(this, ppt, NULL, FALSE, this);
3080 }
3081 }
3082 return Ret;
3083 }
3084
3086 {
3087 LRESULT Ret = FALSE;
3088 /* FIXME: We can't check with IsChild whether the hwnd is somewhere inside
3089 the rebar control! But we shouldn't forward messages that the band
3090 site doesn't handle, such as other controls (start button, tray window */
3091
3092 HRESULT hr = E_FAIL;
3093
3094 if (m_TrayBandSite)
3095 {
3096 hr = m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret);
3097 if (SUCCEEDED(hr))
3098 return Ret;
3099 }
3100
3101 if (m_TrayBandSite == NULL || FAILED(hr))
3102 {
3103 const NMHDR *nmh = (const NMHDR *) lParam;
3104
3105 if (nmh->hwndFrom == m_TrayNotify)
3106 {
3107 switch (nmh->code)
3108 {
3109 case NTNWM_REALIGN:
3110 /* Cause all controls to be aligned */
3112 break;
3113 }
3114 }
3115 }
3116 return Ret;
3117 }
3118
3120 {
3122 if (m_ShowDesktopButton.PtInButton(pt)) // Did you click the button?
3123 {
3125 bHandled = TRUE;
3126 return TRUE;
3127 }
3128
3129 return FALSE;
3130 }
3131
3133 {
3134 /* Let the clock handle the double click */
3136
3137 /* We "handle" this message so users can't cause a weird maximize/restore
3138 window animation when double-clicking the tray window! */
3139 return TRUE;
3140 }
3141
3143 {
3145 return FALSE;
3146 }
3147
3149 {
3150 DestroyWindow();
3151 return TRUE;
3152 }
3153
3155 {
3156 HWND hwndStartMenu;
3157 HRESULT hr = IUnknown_GetWindow(m_StartMenuPopup, &hwndStartMenu);
3159 return FALSE;
3160
3161 if (::IsWindowVisible(hwndStartMenu))
3162 HideStartMenu();
3163 else
3165
3166 return TRUE;
3167 }
3168
3170 {
3171 /*
3172 * TWM_DOEXITWINDOWS is send by the CDesktopBrowser to us
3173 * to show the shutdown dialog. Also a WM_CLOSE message sent
3174 * by apps should show the dialog.
3175 */
3176 return DoExitWindows();
3177 }
3178
3180 {
3181 if (wParam == SC_CLOSE)
3182 {
3183 return DoExitWindows();
3184 }
3185
3186 bHandled = FALSE;
3187 return TRUE;
3188 }
3189
3191 {
3192 bHandled = TRUE;
3193 return (LRESULT)m_TaskSwitch;
3194 }
3195
3196 void RestoreMinimizedNonTaskWnds(BOOL bDestroyed, HWND hwndActive)
3197 {
3198 for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
3199 {
3200 HWND hwnd = g_MinimizedAll[i].hwnd;
3201 if (!hwnd || hwndActive == hwnd)
3202 continue;
3203
3206 {
3207 ::SetWindowPlacement(hwnd, &g_MinimizedAll[i].wndpl); // Restore
3208 }
3209 }
3210
3212
3213 if (!bDestroyed)
3214 ::SetForegroundWindow(hwndActive);
3215 }
3216
3218 {
3219 if (IgnorePulse)
3220 return 0;
3221
3223 IgnorePulse = TRUE;
3226 return 0;
3227 }
3228
3230 {
3231 return HandleHotKey(wParam);
3232 }
3233
3235 {
3241 };
3242
3244 {
3245 WCHAR szClass[32];
3246 GetClassNameW(hwnd, szClass, _countof(szClass));
3247 return wcscmp(szClass, L"#32770") == 0;
3248 }
3249
3251 {
3253 if (hwnd == info->hwndDesktop || hwnd == info->hTrayWnd || hwnd == info->hwndProgman)
3254 return TRUE; // Ignore special windows
3255
3256 if (!info->bShowDesktop)
3257 {
3259 return TRUE;
3260 HWND hwndOwner = ::GetWindow(hwnd, GW_OWNER);
3261 if (hwndOwner && !::IsWindowEnabled(hwndOwner))
3262 return TRUE;
3263 }
3264
3266 {
3267 MINWNDPOS mwp;
3268 mwp.hwnd = hwnd;
3269 mwp.wndpl.length = sizeof(mwp.wndpl);
3270 ::GetWindowPlacement(hwnd, &mwp.wndpl); // Save the position and status
3271
3272 info->pMinimizedAll->Add(mwp);
3273
3275 }
3276
3277 return TRUE;
3278 }
3279
3280 VOID MinimizeAll(BOOL bShowDesktop = FALSE)
3281 {
3282 IgnorePulse = TRUE;
3284
3286 info.hwndDesktop = GetDesktopWindow();;
3287 info.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
3288 info.hwndProgman = FindWindowW(L"Progman", NULL);
3289 info.pMinimizedAll = &g_MinimizedAll;
3290 info.bShowDesktop = bShowDesktop;
3292
3296 }
3297
3299 {
3301 }
3302
3304 {
3305 IgnorePulse = TRUE;
3307
3308 for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
3309 {
3310 HWND hwnd = g_MinimizedAll[i].hwnd;
3312 {
3314 }
3315 }
3316
3319 }
3320
3322 {
3323 LRESULT Ret = FALSE;
3324
3326 {
3327 return FALSE;
3328 }
3329
3330 if (m_TrayBandSite == NULL || FAILED_UNEXPECTEDLY(m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret)))
3331 {
3332 return HandleCommand(LOWORD(wParam));
3333 }
3334 return Ret;
3335 }
3336
3338 {
3339 POINT pt;
3343
3345 {
3347 }
3348
3349 return TRUE;
3350 }
3351
3353 {
3355 {
3357 }
3358 else if (wParam == TIMER_ID_AUTOHIDE)
3359 {
3361 }
3363 {
3366 }
3367 return 0;
3368 }
3369
3371 {
3373 DrawShowDesktopButton(); // We have to draw non-client area
3374 bHandled = TRUE;
3375 return ret;
3376 }
3377
3379 {
3380 RECT *rc = NULL;
3381 /* Ignore WM_NCCALCSIZE if we are not themed or locked */
3383 {
3384 bHandled = FALSE;
3385 return 0;
3386 }
3387 if(!wParam)
3388 {
3389 rc = (RECT*)wParam;
3390 }
3391 else
3392 {
3394 if(prms->lppos->flags & SWP_NOSENDCHANGING)
3395 {
3396 bHandled = FALSE;
3397 return 0;
3398 }
3399 rc = &prms->rgrc[0];
3400 }
3401
3403
3404 return 0;
3405 }
3406
3408 {
3409 HMENU hMenu = (HMENU)wParam;
3411 {
3415 if (g_Arrangement != NONE)
3416 {
3419 MENUITEMINFOW mii = { sizeof(mii) };
3421 mii.fMask = MIIM_TYPE;
3422 mii.fType = MFT_STRING;
3423 mii.dwTypeData = const_cast<LPWSTR>(&strCaption[0]);
3425 }
3426 else
3427 {
3429 }
3430 }
3431 else
3432 {
3438 g_WindowPosBackup.RemoveAll();
3439 }
3440 return 0;
3441 }
3442
3444 {
3445#if 0
3446 LPNMRBAUTOSIZE as = (LPNMRBAUTOSIZE) nmhdr;
3447
3448 if (!as->fChanged)
3449 return 0;
3450
3451 RECT rc;
3452 ::GetWindowRect(m_hWnd, &rc);
3453
3454 SIZE szWindow = {
3455 rc.right - rc.left,
3456 rc.bottom - rc.top };
3457 SIZE szTarget = {
3458 as->rcTarget.right - as->rcTarget.left,
3459 as->rcTarget.bottom - as->rcTarget.top };
3460 SIZE szActual = {
3461 as->rcActual.right - as->rcActual.left,
3462 as->rcActual.bottom - as->rcActual.top };
3463
3464 SIZE borders = {
3465 szWindow.cx - szTarget.cx,
3466 szWindow.cy - szTarget.cx,
3467 };
3468
3469 switch (m_Position)
3470 {
3471 case ABE_LEFT:
3472 szWindow.cx = szActual.cx + borders.cx;
3473 break;
3474 case ABE_TOP:
3475 szWindow.cy = szActual.cy + borders.cy;
3476 break;
3477 case ABE_RIGHT:
3478 szWindow.cx = szActual.cx + borders.cx;
3479 rc.left = rc.right - szWindow.cy;
3480 break;
3481 case ABE_BOTTOM:
3482 szWindow.cy = szActual.cy + borders.cy;
3483 rc.top = rc.bottom - szWindow.cy;
3484 break;
3485 }
3486
3487 SetWindowPos(NULL, rc.left, rc.top, szWindow.cx, szWindow.cy, SWP_NOACTIVATE | SWP_NOZORDER);
3488#else
3489 bHandled = FALSE;
3490#endif
3491 return 0;
3492 }
3493
3495 {
3496 TaskbarSettings* newSettings = (TaskbarSettings*)lParam;
3497
3498 /* Propagate the new settings to the children */
3501
3502 /* Toggle autohide */
3503 if (newSettings->sr.AutoHide != g_TaskbarSettings.sr.AutoHide)
3504 {
3505 g_TaskbarSettings.sr.AutoHide = newSettings->sr.AutoHide;
3508 if (!newSettings->sr.AutoHide)
3510 else
3512 }
3513
3514 /* Toggle lock state */
3515 Lock(newSettings->bLock);
3516
3517 /* Toggle OnTop state */
3518 if (newSettings->sr.AlwaysOnTop != g_TaskbarSettings.sr.AlwaysOnTop)
3519 {
3521 HWND hWndInsertAfter = newSettings->sr.AlwaysOnTop ? HWND_TOPMOST : HWND_BOTTOM;
3522 SetWindowPos(hWndInsertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
3523 }
3524
3526 return 0;
3527 }
3528
3530
3533 {
3534 MSG Msg;
3535 LRESULT lRet;
3536
3537 Msg.hwnd = m_hWnd;
3538 Msg.message = uMsg;
3539 Msg.wParam = wParam;
3540 Msg.lParam = lParam;
3541
3542 if (m_StartMenuBand->TranslateMenuMessage(&Msg, &lRet) == S_OK)
3543 {
3544 return lRet;
3545 }
3546
3547 wParam = Msg.wParam;
3548 lParam = Msg.lParam;
3549 }
3550 MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
3552 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnRebarAutoSize) // Doesn't quite work ;P
3563 MESSAGE_HANDLER(WM_DISPLAYCHANGE, OnDisplayChange)
3590 ALT_MSG_MAP(1)
3591 END_MSG_MAP()
3592
3593 /*****************************************************************************/
3594
3596 {
3597 MSG Msg;
3598
3599 /* FIXME: We should keep a reference here... */
3600
3601 while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
3602 {
3603 if (Msg.message == WM_QUIT)
3604 break;
3605
3606 if (m_StartMenuBand == NULL ||
3607 m_StartMenuBand->IsMenuMessage(&Msg) != S_OK)
3608 {
3611 }
3612 }
3613 }
3614
3616 {
3617 MSG Msg;
3618 BOOL Ret;
3619
3620 /* FIXME: We should keep a reference here... */
3621
3622 while (true)
3623 {
3624 Ret = GetMessage(&Msg, NULL, 0, 0);
3625
3626 if (!Ret || Ret == -1)
3627 break;
3628
3629 if (m_StartMenuBand == NULL ||
3630 m_StartMenuBand->IsMenuMessage(&Msg) != S_OK)
3631 {
3634 }
3635 }
3636 }
3637
3638 /*
3639 * IShellDesktopTray
3640 *
3641 * NOTE: this is a very windows-specific COM interface used by SHCreateDesktop()!
3642 * These are the calls I observed, it may be wrong/incomplete/buggy!!!
3643 * The reason we implement it is because we have to use SHCreateDesktop() so
3644 * that the shell provides the desktop window and all the features that come
3645 * with it (especially positioning of desktop icons)
3646 */
3647
3649 {
3650 /* FIXME: Return ABS_ flags? */
3651 TRACE("IShellDesktopTray::GetState() unimplemented!\n");
3652 return 0;
3653 }
3654
3656 {
3657 TRACE("IShellDesktopTray::GetTrayWindow(0x%p)\n", phWndTray);
3658 *phWndTray = m_hWnd;
3659 return S_OK;
3660 }
3661
3663 {
3664 TRACE("IShellDesktopTray::RegisterDesktopWindow(0x%p)\n", hWndDesktop);
3665
3666 m_DesktopWnd = hWndDesktop;
3667 return S_OK;
3668 }
3669
3670 virtual HRESULT STDMETHODCALLTYPE Unknown(IN DWORD dwUnknown1, IN DWORD dwUnknown2)
3671 {
3672 TRACE("IShellDesktopTray::Unknown(%u,%u) unimplemented!\n", dwUnknown1, dwUnknown2);
3673 return S_OK;
3674 }
3675
3677 {
3678 m_StartButton.SendMessageW(BM_SETSTATE, FALSE, 0);
3679 return S_OK;
3680 }
3681
3683 {
3684 if (!phwnd)
3685 return E_INVALIDARG;
3686 *phwnd = m_hWnd;
3687 return S_OK;
3688 }
3689
3691 {
3692 return E_NOTIMPL;
3693 }
3694
3695 void _Init()
3696 {
3697 m_Position = (DWORD) -1;
3698 }
3699
3701
3704 /*COM_INTERFACE_ENTRY_IID(IID_ITrayWindow, ITrayWindow)*/
3707 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
3708 END_COM_MAP()
3709};
3710
3714 public IContextMenu
3715{
3720
3721public:
3722 HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
3723 {
3724 this->TrayWnd = (CTrayWindow *) pTrayWnd;
3725 this->hWndOwner = hWndOwner;
3726 this->m_idCmdCmFirst = 0;
3727 return S_OK;
3728 }
3729
3732 UINT indexMenu,
3733 UINT idCmdFirst,
3734 UINT idCmdLast,
3735 UINT uFlags)
3736 {
3737 HMENU hMenuBase;
3738
3740
3742 {
3744 MENUITEMINFOW mii = { sizeof(mii) };
3745 mii.fMask = MIIM_ID | MIIM_TYPE;
3747 mii.fType = MFT_STRING;
3748 mii.dwTypeData = const_cast<LPWSTR>(&strRestoreAll[0]);
3750 }
3751
3752 if (!hMenuBase)
3754
3756 {
3757 DeleteMenu(hPopup,
3759 MF_BYCOMMAND);
3760 }
3761
3762 CheckMenuItem(hMenuBase,
3765
3766 UINT idCmdNext;
3767 idCmdNext = Shell_MergeMenus(hPopup, hMenuBase, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
3768 m_idCmdCmFirst = idCmdNext - idCmdFirst;
3769
3770 ::DestroyMenu(hMenuBase);
3771
3772 if (TrayWnd->m_TrayBandSite != NULL)
3773 {
3774 pcm.Release();
3775 if (FAILED(TrayWnd->m_TrayBandSite->AddContextMenus(
3776 hPopup,
3777 indexMenu,
3778 idCmdNext,
3779 idCmdLast,
3780 CMF_NORMAL,
3781 &pcm)))
3782 {
3783 WARN("AddContextMenus failed.\n");
3784 pcm.Release();
3785 }
3786 }
3787
3788 return S_OK;
3789 }
3790
3793 {
3794 UINT uiCmdId = PtrToUlong(lpici->lpVerb);
3795 if (uiCmdId != 0)
3796 {
3797 if (uiCmdId >= m_idCmdCmFirst)
3798 {
3799 CMINVOKECOMMANDINFO cmici = { 0 };
3800
3801 if (pcm != NULL)
3802 {
3803 /* Setup and invoke the shell command */
3804 cmici.cbSize = sizeof(cmici);
3805 cmici.hwnd = hWndOwner;
3806 cmici.lpVerb = (LPCSTR) MAKEINTRESOURCEW(uiCmdId - m_idCmdCmFirst);
3807 cmici.nShow = SW_NORMAL;
3808
3809 pcm->InvokeCommand(&cmici);
3810 }
3811 }
3812 else
3813 {
3814 TrayWnd->ExecContextMenuCmd(uiCmdId);
3815 }
3816 }
3817
3818 return S_OK;
3819 }
3820
3823 UINT uType,
3824 UINT *pwReserved,
3825 LPSTR pszName,
3826 UINT cchMax)
3827 {
3828 return E_NOTIMPL;
3829 }
3830
3832 {
3833 }
3834
3836 {
3837 }
3838
3840 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
3841 END_COM_MAP()
3842};
3843
3844HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu)
3845{
3847 mnu->Initialize(TrayWnd, hWndOwner);
3848 *ppCtxMenu = mnu;
3849 return S_OK;
3850}
3851
3852HRESULT CreateTrayWindow(ITrayWindow ** ppTray)
3853{
3855 if (Tray == NULL)
3856 return E_OUTOFMEMORY;
3857
3858 Tray->_Init();
3859 Tray->Open();
3860
3861 *ppTray = (ITrayWindow *) Tray;
3862
3863 return S_OK;
3864}
3865
3866HRESULT
3868{
3869 CTrayWindow * TrayWindow = static_cast<CTrayWindow *>(Tray);
3870 return TrayWindow->RaiseStartButton();
3871}
3872
3873VOID TrayProcessMessages(ITrayWindow *Tray)
3874{
3875 CTrayWindow * TrayWindow = static_cast<CTrayWindow *>(Tray);
3876 TrayWindow->TrayProcessMessages();
3877}
3878
3879VOID TrayMessageLoop(ITrayWindow *Tray)
3880{
3881 CTrayWindow * TrayWindow = static_cast<CTrayWindow *>(Tray);
3882 TrayWindow->TrayMessageLoop();
3883}
@ TS_TRUE
UINT cchMax
Arabic default style
Definition: afstyles.h:94
static int state
Definition: maze.c:121
HWND hWnd
Definition: settings.c:17
const WCHAR * class
Definition: main.c:68
#define IDB_START
Definition: resource.h:75
#define IDS_START
Definition: resource.h:23
static RECT margins
Definition: print.c:55
@ Create
Definition: registry.c:563
HINSTANCE hExplorerInstance
Definition: explorer.cpp:24
VOID DisplayTrayProperties(IN HWND hwndOwner, IN HWND hwndTaskbar)
Definition: trayprop.cpp:291
#define TWM_OPENSTARTMENU
Definition: precomp.h:131
#define TSWM_UPDATETASKBARPOS
Definition: precomp.h:350
#define TNWM_GETMINIMUMSIZE
Definition: precomp.h:336
HRESULT CStartMenuBtnCtxMenu_CreateInstance(ITrayWindow *TrayWnd, IN HWND hWndOwner, IContextMenu **ppCtxMenu)
HMENU LoadPopupMenu(IN HINSTANCE hInstance, IN LPCWSTR lpMenuName)
Definition: util.cpp:33
#define TWM_GETTASKSWITCH
Definition: precomp.h:130
IMenuPopup * CreateStartMenu(IN ITrayWindow *Tray, OUT IMenuBand **ppMenuBand, IN HBITMAP hbmBanner OPTIONAL, IN BOOL bSmallIcons)
Definition: startmnu.cpp:44
TaskbarSettings g_TaskbarSettings
Definition: settings.cpp:23
#define TWM_PULSE
Definition: precomp.h:133
HRESULT CTrayNotifyWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
Definition: trayntfy.cpp:372
HRESULT CTrayBandSite_CreateInstance(IN ITrayWindow *tray, IN IDeskBand *pTaskBand, OUT ITrayBandSite **pBandSite)
Definition: tbsite.cpp:715
#define TWM_SETTINGSCHANGED
Definition: precomp.h:132
#define NTNWM_REALIGN
Definition: precomp.h:339
HRESULT InitShellServices(HDPA *phdpa)
HRESULT CTaskBand_CreateInstance(IN ITrayWindow *Tray, HWND hWndStartButton, REFIID riid, void **ppv)
Definition: taskband.cpp:346
HRESULT ShutdownShellServices(HDPA hdpa)
#define IDM_SEARCH
Definition: resource.h:71
#define ID_SHELL_CMD_OPEN_TASKMGR
Definition: resource.h:191
#define ID_SHELL_CMD_CUST_NOTIF
Definition: resource.h:197
#define ID_SHELL_CMD_UNDO_ACTION
Definition: resource.h:192
#define IDS_RESTORE_ALL
Definition: resource.h:104
#define IDM_TRAYWND
Definition: resource.h:57
#define ID_SHELL_CMD_PROPERTIES
Definition: resource.h:187
#define IDB_STARTMENU
Definition: resource.h:44
#define ID_SHELL_CMD_TILE_WND_H
Definition: resource.h:195
#define IDS_TRAYWND_UNDO_TILE
Definition: resource.h:106
#define IDC_STARTBTN
Definition: resource.h:135
#define ID_SHELL_CMD_CASCADE_WND
Definition: resource.h:196
#define ID_SHELL_CMD_RESTORE_ALL
Definition: resource.h:199
#define ID_SHELL_CMD_TILE_WND_V
Definition: resource.h:194
#define ID_LOCKTASKBAR
Definition: resource.h:190
#define ID_SHELL_CMD_SHOW_DESKTOP
Definition: resource.h:193
#define IDS_TRAYWND_UNDO_CASCADE
Definition: resource.h:105
#define ID_SHELL_CMD_EXPLORE_ALL_USERS
Definition: resource.h:189
#define ID_SHELL_CMD_ADJUST_DAT
Definition: resource.h:198
#define IDS_HELP_COMMAND
Definition: resource.h:102
#define ID_SHELL_CMD_OPEN_ALL_USERS
Definition: resource.h:188
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
void Release()
Definition: atlcomcli.h:147
int GetSize() const
Definition: atlsimpcoll.h:104
BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar)
Definition: cstringt.h:610
BOOL IsIconic() const
Definition: atlwin.h:926
HWND GetLastActivePopup() const
Definition: atlwin.h:670
HWND SetFocus()
Definition: atlwin.h:1192
BOOL DestroyWindow()
Definition: atlwin.h:456
LRESULT SendMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0)
Definition: atlwin.h:1110
HDC GetWindowDC()
Definition: atlwin.h:778
HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags)
Definition: atlwin.h:450
BOOL GetWindowRect(LPRECT lpRect) const
Definition: atlwin.h:810
CWindow GetParent() const
Definition: atlwin.h:694
BOOL IsWindowVisible() const
Definition: atlwin.h:952
HWND m_hWnd
Definition: atlwin.h:267
BOOL IsWindow() const
Definition: atlwin.h:941
BOOL IsWindowEnabled() const
Definition: atlwin.h:946
BOOL PostMessage(UINT message, WPARAM wParam=0, LPARAM lParam=0)
Definition: atlwin.h:1038
HIMAGELIST m_ImageList
Definition: traywnd.cpp:189
VOID Initialize()
Definition: traywnd.cpp:248
VOID UpdateFont()
Definition: traywnd.cpp:232
LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:299
SIZE GetSize()
Definition: traywnd.cpp:211
VOID UpdateSize()
Definition: traywnd.cpp:216
HWND Create(HWND hwndParent)
Definition: traywnd.cpp:268
HFONT m_Font
Definition: traywnd.cpp:191
virtual ~CStartButton()
Definition: traywnd.cpp:202
LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:374
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:393
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:454
LRESULT OnClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:350
BOOL PtInButton(POINT pt)
Definition: traywnd.cpp:405
HRESULT DoCreate(HWND hwndParent)
Definition: traywnd.cpp:339
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:436
LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:430
VOID OnDraw(HDC hdc, LPRECT prc)
Definition: traywnd.cpp:476
LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
Definition: traywnd.cpp:380
INT WidthOrHeight() const
Definition: traywnd.cpp:332
HRESULT Initialize(ITrayWindow *pTrayWnd, IN HWND hWndOwner)
Definition: traywnd.cpp:3722
virtual HRESULT STDMETHODCALLTYPE QueryContextMenu(HMENU hPopup, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
Definition: traywnd.cpp:3731