xref: /reactos/base/shell/explorer/traywnd.cpp (revision 75b09f3f)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * ReactOS Explorer
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5c84f3983SKatayama Hirofumi MZ  * Copyright 2018 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * this library is free software; you can redistribute it and/or
8c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck  * License as published by the Free Software Foundation; either
10c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck  *
12c2c66affSColin Finck  * this library is distributed in the hope that it will be useful,
13c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15c2c66affSColin Finck  * Lesser General Public License for more details.
16c2c66affSColin Finck  *
17c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20c2c66affSColin Finck  */
21c2c66affSColin Finck 
22c2c66affSColin Finck #include "precomp.h"
23c2c66affSColin Finck #include <commoncontrols.h>
24*75b09f3fSKatayama Hirofumi MZ #include <traycmd.h>
25c2c66affSColin Finck 
26c2c66affSColin Finck HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
27c2c66affSColin Finck 
28c2c66affSColin Finck #define WM_APP_TRAYDESTROY  (WM_APP + 0x100)
29c2c66affSColin Finck 
30c2c66affSColin Finck #define TIMER_ID_AUTOHIDE 1
31c2c66affSColin Finck #define TIMER_ID_MOUSETRACK 2
32c2c66affSColin Finck #define MOUSETRACK_INTERVAL 100
33c2c66affSColin Finck #define AUTOHIDE_DELAY_HIDE 2000
34c2c66affSColin Finck #define AUTOHIDE_DELAY_SHOW 50
35c2c66affSColin Finck #define AUTOHIDE_INTERVAL_ANIMATING 10
36c2c66affSColin Finck 
37c2c66affSColin Finck #define AUTOHIDE_SPEED_SHOW 10
38c2c66affSColin Finck #define AUTOHIDE_SPEED_HIDE 1
39c2c66affSColin Finck 
40c2c66affSColin Finck #define AUTOHIDE_HIDDEN 0
41c2c66affSColin Finck #define AUTOHIDE_SHOWING 1
42c2c66affSColin Finck #define AUTOHIDE_SHOWN 2
43c2c66affSColin Finck #define AUTOHIDE_HIDING 3
44c2c66affSColin Finck 
45c2c66affSColin Finck #define IDHK_RUN 0x1f4
46c2c66affSColin Finck #define IDHK_MINIMIZE_ALL 0x1f5
47c2c66affSColin Finck #define IDHK_RESTORE_ALL 0x1f6
48c2c66affSColin Finck #define IDHK_HELP 0x1f7
49c2c66affSColin Finck #define IDHK_EXPLORE 0x1f8
50c2c66affSColin Finck #define IDHK_FIND 0x1f9
51c2c66affSColin Finck #define IDHK_FIND_COMPUTER 0x1fa
52c2c66affSColin Finck #define IDHK_NEXT_TASK 0x1fb
53c2c66affSColin Finck #define IDHK_PREV_TASK 0x1fc
54c2c66affSColin Finck #define IDHK_SYS_PROPERTIES 0x1fd
55c2c66affSColin Finck #define IDHK_DESKTOP 0x1fe
56c2c66affSColin Finck #define IDHK_PAGER 0x1ff
57c2c66affSColin Finck 
58c2c66affSColin Finck static const WCHAR szTrayWndClass[] = L"Shell_TrayWnd";
59c2c66affSColin Finck 
60*75b09f3fSKatayama Hirofumi MZ struct EFFECTIVE_INFO
61*75b09f3fSKatayama Hirofumi MZ {
62*75b09f3fSKatayama Hirofumi MZ     HWND hwndFound;
63*75b09f3fSKatayama Hirofumi MZ     HWND hwndDesktop;
64*75b09f3fSKatayama Hirofumi MZ     HWND hwndProgman;
65*75b09f3fSKatayama Hirofumi MZ     HWND hTrayWnd;
66*75b09f3fSKatayama Hirofumi MZ     BOOL bMustBeInMonitor;
67*75b09f3fSKatayama Hirofumi MZ };
68*75b09f3fSKatayama Hirofumi MZ 
69*75b09f3fSKatayama Hirofumi MZ static BOOL CALLBACK
70*75b09f3fSKatayama Hirofumi MZ FindEffectiveProc(HWND hwnd, LPARAM lParam)
71*75b09f3fSKatayama Hirofumi MZ {
72*75b09f3fSKatayama Hirofumi MZ     EFFECTIVE_INFO *pei = (EFFECTIVE_INFO *)lParam;
73*75b09f3fSKatayama Hirofumi MZ 
74*75b09f3fSKatayama Hirofumi MZ     if (!IsWindowVisible(hwnd) || IsIconic(hwnd))
75*75b09f3fSKatayama Hirofumi MZ         return TRUE;    // continue
76*75b09f3fSKatayama Hirofumi MZ 
77*75b09f3fSKatayama Hirofumi MZ     if (pei->hTrayWnd == hwnd || pei->hwndDesktop == hwnd ||
78*75b09f3fSKatayama Hirofumi MZ         pei->hwndProgman == hwnd)
79*75b09f3fSKatayama Hirofumi MZ     {
80*75b09f3fSKatayama Hirofumi MZ         return TRUE;    // continue
81*75b09f3fSKatayama Hirofumi MZ     }
82*75b09f3fSKatayama Hirofumi MZ 
83*75b09f3fSKatayama Hirofumi MZ     if (pei->bMustBeInMonitor)
84*75b09f3fSKatayama Hirofumi MZ     {
85*75b09f3fSKatayama Hirofumi MZ         // is the window in the nearest monitor?
86*75b09f3fSKatayama Hirofumi MZ         HMONITOR hMon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
87*75b09f3fSKatayama Hirofumi MZ         if (hMon)
88*75b09f3fSKatayama Hirofumi MZ         {
89*75b09f3fSKatayama Hirofumi MZ             MONITORINFO info;
90*75b09f3fSKatayama Hirofumi MZ             ZeroMemory(&info, sizeof(info));
91*75b09f3fSKatayama Hirofumi MZ             info.cbSize = sizeof(info);
92*75b09f3fSKatayama Hirofumi MZ             if (GetMonitorInfoW(hMon, &info))
93*75b09f3fSKatayama Hirofumi MZ             {
94*75b09f3fSKatayama Hirofumi MZ                 RECT rcWindow, rcMonitor, rcIntersect;
95*75b09f3fSKatayama Hirofumi MZ                 rcMonitor = info.rcMonitor;
96*75b09f3fSKatayama Hirofumi MZ 
97*75b09f3fSKatayama Hirofumi MZ                 GetWindowRect(hwnd, &rcWindow);
98*75b09f3fSKatayama Hirofumi MZ 
99*75b09f3fSKatayama Hirofumi MZ                 if (!IntersectRect(&rcIntersect, &rcMonitor, &rcWindow))
100*75b09f3fSKatayama Hirofumi MZ                     return TRUE;    // continue
101*75b09f3fSKatayama Hirofumi MZ             }
102*75b09f3fSKatayama Hirofumi MZ         }
103*75b09f3fSKatayama Hirofumi MZ     }
104*75b09f3fSKatayama Hirofumi MZ 
105*75b09f3fSKatayama Hirofumi MZ     pei->hwndFound = hwnd;
106*75b09f3fSKatayama Hirofumi MZ     return FALSE;   // stop if found
107*75b09f3fSKatayama Hirofumi MZ }
108*75b09f3fSKatayama Hirofumi MZ 
109*75b09f3fSKatayama Hirofumi MZ static BOOL
110*75b09f3fSKatayama Hirofumi MZ IsThereAnyEffectiveWindow(BOOL bMustBeInMonitor)
111*75b09f3fSKatayama Hirofumi MZ {
112*75b09f3fSKatayama Hirofumi MZ     EFFECTIVE_INFO ei;
113*75b09f3fSKatayama Hirofumi MZ     ei.hwndFound = NULL;
114*75b09f3fSKatayama Hirofumi MZ     ei.hwndDesktop = GetDesktopWindow();
115*75b09f3fSKatayama Hirofumi MZ     ei.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
116*75b09f3fSKatayama Hirofumi MZ     ei.hwndProgman = FindWindowW(L"Progman", NULL);
117*75b09f3fSKatayama Hirofumi MZ     ei.bMustBeInMonitor = bMustBeInMonitor;
118*75b09f3fSKatayama Hirofumi MZ 
119*75b09f3fSKatayama Hirofumi MZ     EnumWindows(FindEffectiveProc, (LPARAM)&ei);
120*75b09f3fSKatayama Hirofumi MZ     if (ei.hwndFound && FALSE)
121*75b09f3fSKatayama Hirofumi MZ     {
122*75b09f3fSKatayama Hirofumi MZ         WCHAR szClass[64], szText[64];
123*75b09f3fSKatayama Hirofumi MZ         GetClassNameW(ei.hwndFound, szClass, _countof(szClass));
124*75b09f3fSKatayama Hirofumi MZ         GetWindowTextW(ei.hwndFound, szText, _countof(szText));
125*75b09f3fSKatayama Hirofumi MZ         MessageBoxW(NULL, szText, szClass, 0);
126*75b09f3fSKatayama Hirofumi MZ     }
127*75b09f3fSKatayama Hirofumi MZ     return ei.hwndFound != NULL;
128*75b09f3fSKatayama Hirofumi MZ }
129*75b09f3fSKatayama Hirofumi MZ 
130*75b09f3fSKatayama Hirofumi MZ CSimpleArray<HWND>  g_MinimizedAll;
131*75b09f3fSKatayama Hirofumi MZ 
132c2c66affSColin Finck /*
133c2c66affSColin Finck  * ITrayWindow
134c2c66affSColin Finck  */
135c2c66affSColin Finck 
136c2c66affSColin Finck const GUID IID_IShellDesktopTray = { 0x213e2df9, 0x9a14, 0x4328, { 0x99, 0xb1, 0x69, 0x61, 0xf9, 0x14, 0x3c, 0xe9 } };
137c2c66affSColin Finck 
138c2c66affSColin Finck class CStartButton
139c2c66affSColin Finck     : public CWindowImpl<CStartButton>
140c2c66affSColin Finck {
141c2c66affSColin Finck     HIMAGELIST m_ImageList;
142c2c66affSColin Finck     SIZE       m_Size;
143c2c66affSColin Finck     HFONT      m_Font;
144c2c66affSColin Finck 
145c2c66affSColin Finck public:
146c2c66affSColin Finck     CStartButton()
147c2c66affSColin Finck         : m_ImageList(NULL),
148c2c66affSColin Finck           m_Font(NULL)
149c2c66affSColin Finck     {
150c2c66affSColin Finck         m_Size.cx = 0;
151c2c66affSColin Finck         m_Size.cy = 0;
152c2c66affSColin Finck     }
153c2c66affSColin Finck 
154c2c66affSColin Finck     virtual ~CStartButton()
155c2c66affSColin Finck     {
156c2c66affSColin Finck         if (m_ImageList != NULL)
157c2c66affSColin Finck             ImageList_Destroy(m_ImageList);
158c2c66affSColin Finck 
159c2c66affSColin Finck         if (m_Font != NULL)
160c2c66affSColin Finck             DeleteObject(m_Font);
161c2c66affSColin Finck     }
162c2c66affSColin Finck 
163c2c66affSColin Finck     SIZE GetSize()
164c2c66affSColin Finck     {
165c2c66affSColin Finck         return m_Size;
166c2c66affSColin Finck     }
167c2c66affSColin Finck 
168c2c66affSColin Finck     VOID UpdateSize()
169c2c66affSColin Finck     {
170c2c66affSColin Finck         SIZE Size = { 0, 0 };
171c2c66affSColin Finck 
172c2c66affSColin Finck         if (m_ImageList == NULL ||
173c2c66affSColin Finck             !SendMessageW(BCM_GETIDEALSIZE, 0, (LPARAM) &Size))
174c2c66affSColin Finck         {
175c2c66affSColin Finck             Size.cx = 2 * GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CYCAPTION) * 3;
176c2c66affSColin Finck         }
177c2c66affSColin Finck 
178c2c66affSColin Finck         Size.cy = max(Size.cy, GetSystemMetrics(SM_CYCAPTION));
179c2c66affSColin Finck 
180c2c66affSColin Finck         /* Save the size of the start button */
181c2c66affSColin Finck         m_Size = Size;
182c2c66affSColin Finck     }
183c2c66affSColin Finck 
184c2c66affSColin Finck     VOID UpdateFont()
185c2c66affSColin Finck     {
186c2c66affSColin Finck         /* Get the system fonts, we use the caption font, always bold, though. */
187c2c66affSColin Finck         NONCLIENTMETRICS ncm = {sizeof(ncm)};
188c2c66affSColin Finck         if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
189c2c66affSColin Finck             return;
190c2c66affSColin Finck 
191c2c66affSColin Finck         if (m_Font)
192c2c66affSColin Finck             DeleteObject(m_Font);
193c2c66affSColin Finck 
194c2c66affSColin Finck         ncm.lfCaptionFont.lfWeight = FW_BOLD;
195c2c66affSColin Finck         m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
196c2c66affSColin Finck 
197c2c66affSColin Finck         SetFont(m_Font, FALSE);
198c2c66affSColin Finck     }
199c2c66affSColin Finck 
200c2c66affSColin Finck     VOID Initialize()
201c2c66affSColin Finck     {
202c2c66affSColin Finck         SubclassWindow(m_hWnd);
203c2c66affSColin Finck         SetWindowTheme(m_hWnd, L"Start", NULL);
204c2c66affSColin Finck 
205c2c66affSColin Finck         m_ImageList = ImageList_LoadImageW(hExplorerInstance,
206c2c66affSColin Finck                                            MAKEINTRESOURCEW(IDB_START),
207c2c66affSColin Finck                                            0, 0, 0,
208c2c66affSColin Finck                                            IMAGE_BITMAP,
209c2c66affSColin Finck                                            LR_LOADTRANSPARENT | LR_CREATEDIBSECTION);
210c2c66affSColin Finck 
211c2c66affSColin Finck         BUTTON_IMAGELIST bil = {m_ImageList, {1,1,1,1}, BUTTON_IMAGELIST_ALIGN_LEFT};
212c2c66affSColin Finck         SendMessageW(BCM_SETIMAGELIST, 0, (LPARAM) &bil);
213c2c66affSColin Finck         UpdateSize();
214c2c66affSColin Finck     }
215c2c66affSColin Finck 
216c2c66affSColin Finck     HWND Create(HWND hwndParent)
217c2c66affSColin Finck     {
218c2c66affSColin Finck         WCHAR szStartCaption[32];
219c2c66affSColin Finck         if (!LoadStringW(hExplorerInstance,
220c2c66affSColin Finck                          IDS_START,
221c2c66affSColin Finck                          szStartCaption,
222c2c66affSColin Finck                          _countof(szStartCaption)))
223c2c66affSColin Finck         {
224c2c66affSColin Finck             wcscpy(szStartCaption, L"Start");
225c2c66affSColin Finck         }
226c2c66affSColin Finck 
227c2c66affSColin Finck         DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | BS_PUSHBUTTON | BS_LEFT | BS_VCENTER;
228c2c66affSColin Finck 
229c2c66affSColin Finck         m_hWnd = CreateWindowEx(
230c2c66affSColin Finck             0,
231c2c66affSColin Finck             WC_BUTTON,
232c2c66affSColin Finck             szStartCaption,
233c2c66affSColin Finck             dwStyle,
234c2c66affSColin Finck             0, 0, 0, 0,
235c2c66affSColin Finck             hwndParent,
236c2c66affSColin Finck             (HMENU) IDC_STARTBTN,
237c2c66affSColin Finck             hExplorerInstance,
238c2c66affSColin Finck             NULL);
239c2c66affSColin Finck 
240c2c66affSColin Finck         if (m_hWnd)
241c2c66affSColin Finck             Initialize();
242c2c66affSColin Finck 
243c2c66affSColin Finck         return m_hWnd;
244c2c66affSColin Finck     }
245c2c66affSColin Finck 
246c2c66affSColin Finck     LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
247c2c66affSColin Finck     {
248c2c66affSColin Finck         if (uMsg == WM_KEYUP && wParam != VK_SPACE)
249c2c66affSColin Finck             return 0;
250c2c66affSColin Finck 
251c2c66affSColin Finck         GetParent().PostMessage(TWM_OPENSTARTMENU);
252c2c66affSColin Finck         return 0;
253c2c66affSColin Finck     }
254c2c66affSColin Finck 
255c2c66affSColin Finck     BEGIN_MSG_MAP(CStartButton)
256c2c66affSColin Finck         MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
257c2c66affSColin Finck     END_MSG_MAP()
258c2c66affSColin Finck 
259c2c66affSColin Finck };
260c2c66affSColin Finck 
261c2c66affSColin Finck class CTrayWindow :
262c2c66affSColin Finck     public CComCoClass<CTrayWindow>,
263c2c66affSColin Finck     public CComObjectRootEx<CComMultiThreadModelNoCS>,
264c2c66affSColin Finck     public CWindowImpl < CTrayWindow, CWindow, CControlWinTraits >,
265c2c66affSColin Finck     public ITrayWindow,
266c2c66affSColin Finck     public IShellDesktopTray,
267c2c66affSColin Finck     public IOleWindow,
268c2c66affSColin Finck     public IContextMenu
269c2c66affSColin Finck {
270c2c66affSColin Finck     CStartButton m_StartButton;
271c2c66affSColin Finck 
272c2c66affSColin Finck     CComPtr<IMenuBand>  m_StartMenuBand;
273c2c66affSColin Finck     CComPtr<IMenuPopup> m_StartMenuPopup;
274c2c66affSColin Finck 
275c2c66affSColin Finck     CComPtr<IDeskBand> m_TaskBand;
276c2c66affSColin Finck     CComPtr<IContextMenu> m_ContextMenu;
277c2c66affSColin Finck     HTHEME m_Theme;
278c2c66affSColin Finck 
279c2c66affSColin Finck     HFONT m_Font;
280c2c66affSColin Finck 
281c2c66affSColin Finck     HWND m_DesktopWnd;
282c2c66affSColin Finck     HWND m_Rebar;
283c2c66affSColin Finck     HWND m_TaskSwitch;
284c2c66affSColin Finck     HWND m_TrayNotify;
285c2c66affSColin Finck 
286455bce68SGiannis Adamopoulos     CComPtr<IUnknown> m_TrayNotifyInstance;
287c2c66affSColin Finck 
288c2c66affSColin Finck     DWORD    m_Position;
289c2c66affSColin Finck     HMONITOR m_Monitor;
290c2c66affSColin Finck     HMONITOR m_PreviousMonitor;
291c2c66affSColin Finck     DWORD    m_DraggingPosition;
292c2c66affSColin Finck     HMONITOR m_DraggingMonitor;
293c2c66affSColin Finck 
294c2c66affSColin Finck     RECT m_TrayRects[4];
295c2c66affSColin Finck     SIZE m_TraySize;
296c2c66affSColin Finck 
297c2c66affSColin Finck     HWND m_TrayPropertiesOwner;
298c2c66affSColin Finck     HWND m_RunFileDlgOwner;
299c2c66affSColin Finck 
300c2c66affSColin Finck     UINT m_AutoHideState;
301c2c66affSColin Finck     SIZE m_AutoHideOffset;
302c2c66affSColin Finck     TRACKMOUSEEVENT m_MouseTrackingInfo;
303c2c66affSColin Finck 
304c2c66affSColin Finck     HDPA m_ShellServices;
305c2c66affSColin Finck 
306c2c66affSColin Finck public:
307c2c66affSColin Finck     CComPtr<ITrayBandSite> m_TrayBandSite;
308c2c66affSColin Finck 
309c2c66affSColin Finck     union
310c2c66affSColin Finck     {
311c2c66affSColin Finck         DWORD Flags;
312c2c66affSColin Finck         struct
313c2c66affSColin Finck         {
314c2c66affSColin Finck             /* UI Status */
315c2c66affSColin Finck             DWORD InSizeMove : 1;
316c2c66affSColin Finck             DWORD IsDragging : 1;
317c2c66affSColin Finck             DWORD NewPosSize : 1;
318c2c66affSColin Finck         };
319c2c66affSColin Finck     };
320c2c66affSColin Finck 
321c2c66affSColin Finck public:
322c2c66affSColin Finck     CTrayWindow() :
323c2c66affSColin Finck         m_StartButton(),
324c2c66affSColin Finck         m_Theme(NULL),
325c2c66affSColin Finck         m_Font(NULL),
326c2c66affSColin Finck         m_DesktopWnd(NULL),
327c2c66affSColin Finck         m_Rebar(NULL),
328c2c66affSColin Finck         m_TaskSwitch(NULL),
329c2c66affSColin Finck         m_TrayNotify(NULL),
330c2c66affSColin Finck         m_Position(0),
331c2c66affSColin Finck         m_Monitor(NULL),
332c2c66affSColin Finck         m_PreviousMonitor(NULL),
333c2c66affSColin Finck         m_DraggingPosition(0),
334c2c66affSColin Finck         m_DraggingMonitor(NULL),
335c2c66affSColin Finck         m_TrayPropertiesOwner(NULL),
336c2c66affSColin Finck         m_RunFileDlgOwner(NULL),
337c2c66affSColin Finck         m_AutoHideState(NULL),
338c2c66affSColin Finck         m_ShellServices(NULL),
339c2c66affSColin Finck         Flags(0)
340c2c66affSColin Finck     {
341c2c66affSColin Finck         ZeroMemory(&m_TrayRects, sizeof(m_TrayRects));
342c2c66affSColin Finck         ZeroMemory(&m_TraySize, sizeof(m_TraySize));
343c2c66affSColin Finck         ZeroMemory(&m_AutoHideOffset, sizeof(m_AutoHideOffset));
344c2c66affSColin Finck         ZeroMemory(&m_MouseTrackingInfo, sizeof(m_MouseTrackingInfo));
345c2c66affSColin Finck     }
346c2c66affSColin Finck 
347c2c66affSColin Finck     virtual ~CTrayWindow()
348c2c66affSColin Finck     {
349c2c66affSColin Finck         if (m_ShellServices != NULL)
350c2c66affSColin Finck         {
351c2c66affSColin Finck             ShutdownShellServices(m_ShellServices);
352c2c66affSColin Finck             m_ShellServices = NULL;
353c2c66affSColin Finck         }
354c2c66affSColin Finck 
355c2c66affSColin Finck         if (m_Font != NULL)
356c2c66affSColin Finck         {
357c2c66affSColin Finck             DeleteObject(m_Font);
358c2c66affSColin Finck             m_Font = NULL;
359c2c66affSColin Finck         }
360c2c66affSColin Finck 
361c2c66affSColin Finck         if (m_Theme)
362c2c66affSColin Finck         {
363c2c66affSColin Finck             CloseThemeData(m_Theme);
364c2c66affSColin Finck             m_Theme = NULL;
365c2c66affSColin Finck         }
366c2c66affSColin Finck 
367c2c66affSColin Finck         PostQuitMessage(0);
368c2c66affSColin Finck     }
369c2c66affSColin Finck 
370c2c66affSColin Finck 
371c2c66affSColin Finck 
372c2c66affSColin Finck 
373c2c66affSColin Finck 
374c2c66affSColin Finck     /**********************************************************
375c2c66affSColin Finck      *    ##### command handling #####
376c2c66affSColin Finck      */
377c2c66affSColin Finck 
378c2c66affSColin Finck     HRESULT ExecResourceCmd(int id)
379c2c66affSColin Finck     {
380c2c66affSColin Finck         WCHAR szCommand[256];
381c2c66affSColin Finck         WCHAR *pszParameters;
382c2c66affSColin Finck 
383c2c66affSColin Finck         if (!LoadStringW(hExplorerInstance,
384c2c66affSColin Finck                          id,
385c2c66affSColin Finck                          szCommand,
386c2c66affSColin Finck                          _countof(szCommand)))
387c2c66affSColin Finck         {
388c2c66affSColin Finck             return E_FAIL;
389c2c66affSColin Finck         }
390c2c66affSColin Finck 
391c2c66affSColin Finck         pszParameters = wcschr(szCommand, L'>');
392c2c66affSColin Finck         if (pszParameters)
393c2c66affSColin Finck         {
394c2c66affSColin Finck             *pszParameters = 0;
395c2c66affSColin Finck             pszParameters++;
396c2c66affSColin Finck         }
397c2c66affSColin Finck 
398c2c66affSColin Finck         ShellExecuteW(m_hWnd, NULL, szCommand, pszParameters, NULL, SW_SHOWNORMAL);
399c2c66affSColin Finck         return S_OK;
400c2c66affSColin Finck     }
401c2c66affSColin Finck 
402c2c66affSColin Finck     LRESULT DoExitWindows()
403c2c66affSColin Finck     {
404c62bccddSHermès Bélusca-Maïto         /* Display the ReactOS Shutdown Dialog */
405c2c66affSColin Finck         ExitWindowsDialog(m_hWnd);
406c62bccddSHermès Bélusca-Maïto 
407c62bccddSHermès Bélusca-Maïto         /*
408c62bccddSHermès Bélusca-Maïto          * If the user presses CTRL+ALT+SHIFT while exiting
409c62bccddSHermès Bélusca-Maïto          * the shutdown dialog, exit the shell cleanly.
410c62bccddSHermès Bélusca-Maïto          */
411c62bccddSHermès Bélusca-Maïto         if ((GetKeyState(VK_CONTROL) & 0x8000) &&
412c62bccddSHermès Bélusca-Maïto             (GetKeyState(VK_SHIFT)   & 0x8000) &&
413c62bccddSHermès Bélusca-Maïto             (GetKeyState(VK_MENU)    & 0x8000))
414c62bccddSHermès Bélusca-Maïto         {
415c62bccddSHermès Bélusca-Maïto             PostMessage(WM_QUIT, 0, 0);
416c62bccddSHermès Bélusca-Maïto         }
417c2c66affSColin Finck         return 0;
418c2c66affSColin Finck     }
419c2c66affSColin Finck 
420c2c66affSColin Finck     DWORD WINAPI RunFileDlgThread()
421c2c66affSColin Finck     {
422c2c66affSColin Finck         HWND hwnd;
423c2c66affSColin Finck         RECT posRect;
424c2c66affSColin Finck 
425c2c66affSColin Finck         m_StartButton.GetWindowRect(&posRect);
426c2c66affSColin Finck 
427c2c66affSColin Finck         hwnd = CreateWindowEx(0,
428c2c66affSColin Finck                               WC_STATIC,
429c2c66affSColin Finck                               NULL,
430c2c66affSColin Finck                               WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT,
431c2c66affSColin Finck                               posRect.left,
432c2c66affSColin Finck                               posRect.top,
433c2c66affSColin Finck                               posRect.right - posRect.left,
434c2c66affSColin Finck                               posRect.bottom - posRect.top,
435c2c66affSColin Finck                               NULL,
436c2c66affSColin Finck                               NULL,
437c2c66affSColin Finck                               NULL,
438c2c66affSColin Finck                               NULL);
439c2c66affSColin Finck 
440c2c66affSColin Finck         m_RunFileDlgOwner = hwnd;
441c2c66affSColin Finck 
442c84f3983SKatayama Hirofumi MZ         // build the default directory from two environment variables
443c84f3983SKatayama Hirofumi MZ         CStringW strDefaultDir, strHomePath;
444c84f3983SKatayama Hirofumi MZ         strDefaultDir.GetEnvironmentVariable(L"HOMEDRIVE");
445c84f3983SKatayama Hirofumi MZ         strHomePath.GetEnvironmentVariable(L"HOMEPATH");
446c84f3983SKatayama Hirofumi MZ         strDefaultDir += strHomePath;
447c84f3983SKatayama Hirofumi MZ 
448c84f3983SKatayama Hirofumi MZ         RunFileDlg(hwnd, NULL, (LPCWSTR)strDefaultDir, NULL, NULL, RFF_CALCDIRECTORY);
449c2c66affSColin Finck 
450c2c66affSColin Finck         m_RunFileDlgOwner = NULL;
451c2c66affSColin Finck         ::DestroyWindow(hwnd);
452c2c66affSColin Finck 
453c2c66affSColin Finck         return 0;
454c2c66affSColin Finck     }
455c2c66affSColin Finck 
456c2c66affSColin Finck     static DWORD WINAPI s_RunFileDlgThread(IN OUT PVOID pParam)
457c2c66affSColin Finck     {
458c2c66affSColin Finck         CTrayWindow * This = (CTrayWindow*) pParam;
459c2c66affSColin Finck         return This->RunFileDlgThread();
460c2c66affSColin Finck     }
461c2c66affSColin Finck 
462c2c66affSColin Finck     void DisplayRunFileDlg()
463c2c66affSColin Finck     {
464c2c66affSColin Finck         HWND hRunDlg;
465c2c66affSColin Finck         if (m_RunFileDlgOwner)
466c2c66affSColin Finck         {
467c2c66affSColin Finck             hRunDlg = ::GetLastActivePopup(m_RunFileDlgOwner);
468c2c66affSColin Finck             if (hRunDlg != NULL &&
469c2c66affSColin Finck                 hRunDlg != m_RunFileDlgOwner)
470c2c66affSColin Finck             {
471c2c66affSColin Finck                 SetForegroundWindow(hRunDlg);
472c2c66affSColin Finck                 return;
473c2c66affSColin Finck             }
474c2c66affSColin Finck         }
475c2c66affSColin Finck 
476c2c66affSColin Finck         CloseHandle(CreateThread(NULL, 0, s_RunFileDlgThread, this, 0, NULL));
477c2c66affSColin Finck     }
478c2c66affSColin Finck 
479c2c66affSColin Finck     DWORD WINAPI TrayPropertiesThread()
480c2c66affSColin Finck     {
481c2c66affSColin Finck         HWND hwnd;
482c2c66affSColin Finck         RECT posRect;
483c2c66affSColin Finck 
484c2c66affSColin Finck         m_StartButton.GetWindowRect(&posRect);
485c2c66affSColin Finck         hwnd = CreateWindowEx(0,
486c2c66affSColin Finck                               WC_STATIC,
487c2c66affSColin Finck                               NULL,
488c2c66affSColin Finck                               WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER | SS_LEFT,
489c2c66affSColin Finck                               posRect.left,
490c2c66affSColin Finck                               posRect.top,
491c2c66affSColin Finck                               posRect.right - posRect.left,
492c2c66affSColin Finck                               posRect.bottom - posRect.top,
493c2c66affSColin Finck                               NULL,
494c2c66affSColin Finck                               NULL,
495c2c66affSColin Finck                               NULL,
496c2c66affSColin Finck                               NULL);
497c2c66affSColin Finck 
498c2c66affSColin Finck         m_TrayPropertiesOwner = hwnd;
499c2c66affSColin Finck 
5002ed535daSGiannis Adamopoulos         DisplayTrayProperties(hwnd, m_hWnd);
501c2c66affSColin Finck 
502c2c66affSColin Finck         m_TrayPropertiesOwner = NULL;
503c2c66affSColin Finck         ::DestroyWindow(hwnd);
504c2c66affSColin Finck 
505c2c66affSColin Finck         return 0;
506c2c66affSColin Finck     }
507c2c66affSColin Finck 
508c2c66affSColin Finck     static DWORD WINAPI s_TrayPropertiesThread(IN OUT PVOID pParam)
509c2c66affSColin Finck     {
510c2c66affSColin Finck         CTrayWindow *This = (CTrayWindow*) pParam;
511c2c66affSColin Finck 
512c2c66affSColin Finck         return This->TrayPropertiesThread();
513c2c66affSColin Finck     }
514c2c66affSColin Finck 
515c2c66affSColin Finck     HWND STDMETHODCALLTYPE DisplayProperties()
516c2c66affSColin Finck     {
517c2c66affSColin Finck         HWND hTrayProp;
518c2c66affSColin Finck 
519c2c66affSColin Finck         if (m_TrayPropertiesOwner)
520c2c66affSColin Finck         {
521c2c66affSColin Finck             hTrayProp = ::GetLastActivePopup(m_TrayPropertiesOwner);
522c2c66affSColin Finck             if (hTrayProp != NULL &&
523c2c66affSColin Finck                 hTrayProp != m_TrayPropertiesOwner)
524c2c66affSColin Finck             {
525c2c66affSColin Finck                 SetForegroundWindow(hTrayProp);
526c2c66affSColin Finck                 return NULL;
527c2c66affSColin Finck             }
528c2c66affSColin Finck         }
529c2c66affSColin Finck 
530c2c66affSColin Finck         CloseHandle(CreateThread(NULL, 0, s_TrayPropertiesThread, this, 0, NULL));
531c2c66affSColin Finck         return NULL;
532c2c66affSColin Finck     }
533c2c66affSColin Finck 
534c2c66affSColin Finck     VOID OpenCommonStartMenuDirectory(IN HWND hWndOwner, IN LPCTSTR lpOperation)
535c2c66affSColin Finck     {
536c2c66affSColin Finck         WCHAR szDir[MAX_PATH];
537c2c66affSColin Finck 
538c2c66affSColin Finck         if (SHGetSpecialFolderPath(hWndOwner,
539c2c66affSColin Finck             szDir,
540c2c66affSColin Finck             CSIDL_COMMON_STARTMENU,
541c2c66affSColin Finck             FALSE))
542c2c66affSColin Finck         {
543c2c66affSColin Finck             ShellExecute(hWndOwner,
544c2c66affSColin Finck                          lpOperation,
545c2c66affSColin Finck                          szDir,
546c2c66affSColin Finck                          NULL,
547c2c66affSColin Finck                          NULL,
548c2c66affSColin Finck                          SW_SHOWNORMAL);
549c2c66affSColin Finck         }
550c2c66affSColin Finck     }
551c2c66affSColin Finck 
552c2c66affSColin Finck     VOID OpenTaskManager(IN HWND hWndOwner)
553c2c66affSColin Finck     {
554c2c66affSColin Finck         ShellExecute(hWndOwner,
555c2c66affSColin Finck                      TEXT("open"),
556c2c66affSColin Finck                      TEXT("taskmgr.exe"),
557c2c66affSColin Finck                      NULL,
558c2c66affSColin Finck                      NULL,
559c2c66affSColin Finck                      SW_SHOWNORMAL);
560c2c66affSColin Finck     }
561c2c66affSColin Finck 
562*75b09f3fSKatayama Hirofumi MZ     VOID ToggleDesktop()
563*75b09f3fSKatayama Hirofumi MZ     {
564*75b09f3fSKatayama Hirofumi MZ         if (::IsThereAnyEffectiveWindow(TRUE))
565*75b09f3fSKatayama Hirofumi MZ         {
566*75b09f3fSKatayama Hirofumi MZ             ShowDesktop();
567*75b09f3fSKatayama Hirofumi MZ         }
568*75b09f3fSKatayama Hirofumi MZ         else
569*75b09f3fSKatayama Hirofumi MZ         {
570*75b09f3fSKatayama Hirofumi MZ             RestoreAll();
571*75b09f3fSKatayama Hirofumi MZ         }
572*75b09f3fSKatayama Hirofumi MZ     }
573*75b09f3fSKatayama Hirofumi MZ 
574c2c66affSColin Finck     BOOL STDMETHODCALLTYPE ExecContextMenuCmd(IN UINT uiCmd)
575c2c66affSColin Finck     {
576c2c66affSColin Finck         switch (uiCmd)
577c2c66affSColin Finck         {
578c2c66affSColin Finck         case ID_SHELL_CMD_PROPERTIES:
579c2c66affSColin Finck             DisplayProperties();
580c2c66affSColin Finck             break;
581c2c66affSColin Finck 
582c2c66affSColin Finck         case ID_SHELL_CMD_OPEN_ALL_USERS:
583c2c66affSColin Finck             OpenCommonStartMenuDirectory(m_hWnd,
584c2c66affSColin Finck                                          TEXT("open"));
585c2c66affSColin Finck             break;
586c2c66affSColin Finck 
587c2c66affSColin Finck         case ID_SHELL_CMD_EXPLORE_ALL_USERS:
588c2c66affSColin Finck             OpenCommonStartMenuDirectory(m_hWnd,
589c2c66affSColin Finck                                          TEXT("explore"));
590c2c66affSColin Finck             break;
591c2c66affSColin Finck 
592c2c66affSColin Finck         case ID_LOCKTASKBAR:
593c2c66affSColin Finck             if (SHRestricted(REST_CLASSICSHELL) == 0)
594c2c66affSColin Finck             {
5952ed535daSGiannis Adamopoulos                 Lock(!g_TaskbarSettings.bLock);
596c2c66affSColin Finck             }
597c2c66affSColin Finck             break;
598c2c66affSColin Finck 
599c2c66affSColin Finck         case ID_SHELL_CMD_OPEN_TASKMGR:
600c2c66affSColin Finck             OpenTaskManager(m_hWnd);
601c2c66affSColin Finck             break;
602c2c66affSColin Finck 
603c2c66affSColin Finck         case ID_SHELL_CMD_UNDO_ACTION:
604c2c66affSColin Finck             break;
605c2c66affSColin Finck 
606c2c66affSColin Finck         case ID_SHELL_CMD_SHOW_DESKTOP:
607*75b09f3fSKatayama Hirofumi MZ             ShowDesktop();
608c2c66affSColin Finck             break;
609c2c66affSColin Finck 
610c2c66affSColin Finck         case ID_SHELL_CMD_TILE_WND_H:
611c2c66affSColin Finck             TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
612c2c66affSColin Finck             break;
613c2c66affSColin Finck 
614c2c66affSColin Finck         case ID_SHELL_CMD_TILE_WND_V:
615c2c66affSColin Finck             TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
616c2c66affSColin Finck             break;
617c2c66affSColin Finck 
618c2c66affSColin Finck         case ID_SHELL_CMD_CASCADE_WND:
619c2c66affSColin Finck             CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
620c2c66affSColin Finck             break;
621c2c66affSColin Finck 
622c2c66affSColin Finck         case ID_SHELL_CMD_CUST_NOTIF:
623c2c66affSColin Finck             ShowCustomizeNotifyIcons(hExplorerInstance, m_hWnd);
624c2c66affSColin Finck             break;
625c2c66affSColin Finck 
626c2c66affSColin Finck         case ID_SHELL_CMD_ADJUST_DAT:
627c2c66affSColin Finck             //FIXME: Use SHRunControlPanel
628c2c66affSColin Finck             ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
629c2c66affSColin Finck             break;
630c2c66affSColin Finck 
631*75b09f3fSKatayama Hirofumi MZ         case ID_SHELL_CMD_RESTORE_ALL:
632*75b09f3fSKatayama Hirofumi MZ             RestoreAll();
633*75b09f3fSKatayama Hirofumi MZ             break;
634*75b09f3fSKatayama Hirofumi MZ 
635c2c66affSColin Finck         default:
636c2c66affSColin Finck             TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
637c2c66affSColin Finck             return FALSE;
638c2c66affSColin Finck         }
639c2c66affSColin Finck 
640c2c66affSColin Finck         return TRUE;
641c2c66affSColin Finck     }
642c2c66affSColin Finck 
643c2c66affSColin Finck     LRESULT HandleHotKey(DWORD id)
644c2c66affSColin Finck     {
645c2c66affSColin Finck         switch (id)
646c2c66affSColin Finck         {
647c2c66affSColin Finck         case IDHK_RUN:
648c2c66affSColin Finck             DisplayRunFileDlg();
649c2c66affSColin Finck             break;
650c2c66affSColin Finck         case IDHK_HELP:
651c2c66affSColin Finck             ExecResourceCmd(IDS_HELP_COMMAND);
652c2c66affSColin Finck             break;
653c2c66affSColin Finck         case IDHK_EXPLORE:
654c2c66affSColin Finck             //FIXME: We don't support this yet:
655c2c66affSColin Finck             //ShellExecuteW(0, L"explore", NULL, NULL, NULL, 1);
6564b6d929bSGiannis Adamopoulos             ShellExecuteW(0, NULL, L"explorer.exe", L"/e ,", NULL, 1);
657c2c66affSColin Finck             break;
658c2c66affSColin Finck         case IDHK_FIND:
659c2c66affSColin Finck             SHFindFiles(NULL, NULL);
660c2c66affSColin Finck             break;
661c2c66affSColin Finck         case IDHK_FIND_COMPUTER:
662c2c66affSColin Finck             SHFindComputer(NULL, NULL);
663c2c66affSColin Finck             break;
664c2c66affSColin Finck         case IDHK_SYS_PROPERTIES:
665c2c66affSColin Finck             //FIXME: Use SHRunControlPanel
666c2c66affSColin Finck             ShellExecuteW(m_hWnd, NULL, L"sysdm.cpl", NULL, NULL, SW_NORMAL);
667c2c66affSColin Finck             break;
668c2c66affSColin Finck         case IDHK_NEXT_TASK:
669c2c66affSColin Finck             break;
670c2c66affSColin Finck         case IDHK_PREV_TASK:
671c2c66affSColin Finck             break;
672c2c66affSColin Finck         case IDHK_MINIMIZE_ALL:
673*75b09f3fSKatayama Hirofumi MZ             MinimizeAll();
674c2c66affSColin Finck             break;
675c2c66affSColin Finck         case IDHK_RESTORE_ALL:
676*75b09f3fSKatayama Hirofumi MZ             RestoreAll();
677c2c66affSColin Finck             break;
678c2c66affSColin Finck         case IDHK_DESKTOP:
679*75b09f3fSKatayama Hirofumi MZ             ToggleDesktop();
680c2c66affSColin Finck             break;
681c2c66affSColin Finck         case IDHK_PAGER:
682c2c66affSColin Finck             break;
683c2c66affSColin Finck         }
684c2c66affSColin Finck 
685c2c66affSColin Finck         return 0;
686c2c66affSColin Finck     }
687c2c66affSColin Finck 
688c2c66affSColin Finck     LRESULT HandleCommand(UINT uCommand)
689c2c66affSColin Finck     {
690c2c66affSColin Finck         switch (uCommand)
691c2c66affSColin Finck         {
692*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_STARTMENU:
693*75b09f3fSKatayama Hirofumi MZ                 // TODO:
694c2c66affSColin Finck                 break;
695*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_RUN_DIALOG:
696c2c66affSColin Finck                 DisplayRunFileDlg();
697c2c66affSColin Finck                 break;
698*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_LOGOFF_DIALOG:
699c2c66affSColin Finck                 LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as DoExitWindows?
700c2c66affSColin Finck                 break;
701*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_CASCADE:
702*75b09f3fSKatayama Hirofumi MZ                 CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
703*75b09f3fSKatayama Hirofumi MZ                 break;
704*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_TILE_H:
705*75b09f3fSKatayama Hirofumi MZ                 TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
706*75b09f3fSKatayama Hirofumi MZ                 break;
707*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_TILE_V:
708*75b09f3fSKatayama Hirofumi MZ                 TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
709*75b09f3fSKatayama Hirofumi MZ                 break;
710*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_TOGGLE_DESKTOP:
711*75b09f3fSKatayama Hirofumi MZ                 ToggleDesktop();
712*75b09f3fSKatayama Hirofumi MZ                 break;
713*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_DATE_AND_TIME:
714*75b09f3fSKatayama Hirofumi MZ                 ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
715*75b09f3fSKatayama Hirofumi MZ                 break;
716*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_TASKBAR_PROPERTIES:
717*75b09f3fSKatayama Hirofumi MZ                 DisplayProperties();
718*75b09f3fSKatayama Hirofumi MZ                 break;
719*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_MINIMIZE_ALL:
720*75b09f3fSKatayama Hirofumi MZ                 MinimizeAll();
721*75b09f3fSKatayama Hirofumi MZ                 break;
722*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_RESTORE_ALL:
723*75b09f3fSKatayama Hirofumi MZ                 RestoreAll();
724*75b09f3fSKatayama Hirofumi MZ                 break;
725*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_SHOW_DESKTOP:
726*75b09f3fSKatayama Hirofumi MZ                 ShowDesktop();
727*75b09f3fSKatayama Hirofumi MZ                 break;
728*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_SHOW_TASK_MGR:
729*75b09f3fSKatayama Hirofumi MZ                 OpenTaskManager(m_hWnd);
730*75b09f3fSKatayama Hirofumi MZ                 break;
731*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_CUSTOMIZE_TASKBAR:
732*75b09f3fSKatayama Hirofumi MZ                 break;
733*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_LOCK_TASKBAR:
734*75b09f3fSKatayama Hirofumi MZ                 if (SHRestricted(REST_CLASSICSHELL) == 0)
735*75b09f3fSKatayama Hirofumi MZ                 {
736*75b09f3fSKatayama Hirofumi MZ                     Lock(!g_TaskbarSettings.bLock);
737*75b09f3fSKatayama Hirofumi MZ                 }
738*75b09f3fSKatayama Hirofumi MZ                 break;
739*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_HELP_AND_SUPPORT:
740*75b09f3fSKatayama Hirofumi MZ                 ExecResourceCmd(IDS_HELP_COMMAND);
741*75b09f3fSKatayama Hirofumi MZ                 break;
742*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_CONTROL_PANEL:
743*75b09f3fSKatayama Hirofumi MZ                 // TODO:
744*75b09f3fSKatayama Hirofumi MZ                 break;
745*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_SHUTDOWN_DIALOG:
746c2c66affSColin Finck                 DoExitWindows();
747c2c66affSColin Finck                 break;
748*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_PRINTERS_AND_FAXES:
749*75b09f3fSKatayama Hirofumi MZ                 // TODO:
750*75b09f3fSKatayama Hirofumi MZ                 break;
751*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_LOCK_DESKTOP:
752*75b09f3fSKatayama Hirofumi MZ                 // TODO:
753*75b09f3fSKatayama Hirofumi MZ                 break;
754*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_SWITCH_USER_DIALOG:
755*75b09f3fSKatayama Hirofumi MZ                 // TODO:
756*75b09f3fSKatayama Hirofumi MZ                 break;
757*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_SEARCH_FILES:
758*75b09f3fSKatayama Hirofumi MZ                 SHFindFiles(NULL, NULL);
759*75b09f3fSKatayama Hirofumi MZ                 break;
760*75b09f3fSKatayama Hirofumi MZ             case TRAYCMD_SEARCH_COMPUTERS:
761*75b09f3fSKatayama Hirofumi MZ                 SHFindComputer(NULL, NULL);
762*75b09f3fSKatayama Hirofumi MZ                 break;
763*75b09f3fSKatayama Hirofumi MZ 
764*75b09f3fSKatayama Hirofumi MZ             default:
765*75b09f3fSKatayama Hirofumi MZ                 break;
766c2c66affSColin Finck         }
767c2c66affSColin Finck 
768c2c66affSColin Finck         return FALSE;
769c2c66affSColin Finck     }
770c2c66affSColin Finck 
771c2c66affSColin Finck 
772c2c66affSColin Finck     UINT TrackMenu(
773c2c66affSColin Finck         IN HMENU hMenu,
774c2c66affSColin Finck         IN POINT *ppt OPTIONAL,
775c2c66affSColin Finck         IN HWND hwndExclude OPTIONAL,
776c2c66affSColin Finck         IN BOOL TrackUp,
777c2c66affSColin Finck         IN BOOL IsContextMenu)
778c2c66affSColin Finck     {
779c2c66affSColin Finck         TPMPARAMS tmp, *ptmp = NULL;
780c2c66affSColin Finck         POINT pt;
781c2c66affSColin Finck         UINT cmdId;
782c2c66affSColin Finck         UINT fuFlags;
783c2c66affSColin Finck 
784c2c66affSColin Finck         if (hwndExclude != NULL)
785c2c66affSColin Finck         {
786c2c66affSColin Finck             /* Get the client rectangle and map it to screen coordinates */
787c2c66affSColin Finck             if (::GetClientRect(hwndExclude,
788c2c66affSColin Finck                 &tmp.rcExclude) &&
789c2c66affSColin Finck                 ::MapWindowPoints(hwndExclude,
790c2c66affSColin Finck                 NULL,
791c2c66affSColin Finck                 (LPPOINT) &tmp.rcExclude,
792c2c66affSColin Finck                 2) != 0)
793c2c66affSColin Finck             {
794c2c66affSColin Finck                 ptmp = &tmp;
795c2c66affSColin Finck             }
796c2c66affSColin Finck         }
797c2c66affSColin Finck 
798c2c66affSColin Finck         if (ppt == NULL)
799c2c66affSColin Finck         {
800c2c66affSColin Finck             if (ptmp == NULL &&
801c2c66affSColin Finck                 GetClientRect(&tmp.rcExclude) &&
802c2c66affSColin Finck                 MapWindowPoints(
803c2c66affSColin Finck                 NULL,
804c2c66affSColin Finck                 (LPPOINT) &tmp.rcExclude,
805c2c66affSColin Finck                 2) != 0)
806c2c66affSColin Finck             {
807c2c66affSColin Finck                 ptmp = &tmp;
808c2c66affSColin Finck             }
809c2c66affSColin Finck 
810c2c66affSColin Finck             if (ptmp != NULL)
811c2c66affSColin Finck             {
812c2c66affSColin Finck                 /* NOTE: TrackPopupMenuEx will eventually align the track position
813c2c66affSColin Finck                          for us, no need to take care of it here as long as the
814c2c66affSColin Finck                          coordinates are somewhere within the exclusion rectangle */
815c2c66affSColin Finck                 pt.x = ptmp->rcExclude.left;
816c2c66affSColin Finck                 pt.y = ptmp->rcExclude.top;
817c2c66affSColin Finck             }
818c2c66affSColin Finck             else
819c2c66affSColin Finck                 pt.x = pt.y = 0;
820c2c66affSColin Finck         }
821c2c66affSColin Finck         else
822c2c66affSColin Finck             pt = *ppt;
823c2c66affSColin Finck 
824c2c66affSColin Finck         tmp.cbSize = sizeof(tmp);
825c2c66affSColin Finck 
826c2c66affSColin Finck         fuFlags = TPM_RETURNCMD | TPM_VERTICAL;
827c2c66affSColin Finck         fuFlags |= (TrackUp ? TPM_BOTTOMALIGN : TPM_TOPALIGN);
828c2c66affSColin Finck         if (IsContextMenu)
829c2c66affSColin Finck             fuFlags |= TPM_RIGHTBUTTON;
830c2c66affSColin Finck         else
831c2c66affSColin Finck             fuFlags |= (TrackUp ? TPM_VERNEGANIMATION : TPM_VERPOSANIMATION);
832c2c66affSColin Finck 
833c2c66affSColin Finck         cmdId = TrackPopupMenuEx(hMenu,
834c2c66affSColin Finck                                  fuFlags,
835c2c66affSColin Finck                                  pt.x,
836c2c66affSColin Finck                                  pt.y,
837c2c66affSColin Finck                                  m_hWnd,
838c2c66affSColin Finck                                  ptmp);
839c2c66affSColin Finck 
840c2c66affSColin Finck         return cmdId;
841c2c66affSColin Finck     }
842c2c66affSColin Finck 
843c2c66affSColin Finck     HRESULT TrackCtxMenu(
844c2c66affSColin Finck         IN IContextMenu * contextMenu,
845c2c66affSColin Finck         IN POINT *ppt OPTIONAL,
846c2c66affSColin Finck         IN HWND hwndExclude OPTIONAL,
847c2c66affSColin Finck         IN BOOL TrackUp,
848c2c66affSColin Finck         IN PVOID Context OPTIONAL)
849c2c66affSColin Finck     {
85058825de8SKatayama Hirofumi MZ         POINT pt;
85158825de8SKatayama Hirofumi MZ         TPMPARAMS params;
85258825de8SKatayama Hirofumi MZ         RECT rc;
853c2c66affSColin Finck         HRESULT hr;
854c2c66affSColin Finck         UINT uCommand;
855c2c66affSColin Finck         HMENU popup = CreatePopupMenu();
856c2c66affSColin Finck 
857c2c66affSColin Finck         if (popup == NULL)
858c2c66affSColin Finck             return E_FAIL;
859c2c66affSColin Finck 
86058825de8SKatayama Hirofumi MZ         if (ppt)
86158825de8SKatayama Hirofumi MZ         {
86258825de8SKatayama Hirofumi MZ             pt = *ppt;
86358825de8SKatayama Hirofumi MZ         }
86458825de8SKatayama Hirofumi MZ         else
86558825de8SKatayama Hirofumi MZ         {
86658825de8SKatayama Hirofumi MZ             ::GetWindowRect(m_hWnd, &rc);
86758825de8SKatayama Hirofumi MZ             pt.x = rc.left;
86858825de8SKatayama Hirofumi MZ             pt.y = rc.top;
86958825de8SKatayama Hirofumi MZ         }
87058825de8SKatayama Hirofumi MZ 
871c2c66affSColin Finck         TRACE("Before Query\n");
872c2c66affSColin Finck         hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
873c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
874c2c66affSColin Finck         {
875c2c66affSColin Finck             TRACE("Query failed\n");
876c2c66affSColin Finck             DestroyMenu(popup);
877c2c66affSColin Finck             return hr;
878c2c66affSColin Finck         }
879c2c66affSColin Finck 
880c2c66affSColin Finck         TRACE("Before Tracking\n");
88158825de8SKatayama Hirofumi MZ         ::SetForegroundWindow(m_hWnd);
88258825de8SKatayama Hirofumi MZ         if (hwndExclude)
88358825de8SKatayama Hirofumi MZ         {
88458825de8SKatayama Hirofumi MZ             ::GetWindowRect(hwndExclude, &rc);
88558825de8SKatayama Hirofumi MZ             ZeroMemory(&params, sizeof(params));
88658825de8SKatayama Hirofumi MZ             params.cbSize = sizeof(params);
88758825de8SKatayama Hirofumi MZ             params.rcExclude = rc;
88858825de8SKatayama Hirofumi MZ             uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, pt.x, pt.y, m_hWnd, &params);
88958825de8SKatayama Hirofumi MZ         }
89058825de8SKatayama Hirofumi MZ         else
89158825de8SKatayama Hirofumi MZ         {
89258825de8SKatayama Hirofumi MZ             uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, pt.x, pt.y, m_hWnd, NULL);
89358825de8SKatayama Hirofumi MZ         }
89458825de8SKatayama Hirofumi MZ         ::PostMessage(m_hWnd, WM_NULL, 0, 0);
895c2c66affSColin Finck 
896c2c66affSColin Finck         if (uCommand != 0)
897c2c66affSColin Finck         {
898c2c66affSColin Finck             TRACE("Before InvokeCommand\n");
899c2c66affSColin Finck             CMINVOKECOMMANDINFO cmi = { 0 };
900c2c66affSColin Finck             cmi.cbSize = sizeof(cmi);
901c2c66affSColin Finck             cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
902c2c66affSColin Finck             cmi.hwnd = m_hWnd;
903c2c66affSColin Finck             hr = contextMenu->InvokeCommand(&cmi);
904c2c66affSColin Finck         }
905c2c66affSColin Finck         else
906c2c66affSColin Finck         {
907c2c66affSColin Finck             TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand, GetLastError());
908c2c66affSColin Finck             hr = S_FALSE;
909c2c66affSColin Finck         }
910c2c66affSColin Finck 
911c2c66affSColin Finck         DestroyMenu(popup);
912c2c66affSColin Finck         return hr;
913c2c66affSColin Finck     }
914c2c66affSColin Finck 
915c2c66affSColin Finck 
916c2c66affSColin Finck 
917c2c66affSColin Finck 
918c2c66affSColin Finck 
919c2c66affSColin Finck     /**********************************************************
920c2c66affSColin Finck      *    ##### moving and sizing handling #####
921c2c66affSColin Finck      */
922c2c66affSColin Finck 
923c2c66affSColin Finck     void UpdateFonts()
924c2c66affSColin Finck     {
925c2c66affSColin Finck         /* There is nothing to do if themes are enabled */
926c2c66affSColin Finck         if (m_Theme)
927c2c66affSColin Finck             return;
928c2c66affSColin Finck 
929c2c66affSColin Finck         m_StartButton.UpdateFont();
930c2c66affSColin Finck 
931c2c66affSColin Finck         NONCLIENTMETRICS ncm = {sizeof(ncm)};
932c2c66affSColin Finck         if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE))
933c2c66affSColin Finck         {
934c2c66affSColin Finck             ERR("SPI_GETNONCLIENTMETRICS failed\n");
935c2c66affSColin Finck             return;
936c2c66affSColin Finck         }
937c2c66affSColin Finck 
938c2c66affSColin Finck         if (m_Font != NULL)
939c2c66affSColin Finck             DeleteObject(m_Font);
940c2c66affSColin Finck 
941c2c66affSColin Finck         ncm.lfCaptionFont.lfWeight = FW_NORMAL;
942c2c66affSColin Finck         m_Font = CreateFontIndirect(&ncm.lfCaptionFont);
943c2c66affSColin Finck         if (!m_Font)
944c2c66affSColin Finck         {
945c2c66affSColin Finck             ERR("CreateFontIndirect failed\n");
946c2c66affSColin Finck             return;
947c2c66affSColin Finck         }
948c2c66affSColin Finck 
949c2c66affSColin Finck         SendMessage(m_Rebar, WM_SETFONT, (WPARAM) m_Font, TRUE);
950c2c66affSColin Finck         SendMessage(m_TaskSwitch, WM_SETFONT, (WPARAM) m_Font, TRUE);
951c2c66affSColin Finck         SendMessage(m_TrayNotify, WM_SETFONT, (WPARAM) m_Font, TRUE);
952c2c66affSColin Finck     }
953c2c66affSColin Finck 
954c2c66affSColin Finck     HMONITOR GetScreenRectFromRect(
955c2c66affSColin Finck         IN OUT RECT *pRect,
956c2c66affSColin Finck         IN DWORD dwFlags)
957c2c66affSColin Finck     {
958c2c66affSColin Finck         MONITORINFO mi;
959c2c66affSColin Finck         HMONITOR hMon;
960c2c66affSColin Finck 
961c2c66affSColin Finck         mi.cbSize = sizeof(mi);
962c2c66affSColin Finck         hMon = MonitorFromRect(pRect, dwFlags);
963c2c66affSColin Finck         if (hMon != NULL &&
964c2c66affSColin Finck             GetMonitorInfo(hMon, &mi))
965c2c66affSColin Finck         {
966c2c66affSColin Finck             *pRect = mi.rcMonitor;
967c2c66affSColin Finck         }
968c2c66affSColin Finck         else
969c2c66affSColin Finck         {
970c2c66affSColin Finck             pRect->left = 0;
971c2c66affSColin Finck             pRect->top = 0;
972c2c66affSColin Finck             pRect->right = GetSystemMetrics(SM_CXSCREEN);
973c2c66affSColin Finck             pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
974c2c66affSColin Finck 
975c2c66affSColin Finck             hMon = NULL;
976c2c66affSColin Finck         }
977c2c66affSColin Finck 
978c2c66affSColin Finck         return hMon;
979c2c66affSColin Finck     }
980c2c66affSColin Finck 
981c2c66affSColin Finck     HMONITOR GetMonitorFromRect(
982c2c66affSColin Finck         IN const RECT *pRect)
983c2c66affSColin Finck     {
984c2c66affSColin Finck         HMONITOR hMon;
985c2c66affSColin Finck 
986c2c66affSColin Finck         /* In case the monitor sizes or saved sizes differ a bit (probably
987c2c66affSColin Finck            not a lot, only so the tray window overlaps into another monitor
988c2c66affSColin Finck            now), minimize the risk that we determine a wrong monitor by
989c2c66affSColin Finck            using the center point of the tray window if we can't determine
990c2c66affSColin Finck            it using the rectangle. */
991c2c66affSColin Finck         hMon = MonitorFromRect(pRect, MONITOR_DEFAULTTONULL);
992c2c66affSColin Finck         if (hMon == NULL)
993c2c66affSColin Finck         {
994c2c66affSColin Finck             POINT pt;
995c2c66affSColin Finck 
996c2c66affSColin Finck             pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
997c2c66affSColin Finck             pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
998c2c66affSColin Finck 
999c2c66affSColin Finck             /* be less error-prone, find the nearest monitor */
1000c2c66affSColin Finck             hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
1001c2c66affSColin Finck         }
1002c2c66affSColin Finck 
1003c2c66affSColin Finck         return hMon;
1004c2c66affSColin Finck     }
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     HMONITOR GetScreenRect(
1007c2c66affSColin Finck         IN HMONITOR hMonitor,
1008c2c66affSColin Finck         IN OUT RECT *pRect)
1009c2c66affSColin Finck     {
1010c2c66affSColin Finck         HMONITOR hMon = NULL;
1011c2c66affSColin Finck 
1012c2c66affSColin Finck         if (hMonitor != NULL)
1013c2c66affSColin Finck         {
1014c2c66affSColin Finck             MONITORINFO mi;
1015c2c66affSColin Finck 
1016c2c66affSColin Finck             mi.cbSize = sizeof(mi);
1017c2c66affSColin Finck             if (!GetMonitorInfo(hMonitor, &mi))
1018c2c66affSColin Finck             {
1019c2c66affSColin Finck                 /* Hm, the monitor is gone? Try to find a monitor where it
1020c2c66affSColin Finck                    could be located now */
1021c2c66affSColin Finck                 hMon = GetMonitorFromRect(pRect);
1022c2c66affSColin Finck                 if (hMon == NULL ||
1023c2c66affSColin Finck                     !GetMonitorInfo(hMon, &mi))
1024c2c66affSColin Finck                 {
1025c2c66affSColin Finck                     hMon = NULL;
1026c2c66affSColin Finck                     goto GetPrimaryRect;
1027c2c66affSColin Finck                 }
1028c2c66affSColin Finck             }
1029c2c66affSColin Finck 
1030c2c66affSColin Finck             *pRect = mi.rcMonitor;
1031c2c66affSColin Finck         }
1032c2c66affSColin Finck         else
1033c2c66affSColin Finck         {
1034c2c66affSColin Finck GetPrimaryRect:
1035c2c66affSColin Finck             pRect->left = 0;
1036c2c66affSColin Finck             pRect->top = 0;
1037c2c66affSColin Finck             pRect->right = GetSystemMetrics(SM_CXSCREEN);
1038c2c66affSColin Finck             pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
1039c2c66affSColin Finck         }
1040c2c66affSColin Finck 
1041c2c66affSColin Finck         return hMon;
1042c2c66affSColin Finck     }
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     VOID AdjustSizerRect(RECT *rc, DWORD pos)
1045c2c66affSColin Finck     {
1046c2c66affSColin Finck         int iSizerPart[4] = {TBP_SIZINGBARLEFT, TBP_SIZINGBARTOP, TBP_SIZINGBARRIGHT, TBP_SIZINGBARBOTTOM};
1047c2c66affSColin Finck         SIZE size;
1048c2c66affSColin Finck 
1049c2c66affSColin Finck         if (pos > ABE_BOTTOM)
1050c2c66affSColin Finck             pos = ABE_BOTTOM;
1051c2c66affSColin Finck 
1052c2c66affSColin Finck         HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[pos], 0, NULL, TS_TRUE, &size);
1053c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
1054c2c66affSColin Finck             return;
1055c2c66affSColin Finck 
1056c2c66affSColin Finck         switch (pos)
1057c2c66affSColin Finck         {
1058c2c66affSColin Finck             case ABE_TOP:
1059c2c66affSColin Finck                 rc->bottom -= size.cy;
1060c2c66affSColin Finck                 break;
1061c2c66affSColin Finck             case ABE_BOTTOM:
1062c2c66affSColin Finck                 rc->top += size.cy;
1063c2c66affSColin Finck                 break;
1064c2c66affSColin Finck             case ABE_LEFT:
1065c2c66affSColin Finck                 rc->right -= size.cx;
1066c2c66affSColin Finck                 break;
1067c2c66affSColin Finck             case ABE_RIGHT:
1068c2c66affSColin Finck                 rc->left += size.cx;
1069c2c66affSColin Finck                 break;
1070c2c66affSColin Finck         }
1071c2c66affSColin Finck     }
1072c2c66affSColin Finck 
1073c2c66affSColin Finck     VOID MakeTrayRectWithSize(IN DWORD Position,
1074c2c66affSColin Finck                               IN const SIZE *pTraySize,
1075c2c66affSColin Finck                               IN OUT RECT *pRect)
1076c2c66affSColin Finck     {
1077c2c66affSColin Finck         switch (Position)
1078c2c66affSColin Finck         {
1079c2c66affSColin Finck         case ABE_LEFT:
1080c2c66affSColin Finck             pRect->right = pRect->left + pTraySize->cx;
1081c2c66affSColin Finck             break;
1082c2c66affSColin Finck 
1083c2c66affSColin Finck         case ABE_TOP:
1084c2c66affSColin Finck             pRect->bottom = pRect->top + pTraySize->cy;
1085c2c66affSColin Finck             break;
1086c2c66affSColin Finck 
1087c2c66affSColin Finck         case ABE_RIGHT:
1088c2c66affSColin Finck             pRect->left = pRect->right - pTraySize->cx;
1089c2c66affSColin Finck             break;
1090c2c66affSColin Finck 
1091c2c66affSColin Finck         case ABE_BOTTOM:
1092c2c66affSColin Finck         default:
1093c2c66affSColin Finck             pRect->top = pRect->bottom - pTraySize->cy;
1094c2c66affSColin Finck             break;
1095c2c66affSColin Finck         }
1096c2c66affSColin Finck     }
1097c2c66affSColin Finck 
1098c2c66affSColin Finck     VOID GetTrayRectFromScreenRect(IN DWORD Position,
1099c2c66affSColin Finck                                    IN const RECT *pScreen,
1100c2c66affSColin Finck                                    IN const SIZE *pTraySize OPTIONAL,
1101c2c66affSColin Finck                                    OUT RECT *pRect)
1102c2c66affSColin Finck     {
1103c2c66affSColin Finck         if (pTraySize == NULL)
1104c2c66affSColin Finck             pTraySize = &m_TraySize;
1105c2c66affSColin Finck 
1106c2c66affSColin Finck         *pRect = *pScreen;
1107c2c66affSColin Finck 
1108c2c66affSColin Finck         if(!m_Theme)
1109c2c66affSColin Finck         {
1110c2c66affSColin Finck             /* Move the border outside of the screen */
1111c2c66affSColin Finck             InflateRect(pRect,
1112c2c66affSColin Finck                         GetSystemMetrics(SM_CXEDGE),
1113c2c66affSColin Finck                         GetSystemMetrics(SM_CYEDGE));
1114c2c66affSColin Finck         }
1115c2c66affSColin Finck 
1116c2c66affSColin Finck         MakeTrayRectWithSize(Position, pTraySize, pRect);
1117c2c66affSColin Finck     }
1118c2c66affSColin Finck 
1119c2c66affSColin Finck     BOOL IsPosHorizontal()
1120c2c66affSColin Finck     {
1121c2c66affSColin Finck         return m_Position == ABE_TOP || m_Position == ABE_BOTTOM;
1122c2c66affSColin Finck     }
1123c2c66affSColin Finck 
1124c2c66affSColin Finck     HMONITOR CalculateValidSize(
1125c2c66affSColin Finck         IN DWORD Position,
1126c2c66affSColin Finck         IN OUT RECT *pRect)
1127c2c66affSColin Finck     {
1128c2c66affSColin Finck         RECT rcScreen;
1129c2c66affSColin Finck         //BOOL Horizontal;
1130c2c66affSColin Finck         HMONITOR hMon;
1131c2c66affSColin Finck         SIZE szMax, szWnd;
1132c2c66affSColin Finck 
1133c2c66affSColin Finck         //Horizontal = IsPosHorizontal();
1134c2c66affSColin Finck 
1135c2c66affSColin Finck         szWnd.cx = pRect->right - pRect->left;
1136c2c66affSColin Finck         szWnd.cy = pRect->bottom - pRect->top;
1137c2c66affSColin Finck 
1138c2c66affSColin Finck         rcScreen = *pRect;
1139c2c66affSColin Finck         hMon = GetScreenRectFromRect(
1140c2c66affSColin Finck             &rcScreen,
1141c2c66affSColin Finck             MONITOR_DEFAULTTONEAREST);
1142c2c66affSColin Finck 
1143c2c66affSColin Finck         /* Calculate the maximum size of the tray window and limit the window
1144c2c66affSColin Finck            size to half of the screen's size. */
1145c2c66affSColin Finck         szMax.cx = (rcScreen.right - rcScreen.left) / 2;
1146c2c66affSColin Finck         szMax.cy = (rcScreen.bottom - rcScreen.top) / 2;
1147c2c66affSColin Finck         if (szWnd.cx > szMax.cx)
1148c2c66affSColin Finck             szWnd.cx = szMax.cx;
1149c2c66affSColin Finck         if (szWnd.cy > szMax.cy)
1150c2c66affSColin Finck             szWnd.cy = szMax.cy;
1151c2c66affSColin Finck 
1152c2c66affSColin Finck         /* FIXME - calculate */
1153c2c66affSColin Finck 
1154c2c66affSColin Finck         GetTrayRectFromScreenRect(Position,
1155c2c66affSColin Finck                                   &rcScreen,
1156c2c66affSColin Finck                                   &szWnd,
1157c2c66affSColin Finck                                   pRect);
1158c2c66affSColin Finck 
1159c2c66affSColin Finck         return hMon;
1160c2c66affSColin Finck     }
1161c2c66affSColin Finck 
1162c2c66affSColin Finck #if 0
1163c2c66affSColin Finck     VOID
1164c2c66affSColin Finck         GetMinimumWindowSize(
1165c2c66affSColin Finck         OUT RECT *pRect)
1166c2c66affSColin Finck     {
1167c2c66affSColin Finck         RECT rcMin = {0};
1168c2c66affSColin Finck 
1169c2c66affSColin Finck         AdjustWindowRectEx(&rcMin,
1170c2c66affSColin Finck                            GetWindowLong(m_hWnd,
1171c2c66affSColin Finck                            GWL_STYLE),
1172c2c66affSColin Finck                            FALSE,
1173c2c66affSColin Finck                            GetWindowLong(m_hWnd,
1174c2c66affSColin Finck                            GWL_EXSTYLE));
1175c2c66affSColin Finck 
1176c2c66affSColin Finck         *pRect = rcMin;
1177c2c66affSColin Finck     }
1178c2c66affSColin Finck #endif
1179c2c66affSColin Finck 
1180c2c66affSColin Finck 
1181c2c66affSColin Finck     DWORD GetDraggingRectFromPt(
1182c2c66affSColin Finck         IN POINT pt,
1183c2c66affSColin Finck         OUT RECT *pRect,
1184c2c66affSColin Finck         OUT HMONITOR *phMonitor)
1185c2c66affSColin Finck     {
1186c2c66affSColin Finck         HMONITOR hMon, hMonNew;
1187c2c66affSColin Finck         DWORD PosH, PosV, Pos;
1188c2c66affSColin Finck         SIZE DeltaPt, ScreenOffset;
1189c2c66affSColin Finck         RECT rcScreen;
1190c2c66affSColin Finck 
1191c2c66affSColin Finck         rcScreen.left = 0;
1192c2c66affSColin Finck         rcScreen.top = 0;
1193c2c66affSColin Finck 
1194c2c66affSColin Finck         /* Determine the screen rectangle */
1195c2c66affSColin Finck         hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
1196c2c66affSColin Finck         if (hMon != NULL)
1197c2c66affSColin Finck         {
1198c2c66affSColin Finck             MONITORINFO mi;
1199c2c66affSColin Finck 
1200c2c66affSColin Finck             mi.cbSize = sizeof(mi);
1201c2c66affSColin Finck             if (!GetMonitorInfo(hMon, &mi))
1202c2c66affSColin Finck             {
1203c2c66affSColin Finck                 hMon = NULL;
1204c2c66affSColin Finck                 goto GetPrimaryScreenRect;
1205c2c66affSColin Finck             }
1206c2c66affSColin Finck 
1207c2c66affSColin Finck             /* make left top corner of the screen zero based to
1208c2c66affSColin Finck                make calculations easier */
1209c2c66affSColin Finck             pt.x -= mi.rcMonitor.left;
1210c2c66affSColin Finck             pt.y -= mi.rcMonitor.top;
1211c2c66affSColin Finck 
1212c2c66affSColin Finck             ScreenOffset.cx = mi.rcMonitor.left;
1213c2c66affSColin Finck             ScreenOffset.cy = mi.rcMonitor.top;
1214c2c66affSColin Finck             rcScreen.right = mi.rcMonitor.right - mi.rcMonitor.left;
1215c2c66affSColin Finck             rcScreen.bottom = mi.rcMonitor.bottom - mi.rcMonitor.top;
1216c2c66affSColin Finck         }
1217c2c66affSColin Finck         else
1218c2c66affSColin Finck         {
1219c2c66affSColin Finck GetPrimaryScreenRect:
1220c2c66affSColin Finck             ScreenOffset.cx = 0;
1221c2c66affSColin Finck             ScreenOffset.cy = 0;
1222c2c66affSColin Finck             rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
1223c2c66affSColin Finck             rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
1224c2c66affSColin Finck         }
1225c2c66affSColin Finck 
1226c2c66affSColin Finck         /* Calculate the nearest screen border */
1227c2c66affSColin Finck         if (pt.x < rcScreen.right / 2)
1228c2c66affSColin Finck         {
1229c2c66affSColin Finck             DeltaPt.cx = pt.x;
1230c2c66affSColin Finck             PosH = ABE_LEFT;
1231c2c66affSColin Finck         }
1232c2c66affSColin Finck         else
1233c2c66affSColin Finck         {
1234c2c66affSColin Finck             DeltaPt.cx = rcScreen.right - pt.x;
1235c2c66affSColin Finck             PosH = ABE_RIGHT;
1236c2c66affSColin Finck         }
1237c2c66affSColin Finck 
1238c2c66affSColin Finck         if (pt.y < rcScreen.bottom / 2)
1239c2c66affSColin Finck         {
1240c2c66affSColin Finck             DeltaPt.cy = pt.y;
1241c2c66affSColin Finck             PosV = ABE_TOP;
1242c2c66affSColin Finck         }
1243c2c66affSColin Finck         else
1244c2c66affSColin Finck         {
1245c2c66affSColin Finck             DeltaPt.cy = rcScreen.bottom - pt.y;
1246c2c66affSColin Finck             PosV = ABE_BOTTOM;
1247c2c66affSColin Finck         }
1248c2c66affSColin Finck 
1249c2c66affSColin Finck         Pos = (DeltaPt.cx * rcScreen.bottom < DeltaPt.cy * rcScreen.right) ? PosH : PosV;
1250c2c66affSColin Finck 
1251c2c66affSColin Finck         /* Fix the screen origin to be relative to the primary monitor again */
1252c2c66affSColin Finck         OffsetRect(&rcScreen,
1253c2c66affSColin Finck                    ScreenOffset.cx,
1254c2c66affSColin Finck                    ScreenOffset.cy);
1255c2c66affSColin Finck 
1256c2c66affSColin Finck         RECT rcPos = m_TrayRects[Pos];
1257c2c66affSColin Finck 
1258c2c66affSColin Finck         hMonNew = GetMonitorFromRect(&rcPos);
1259c2c66affSColin Finck         if (hMon != hMonNew)
1260c2c66affSColin Finck         {
1261c2c66affSColin Finck             SIZE szTray;
1262c2c66affSColin Finck 
1263c2c66affSColin Finck             /* Recalculate the rectangle, we're dragging to another monitor.
1264c2c66affSColin Finck                We don't need to recalculate the rect on single monitor systems. */
1265c2c66affSColin Finck             szTray.cx = rcPos.right - rcPos.left;
1266c2c66affSColin Finck             szTray.cy = rcPos.bottom - rcPos.top;
1267c2c66affSColin Finck 
1268c2c66affSColin Finck             GetTrayRectFromScreenRect(Pos, &rcScreen, &szTray, pRect);
1269c2c66affSColin Finck             hMon = hMonNew;
1270c2c66affSColin Finck         }
1271c2c66affSColin Finck         else
1272c2c66affSColin Finck         {
1273c2c66affSColin Finck             /* The user is dragging the tray window on the same monitor. We don't need
1274c2c66affSColin Finck                to recalculate the rectangle */
1275c2c66affSColin Finck             *pRect = rcPos;
1276c2c66affSColin Finck         }
1277c2c66affSColin Finck 
1278c2c66affSColin Finck         *phMonitor = hMon;
1279c2c66affSColin Finck 
1280c2c66affSColin Finck         return Pos;
1281c2c66affSColin Finck     }
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     DWORD GetDraggingRectFromRect(
1284c2c66affSColin Finck         IN OUT RECT *pRect,
1285c2c66affSColin Finck         OUT HMONITOR *phMonitor)
1286c2c66affSColin Finck     {
1287c2c66affSColin Finck         POINT pt;
1288c2c66affSColin Finck 
1289c2c66affSColin Finck         /* Calculate the center of the rectangle. We call
1290c2c66affSColin Finck            GetDraggingRectFromPt to calculate a valid
1291c2c66affSColin Finck            dragging rectangle */
1292c2c66affSColin Finck         pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
1293c2c66affSColin Finck         pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
1294c2c66affSColin Finck 
1295c2c66affSColin Finck         return GetDraggingRectFromPt(
1296c2c66affSColin Finck             pt,
1297c2c66affSColin Finck             pRect,
1298c2c66affSColin Finck             phMonitor);
1299c2c66affSColin Finck     }
1300c2c66affSColin Finck 
1301c2c66affSColin Finck     VOID ChangingWinPos(IN OUT LPWINDOWPOS pwp)
1302c2c66affSColin Finck     {
1303c2c66affSColin Finck         RECT rcTray;
1304c2c66affSColin Finck 
1305c2c66affSColin Finck         if (IsDragging)
1306c2c66affSColin Finck         {
1307c2c66affSColin Finck             rcTray.left = pwp->x;
1308c2c66affSColin Finck             rcTray.top = pwp->y;
1309c2c66affSColin Finck             rcTray.right = rcTray.left + pwp->cx;
1310c2c66affSColin Finck             rcTray.bottom = rcTray.top + pwp->cy;
1311c2c66affSColin Finck 
1312c2c66affSColin Finck             if (!EqualRect(&rcTray,
1313c2c66affSColin Finck                 &m_TrayRects[m_DraggingPosition]))
1314c2c66affSColin Finck             {
1315c2c66affSColin Finck                 /* Recalculate the rectangle, the user dragged the tray
1316c2c66affSColin Finck                    window to another monitor or the window was somehow else
1317c2c66affSColin Finck                    moved or resized */
1318c2c66affSColin Finck                 m_DraggingPosition = GetDraggingRectFromRect(
1319c2c66affSColin Finck                     &rcTray,
1320c2c66affSColin Finck                     &m_DraggingMonitor);
1321c2c66affSColin Finck                 //m_TrayRects[DraggingPosition] = rcTray;
1322c2c66affSColin Finck             }
1323c2c66affSColin Finck 
1324c2c66affSColin Finck             //Monitor = CalculateValidSize(DraggingPosition,
1325c2c66affSColin Finck             //                             &rcTray);
1326c2c66affSColin Finck 
1327c2c66affSColin Finck             m_Monitor = m_DraggingMonitor;
1328c2c66affSColin Finck             m_Position = m_DraggingPosition;
1329c2c66affSColin Finck             IsDragging = FALSE;
1330c2c66affSColin Finck 
1331c2c66affSColin Finck             m_TrayRects[m_Position] = rcTray;
1332c2c66affSColin Finck             goto ChangePos;
1333c2c66affSColin Finck         }
1334c2c66affSColin Finck         else if (GetWindowRect(&rcTray))
1335c2c66affSColin Finck         {
1336c2c66affSColin Finck             if (InSizeMove)
1337c2c66affSColin Finck             {
1338c2c66affSColin Finck                 if (!(pwp->flags & SWP_NOMOVE))
1339c2c66affSColin Finck                 {
1340c2c66affSColin Finck                     rcTray.left = pwp->x;
1341c2c66affSColin Finck                     rcTray.top = pwp->y;
1342c2c66affSColin Finck                 }
1343c2c66affSColin Finck 
1344c2c66affSColin Finck                 if (!(pwp->flags & SWP_NOSIZE))
1345c2c66affSColin Finck                 {
1346c2c66affSColin Finck                     rcTray.right = rcTray.left + pwp->cx;
1347c2c66affSColin Finck                     rcTray.bottom = rcTray.top + pwp->cy;
1348c2c66affSColin Finck                 }
1349c2c66affSColin Finck 
1350c2c66affSColin Finck                 m_Position = GetDraggingRectFromRect(&rcTray, &m_Monitor);
1351c2c66affSColin Finck 
1352c2c66affSColin Finck                 if (!(pwp->flags & (SWP_NOMOVE | SWP_NOSIZE)))
1353c2c66affSColin Finck                 {
1354c2c66affSColin Finck                     SIZE szWnd;
1355c2c66affSColin Finck 
1356c2c66affSColin Finck                     szWnd.cx = pwp->cx;
1357c2c66affSColin Finck                     szWnd.cy = pwp->cy;
1358c2c66affSColin Finck 
1359c2c66affSColin Finck                     MakeTrayRectWithSize(m_Position, &szWnd, &rcTray);
1360c2c66affSColin Finck                 }
1361c2c66affSColin Finck 
1362c2c66affSColin Finck                 m_TrayRects[m_Position] = rcTray;
1363c2c66affSColin Finck             }
1364c2c66affSColin Finck             else
1365c2c66affSColin Finck             {
1366c2c66affSColin Finck                 /* If the user isn't resizing the tray window we need to make sure the
1367c2c66affSColin Finck                    new size or position is valid. this is to prevent changes to the window
1368c2c66affSColin Finck                    without user interaction. */
1369c2c66affSColin Finck                 rcTray = m_TrayRects[m_Position];
1370c2c66affSColin Finck 
13712ed535daSGiannis Adamopoulos                 if (g_TaskbarSettings.sr.AutoHide)
1372c2c66affSColin Finck                 {
1373c2c66affSColin Finck                     rcTray.left += m_AutoHideOffset.cx;
1374c2c66affSColin Finck                     rcTray.right += m_AutoHideOffset.cx;
1375c2c66affSColin Finck                     rcTray.top += m_AutoHideOffset.cy;
1376c2c66affSColin Finck                     rcTray.bottom += m_AutoHideOffset.cy;
1377c2c66affSColin Finck                 }
1378c2c66affSColin Finck 
13794238f223SGiannis Adamopoulos             }
13804238f223SGiannis Adamopoulos 
13814238f223SGiannis Adamopoulos ChangePos:
13824238f223SGiannis Adamopoulos             m_TraySize.cx = rcTray.right - rcTray.left;
13834238f223SGiannis Adamopoulos             m_TraySize.cy = rcTray.bottom - rcTray.top;
13844238f223SGiannis Adamopoulos 
1385c2c66affSColin Finck             pwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
1386c2c66affSColin Finck             pwp->x = rcTray.left;
1387c2c66affSColin Finck             pwp->y = rcTray.top;
1388c2c66affSColin Finck             pwp->cx = m_TraySize.cx;
1389c2c66affSColin Finck             pwp->cy = m_TraySize.cy;
1390c2c66affSColin Finck         }
1391c2c66affSColin Finck     }
1392c2c66affSColin Finck 
1393c2c66affSColin Finck     VOID ApplyClipping(IN BOOL Clip)
1394c2c66affSColin Finck     {
1395c2c66affSColin Finck         RECT rcClip, rcWindow;
1396c2c66affSColin Finck         HRGN hClipRgn;
1397c2c66affSColin Finck 
1398c2c66affSColin Finck         if (GetWindowRect(&rcWindow))
1399c2c66affSColin Finck         {
1400c2c66affSColin Finck             /* Disable clipping on systems with only one monitor */
1401c2c66affSColin Finck             if (GetSystemMetrics(SM_CMONITORS) <= 1)
1402c2c66affSColin Finck                 Clip = FALSE;
1403c2c66affSColin Finck 
1404c2c66affSColin Finck             if (Clip)
1405c2c66affSColin Finck             {
1406c2c66affSColin Finck                 rcClip = rcWindow;
1407c2c66affSColin Finck 
1408c2c66affSColin Finck                 GetScreenRect(m_Monitor, &rcClip);
1409c2c66affSColin Finck 
1410c2c66affSColin Finck                 if (!IntersectRect(&rcClip, &rcClip, &rcWindow))
1411c2c66affSColin Finck                 {
1412c2c66affSColin Finck                     rcClip = rcWindow;
1413c2c66affSColin Finck                 }
1414c2c66affSColin Finck 
1415c2c66affSColin Finck                 OffsetRect(&rcClip,
1416c2c66affSColin Finck                            -rcWindow.left,
1417c2c66affSColin Finck                            -rcWindow.top);
1418c2c66affSColin Finck 
1419c2c66affSColin Finck                 hClipRgn = CreateRectRgnIndirect(&rcClip);
1420c2c66affSColin Finck             }
1421c2c66affSColin Finck             else
1422c2c66affSColin Finck                 hClipRgn = NULL;
1423c2c66affSColin Finck 
1424c2c66affSColin Finck             /* Set the clipping region or make sure the window isn't clipped
1425c2c66affSColin Finck                by disabling it explicitly. */
1426c2c66affSColin Finck             SetWindowRgn(hClipRgn, TRUE);
1427c2c66affSColin Finck         }
1428c2c66affSColin Finck     }
1429c2c66affSColin Finck 
1430c2c66affSColin Finck     VOID ResizeWorkArea()
1431c2c66affSColin Finck     {
1432c2c66affSColin Finck #if !WIN7_DEBUG_MODE
1433c2c66affSColin Finck         RECT rcTray, rcWorkArea;
1434c2c66affSColin Finck 
1435c2c66affSColin Finck         /* If monitor has changed then fix the previous monitors work area */
1436c2c66affSColin Finck         if (m_PreviousMonitor != m_Monitor)
1437c2c66affSColin Finck         {
1438c2c66affSColin Finck             GetScreenRect(m_PreviousMonitor, &rcWorkArea);
1439c2c66affSColin Finck             SystemParametersInfoW(SPI_SETWORKAREA,
1440c2c66affSColin Finck                                   1,
1441c2c66affSColin Finck                                   &rcWorkArea,
1442c2c66affSColin Finck                                   SPIF_SENDCHANGE);
1443c2c66affSColin Finck         }
1444c2c66affSColin Finck 
1445c2c66affSColin Finck         rcTray = m_TrayRects[m_Position];
1446c2c66affSColin Finck 
1447c2c66affSColin Finck         GetScreenRect(m_Monitor, &rcWorkArea);
1448c2c66affSColin Finck         m_PreviousMonitor = m_Monitor;
1449c2c66affSColin Finck 
1450c2c66affSColin Finck         /* If AutoHide is false then change the workarea to exclude
1451c2c66affSColin Finck            the area that the taskbar covers. */
14522ed535daSGiannis Adamopoulos         if (!g_TaskbarSettings.sr.AutoHide)
1453c2c66affSColin Finck         {
1454c2c66affSColin Finck             switch (m_Position)
1455c2c66affSColin Finck             {
1456c2c66affSColin Finck             case ABE_TOP:
1457c2c66affSColin Finck                 rcWorkArea.top = rcTray.bottom;
1458c2c66affSColin Finck                 break;
1459c2c66affSColin Finck             case ABE_LEFT:
1460c2c66affSColin Finck                 rcWorkArea.left = rcTray.right;
1461c2c66affSColin Finck                 break;
1462c2c66affSColin Finck             case ABE_RIGHT:
1463c2c66affSColin Finck                 rcWorkArea.right = rcTray.left;
1464c2c66affSColin Finck                 break;
1465c2c66affSColin Finck             case ABE_BOTTOM:
1466c2c66affSColin Finck                 rcWorkArea.bottom = rcTray.top;
1467c2c66affSColin Finck                 break;
1468c2c66affSColin Finck             }
1469c2c66affSColin Finck         }
1470c2c66affSColin Finck 
1471c2c66affSColin Finck         /*
1472c2c66affSColin Finck          * Resize the current monitor work area. Win32k will also send
1473c2c66affSColin Finck          * a WM_SIZE message to automatically resize the desktop.
1474c2c66affSColin Finck          */
1475c2c66affSColin Finck         SystemParametersInfoW(SPI_SETWORKAREA,
1476c2c66affSColin Finck                               1,
1477c2c66affSColin Finck                               &rcWorkArea,
1478c2c66affSColin Finck                               SPIF_SENDCHANGE);
1479c2c66affSColin Finck #endif
1480c2c66affSColin Finck     }
1481c2c66affSColin Finck 
1482c2c66affSColin Finck     VOID CheckTrayWndPosition()
1483c2c66affSColin Finck     {
14844238f223SGiannis Adamopoulos         /* Force the rebar bands to resize */
1485c2c66affSColin Finck         IUnknown_Exec(m_TrayBandSite,
1486c2c66affSColin Finck                       IID_IDeskBand,
1487c2c66affSColin Finck                       DBID_BANDINFOCHANGED,
1488c2c66affSColin Finck                       0,
1489c2c66affSColin Finck                       NULL,
1490c2c66affSColin Finck                       NULL);
1491c2c66affSColin Finck 
14924238f223SGiannis Adamopoulos         /* Calculate the size of the taskbar based on the rebar */
14934238f223SGiannis Adamopoulos         FitToRebar(&m_TrayRects[m_Position]);
1494c2c66affSColin Finck 
1495c2c66affSColin Finck         /* Move the tray window */
14964238f223SGiannis Adamopoulos         /* The handler of WM_WINDOWPOSCHANGING will override whatever size
14974238f223SGiannis Adamopoulos          * and position we use here with m_TrayRects */
14984238f223SGiannis Adamopoulos         SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE);
1499c2c66affSColin Finck         ResizeWorkArea();
1500c2c66affSColin Finck         ApplyClipping(TRUE);
1501c2c66affSColin Finck     }
1502c2c66affSColin Finck 
1503c2c66affSColin Finck     VOID RegLoadSettings()
1504c2c66affSColin Finck     {
1505c2c66affSColin Finck         DWORD Pos;
1506c2c66affSColin Finck         RECT rcScreen;
1507c2c66affSColin Finck         SIZE WndSize, EdgeSize, DlgFrameSize;
1508c2c66affSColin Finck         SIZE StartBtnSize = m_StartButton.GetSize();
1509c2c66affSColin Finck 
1510c2c66affSColin Finck         EdgeSize.cx = GetSystemMetrics(SM_CXEDGE);
1511c2c66affSColin Finck         EdgeSize.cy = GetSystemMetrics(SM_CYEDGE);
1512c2c66affSColin Finck         DlgFrameSize.cx = GetSystemMetrics(SM_CXDLGFRAME);
1513c2c66affSColin Finck         DlgFrameSize.cy = GetSystemMetrics(SM_CYDLGFRAME);
1514c2c66affSColin Finck 
15152ed535daSGiannis Adamopoulos         m_Position = g_TaskbarSettings.sr.Position;
15162ed535daSGiannis Adamopoulos         rcScreen = g_TaskbarSettings.sr.Rect;
15172ed535daSGiannis Adamopoulos         GetScreenRectFromRect(&rcScreen, MONITOR_DEFAULTTONEAREST);
15182ed535daSGiannis Adamopoulos 
15192ed535daSGiannis Adamopoulos         if (!g_TaskbarSettings.sr.Size.cx || !g_TaskbarSettings.sr.Size.cy)
1520c2c66affSColin Finck         {
1521c2c66affSColin Finck             /* Use the minimum size of the taskbar, we'll use the start
1522c2c66affSColin Finck                button as a minimum for now. Make sure we calculate the
1523c2c66affSColin Finck                entire window size, not just the client size. However, we
1524c2c66affSColin Finck                use a thinner border than a standard thick border, so that
1525c2c66affSColin Finck                the start button and bands are not stuck to the screen border. */
1526c2c66affSColin Finck             if(!m_Theme)
1527c2c66affSColin Finck             {
15282ed535daSGiannis Adamopoulos                 g_TaskbarSettings.sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
15292ed535daSGiannis Adamopoulos                 g_TaskbarSettings.sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
1530c2c66affSColin Finck             }
1531c2c66affSColin Finck             else
1532c2c66affSColin Finck             {
15332ed535daSGiannis Adamopoulos                 g_TaskbarSettings.sr.Size.cx = StartBtnSize.cx - EdgeSize.cx;
15342ed535daSGiannis Adamopoulos                 g_TaskbarSettings.sr.Size.cy = StartBtnSize.cy - EdgeSize.cy;
15352ed535daSGiannis Adamopoulos                 if(!g_TaskbarSettings.bLock)
15362ed535daSGiannis Adamopoulos                     g_TaskbarSettings.sr.Size.cy += GetSystemMetrics(SM_CYSIZEFRAME);
1537c2c66affSColin Finck             }
1538c2c66affSColin Finck         }
1539c2c66affSColin Finck         /* Determine a minimum tray window rectangle. The "client" height is
1540c2c66affSColin Finck            zero here since we cannot determine an optimal minimum width when
1541c2c66affSColin Finck            loaded as a vertical tray window. We just need to make sure the values
1542c2c66affSColin Finck            loaded from the registry are at least. The windows explorer behaves
1543c2c66affSColin Finck            the same way, it allows the user to save a zero width vertical tray
1544c2c66affSColin Finck            window, but not a zero height horizontal tray window. */
1545c2c66affSColin Finck         if(!m_Theme)
1546c2c66affSColin Finck         {
1547c2c66affSColin Finck             WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
1548c2c66affSColin Finck             WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
1549c2c66affSColin Finck         }
1550c2c66affSColin Finck         else
1551c2c66affSColin Finck         {
1552c2c66affSColin Finck             WndSize.cx = StartBtnSize.cx;
1553c2c66affSColin Finck             WndSize.cy = StartBtnSize.cy - EdgeSize.cx;
1554c2c66affSColin Finck         }
1555c2c66affSColin Finck 
15562ed535daSGiannis Adamopoulos         if (WndSize.cx < g_TaskbarSettings.sr.Size.cx)
15572ed535daSGiannis Adamopoulos             WndSize.cx = g_TaskbarSettings.sr.Size.cx;
15582ed535daSGiannis Adamopoulos         if (WndSize.cy < g_TaskbarSettings.sr.Size.cy)
15592ed535daSGiannis Adamopoulos             WndSize.cy = g_TaskbarSettings.sr.Size.cy;
1560c2c66affSColin Finck 
1561c2c66affSColin Finck         /* Save the calculated size */
1562c2c66affSColin Finck         m_TraySize = WndSize;
1563c2c66affSColin Finck 
1564c2c66affSColin Finck         /* Calculate all docking rectangles. We need to do this here so they're
1565c2c66affSColin Finck            initialized and dragging the tray window to another position gives
1566c2c66affSColin Finck            usable results */
1567c2c66affSColin Finck         for (Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
1568c2c66affSColin Finck         {
1569c2c66affSColin Finck             GetTrayRectFromScreenRect(Pos,
1570c2c66affSColin Finck                                       &rcScreen,
1571c2c66affSColin Finck                                       &m_TraySize,
1572c2c66affSColin Finck                                       &m_TrayRects[Pos]);
1573c2c66affSColin Finck             // 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);
1574c2c66affSColin Finck         }
1575c2c66affSColin Finck 
1576c2c66affSColin Finck         /* Determine which monitor we are on. It shouldn't matter which docked
1577c2c66affSColin Finck            position rectangle we use */
1578c2c66affSColin Finck         m_Monitor = GetMonitorFromRect(&m_TrayRects[ABE_LEFT]);
1579c2c66affSColin Finck     }
1580c2c66affSColin Finck 
1581c2c66affSColin Finck     VOID AlignControls(IN PRECT prcClient OPTIONAL)
1582c2c66affSColin Finck     {
1583c2c66affSColin Finck         RECT rcClient;
1584c2c66affSColin Finck         SIZE TraySize, StartSize;
1585c2c66affSColin Finck         POINT ptTrayNotify = { 0, 0 };
1586c2c66affSColin Finck         BOOL Horizontal;
1587c2c66affSColin Finck         HDWP dwp;
1588c2c66affSColin Finck 
1589c2c66affSColin Finck         m_StartButton.UpdateSize();
1590c2c66affSColin Finck         if (prcClient != NULL)
1591c2c66affSColin Finck         {
1592c2c66affSColin Finck             rcClient = *prcClient;
1593c2c66affSColin Finck         }
1594c2c66affSColin Finck         else
1595c2c66affSColin Finck         {
1596c2c66affSColin Finck             if (!GetClientRect(&rcClient))
1597c2c66affSColin Finck             {
1598c2c66affSColin Finck                 ERR("Could not get client rect lastErr=%d\n", GetLastError());
1599c2c66affSColin Finck                 return;
1600c2c66affSColin Finck             }
1601c2c66affSColin Finck         }
1602c2c66affSColin Finck 
1603c2c66affSColin Finck         Horizontal = IsPosHorizontal();
1604c2c66affSColin Finck 
1605c2c66affSColin Finck         /* We're about to resize/move the start button, the rebar control and
1606c2c66affSColin Finck            the tray notification control */
1607c2c66affSColin Finck         dwp = BeginDeferWindowPos(3);
1608c2c66affSColin Finck         if (dwp == NULL)
1609c2c66affSColin Finck         {
1610c2c66affSColin Finck             ERR("BeginDeferWindowPos failed. lastErr=%d\n", GetLastError());
1611c2c66affSColin Finck             return;
1612c2c66affSColin Finck         }
1613c2c66affSColin Finck 
1614c2c66affSColin Finck         /* Limit the Start button width to the client width, if necessary */
1615c2c66affSColin Finck         StartSize = m_StartButton.GetSize();
1616c2c66affSColin Finck         if (StartSize.cx > rcClient.right)
1617c2c66affSColin Finck             StartSize.cx = rcClient.right;
1618c2c66affSColin Finck 
1619c2c66affSColin Finck         if (!m_Theme)
1620c2c66affSColin Finck         {
1621c2c66affSColin Finck             HWND hwndTaskToolbar = ::GetWindow(m_TaskSwitch, GW_CHILD);
1622c2c66affSColin Finck             if (hwndTaskToolbar)
1623c2c66affSColin Finck             {
1624c2c66affSColin Finck                 DWORD size = SendMessageW(hwndTaskToolbar, TB_GETBUTTONSIZE, 0, 0);
1625c2c66affSColin Finck                 StartSize.cy = HIWORD(size);
1626c2c66affSColin Finck             }
1627c2c66affSColin Finck         }
1628c2c66affSColin Finck 
1629c2c66affSColin Finck         if (m_StartButton.m_hWnd != NULL)
1630c2c66affSColin Finck         {
1631c2c66affSColin Finck             /* Resize and reposition the button */
1632c2c66affSColin Finck             dwp = m_StartButton.DeferWindowPos(dwp,
1633c2c66affSColin Finck                                                NULL,
1634c2c66affSColin Finck                                                0,
1635c2c66affSColin Finck                                                0,
1636c2c66affSColin Finck                                                StartSize.cx,
1637c2c66affSColin Finck                                                StartSize.cy,
1638c2c66affSColin Finck                                                SWP_NOZORDER | SWP_NOACTIVATE);
1639c2c66affSColin Finck             if (dwp == NULL)
1640c2c66affSColin Finck             {
1641c2c66affSColin Finck                 ERR("DeferWindowPos for start button failed. lastErr=%d\n", GetLastError());
1642c2c66affSColin Finck                 return;
1643c2c66affSColin Finck             }
1644c2c66affSColin Finck         }
1645c2c66affSColin Finck 
1646c2c66affSColin Finck         /* Determine the size that the tray notification window needs */
1647c2c66affSColin Finck         if (Horizontal)
1648c2c66affSColin Finck         {
1649c2c66affSColin Finck             TraySize.cx = 0;
1650c2c66affSColin Finck             TraySize.cy = rcClient.bottom;
1651c2c66affSColin Finck         }
1652c2c66affSColin Finck         else
1653c2c66affSColin Finck         {
1654c2c66affSColin Finck             TraySize.cx = rcClient.right;
1655c2c66affSColin Finck             TraySize.cy = 0;
1656c2c66affSColin Finck         }
1657c2c66affSColin Finck 
1658c2c66affSColin Finck         if (m_TrayNotify != NULL &&
1659c2c66affSColin Finck             SendMessage(m_TrayNotify,
1660c2c66affSColin Finck                         TNWM_GETMINIMUMSIZE,
1661c2c66affSColin Finck                         (WPARAM)Horizontal,
1662c2c66affSColin Finck                         (LPARAM)&TraySize))
1663c2c66affSColin Finck         {
1664c2c66affSColin Finck             /* Move the tray notification window to the desired location */
1665c2c66affSColin Finck             if (Horizontal)
1666c2c66affSColin Finck                 ptTrayNotify.x = rcClient.right - TraySize.cx;
1667c2c66affSColin Finck             else
1668c2c66affSColin Finck                 ptTrayNotify.y = rcClient.bottom - TraySize.cy;
1669c2c66affSColin Finck 
1670c2c66affSColin Finck             dwp = ::DeferWindowPos(dwp,
1671c2c66affSColin Finck                                    m_TrayNotify,
1672c2c66affSColin Finck                                    NULL,
1673c2c66affSColin Finck                                    ptTrayNotify.x,
1674c2c66affSColin Finck                                    ptTrayNotify.y,
1675c2c66affSColin Finck                                    TraySize.cx,
1676c2c66affSColin Finck                                    TraySize.cy,
1677c2c66affSColin Finck                                    SWP_NOZORDER | SWP_NOACTIVATE);
1678c2c66affSColin Finck             if (dwp == NULL)
1679c2c66affSColin Finck             {
1680c2c66affSColin Finck                 ERR("DeferWindowPos for notification area failed. lastErr=%d\n", GetLastError());
1681c2c66affSColin Finck                 return;
1682c2c66affSColin Finck             }
1683c2c66affSColin Finck         }
1684c2c66affSColin Finck 
1685c2c66affSColin Finck         /* Resize/Move the rebar control */
1686c2c66affSColin Finck         if (m_Rebar != NULL)
1687c2c66affSColin Finck         {
1688c2c66affSColin Finck             POINT ptRebar = { 0, 0 };
1689c2c66affSColin Finck             SIZE szRebar;
1690c2c66affSColin Finck 
1691c2c66affSColin Finck             SetWindowStyle(m_Rebar, CCS_VERT, Horizontal ? 0 : CCS_VERT);
1692c2c66affSColin Finck 
1693c2c66affSColin Finck             if (Horizontal)
1694c2c66affSColin Finck             {
1695c2c66affSColin Finck                 ptRebar.x = StartSize.cx + GetSystemMetrics(SM_CXSIZEFRAME);
1696c2c66affSColin Finck                 szRebar.cx = ptTrayNotify.x - ptRebar.x;
1697c2c66affSColin Finck                 szRebar.cy = rcClient.bottom;
1698c2c66affSColin Finck             }
1699c2c66affSColin Finck             else
1700c2c66affSColin Finck             {
1701c2c66affSColin Finck                 ptRebar.y = StartSize.cy + GetSystemMetrics(SM_CYSIZEFRAME);
1702c2c66affSColin Finck                 szRebar.cx = rcClient.right;
1703c2c66affSColin Finck                 szRebar.cy = ptTrayNotify.y - ptRebar.y;
1704c2c66affSColin Finck             }
1705c2c66affSColin Finck 
1706c2c66affSColin Finck             dwp = ::DeferWindowPos(dwp,
1707c2c66affSColin Finck                                    m_Rebar,
1708c2c66affSColin Finck                                    NULL,
1709c2c66affSColin Finck                                    ptRebar.x,
1710c2c66affSColin Finck                                    ptRebar.y,
1711c2c66affSColin Finck                                    szRebar.cx,
1712c2c66affSColin Finck                                    szRebar.cy,
1713c2c66affSColin Finck                                    SWP_NOZORDER | SWP_NOACTIVATE);
1714c2c66affSColin Finck         }
1715c2c66affSColin Finck 
1716c2c66affSColin Finck         if (dwp != NULL)
1717c2c66affSColin Finck             EndDeferWindowPos(dwp);
1718c2c66affSColin Finck 
1719c2c66affSColin Finck         if (m_TaskSwitch != NULL)
1720c2c66affSColin Finck         {
1721c2c66affSColin Finck             /* Update the task switch window configuration */
1722c2c66affSColin Finck             SendMessage(m_TaskSwitch, TSWM_UPDATETASKBARPOS, 0, 0);
1723c2c66affSColin Finck         }
1724c2c66affSColin Finck     }
1725c2c66affSColin Finck 
1726c2c66affSColin Finck     void FitToRebar(PRECT pRect)
1727c2c66affSColin Finck     {
1728c2c66affSColin Finck         /* Get the rect of the rebar */
1729c2c66affSColin Finck         RECT rebarRect, taskbarRect, clientRect;
1730c2c66affSColin Finck         ::GetWindowRect(m_Rebar, &rebarRect);
1731c2c66affSColin Finck         ::GetWindowRect(m_hWnd, &taskbarRect);
1732c2c66affSColin Finck         ::GetClientRect(m_hWnd, &clientRect);
1733c2c66affSColin Finck         OffsetRect(&rebarRect, -taskbarRect.left, -taskbarRect.top);
1734c2c66affSColin Finck 
1735c2c66affSColin Finck         /* Calculate the difference of size of the taskbar and the rebar */
1736c2c66affSColin Finck         SIZE margins;
1737c2c66affSColin Finck         margins.cx = taskbarRect.right - taskbarRect.left - clientRect.right + clientRect.left;
1738c2c66affSColin Finck         margins.cy = taskbarRect.bottom - taskbarRect.top - clientRect.bottom + clientRect.top;
1739c2c66affSColin Finck 
1740c2c66affSColin Finck         /* Calculate the new size of the rebar and make it resize, then change the new taskbar size */
1741c2c66affSColin Finck         switch (m_Position)
1742c2c66affSColin Finck         {
1743c2c66affSColin Finck         case ABE_TOP:
1744c2c66affSColin Finck             rebarRect.bottom = rebarRect.top + pRect->bottom - pRect->top - margins.cy;
1745c2c66affSColin Finck             ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
1746c2c66affSColin Finck             pRect->bottom = pRect->top + rebarRect.bottom - rebarRect.top + margins.cy;
1747c2c66affSColin Finck             break;
1748c2c66affSColin Finck         case ABE_BOTTOM:
1749c2c66affSColin Finck             rebarRect.top = rebarRect.bottom - (pRect->bottom - pRect->top - margins.cy);
1750c2c66affSColin Finck             ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
1751c2c66affSColin Finck             pRect->top = pRect->bottom - (rebarRect.bottom - rebarRect.top + margins.cy);
1752c2c66affSColin Finck             break;
1753c2c66affSColin Finck         case ABE_LEFT:
1754c2c66affSColin Finck             rebarRect.right = rebarRect.left + (pRect->right - pRect->left - margins.cx);
1755c2c66affSColin Finck             ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
1756c2c66affSColin Finck             pRect->right = pRect->left + (rebarRect.right - rebarRect.left + margins.cx);
1757c2c66affSColin Finck             break;
1758c2c66affSColin Finck         case ABE_RIGHT:
1759c2c66affSColin Finck             rebarRect.left = rebarRect.right - (pRect->right - pRect->left - margins.cx);
1760c2c66affSColin Finck             ::SendMessageW(m_Rebar, RB_SIZETORECT, RBSTR_CHANGERECT,  (LPARAM)&rebarRect);
1761c2c66affSColin Finck             pRect->left = pRect->right - (rebarRect.right - rebarRect.left + margins.cx);
1762c2c66affSColin Finck             break;
1763c2c66affSColin Finck         }
1764c2c66affSColin Finck 
1765c2c66affSColin Finck         CalculateValidSize(m_Position, pRect);
1766c2c66affSColin Finck     }
1767c2c66affSColin Finck 
1768c2c66affSColin Finck     void PopupStartMenu()
1769c2c66affSColin Finck     {
1770c2c66affSColin Finck         if (m_StartMenuPopup != NULL)
1771c2c66affSColin Finck         {
1772c2c66affSColin Finck             POINTL pt;
1773c2c66affSColin Finck             RECTL rcExclude;
1774c2c66affSColin Finck             DWORD dwFlags = 0;
1775c2c66affSColin Finck 
1776c2c66affSColin Finck             if (m_StartButton.GetWindowRect((RECT*) &rcExclude))
1777c2c66affSColin Finck             {
1778c2c66affSColin Finck                 switch (m_Position)
1779c2c66affSColin Finck                 {
1780c2c66affSColin Finck                 case ABE_BOTTOM:
1781c2c66affSColin Finck                     pt.x = rcExclude.left;
1782c2c66affSColin Finck                     pt.y = rcExclude.top;
1783c2c66affSColin Finck                     dwFlags |= MPPF_TOP;
1784c2c66affSColin Finck                     break;
1785c2c66affSColin Finck                 case ABE_TOP:
1786c2c66affSColin Finck                     pt.x = rcExclude.left;
1787c2c66affSColin Finck                     pt.y = rcExclude.bottom;
1788c2c66affSColin Finck                     dwFlags |= MPPF_BOTTOM;
1789c2c66affSColin Finck                     break;
1790c2c66affSColin Finck                 case ABE_LEFT:
1791c2c66affSColin Finck                     pt.x = rcExclude.right;
1792c2c66affSColin Finck                     pt.y = rcExclude.top;
1793c2c66affSColin Finck                     dwFlags |= MPPF_RIGHT;
1794c2c66affSColin Finck                     break;
1795c2c66affSColin Finck                 case ABE_RIGHT:
1796c2c66affSColin Finck                     pt.x = rcExclude.left;
1797c2c66affSColin Finck                     pt.y = rcExclude.top;
1798c2c66affSColin Finck                     dwFlags |= MPPF_LEFT;
1799c2c66affSColin Finck                     break;
1800c2c66affSColin Finck                 }
1801c2c66affSColin Finck 
1802c2c66affSColin Finck                 m_StartMenuPopup->Popup(&pt, &rcExclude, dwFlags);
1803c2c66affSColin Finck 
1804c2c66affSColin Finck                 m_StartButton.SendMessageW(BM_SETSTATE, TRUE, 0);
1805c2c66affSColin Finck             }
1806c2c66affSColin Finck         }
1807c2c66affSColin Finck     }
1808c2c66affSColin Finck 
1809c2c66affSColin Finck     void ProcessMouseTracking()
1810c2c66affSColin Finck     {
1811c2c66affSColin Finck         RECT rcCurrent;
1812c2c66affSColin Finck         POINT pt;
1813c2c66affSColin Finck         BOOL over;
1814c2c66affSColin Finck         UINT state = m_AutoHideState;
1815c2c66affSColin Finck 
1816c2c66affSColin Finck         GetCursorPos(&pt);
1817c2c66affSColin Finck         GetWindowRect(&rcCurrent);
1818c2c66affSColin Finck         over = PtInRect(&rcCurrent, pt);
1819c2c66affSColin Finck 
1820c2c66affSColin Finck         if (m_StartButton.SendMessage( BM_GETSTATE, 0, 0) != BST_UNCHECKED)
1821c2c66affSColin Finck         {
1822c2c66affSColin Finck             over = TRUE;
1823c2c66affSColin Finck         }
1824c2c66affSColin Finck 
1825c2c66affSColin Finck         if (over)
1826c2c66affSColin Finck         {
1827c2c66affSColin Finck             if (state == AUTOHIDE_HIDING)
1828c2c66affSColin Finck             {
1829c2c66affSColin Finck                 TRACE("AutoHide cancelling hide.\n");
1830c2c66affSColin Finck                 m_AutoHideState = AUTOHIDE_SHOWING;
1831c2c66affSColin Finck                 SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
1832c2c66affSColin Finck             }
1833c2c66affSColin Finck             else if (state == AUTOHIDE_HIDDEN)
1834c2c66affSColin Finck             {
1835c2c66affSColin Finck                 TRACE("AutoHide starting show.\n");
1836c2c66affSColin Finck                 m_AutoHideState = AUTOHIDE_SHOWING;
1837c2c66affSColin Finck                 SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_SHOW, NULL);
1838c2c66affSColin Finck             }
1839c2c66affSColin Finck         }
1840c2c66affSColin Finck         else
1841c2c66affSColin Finck         {
1842c2c66affSColin Finck             if (state == AUTOHIDE_SHOWING)
1843c2c66affSColin Finck             {
1844c2c66affSColin Finck                 TRACE("AutoHide cancelling show.\n");
1845c2c66affSColin Finck                 m_AutoHideState = AUTOHIDE_HIDING;
1846c2c66affSColin Finck                 SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
1847c2c66affSColin Finck             }
1848c2c66affSColin Finck             else if (state == AUTOHIDE_SHOWN)
1849c2c66affSColin Finck             {
1850c2c66affSColin Finck                 TRACE("AutoHide starting hide.\n");
1851c2c66affSColin Finck                 m_AutoHideState = AUTOHIDE_HIDING;
1852c2c66affSColin Finck                 SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
1853c2c66affSColin Finck             }
1854c2c66affSColin Finck 
1855c2c66affSColin Finck             KillTimer(TIMER_ID_MOUSETRACK);
1856c2c66affSColin Finck         }
1857c2c66affSColin Finck     }
1858c2c66affSColin Finck 
1859c2c66affSColin Finck     void ProcessAutoHide()
1860c2c66affSColin Finck     {
1861c2c66affSColin Finck         INT w = m_TraySize.cx - GetSystemMetrics(SM_CXBORDER) * 2 - 1;
1862c2c66affSColin Finck         INT h = m_TraySize.cy - GetSystemMetrics(SM_CYBORDER) * 2 - 1;
1863c2c66affSColin Finck 
1864c2c66affSColin Finck         switch (m_AutoHideState)
1865c2c66affSColin Finck         {
1866c2c66affSColin Finck         case AUTOHIDE_HIDING:
1867c2c66affSColin Finck             switch (m_Position)
1868c2c66affSColin Finck             {
1869c2c66affSColin Finck             case ABE_LEFT:
1870c2c66affSColin Finck                 m_AutoHideOffset.cy = 0;
1871c2c66affSColin Finck                 m_AutoHideOffset.cx -= AUTOHIDE_SPEED_HIDE;
1872c2c66affSColin Finck                 if (m_AutoHideOffset.cx < -w)
1873c2c66affSColin Finck                     m_AutoHideOffset.cx = -w;
1874c2c66affSColin Finck                 break;
1875c2c66affSColin Finck             case ABE_TOP:
1876c2c66affSColin Finck                 m_AutoHideOffset.cx = 0;
1877c2c66affSColin Finck                 m_AutoHideOffset.cy -= AUTOHIDE_SPEED_HIDE;
1878c2c66affSColin Finck                 if (m_AutoHideOffset.cy < -h)
1879c2c66affSColin Finck                     m_AutoHideOffset.cy = -h;
1880c2c66affSColin Finck                 break;
1881c2c66affSColin Finck             case ABE_RIGHT:
1882c2c66affSColin Finck                 m_AutoHideOffset.cy = 0;
1883c2c66affSColin Finck                 m_AutoHideOffset.cx += AUTOHIDE_SPEED_HIDE;
1884c2c66affSColin Finck                 if (m_AutoHideOffset.cx > w)
1885c2c66affSColin Finck                     m_AutoHideOffset.cx = w;
1886c2c66affSColin Finck                 break;
1887c2c66affSColin Finck             case ABE_BOTTOM:
1888c2c66affSColin Finck                 m_AutoHideOffset.cx = 0;
1889c2c66affSColin Finck                 m_AutoHideOffset.cy += AUTOHIDE_SPEED_HIDE;
1890c2c66affSColin Finck                 if (m_AutoHideOffset.cy > h)
1891c2c66affSColin Finck                     m_AutoHideOffset.cy = h;
1892c2c66affSColin Finck                 break;
1893c2c66affSColin Finck             }
1894c2c66affSColin Finck 
1895c2c66affSColin Finck             if (m_AutoHideOffset.cx != w && m_AutoHideOffset.cy != h)
1896c2c66affSColin Finck             {
1897c2c66affSColin Finck                 SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
1898c2c66affSColin Finck                 break;
1899c2c66affSColin Finck             }
1900c2c66affSColin Finck 
1901c2c66affSColin Finck             /* fallthrough */
1902c2c66affSColin Finck         case AUTOHIDE_HIDDEN:
1903c2c66affSColin Finck 
1904c2c66affSColin Finck             switch (m_Position)
1905c2c66affSColin Finck             {
1906c2c66affSColin Finck             case ABE_LEFT:
1907c2c66affSColin Finck                 m_AutoHideOffset.cx = -w;
1908c2c66affSColin Finck                 m_AutoHideOffset.cy = 0;
1909c2c66affSColin Finck                 break;
1910c2c66affSColin Finck             case ABE_TOP:
1911c2c66affSColin Finck                 m_AutoHideOffset.cx = 0;
1912c2c66affSColin Finck                 m_AutoHideOffset.cy = -h;
1913c2c66affSColin Finck                 break;
1914c2c66affSColin Finck             case ABE_RIGHT:
1915c2c66affSColin Finck                 m_AutoHideOffset.cx = w;
1916c2c66affSColin Finck                 m_AutoHideOffset.cy = 0;
1917c2c66affSColin Finck                 break;
1918c2c66affSColin Finck             case ABE_BOTTOM:
1919c2c66affSColin Finck                 m_AutoHideOffset.cx = 0;
1920c2c66affSColin Finck                 m_AutoHideOffset.cy = h;
1921c2c66affSColin Finck                 break;
1922c2c66affSColin Finck             }
1923c2c66affSColin Finck 
1924c2c66affSColin Finck             KillTimer(TIMER_ID_AUTOHIDE);
1925c2c66affSColin Finck             m_AutoHideState = AUTOHIDE_HIDDEN;
1926c2c66affSColin Finck             break;
1927c2c66affSColin Finck 
1928c2c66affSColin Finck         case AUTOHIDE_SHOWING:
1929c2c66affSColin Finck             if (m_AutoHideOffset.cx >= AUTOHIDE_SPEED_SHOW)
1930c2c66affSColin Finck             {
1931c2c66affSColin Finck                 m_AutoHideOffset.cx -= AUTOHIDE_SPEED_SHOW;
1932c2c66affSColin Finck             }
1933c2c66affSColin Finck             else if (m_AutoHideOffset.cx <= -AUTOHIDE_SPEED_SHOW)
1934c2c66affSColin Finck             {
1935c2c66affSColin Finck                 m_AutoHideOffset.cx += AUTOHIDE_SPEED_SHOW;
1936c2c66affSColin Finck             }
1937c2c66affSColin Finck             else
1938c2c66affSColin Finck             {
1939c2c66affSColin Finck                 m_AutoHideOffset.cx = 0;
1940c2c66affSColin Finck             }
1941c2c66affSColin Finck 
1942c2c66affSColin Finck             if (m_AutoHideOffset.cy >= AUTOHIDE_SPEED_SHOW)
1943c2c66affSColin Finck             {
1944c2c66affSColin Finck                 m_AutoHideOffset.cy -= AUTOHIDE_SPEED_SHOW;
1945c2c66affSColin Finck             }
1946c2c66affSColin Finck             else if (m_AutoHideOffset.cy <= -AUTOHIDE_SPEED_SHOW)
1947c2c66affSColin Finck             {
1948c2c66affSColin Finck                 m_AutoHideOffset.cy += AUTOHIDE_SPEED_SHOW;
1949c2c66affSColin Finck             }
1950c2c66affSColin Finck             else
1951c2c66affSColin Finck             {
1952c2c66affSColin Finck                 m_AutoHideOffset.cy = 0;
1953c2c66affSColin Finck             }
1954c2c66affSColin Finck 
1955c2c66affSColin Finck             if (m_AutoHideOffset.cx != 0 || m_AutoHideOffset.cy != 0)
1956c2c66affSColin Finck             {
1957c2c66affSColin Finck                 SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
1958c2c66affSColin Finck                 break;
1959c2c66affSColin Finck             }
1960c2c66affSColin Finck 
1961c2c66affSColin Finck             /* fallthrough */
1962c2c66affSColin Finck         case AUTOHIDE_SHOWN:
1963c2c66affSColin Finck 
1964c2c66affSColin Finck             KillTimer(TIMER_ID_AUTOHIDE);
1965c2c66affSColin Finck             m_AutoHideState = AUTOHIDE_SHOWN;
1966c2c66affSColin Finck             break;
1967c2c66affSColin Finck         }
1968c2c66affSColin Finck 
19694238f223SGiannis Adamopoulos         SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER);
1970c2c66affSColin Finck     }
1971c2c66affSColin Finck 
1972c2c66affSColin Finck 
1973c2c66affSColin Finck 
1974c2c66affSColin Finck 
1975c2c66affSColin Finck 
1976c2c66affSColin Finck     /**********************************************************
1977c2c66affSColin Finck      *    ##### taskbar drawing #####
1978c2c66affSColin Finck      */
1979c2c66affSColin Finck 
1980c2c66affSColin Finck     LRESULT EraseBackgroundWithTheme(HDC hdc)
1981c2c66affSColin Finck     {
1982c2c66affSColin Finck         RECT rect;
1983c2c66affSColin Finck         int iSBkgndPart[4] = {TBP_BACKGROUNDLEFT, TBP_BACKGROUNDTOP, TBP_BACKGROUNDRIGHT, TBP_BACKGROUNDBOTTOM};
1984c2c66affSColin Finck 
1985c2c66affSColin Finck         ASSERT(m_Position <= ABE_BOTTOM);
1986c2c66affSColin Finck 
1987c2c66affSColin Finck         if (m_Theme)
1988c2c66affSColin Finck         {
1989c2c66affSColin Finck             GetClientRect(&rect);
1990c2c66affSColin Finck             DrawThemeBackground(m_Theme, hdc, iSBkgndPart[m_Position], 0, &rect, 0);
1991c2c66affSColin Finck         }
1992c2c66affSColin Finck 
1993c2c66affSColin Finck         return 0;
1994c2c66affSColin Finck     }
1995c2c66affSColin Finck 
1996c2c66affSColin Finck     int DrawSizerWithTheme(IN HRGN hRgn)
1997c2c66affSColin Finck     {
1998c2c66affSColin Finck         HDC hdc;
1999c2c66affSColin Finck         RECT rect;
2000c2c66affSColin Finck         int iSizerPart[4] = {TBP_SIZINGBARLEFT, TBP_SIZINGBARTOP, TBP_SIZINGBARRIGHT, TBP_SIZINGBARBOTTOM};
2001c2c66affSColin Finck         SIZE size;
2002c2c66affSColin Finck 
2003c2c66affSColin Finck         ASSERT(m_Position <= ABE_BOTTOM);
2004c2c66affSColin Finck 
2005c2c66affSColin Finck         HRESULT hr = GetThemePartSize(m_Theme, NULL, iSizerPart[m_Position], 0, NULL, TS_TRUE, &size);
2006c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
2007c2c66affSColin Finck             return 0;
2008c2c66affSColin Finck 
2009c2c66affSColin Finck         GetWindowRect(&rect);
2010c2c66affSColin Finck         OffsetRect(&rect, -rect.left, -rect.top);
2011c2c66affSColin Finck 
2012c2c66affSColin Finck         hdc = GetWindowDC();
2013c2c66affSColin Finck 
2014c2c66affSColin Finck         switch (m_Position)
2015c2c66affSColin Finck         {
2016c2c66affSColin Finck         case ABE_LEFT:
2017c2c66affSColin Finck             rect.left = rect.right - size.cx;
2018c2c66affSColin Finck             break;
2019c2c66affSColin Finck         case ABE_TOP:
2020c2c66affSColin Finck             rect.top = rect.bottom - size.cy;
2021c2c66affSColin Finck             break;
2022c2c66affSColin Finck         case ABE_RIGHT:
2023c2c66affSColin Finck             rect.right = rect.left + size.cx;
2024c2c66affSColin Finck             break;
2025c2c66affSColin Finck         case ABE_BOTTOM:
2026c2c66affSColin Finck         default:
2027c2c66affSColin Finck             rect.bottom = rect.top + size.cy;
2028c2c66affSColin Finck             break;
2029c2c66affSColin Finck         }
2030c2c66affSColin Finck 
2031c2c66affSColin Finck         DrawThemeBackground(m_Theme, hdc, iSizerPart[m_Position], 0, &rect, 0);
2032c2c66affSColin Finck 
2033c2c66affSColin Finck         ReleaseDC(hdc);
2034c2c66affSColin Finck         return 0;
2035c2c66affSColin Finck     }
2036c2c66affSColin Finck 
2037c2c66affSColin Finck 
2038c2c66affSColin Finck 
2039c2c66affSColin Finck 
2040c2c66affSColin Finck 
2041c2c66affSColin Finck     /*
2042c2c66affSColin Finck      * ITrayWindow
2043c2c66affSColin Finck      */
2044c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE Open()
2045c2c66affSColin Finck     {
2046c2c66affSColin Finck         RECT rcWnd;
2047c2c66affSColin Finck 
2048c2c66affSColin Finck         /* Check if there's already a window created and try to show it.
2049c2c66affSColin Finck            If it was somehow destroyed just create a new tray window. */
2050c2c66affSColin Finck         if (m_hWnd != NULL && IsWindow())
2051c2c66affSColin Finck         {
2052c2c66affSColin Finck             return S_OK;
2053c2c66affSColin Finck         }
2054c2c66affSColin Finck 
2055c2c66affSColin Finck         DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
20562ed535daSGiannis Adamopoulos         if (g_TaskbarSettings.sr.AlwaysOnTop)
2057c2c66affSColin Finck             dwExStyle |= WS_EX_TOPMOST;
2058c2c66affSColin Finck 
2059c2c66affSColin Finck         DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
2060c2c66affSColin Finck         if(!m_Theme)
2061c2c66affSColin Finck         {
2062c2c66affSColin Finck             dwStyle |= WS_THICKFRAME | WS_BORDER;
2063c2c66affSColin Finck         }
2064c2c66affSColin Finck 
2065c2c66affSColin Finck         ZeroMemory(&rcWnd, sizeof(rcWnd));
2066c2c66affSColin Finck         if (m_Position != (DWORD) -1)
2067c2c66affSColin Finck             rcWnd = m_TrayRects[m_Position];
2068c2c66affSColin Finck 
2069c2c66affSColin Finck         if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
2070c2c66affSColin Finck             return E_FAIL;
2071c2c66affSColin Finck 
2072c2c66affSColin Finck         /* Align all controls on the tray window */
2073c2c66affSColin Finck         AlignControls(NULL);
2074c2c66affSColin Finck 
2075c2c66affSColin Finck         /* Move the tray window to the right position and resize it if necessary */
2076c2c66affSColin Finck         CheckTrayWndPosition();
2077c2c66affSColin Finck 
2078c2c66affSColin Finck         return S_OK;
2079c2c66affSColin Finck     }
2080c2c66affSColin Finck 
2081c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE Close()
2082c2c66affSColin Finck     {
2083c2c66affSColin Finck         if (m_hWnd != NULL)
2084c2c66affSColin Finck         {
2085c2c66affSColin Finck             SendMessage(m_hWnd,
2086c2c66affSColin Finck                         WM_APP_TRAYDESTROY,
2087c2c66affSColin Finck                         0,
2088c2c66affSColin Finck                         0);
2089c2c66affSColin Finck         }
2090c2c66affSColin Finck 
2091c2c66affSColin Finck         return S_OK;
2092c2c66affSColin Finck     }
2093c2c66affSColin Finck 
2094c2c66affSColin Finck     HWND STDMETHODCALLTYPE GetHWND()
2095c2c66affSColin Finck     {
2096c2c66affSColin Finck         return m_hWnd;
2097c2c66affSColin Finck     }
2098c2c66affSColin Finck 
2099c2c66affSColin Finck     BOOL STDMETHODCALLTYPE IsSpecialHWND(IN HWND hWnd)
2100c2c66affSColin Finck     {
2101c2c66affSColin Finck         return (m_hWnd == hWnd ||
2102c2c66affSColin Finck                 (m_DesktopWnd != NULL && m_hWnd == m_DesktopWnd));
2103c2c66affSColin Finck     }
2104c2c66affSColin Finck 
2105c2c66affSColin Finck     BOOL STDMETHODCALLTYPE IsHorizontal()
2106c2c66affSColin Finck     {
2107c2c66affSColin Finck         return IsPosHorizontal();
2108c2c66affSColin Finck     }
2109c2c66affSColin Finck 
2110c2c66affSColin Finck     BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
2111c2c66affSColin Finck     {
21122ed535daSGiannis Adamopoulos         BOOL bPrevLock = g_TaskbarSettings.bLock;
2113c2c66affSColin Finck 
21142ed535daSGiannis Adamopoulos         if (g_TaskbarSettings.bLock != bLock)
2115c2c66affSColin Finck         {
21162ed535daSGiannis Adamopoulos             g_TaskbarSettings.bLock = bLock;
2117c2c66affSColin Finck 
2118c2c66affSColin Finck             if (m_TrayBandSite != NULL)
2119c2c66affSColin Finck             {
2120c2c66affSColin Finck                 if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
2121c2c66affSColin Finck                 {
2122c2c66affSColin Finck                     /* Reset?? */
21232ed535daSGiannis Adamopoulos                     g_TaskbarSettings.bLock = bPrevLock;
2124c2c66affSColin Finck                     return bPrevLock;
2125c2c66affSColin Finck                 }
2126c2c66affSColin Finck             }
2127c2c66affSColin Finck 
2128c2c66affSColin Finck             if (m_Theme)
2129c2c66affSColin Finck             {
2130c2c66affSColin Finck                 /* Update cached tray sizes */
2131c2c66affSColin Finck                 for(DWORD Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
2132c2c66affSColin Finck                 {
2133c2c66affSColin Finck                     RECT rcGripper = {0};
2134c2c66affSColin Finck                     AdjustSizerRect(&rcGripper, Pos);
2135c2c66affSColin Finck 
21362ed535daSGiannis Adamopoulos                     if(g_TaskbarSettings.bLock)
2137c2c66affSColin Finck                     {
2138c2c66affSColin Finck                         m_TrayRects[Pos].top += rcGripper.top;
2139c2c66affSColin Finck                         m_TrayRects[Pos].left += rcGripper.left;
2140c2c66affSColin Finck                         m_TrayRects[Pos].bottom += rcGripper.bottom;
2141c2c66affSColin Finck                         m_TrayRects[Pos].right += rcGripper.right;
2142c2c66affSColin Finck                     }
2143c2c66affSColin Finck                     else
2144c2c66affSColin Finck                     {
2145c2c66affSColin Finck                         m_TrayRects[Pos].top -= rcGripper.top;
2146c2c66affSColin Finck                         m_TrayRects[Pos].left -= rcGripper.left;
2147c2c66affSColin Finck                         m_TrayRects[Pos].bottom -= rcGripper.bottom;
2148c2c66affSColin Finck                         m_TrayRects[Pos].right -= rcGripper.right;
2149c2c66affSColin Finck                     }
2150c2c66affSColin Finck                 }
2151c2c66affSColin Finck             }
2152c2c66affSColin Finck             SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
2153c2c66affSColin Finck             ResizeWorkArea();
2154c2c66affSColin Finck             ApplyClipping(TRUE);
2155c2c66affSColin Finck         }
2156c2c66affSColin Finck 
2157c2c66affSColin Finck         return bPrevLock;
2158c2c66affSColin Finck     }
2159c2c66affSColin Finck 
2160c2c66affSColin Finck 
2161c2c66affSColin Finck     /*
2162c2c66affSColin Finck      *  IContextMenu
2163c2c66affSColin Finck      */
2164c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE QueryContextMenu(HMENU hPopup,
2165c2c66affSColin Finck                                                UINT indexMenu,
2166c2c66affSColin Finck                                                UINT idCmdFirst,
2167c2c66affSColin Finck                                                UINT idCmdLast,
2168c2c66affSColin Finck                                                UINT uFlags)
2169c2c66affSColin Finck     {
2170c2c66affSColin Finck         if (!m_ContextMenu)
2171c2c66affSColin Finck         {
2172c2c66affSColin Finck             HRESULT hr = TrayWindowCtxMenuCreator(this, m_hWnd, &m_ContextMenu);
2173c2c66affSColin Finck             if (FAILED_UNEXPECTEDLY(hr))
2174c2c66affSColin Finck                 return hr;
2175c2c66affSColin Finck         }
2176c2c66affSColin Finck 
2177c2c66affSColin Finck         return m_ContextMenu->QueryContextMenu(hPopup, indexMenu, idCmdFirst, idCmdLast, uFlags);
2178c2c66affSColin Finck     }
2179c2c66affSColin Finck 
2180c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
2181c2c66affSColin Finck     {
2182c2c66affSColin Finck         if (!m_ContextMenu)
2183c2c66affSColin Finck             return E_INVALIDARG;
2184c2c66affSColin Finck 
2185c2c66affSColin Finck         return m_ContextMenu->InvokeCommand(lpici);
2186c2c66affSColin Finck     }
2187c2c66affSColin Finck 
2188c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE GetCommandString(UINT_PTR idCmd,
2189c2c66affSColin Finck                                                UINT uType,
2190c2c66affSColin Finck                                                UINT *pwReserved,
2191c2c66affSColin Finck                                                LPSTR pszName,
2192c2c66affSColin Finck                                                UINT cchMax)
2193c2c66affSColin Finck     {
2194c2c66affSColin Finck         if (!m_ContextMenu)
2195c2c66affSColin Finck             return E_INVALIDARG;
2196c2c66affSColin Finck 
2197c2c66affSColin Finck         return m_ContextMenu->GetCommandString(idCmd, uType, pwReserved, pszName, cchMax);
2198c2c66affSColin Finck     }
2199c2c66affSColin Finck 
2200c2c66affSColin Finck 
2201c2c66affSColin Finck     /**********************************************************
2202c2c66affSColin Finck      *    ##### message handling #####
2203c2c66affSColin Finck      */
2204c2c66affSColin Finck 
2205c2c66affSColin Finck     LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2206c2c66affSColin Finck     {
2207c2c66affSColin Finck         HRESULT hRet;
2208c2c66affSColin Finck 
2209c2c66affSColin Finck         ((ITrayWindow*)this)->AddRef();
2210c2c66affSColin Finck 
2211c2c66affSColin Finck         SetWindowTheme(m_hWnd, L"TaskBar", NULL);
2212c2c66affSColin Finck 
2213c2c66affSColin Finck         /* Create the Start button */
2214c2c66affSColin Finck         m_StartButton.Create(m_hWnd);
2215c2c66affSColin Finck 
2216c2c66affSColin Finck         /* Load the saved tray window settings */
2217c2c66affSColin Finck         RegLoadSettings();
2218c2c66affSColin Finck 
2219c2c66affSColin Finck         /* Create and initialize the start menu */
2220c2c66affSColin Finck         HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance, MAKEINTRESOURCEW(IDB_STARTMENU));
2221c2c66affSColin Finck         m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
2222c2c66affSColin Finck 
2223c2c66affSColin Finck         /* Create the task band */
2224c2c66affSColin Finck         hRet = CTaskBand_CreateInstance(this, m_StartButton.m_hWnd, IID_PPV_ARG(IDeskBand, &m_TaskBand));
2225c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
2226c2c66affSColin Finck             return FALSE;
2227c2c66affSColin Finck 
2228c2c66affSColin Finck         /* Create the rebar band site. This actually creates the rebar and the tasks toolbar. */
2229c2c66affSColin Finck         hRet = CTrayBandSite_CreateInstance(this, m_TaskBand, &m_TrayBandSite);
2230c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
2231c2c66affSColin Finck             return FALSE;
2232c2c66affSColin Finck 
2233455bce68SGiannis Adamopoulos         /* Create the tray notification window */
2234455bce68SGiannis Adamopoulos         hRet = CTrayNotifyWnd_CreateInstance(m_hWnd, IID_PPV_ARG(IUnknown, &m_TrayNotifyInstance));
2235455bce68SGiannis Adamopoulos         if (FAILED_UNEXPECTEDLY(hRet))
2236455bce68SGiannis Adamopoulos             return FALSE;
2237455bce68SGiannis Adamopoulos 
2238c2c66affSColin Finck         /* Get the hwnd of the rebar */
2239c2c66affSColin Finck         hRet = IUnknown_GetWindow(m_TrayBandSite, &m_Rebar);
2240c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
2241c2c66affSColin Finck             return FALSE;
2242c2c66affSColin Finck 
2243c2c66affSColin Finck         /* Get the hwnd of the tasks toolbar */
2244c2c66affSColin Finck         hRet = IUnknown_GetWindow(m_TaskBand, &m_TaskSwitch);
2245c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
2246c2c66affSColin Finck             return FALSE;
2247c2c66affSColin Finck 
2248455bce68SGiannis Adamopoulos         /* Get the hwnd of the tray notification window */
2249455bce68SGiannis Adamopoulos         hRet = IUnknown_GetWindow(m_TrayNotifyInstance, &m_TrayNotify);
2250455bce68SGiannis Adamopoulos         if (FAILED_UNEXPECTEDLY(hRet))
2251455bce68SGiannis Adamopoulos             return FALSE;
2252c2c66affSColin Finck 
2253455bce68SGiannis Adamopoulos         SetWindowTheme(m_Rebar, L"TaskBar", NULL);
2254c2c66affSColin Finck 
2255c2c66affSColin Finck         UpdateFonts();
2256c2c66affSColin Finck 
2257c2c66affSColin Finck         InitShellServices(&m_ShellServices);
2258c2c66affSColin Finck 
22592ed535daSGiannis Adamopoulos         if (g_TaskbarSettings.sr.AutoHide)
2260c2c66affSColin Finck         {
2261c2c66affSColin Finck             m_AutoHideState = AUTOHIDE_HIDING;
2262c2c66affSColin Finck             SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
2263c2c66affSColin Finck         }
2264c2c66affSColin Finck 
2265b95fff5bSGiannis Adamopoulos         /* Set the initial lock state in the band site */
2266b95fff5bSGiannis Adamopoulos         m_TrayBandSite->Lock(g_TaskbarSettings.bLock);
2267b95fff5bSGiannis Adamopoulos 
2268c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_RUN, MOD_WIN, 'R');
2269c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_MINIMIZE_ALL, MOD_WIN, 'M');
2270c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_RESTORE_ALL, MOD_WIN|MOD_SHIFT, 'M');
2271c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_HELP, MOD_WIN, VK_F1);
2272c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_EXPLORE, MOD_WIN, 'E');
2273c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_FIND, MOD_WIN, 'F');
2274c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_FIND_COMPUTER, MOD_WIN|MOD_CONTROL, 'F');
2275c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_NEXT_TASK, MOD_WIN, VK_TAB);
2276c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_PREV_TASK, MOD_WIN|MOD_SHIFT, VK_TAB);
2277c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_SYS_PROPERTIES, MOD_WIN, VK_PAUSE);
2278c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_DESKTOP, MOD_WIN, 'D');
2279c2c66affSColin Finck         RegisterHotKey(m_hWnd, IDHK_PAGER, MOD_WIN, 'B');
2280c2c66affSColin Finck 
2281c2c66affSColin Finck         return TRUE;
2282c2c66affSColin Finck     }
2283c2c66affSColin Finck 
2284c2c66affSColin Finck     LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2285c2c66affSColin Finck     {
2286c2c66affSColin Finck         if (m_Theme)
2287c2c66affSColin Finck             CloseThemeData(m_Theme);
2288c2c66affSColin Finck 
2289c2c66affSColin Finck         m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
2290c2c66affSColin Finck 
2291c2c66affSColin Finck         if (m_Theme)
2292c2c66affSColin Finck         {
2293c2c66affSColin Finck             SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
2294c2c66affSColin Finck         }
2295c2c66affSColin Finck         else
2296c2c66affSColin Finck         {
2297c2c66affSColin Finck             SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME | WS_BORDER);
2298c2c66affSColin Finck         }
2299c2c66affSColin Finck         SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
2300c2c66affSColin Finck 
2301c2c66affSColin Finck         return TRUE;
2302c2c66affSColin Finck     }
2303c2c66affSColin Finck 
2304c2c66affSColin Finck     LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2305c2c66affSColin Finck     {
2306c2c66affSColin Finck         if (wParam == SPI_SETNONCLIENTMETRICS)
2307c2c66affSColin Finck         {
2308c2c66affSColin Finck             SendMessage(m_TrayNotify, uMsg, wParam, lParam);
2309c2c66affSColin Finck             SendMessage(m_TaskSwitch, uMsg, wParam, lParam);
2310c2c66affSColin Finck             UpdateFonts();
2311c2c66affSColin Finck             AlignControls(NULL);
2312c2c66affSColin Finck             CheckTrayWndPosition();
2313c2c66affSColin Finck         }
2314c2c66affSColin Finck 
2315c2c66affSColin Finck         return 0;
2316c2c66affSColin Finck     }
2317c2c66affSColin Finck 
2318c2c66affSColin Finck     LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2319c2c66affSColin Finck     {
2320c2c66affSColin Finck         HDC hdc = (HDC) wParam;
2321c2c66affSColin Finck 
2322c2c66affSColin Finck         if (!m_Theme)
2323c2c66affSColin Finck         {
2324c2c66affSColin Finck             bHandled = FALSE;
2325c2c66affSColin Finck             return 0;
2326c2c66affSColin Finck         }
2327c2c66affSColin Finck 
2328c2c66affSColin Finck         return EraseBackgroundWithTheme(hdc);
2329c2c66affSColin Finck     }
2330c2c66affSColin Finck 
2331c2c66affSColin Finck     LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2332c2c66affSColin Finck     {
2333c2c66affSColin Finck         /* Load the saved tray window settings */
2334c2c66affSColin Finck         RegLoadSettings();
2335c2c66affSColin Finck 
2336c2c66affSColin Finck         /* Move the tray window to the right position and resize it if necessary */
2337c2c66affSColin Finck         CheckTrayWndPosition();
2338c2c66affSColin Finck 
2339c2c66affSColin Finck         return TRUE;
2340c2c66affSColin Finck     }
2341c2c66affSColin Finck 
2342c2c66affSColin Finck     LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2343c2c66affSColin Finck     {
2344c2c66affSColin Finck         if (m_TrayNotify)
23457f35908aSGiannis Adamopoulos             ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
2346c2c66affSColin Finck         return TRUE;
2347c2c66affSColin Finck     }
2348c2c66affSColin Finck 
2349c2c66affSColin Finck     LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2350c2c66affSColin Finck     {
2351c2c66affSColin Finck         if (!m_Theme)
2352c2c66affSColin Finck         {
2353c2c66affSColin Finck             bHandled = FALSE;
2354c2c66affSColin Finck             return 0;
2355c2c66affSColin Finck         }
2356c54c5ebbSGiannis Adamopoulos         else if (g_TaskbarSettings.bLock)
2357c54c5ebbSGiannis Adamopoulos         {
2358c54c5ebbSGiannis Adamopoulos             return 0;
2359c54c5ebbSGiannis Adamopoulos         }
2360c2c66affSColin Finck 
2361c2c66affSColin Finck         return DrawSizerWithTheme((HRGN) wParam);
2362c2c66affSColin Finck     }
2363c2c66affSColin Finck 
2364c2c66affSColin Finck     LRESULT OnCtlColorBtn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2365c2c66affSColin Finck     {
2366c2c66affSColin Finck         SetBkMode((HDC) wParam, TRANSPARENT);
2367c2c66affSColin Finck         return (LRESULT) GetStockObject(HOLLOW_BRUSH);
2368c2c66affSColin Finck     }
2369c2c66affSColin Finck 
2370c2c66affSColin Finck     LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2371c2c66affSColin Finck     {
2372c2c66affSColin Finck         RECT rcClient;
2373c2c66affSColin Finck         POINT pt;
2374c2c66affSColin Finck 
23752ed535daSGiannis Adamopoulos         if (g_TaskbarSettings.bLock)
2376c2c66affSColin Finck         {
2377c2c66affSColin Finck             /* The user may not be able to resize the tray window.
2378c2c66affSColin Finck             Pretend like the window is not sizeable when the user
2379c2c66affSColin Finck             clicks on the border. */
2380c2c66affSColin Finck             return HTBORDER;
2381c2c66affSColin Finck         }
2382c2c66affSColin Finck 
2383c2c66affSColin Finck         SetLastError(ERROR_SUCCESS);
2384c2c66affSColin Finck         if (GetClientRect(&rcClient) &&
2385c2c66affSColin Finck             (MapWindowPoints(NULL, (LPPOINT) &rcClient, 2) != 0 || GetLastError() == ERROR_SUCCESS))
2386c2c66affSColin Finck         {
2387c2c66affSColin Finck             pt.x = (SHORT) LOWORD(lParam);
2388c2c66affSColin Finck             pt.y = (SHORT) HIWORD(lParam);
2389c2c66affSColin Finck 
2390eff4c213SHermès Bélusca-Maïto             if (PtInRect(&rcClient, pt))
2391c2c66affSColin Finck             {
2392c2c66affSColin Finck                 /* The user is trying to drag the tray window */
2393c2c66affSColin Finck                 return HTCAPTION;
2394c2c66affSColin Finck             }
2395c2c66affSColin Finck 
2396c2c66affSColin Finck             /* Depending on the position of the tray window, allow only
2397c2c66affSColin Finck             changing the border next to the monitor working area */
2398c2c66affSColin Finck             switch (m_Position)
2399c2c66affSColin Finck             {
2400c2c66affSColin Finck             case ABE_TOP:
2401c2c66affSColin Finck                 if (pt.y > rcClient.bottom)
2402c2c66affSColin Finck                     return HTBOTTOM;
2403c2c66affSColin Finck                 break;
2404c2c66affSColin Finck             case ABE_LEFT:
2405c2c66affSColin Finck                 if (pt.x > rcClient.right)
2406c2c66affSColin Finck                     return HTRIGHT;
2407c2c66affSColin Finck                 break;
2408c2c66affSColin Finck             case ABE_RIGHT:
2409c2c66affSColin Finck                 if (pt.x < rcClient.left)
2410c2c66affSColin Finck                     return HTLEFT;
2411c2c66affSColin Finck                 break;
2412c2c66affSColin Finck             case ABE_BOTTOM:
2413c2c66affSColin Finck             default:
2414c2c66affSColin Finck                 if (pt.y < rcClient.top)
2415c2c66affSColin Finck                     return HTTOP;
2416c2c66affSColin Finck                 break;
2417c2c66affSColin Finck             }
2418c2c66affSColin Finck         }
2419c2c66affSColin Finck         return HTBORDER;
2420c2c66affSColin Finck     }
2421c2c66affSColin Finck 
2422c2c66affSColin Finck     LRESULT OnMoving(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2423c2c66affSColin Finck     {
2424c2c66affSColin Finck         POINT ptCursor;
2425c2c66affSColin Finck         PRECT pRect = (PRECT) lParam;
2426c2c66affSColin Finck 
2427c2c66affSColin Finck         /* We need to ensure that an application can not accidently
2428c2c66affSColin Finck         move the tray window (using SetWindowPos). However, we still
2429c2c66affSColin Finck         need to be able to move the window in case the user wants to
2430c2c66affSColin Finck         drag the tray window to another position or in case the user
2431c2c66affSColin Finck         wants to resize the tray window. */
24322ed535daSGiannis Adamopoulos         if (!g_TaskbarSettings.bLock && GetCursorPos(&ptCursor))
2433c2c66affSColin Finck         {
2434c2c66affSColin Finck             IsDragging = TRUE;
2435c2c66affSColin Finck             m_DraggingPosition = GetDraggingRectFromPt(ptCursor, pRect, &m_DraggingMonitor);
2436c2c66affSColin Finck         }
2437c2c66affSColin Finck         else
2438c2c66affSColin Finck         {
2439c2c66affSColin Finck             *pRect = m_TrayRects[m_Position];
2440c2c66affSColin Finck         }
2441c2c66affSColin Finck         return TRUE;
2442c2c66affSColin Finck     }
2443c2c66affSColin Finck 
2444c2c66affSColin Finck     LRESULT OnSizing(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2445c2c66affSColin Finck     {
2446c2c66affSColin Finck         PRECT pRect = (PRECT) lParam;
2447c2c66affSColin Finck 
24482ed535daSGiannis Adamopoulos         if (!g_TaskbarSettings.bLock)
2449c2c66affSColin Finck         {
2450c2c66affSColin Finck             FitToRebar(pRect);
2451c2c66affSColin Finck         }
2452c2c66affSColin Finck         else
2453c2c66affSColin Finck         {
2454c2c66affSColin Finck             *pRect = m_TrayRects[m_Position];
2455c2c66affSColin Finck         }
2456c2c66affSColin Finck         return TRUE;
2457c2c66affSColin Finck     }
2458c2c66affSColin Finck 
24594238f223SGiannis Adamopoulos     LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2460c2c66affSColin Finck     {
2461c2c66affSColin Finck         ChangingWinPos((LPWINDOWPOS) lParam);
2462c2c66affSColin Finck         return TRUE;
2463c2c66affSColin Finck     }
2464c2c66affSColin Finck 
2465c2c66affSColin Finck     LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2466c2c66affSColin Finck     {
2467c2c66affSColin Finck         RECT rcClient;
2468c2c66affSColin Finck         if (wParam == SIZE_RESTORED && lParam == 0)
2469c2c66affSColin Finck         {
2470c2c66affSColin Finck             ResizeWorkArea();
2471c2c66affSColin Finck             /* Clip the tray window on multi monitor systems so the edges can't
2472c2c66affSColin Finck             overlap into another monitor */
2473c2c66affSColin Finck             ApplyClipping(TRUE);
2474c2c66affSColin Finck 
2475c2c66affSColin Finck             if (!GetClientRect(&rcClient))
2476c2c66affSColin Finck             {
2477c2c66affSColin Finck                 return FALSE;
2478c2c66affSColin Finck             }
2479c2c66affSColin Finck         }
2480c2c66affSColin Finck         else
2481c2c66affSColin Finck         {
2482c2c66affSColin Finck             rcClient.left = rcClient.top = 0;
2483c2c66affSColin Finck             rcClient.right = LOWORD(lParam);
2484c2c66affSColin Finck             rcClient.bottom = HIWORD(lParam);
2485c2c66affSColin Finck         }
2486c2c66affSColin Finck 
2487c2c66affSColin Finck         AlignControls(&rcClient);
2488c2c66affSColin Finck         return TRUE;
2489c2c66affSColin Finck     }
2490c2c66affSColin Finck 
2491c2c66affSColin Finck     LRESULT OnEnterSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2492c2c66affSColin Finck     {
2493c2c66affSColin Finck         InSizeMove = TRUE;
2494c2c66affSColin Finck         IsDragging = FALSE;
24952ed535daSGiannis Adamopoulos         if (!g_TaskbarSettings.bLock)
2496c2c66affSColin Finck         {
2497c2c66affSColin Finck             /* Remove the clipping on multi monitor systems while dragging around */
2498c2c66affSColin Finck             ApplyClipping(FALSE);
2499c2c66affSColin Finck         }
2500c2c66affSColin Finck         return TRUE;
2501c2c66affSColin Finck     }
2502c2c66affSColin Finck 
2503c2c66affSColin Finck     LRESULT OnExitSizeMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2504c2c66affSColin Finck     {
2505c2c66affSColin Finck         InSizeMove = FALSE;
25062ed535daSGiannis Adamopoulos         if (!g_TaskbarSettings.bLock)
2507c2c66affSColin Finck         {
2508c2c66affSColin Finck             FitToRebar(&m_TrayRects[m_Position]);
2509c2c66affSColin Finck 
2510c2c66affSColin Finck             /* Apply clipping */
2511c2c66affSColin Finck             PostMessage(WM_SIZE, SIZE_RESTORED, 0);
2512c2c66affSColin Finck         }
2513c2c66affSColin Finck         return TRUE;
2514c2c66affSColin Finck     }
2515c2c66affSColin Finck 
2516c2c66affSColin Finck     LRESULT OnSysChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2517c2c66affSColin Finck     {
2518c2c66affSColin Finck         switch (wParam)
2519c2c66affSColin Finck         {
2520c2c66affSColin Finck         case TEXT(' '):
2521c2c66affSColin Finck         {
2522c2c66affSColin Finck             /* The user pressed Alt+Space, this usually brings up the system menu of a window.
2523c2c66affSColin Finck             The tray window needs to handle this specially, since it normally doesn't have
2524c2c66affSColin Finck             a system menu. */
2525c2c66affSColin Finck 
2526c2c66affSColin Finck             static const UINT uidDisableItem [] = {
2527c2c66affSColin Finck                 SC_RESTORE,
2528c2c66affSColin Finck                 SC_MOVE,
2529c2c66affSColin Finck                 SC_SIZE,
2530c2c66affSColin Finck                 SC_MAXIMIZE,
2531c2c66affSColin Finck                 SC_MINIMIZE,
2532c2c66affSColin Finck             };
2533c2c66affSColin Finck             HMENU hSysMenu;
2534c2c66affSColin Finck             UINT i, uId;
2535c2c66affSColin Finck 
2536c2c66affSColin Finck             /* temporarily enable the system menu */
2537c2c66affSColin Finck             SetWindowStyle(m_hWnd, WS_SYSMENU, WS_SYSMENU);
2538c2c66affSColin Finck 
2539c2c66affSColin Finck             hSysMenu = GetSystemMenu(FALSE);
2540c2c66affSColin Finck             if (hSysMenu != NULL)
2541c2c66affSColin Finck             {
2542c2c66affSColin Finck                 /* Disable all items that are not relevant */
2543c2c66affSColin Finck                 for (i = 0; i < _countof(uidDisableItem); i++)
2544c2c66affSColin Finck                 {
2545c2c66affSColin Finck                     EnableMenuItem(hSysMenu,
2546c2c66affSColin Finck                                    uidDisableItem[i],
2547c2c66affSColin Finck                                    MF_BYCOMMAND | MF_GRAYED);
2548c2c66affSColin Finck                 }
2549c2c66affSColin Finck 
2550c2c66affSColin Finck                 EnableMenuItem(hSysMenu,
2551c2c66affSColin Finck                                SC_CLOSE,
2552c2c66affSColin Finck                                MF_BYCOMMAND |
2553c2c66affSColin Finck                                (SHRestricted(REST_NOCLOSE) ? MF_GRAYED : MF_ENABLED));
2554c2c66affSColin Finck 
2555c2c66affSColin Finck                 /* Display the system menu */
2556c2c66affSColin Finck                 uId = TrackMenu(
2557c2c66affSColin Finck                     hSysMenu,
2558c2c66affSColin Finck                     NULL,
2559c2c66affSColin Finck                     m_StartButton.m_hWnd,
2560c2c66affSColin Finck                     m_Position != ABE_TOP,
2561c2c66affSColin Finck                     FALSE);
2562c2c66affSColin Finck                 if (uId != 0)
2563c2c66affSColin Finck                 {
2564c2c66affSColin Finck                     SendMessage(m_hWnd, WM_SYSCOMMAND, (WPARAM) uId, 0);
2565c2c66affSColin Finck                 }
2566c2c66affSColin Finck             }
2567c2c66affSColin Finck 
2568c2c66affSColin Finck             /* revert the system menu window style */
2569c2c66affSColin Finck             SetWindowStyle(m_hWnd, WS_SYSMENU, 0);
2570c2c66affSColin Finck             break;
2571c2c66affSColin Finck         }
2572c2c66affSColin Finck 
2573c2c66affSColin Finck         default:
2574c2c66affSColin Finck             bHandled = FALSE;
2575c2c66affSColin Finck         }
2576c2c66affSColin Finck         return TRUE;
2577c2c66affSColin Finck     }
2578c2c66affSColin Finck 
2579c2c66affSColin Finck     LRESULT OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2580c2c66affSColin Finck     {
2581c2c66affSColin Finck         /* This handler implements the trick that makes  the start button to
2582c2c66affSColin Finck            get pressed when the user clicked left or below the button */
2583c2c66affSColin Finck 
2584c2c66affSColin Finck         POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
2585c2c66affSColin Finck         WINDOWINFO wi = {sizeof(WINDOWINFO)};
2586c2c66affSColin Finck         RECT rcStartBtn;
2587c2c66affSColin Finck 
2588c2c66affSColin Finck         bHandled = FALSE;
2589c2c66affSColin Finck 
2590c2c66affSColin Finck         m_StartButton.GetWindowRect(&rcStartBtn);
2591c2c66affSColin Finck         GetWindowInfo(m_hWnd, &wi);
2592c2c66affSColin Finck 
2593c2c66affSColin Finck         switch (m_Position)
2594c2c66affSColin Finck         {
2595c2c66affSColin Finck             case ABE_TOP:
2596c2c66affSColin Finck             case ABE_LEFT:
2597c2c66affSColin Finck             {
2598c2c66affSColin Finck                 if (pt.x > rcStartBtn.right || pt.y > rcStartBtn.bottom)
2599c2c66affSColin Finck                     return 0;
2600c2c66affSColin Finck                 break;
2601c2c66affSColin Finck             }
2602c2c66affSColin Finck             case ABE_RIGHT:
2603c2c66affSColin Finck             {
2604c2c66affSColin Finck                 if (pt.x < rcStartBtn.left || pt.y > rcStartBtn.bottom)
2605c2c66affSColin Finck                     return 0;
2606c2c66affSColin Finck 
2607c2c66affSColin Finck                 if (rcStartBtn.right + (int)wi.cxWindowBorders * 2 + 1 < wi.rcWindow.right &&
2608c2c66affSColin Finck                     pt.x > rcStartBtn.right)
2609c2c66affSColin Finck                 {
2610c2c66affSColin Finck                     return 0;
2611c2c66affSColin Finck                 }
2612c2c66affSColin Finck                 break;
2613c2c66affSColin Finck             }
2614c2c66affSColin Finck             case ABE_BOTTOM:
2615c2c66affSColin Finck             {
2616c2c66affSColin Finck                 if (pt.x > rcStartBtn.right || pt.y < rcStartBtn.top)
2617c2c66affSColin Finck                 {
2618c2c66affSColin Finck                     return 0;
2619c2c66affSColin Finck                 }
2620c2c66affSColin Finck 
2621c2c66affSColin Finck                 if (rcStartBtn.bottom + (int)wi.cyWindowBorders * 2 + 1 < wi.rcWindow.bottom &&
2622c2c66affSColin Finck                     pt.y > rcStartBtn.bottom)
2623c2c66affSColin Finck                 {
2624c2c66affSColin Finck                     return 0;
2625c2c66affSColin Finck                 }
2626c2c66affSColin Finck 
2627c2c66affSColin Finck                 break;
2628c2c66affSColin Finck             }
2629c2c66affSColin Finck         }
2630c2c66affSColin Finck 
2631c2c66affSColin Finck         bHandled = TRUE;
2632c2c66affSColin Finck         PopupStartMenu();
2633c2c66affSColin Finck         return 0;
2634c2c66affSColin Finck     }
2635c2c66affSColin Finck 
2636c2c66affSColin Finck     LRESULT OnNcRButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2637c2c66affSColin Finck     {
2638c2c66affSColin Finck         /* We want the user to be able to get a context menu even on the nonclient
2639c2c66affSColin Finck         area (including the sizing border)! */
2640c2c66affSColin Finck         uMsg = WM_CONTEXTMENU;
2641c2c66affSColin Finck         wParam = (WPARAM) m_hWnd;
2642c2c66affSColin Finck 
2643c2c66affSColin Finck         return OnContextMenu(uMsg, wParam, lParam, bHandled);
2644c2c66affSColin Finck     }
2645c2c66affSColin Finck 
2646c2c66affSColin Finck     LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2647c2c66affSColin Finck     {
2648c2c66affSColin Finck         LRESULT Ret = FALSE;
2649c2c66affSColin Finck         POINT pt, *ppt = NULL;
2650c2c66affSColin Finck         HWND hWndExclude = NULL;
2651c2c66affSColin Finck 
2652c2c66affSColin Finck         /* Check if the administrator has forbidden access to context menus */
2653c2c66affSColin Finck         if (SHRestricted(REST_NOTRAYCONTEXTMENU))
2654c2c66affSColin Finck             return FALSE;
2655c2c66affSColin Finck 
2656c2c66affSColin Finck         pt.x = (SHORT) LOWORD(lParam);
2657c2c66affSColin Finck         pt.y = (SHORT) HIWORD(lParam);
2658c2c66affSColin Finck 
2659c2c66affSColin Finck         if (pt.x != -1 || pt.y != -1)
2660c2c66affSColin Finck             ppt = &pt;
2661c2c66affSColin Finck         else
2662c2c66affSColin Finck             hWndExclude = m_StartButton.m_hWnd;
2663c2c66affSColin Finck 
2664c2c66affSColin Finck         if ((HWND) wParam == m_StartButton.m_hWnd)
2665c2c66affSColin Finck         {
2666c2c66affSColin Finck             /* Make sure we can't track the context menu if the start
2667c2c66affSColin Finck             menu is currently being shown */
2668c2c66affSColin Finck             if (!(m_StartButton.SendMessage(BM_GETSTATE, 0, 0) & BST_PUSHED))
2669c2c66affSColin Finck             {
2670c2c66affSColin Finck                 CComPtr<IContextMenu> ctxMenu;
2671c2c66affSColin Finck                 StartMenuBtnCtxMenuCreator(this, m_hWnd, &ctxMenu);
2672c2c66affSColin Finck                 TrackCtxMenu(ctxMenu, ppt, hWndExclude, m_Position == ABE_BOTTOM, this);
2673c2c66affSColin Finck             }
2674c2c66affSColin Finck         }
2675c2c66affSColin Finck         else
2676c2c66affSColin Finck         {
2677c2c66affSColin Finck             /* See if the context menu should be handled by the task band site */
2678c2c66affSColin Finck             if (ppt != NULL && m_TrayBandSite != NULL)
2679c2c66affSColin Finck             {
2680c2c66affSColin Finck                 HWND hWndAtPt;
2681c2c66affSColin Finck                 POINT ptClient = *ppt;
2682c2c66affSColin Finck 
2683c2c66affSColin Finck                 /* Convert the coordinates to client-coordinates */
2684c2c66affSColin Finck                 ::MapWindowPoints(NULL, m_hWnd, &ptClient, 1);
2685c2c66affSColin Finck 
2686c2c66affSColin Finck                 hWndAtPt = ChildWindowFromPoint(ptClient);
2687c2c66affSColin Finck                 if (hWndAtPt != NULL &&
2688c2c66affSColin Finck                     (hWndAtPt == m_Rebar || ::IsChild(m_Rebar, hWndAtPt)))
2689c2c66affSColin Finck                 {
2690c2c66affSColin Finck                     /* Check if the user clicked on the task switch window */
2691c2c66affSColin Finck                     ptClient = *ppt;
2692c2c66affSColin Finck                     ::MapWindowPoints(NULL, m_Rebar, &ptClient, 1);
2693c2c66affSColin Finck 
2694c2c66affSColin Finck                     hWndAtPt = ::ChildWindowFromPointEx(m_Rebar, ptClient, CWP_SKIPINVISIBLE | CWP_SKIPDISABLED);
2695c2c66affSColin Finck                     if (hWndAtPt == m_TaskSwitch)
2696c2c66affSColin Finck                         goto HandleTrayContextMenu;
2697c2c66affSColin Finck 
2698c2c66affSColin Finck                     /* Forward the message to the task band site */
2699c2c66affSColin Finck                     m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret);
2700c2c66affSColin Finck                 }
2701c2c66affSColin Finck                 else
2702c2c66affSColin Finck                     goto HandleTrayContextMenu;
2703c2c66affSColin Finck             }
2704c2c66affSColin Finck             else
2705c2c66affSColin Finck             {
2706c2c66affSColin Finck HandleTrayContextMenu:
2707c2c66affSColin Finck                 /* Tray the default tray window context menu */
2708c2c66affSColin Finck                 TrackCtxMenu(this, ppt, NULL, FALSE, this);
2709c2c66affSColin Finck             }
2710c2c66affSColin Finck         }
2711c2c66affSColin Finck         return Ret;
2712c2c66affSColin Finck     }
2713c2c66affSColin Finck 
2714c2c66affSColin Finck     LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2715c2c66affSColin Finck     {
2716c2c66affSColin Finck         LRESULT Ret = FALSE;
2717c2c66affSColin Finck         /* FIXME: We can't check with IsChild whether the hwnd is somewhere inside
2718c2c66affSColin Finck         the rebar control! But we shouldn't forward messages that the band
2719c2c66affSColin Finck         site doesn't handle, such as other controls (start button, tray window */
2720c2c66affSColin Finck 
2721c2c66affSColin Finck         HRESULT hr = E_FAIL;
2722c2c66affSColin Finck 
2723c2c66affSColin Finck         if (m_TrayBandSite)
2724c2c66affSColin Finck         {
2725c2c66affSColin Finck             hr = m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret);
2726c2c66affSColin Finck             if (SUCCEEDED(hr))
2727c2c66affSColin Finck                 return Ret;
2728c2c66affSColin Finck         }
2729c2c66affSColin Finck 
2730c2c66affSColin Finck         if (m_TrayBandSite == NULL || FAILED(hr))
2731c2c66affSColin Finck         {
2732c2c66affSColin Finck             const NMHDR *nmh = (const NMHDR *) lParam;
2733c2c66affSColin Finck 
2734c2c66affSColin Finck             if (nmh->hwndFrom == m_TrayNotify)
2735c2c66affSColin Finck             {
2736c2c66affSColin Finck                 switch (nmh->code)
2737c2c66affSColin Finck                 {
2738c2c66affSColin Finck                 case NTNWM_REALIGN:
2739c2c66affSColin Finck                     /* Cause all controls to be aligned */
2740c2c66affSColin Finck                     PostMessage(WM_SIZE, SIZE_RESTORED, 0);
2741c2c66affSColin Finck                     break;
2742c2c66affSColin Finck                 }
2743c2c66affSColin Finck             }
2744c2c66affSColin Finck         }
2745c2c66affSColin Finck         return Ret;
2746c2c66affSColin Finck     }
2747c2c66affSColin Finck 
2748c2c66affSColin Finck     LRESULT OnNcLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2749c2c66affSColin Finck     {
27507f35908aSGiannis Adamopoulos         /* Let the clock handle the double click */
27517f35908aSGiannis Adamopoulos         ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
27527f35908aSGiannis Adamopoulos 
2753c2c66affSColin Finck         /* We "handle" this message so users can't cause a weird maximize/restore
2754c2c66affSColin Finck         window animation when double-clicking the tray window! */
2755c2c66affSColin Finck         return TRUE;
2756c2c66affSColin Finck     }
2757c2c66affSColin Finck 
2758c2c66affSColin Finck     LRESULT OnAppTrayDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2759c2c66affSColin Finck     {
2760c2c66affSColin Finck         DestroyWindow();
2761c2c66affSColin Finck         return TRUE;
2762c2c66affSColin Finck     }
2763c2c66affSColin Finck 
2764c2c66affSColin Finck     LRESULT OnOpenStartMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2765c2c66affSColin Finck     {
2766c2c66affSColin Finck         HWND hwndStartMenu;
2767c2c66affSColin Finck         HRESULT hr = IUnknown_GetWindow(m_StartMenuPopup, &hwndStartMenu);
2768c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hr))
2769c2c66affSColin Finck             return FALSE;
2770c2c66affSColin Finck 
2771c2c66affSColin Finck         if (::IsWindowVisible(hwndStartMenu))
2772c2c66affSColin Finck         {
2773c2c66affSColin Finck             m_StartMenuPopup->OnSelect(MPOS_CANCELLEVEL);
2774c2c66affSColin Finck         }
2775c2c66affSColin Finck         else
2776c2c66affSColin Finck         {
2777c2c66affSColin Finck             PopupStartMenu();
2778c2c66affSColin Finck         }
2779c2c66affSColin Finck 
2780c2c66affSColin Finck         return TRUE;
2781c2c66affSColin Finck     }
2782c2c66affSColin Finck 
2783c2c66affSColin Finck     LRESULT OnDoExitWindows(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2784c2c66affSColin Finck     {
2785c2c66affSColin Finck         /*
2786c2c66affSColin Finck          * TWM_DOEXITWINDOWS is send by the CDesktopBrowser to us
2787c2c66affSColin Finck          * to show the shutdown dialog. Also a WM_CLOSE message sent
2788c2c66affSColin Finck          * by apps should show the dialog.
2789c2c66affSColin Finck          */
2790c2c66affSColin Finck         return DoExitWindows();
2791c2c66affSColin Finck     }
2792c2c66affSColin Finck 
2793c2c66affSColin Finck     LRESULT OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2794c2c66affSColin Finck     {
2795c2c66affSColin Finck         if (wParam == SC_CLOSE)
2796c2c66affSColin Finck         {
2797c2c66affSColin Finck             return DoExitWindows();
2798c2c66affSColin Finck         }
2799c2c66affSColin Finck 
2800c2c66affSColin Finck         bHandled = FALSE;
2801c2c66affSColin Finck         return TRUE;
2802c2c66affSColin Finck     }
2803c2c66affSColin Finck 
2804c2c66affSColin Finck     LRESULT OnHotkey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2805c2c66affSColin Finck     {
2806c2c66affSColin Finck         return HandleHotKey(wParam);
2807c2c66affSColin Finck     }
2808c2c66affSColin Finck 
2809*75b09f3fSKatayama Hirofumi MZ     struct MINIMIZE_INFO
2810*75b09f3fSKatayama Hirofumi MZ     {
2811*75b09f3fSKatayama Hirofumi MZ         HWND hwndDesktop;
2812*75b09f3fSKatayama Hirofumi MZ         HWND hTrayWnd;
2813*75b09f3fSKatayama Hirofumi MZ         HWND hwndProgman;
2814*75b09f3fSKatayama Hirofumi MZ         BOOL bRet;
2815*75b09f3fSKatayama Hirofumi MZ         CSimpleArray<HWND> *pMinimizedAll;
2816*75b09f3fSKatayama Hirofumi MZ         BOOL bShowDesktop;
2817*75b09f3fSKatayama Hirofumi MZ     };
2818*75b09f3fSKatayama Hirofumi MZ 
2819*75b09f3fSKatayama Hirofumi MZ     static BOOL IsDialog(HWND hwnd)
2820*75b09f3fSKatayama Hirofumi MZ     {
2821*75b09f3fSKatayama Hirofumi MZ         WCHAR szClass[32];
2822*75b09f3fSKatayama Hirofumi MZ         GetClassNameW(hwnd, szClass, _countof(szClass));
2823*75b09f3fSKatayama Hirofumi MZ         return wcscmp(szClass, L"#32770") == 0;
2824*75b09f3fSKatayama Hirofumi MZ     }
2825*75b09f3fSKatayama Hirofumi MZ 
2826*75b09f3fSKatayama Hirofumi MZ     static BOOL CALLBACK MinimizeWindowsProc(HWND hwnd, LPARAM lParam)
2827*75b09f3fSKatayama Hirofumi MZ     {
2828*75b09f3fSKatayama Hirofumi MZ         MINIMIZE_INFO *info = (MINIMIZE_INFO *)lParam;
2829*75b09f3fSKatayama Hirofumi MZ         if (hwnd == info->hwndDesktop || hwnd == info->hTrayWnd ||
2830*75b09f3fSKatayama Hirofumi MZ             hwnd == info->hwndProgman)
2831*75b09f3fSKatayama Hirofumi MZ         {
2832*75b09f3fSKatayama Hirofumi MZ             return TRUE;
2833*75b09f3fSKatayama Hirofumi MZ         }
2834*75b09f3fSKatayama Hirofumi MZ         if (!info->bShowDesktop)
2835*75b09f3fSKatayama Hirofumi MZ         {
2836*75b09f3fSKatayama Hirofumi MZ             if (!::IsWindowEnabled(hwnd) || IsDialog(hwnd))
2837*75b09f3fSKatayama Hirofumi MZ                 return TRUE;
2838*75b09f3fSKatayama Hirofumi MZ             HWND hwndOwner = ::GetWindow(hwnd, GW_OWNER);
2839*75b09f3fSKatayama Hirofumi MZ             if (hwndOwner && !::IsWindowEnabled(hwndOwner))
2840*75b09f3fSKatayama Hirofumi MZ                 return TRUE;
2841*75b09f3fSKatayama Hirofumi MZ         }
2842*75b09f3fSKatayama Hirofumi MZ         if (::IsWindowVisible(hwnd) && !::IsIconic(hwnd))
2843*75b09f3fSKatayama Hirofumi MZ         {
2844*75b09f3fSKatayama Hirofumi MZ             ::ShowWindowAsync(hwnd, SW_MINIMIZE);
2845*75b09f3fSKatayama Hirofumi MZ             info->bRet = TRUE;
2846*75b09f3fSKatayama Hirofumi MZ             info->pMinimizedAll->Add(hwnd);
2847*75b09f3fSKatayama Hirofumi MZ         }
2848*75b09f3fSKatayama Hirofumi MZ         return TRUE;
2849*75b09f3fSKatayama Hirofumi MZ     }
2850*75b09f3fSKatayama Hirofumi MZ 
2851*75b09f3fSKatayama Hirofumi MZ     VOID MinimizeAll(BOOL bShowDesktop = FALSE)
2852*75b09f3fSKatayama Hirofumi MZ     {
2853*75b09f3fSKatayama Hirofumi MZ         MINIMIZE_INFO info;
2854*75b09f3fSKatayama Hirofumi MZ         info.hwndDesktop = GetDesktopWindow();;
2855*75b09f3fSKatayama Hirofumi MZ         info.hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
2856*75b09f3fSKatayama Hirofumi MZ         info.hwndProgman = FindWindowW(L"Progman", NULL);
2857*75b09f3fSKatayama Hirofumi MZ         info.bRet = FALSE;
2858*75b09f3fSKatayama Hirofumi MZ         info.pMinimizedAll = &g_MinimizedAll;
2859*75b09f3fSKatayama Hirofumi MZ         info.bShowDesktop = bShowDesktop;
2860*75b09f3fSKatayama Hirofumi MZ         EnumWindows(MinimizeWindowsProc, (LPARAM)&info);
2861*75b09f3fSKatayama Hirofumi MZ 
2862*75b09f3fSKatayama Hirofumi MZ         // invalid handles should be cleared to avoid mismatch of handles
2863*75b09f3fSKatayama Hirofumi MZ         for (INT i = 0; i < g_MinimizedAll.GetSize(); ++i)
2864*75b09f3fSKatayama Hirofumi MZ         {
2865*75b09f3fSKatayama Hirofumi MZ             if (!::IsWindow(g_MinimizedAll[i]))
2866*75b09f3fSKatayama Hirofumi MZ                 g_MinimizedAll[i] = NULL;
2867*75b09f3fSKatayama Hirofumi MZ         }
2868*75b09f3fSKatayama Hirofumi MZ 
2869*75b09f3fSKatayama Hirofumi MZ         ::SetForegroundWindow(m_DesktopWnd);
2870*75b09f3fSKatayama Hirofumi MZ         ::SetFocus(m_DesktopWnd);
2871*75b09f3fSKatayama Hirofumi MZ     }
2872*75b09f3fSKatayama Hirofumi MZ 
2873*75b09f3fSKatayama Hirofumi MZ     VOID ShowDesktop()
2874*75b09f3fSKatayama Hirofumi MZ     {
2875*75b09f3fSKatayama Hirofumi MZ         MinimizeAll(TRUE);
2876*75b09f3fSKatayama Hirofumi MZ     }
2877*75b09f3fSKatayama Hirofumi MZ 
2878*75b09f3fSKatayama Hirofumi MZ     VOID RestoreAll()
2879*75b09f3fSKatayama Hirofumi MZ     {
2880*75b09f3fSKatayama Hirofumi MZ         for (INT i = g_MinimizedAll.GetSize() - 1; i >= 0; --i)
2881*75b09f3fSKatayama Hirofumi MZ         {
2882*75b09f3fSKatayama Hirofumi MZ             HWND hwnd = g_MinimizedAll[i];
2883*75b09f3fSKatayama Hirofumi MZ             if (::IsWindowVisible(hwnd) && ::IsIconic(hwnd))
2884*75b09f3fSKatayama Hirofumi MZ             {
2885*75b09f3fSKatayama Hirofumi MZ                 ::ShowWindow(hwnd, SW_RESTORE);
2886*75b09f3fSKatayama Hirofumi MZ             }
2887*75b09f3fSKatayama Hirofumi MZ         }
2888*75b09f3fSKatayama Hirofumi MZ         g_MinimizedAll.RemoveAll();
2889*75b09f3fSKatayama Hirofumi MZ     }
2890*75b09f3fSKatayama Hirofumi MZ 
2891c2c66affSColin Finck     LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2892c2c66affSColin Finck     {
2893c2c66affSColin Finck         LRESULT Ret = FALSE;
2894c2c66affSColin Finck 
2895c2c66affSColin Finck         if ((HWND) lParam == m_StartButton.m_hWnd)
2896c2c66affSColin Finck         {
2897c2c66affSColin Finck             return FALSE;
2898c2c66affSColin Finck         }
2899c2c66affSColin Finck 
2900c2c66affSColin Finck         if (m_TrayBandSite == NULL || FAILED_UNEXPECTEDLY(m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam, &Ret)))
2901c2c66affSColin Finck         {
2902c2c66affSColin Finck             return HandleCommand(LOWORD(wParam));
2903c2c66affSColin Finck         }
2904c2c66affSColin Finck         return Ret;
2905c2c66affSColin Finck     }
2906c2c66affSColin Finck 
2907c2c66affSColin Finck     LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2908c2c66affSColin Finck     {
29092ed535daSGiannis Adamopoulos         if (g_TaskbarSettings.sr.AutoHide)
2910c2c66affSColin Finck         {
2911c2c66affSColin Finck             SetTimer(TIMER_ID_MOUSETRACK, MOUSETRACK_INTERVAL, NULL);
2912c2c66affSColin Finck         }
2913c2c66affSColin Finck 
2914c2c66affSColin Finck         return TRUE;
2915c2c66affSColin Finck     }
2916c2c66affSColin Finck 
2917c2c66affSColin Finck     LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2918c2c66affSColin Finck     {
2919c2c66affSColin Finck         if (wParam == TIMER_ID_MOUSETRACK)
2920c2c66affSColin Finck         {
2921c2c66affSColin Finck             ProcessMouseTracking();
2922c2c66affSColin Finck         }
2923c2c66affSColin Finck         else if (wParam == TIMER_ID_AUTOHIDE)
2924c2c66affSColin Finck         {
2925c2c66affSColin Finck             ProcessAutoHide();
2926c2c66affSColin Finck         }
2927c2c66affSColin Finck 
2928c2c66affSColin Finck         bHandled = FALSE;
2929c2c66affSColin Finck         return TRUE;
2930c2c66affSColin Finck     }
2931c2c66affSColin Finck 
2932c2c66affSColin Finck     LRESULT OnNcCalcSize(INT code, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2933c2c66affSColin Finck     {
2934c2c66affSColin Finck         RECT *rc = NULL;
2935c2c66affSColin Finck         /* Ignore WM_NCCALCSIZE if we are not themed or locked */
29362ed535daSGiannis Adamopoulos         if(!m_Theme || g_TaskbarSettings.bLock)
2937c2c66affSColin Finck         {
2938c2c66affSColin Finck             bHandled = FALSE;
2939c2c66affSColin Finck             return 0;
2940c2c66affSColin Finck         }
2941c2c66affSColin Finck         if(!wParam)
2942c2c66affSColin Finck         {
2943c2c66affSColin Finck             rc = (RECT*)wParam;
2944c2c66affSColin Finck         }
2945c2c66affSColin Finck         else
2946c2c66affSColin Finck         {
2947c2c66affSColin Finck             NCCALCSIZE_PARAMS *prms = (NCCALCSIZE_PARAMS*)lParam;
2948c2c66affSColin Finck             if(prms->lppos->flags & SWP_NOSENDCHANGING)
2949c2c66affSColin Finck             {
2950c2c66affSColin Finck                 bHandled = FALSE;
2951c2c66affSColin Finck                 return 0;
2952c2c66affSColin Finck             }
2953c2c66affSColin Finck             rc = &prms->rgrc[0];
2954c2c66affSColin Finck         }
2955c2c66affSColin Finck 
2956c2c66affSColin Finck         AdjustSizerRect(rc, m_Position);
2957c2c66affSColin Finck 
2958c2c66affSColin Finck         return 0;
2959c2c66affSColin Finck     }
2960c2c66affSColin Finck 
2961*75b09f3fSKatayama Hirofumi MZ     LRESULT OnInitMenuPopup(INT code, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
2962*75b09f3fSKatayama Hirofumi MZ     {
2963*75b09f3fSKatayama Hirofumi MZ         HMENU hMenu = (HMENU)wParam;
2964*75b09f3fSKatayama Hirofumi MZ         if (::IsThereAnyEffectiveWindow(FALSE))
2965*75b09f3fSKatayama Hirofumi MZ         {
2966*75b09f3fSKatayama Hirofumi MZ             ::EnableMenuItem(hMenu, ID_SHELL_CMD_CASCADE_WND, MF_BYCOMMAND | MF_ENABLED);
2967*75b09f3fSKatayama Hirofumi MZ             ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_H, MF_BYCOMMAND | MF_ENABLED);
2968*75b09f3fSKatayama Hirofumi MZ             ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_V, MF_BYCOMMAND | MF_ENABLED);
2969*75b09f3fSKatayama Hirofumi MZ         }
2970*75b09f3fSKatayama Hirofumi MZ         else
2971*75b09f3fSKatayama Hirofumi MZ         {
2972*75b09f3fSKatayama Hirofumi MZ             ::EnableMenuItem(hMenu, ID_SHELL_CMD_CASCADE_WND, MF_BYCOMMAND | MF_GRAYED);
2973*75b09f3fSKatayama Hirofumi MZ             ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_H, MF_BYCOMMAND | MF_GRAYED);
2974*75b09f3fSKatayama Hirofumi MZ             ::EnableMenuItem(hMenu, ID_SHELL_CMD_TILE_WND_V, MF_BYCOMMAND | MF_GRAYED);
2975*75b09f3fSKatayama Hirofumi MZ         }
2976*75b09f3fSKatayama Hirofumi MZ         return 0;
2977*75b09f3fSKatayama Hirofumi MZ     }
2978*75b09f3fSKatayama Hirofumi MZ 
2979c2c66affSColin Finck     LRESULT OnRebarAutoSize(INT code, LPNMHDR nmhdr, BOOL& bHandled)
2980c2c66affSColin Finck     {
2981c2c66affSColin Finck #if 0
2982c2c66affSColin Finck         LPNMRBAUTOSIZE as = (LPNMRBAUTOSIZE) nmhdr;
2983c2c66affSColin Finck 
2984c2c66affSColin Finck         if (!as->fChanged)
2985c2c66affSColin Finck             return 0;
2986c2c66affSColin Finck 
2987c2c66affSColin Finck         RECT rc;
2988c2c66affSColin Finck         ::GetWindowRect(m_hWnd, &rc);
2989c2c66affSColin Finck 
2990c2c66affSColin Finck         SIZE szWindow = {
2991c2c66affSColin Finck             rc.right - rc.left,
2992c2c66affSColin Finck             rc.bottom - rc.top };
2993c2c66affSColin Finck         SIZE szTarget = {
2994c2c66affSColin Finck             as->rcTarget.right - as->rcTarget.left,
2995c2c66affSColin Finck             as->rcTarget.bottom - as->rcTarget.top };
2996c2c66affSColin Finck         SIZE szActual = {
2997c2c66affSColin Finck             as->rcActual.right - as->rcActual.left,
2998c2c66affSColin Finck             as->rcActual.bottom - as->rcActual.top };
2999c2c66affSColin Finck 
3000c2c66affSColin Finck         SIZE borders = {
3001c2c66affSColin Finck             szWindow.cx - szTarget.cx,
3002c2c66affSColin Finck             szWindow.cy - szTarget.cx,
3003c2c66affSColin Finck         };
3004c2c66affSColin Finck 
3005c2c66affSColin Finck         switch (m_Position)
3006c2c66affSColin Finck         {
3007c2c66affSColin Finck         case ABE_LEFT:
3008c2c66affSColin Finck             szWindow.cx = szActual.cx + borders.cx;
3009c2c66affSColin Finck             break;
3010c2c66affSColin Finck         case ABE_TOP:
3011c2c66affSColin Finck             szWindow.cy = szActual.cy + borders.cy;
3012c2c66affSColin Finck             break;
3013c2c66affSColin Finck         case ABE_RIGHT:
3014c2c66affSColin Finck             szWindow.cx = szActual.cx + borders.cx;
3015c2c66affSColin Finck             rc.left = rc.right - szWindow.cy;
3016c2c66affSColin Finck             break;
3017c2c66affSColin Finck         case ABE_BOTTOM:
3018c2c66affSColin Finck             szWindow.cy = szActual.cy + borders.cy;
3019c2c66affSColin Finck             rc.top = rc.bottom - szWindow.cy;
3020c2c66affSColin Finck             break;
3021c2c66affSColin Finck         }
3022c2c66affSColin Finck 
3023c2c66affSColin Finck         SetWindowPos(NULL, rc.left, rc.top, szWindow.cx, szWindow.cy, SWP_NOACTIVATE | SWP_NOZORDER);
3024c2c66affSColin Finck #else
3025c2c66affSColin Finck         bHandled = FALSE;
3026c2c66affSColin Finck #endif
3027c2c66affSColin Finck         return 0;
3028c2c66affSColin Finck     }
3029c2c66affSColin Finck 
30302ed535daSGiannis Adamopoulos     LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
30312ed535daSGiannis Adamopoulos     {
30322ed535daSGiannis Adamopoulos         TaskbarSettings* newSettings = (TaskbarSettings*)lParam;
30332ed535daSGiannis Adamopoulos 
30342ed535daSGiannis Adamopoulos         /* Propagate the new settings to the children */
30352ed535daSGiannis Adamopoulos         ::SendMessageW(m_TaskSwitch, uMsg, wParam, lParam);
30362ed535daSGiannis Adamopoulos         ::SendMessageW(m_TrayNotify, uMsg, wParam, lParam);
30372ed535daSGiannis Adamopoulos 
30382ed535daSGiannis Adamopoulos         /* Toggle autohide */
30392ed535daSGiannis Adamopoulos         if (newSettings->sr.AutoHide != g_TaskbarSettings.sr.AutoHide)
30402ed535daSGiannis Adamopoulos         {
30412ed535daSGiannis Adamopoulos             g_TaskbarSettings.sr.AutoHide = newSettings->sr.AutoHide;
30422ed535daSGiannis Adamopoulos             memset(&m_AutoHideOffset, 0, sizeof(m_AutoHideOffset));
30432ed535daSGiannis Adamopoulos             m_AutoHideState = AUTOHIDE_SHOWN;
30442ed535daSGiannis Adamopoulos             if (!newSettings->sr.AutoHide)
30452ed535daSGiannis Adamopoulos                 SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER);
30462ed535daSGiannis Adamopoulos             else
30472ed535daSGiannis Adamopoulos                 SetTimer(TIMER_ID_MOUSETRACK, MOUSETRACK_INTERVAL, NULL);
30482ed535daSGiannis Adamopoulos         }
30492ed535daSGiannis Adamopoulos 
30502ed535daSGiannis Adamopoulos         /* Toggle lock state */
30512ed535daSGiannis Adamopoulos         Lock(newSettings->bLock);
30522ed535daSGiannis Adamopoulos 
30532ed535daSGiannis Adamopoulos         /* Toggle OnTop state */
30542ed535daSGiannis Adamopoulos         if (newSettings->sr.AlwaysOnTop != g_TaskbarSettings.sr.AlwaysOnTop)
30552ed535daSGiannis Adamopoulos         {
30562ed535daSGiannis Adamopoulos             g_TaskbarSettings.sr.AlwaysOnTop = newSettings->sr.AlwaysOnTop;
30572ed535daSGiannis Adamopoulos             HWND hWndInsertAfter = newSettings->sr.AlwaysOnTop ? HWND_TOPMOST : HWND_BOTTOM;
30582ed535daSGiannis Adamopoulos             SetWindowPos(hWndInsertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
30592ed535daSGiannis Adamopoulos         }
30602ed535daSGiannis Adamopoulos 
30612ed535daSGiannis Adamopoulos         g_TaskbarSettings.Save();
30622ed535daSGiannis Adamopoulos         return 0;
30632ed535daSGiannis Adamopoulos     }
30642ed535daSGiannis Adamopoulos 
3065c2c66affSColin Finck     DECLARE_WND_CLASS_EX(szTrayWndClass, CS_DBLCLKS, COLOR_3DFACE)
3066c2c66affSColin Finck 
3067c2c66affSColin Finck     BEGIN_MSG_MAP(CTrayWindow)
3068c2c66affSColin Finck         if (m_StartMenuBand != NULL)
3069c2c66affSColin Finck         {
3070c2c66affSColin Finck             MSG Msg;
3071c2c66affSColin Finck             LRESULT lRet;
3072c2c66affSColin Finck 
3073c2c66affSColin Finck             Msg.hwnd = m_hWnd;
3074c2c66affSColin Finck             Msg.message = uMsg;
3075c2c66affSColin Finck             Msg.wParam = wParam;
3076c2c66affSColin Finck             Msg.lParam = lParam;
3077c2c66affSColin Finck 
3078c2c66affSColin Finck             if (m_StartMenuBand->TranslateMenuMessage(&Msg, &lRet) == S_OK)
3079c2c66affSColin Finck             {
3080c2c66affSColin Finck                 return lRet;
3081c2c66affSColin Finck             }
3082c2c66affSColin Finck 
3083c2c66affSColin Finck             wParam = Msg.wParam;
3084c2c66affSColin Finck             lParam = Msg.lParam;
3085c2c66affSColin Finck         }
3086c2c66affSColin Finck         MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
3087c2c66affSColin Finck         MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged)
3088c2c66affSColin Finck         NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnRebarAutoSize) // Doesn't quite work ;P
3089c2c66affSColin Finck         MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
3090c2c66affSColin Finck         MESSAGE_HANDLER(WM_SIZE, OnSize)
3091c2c66affSColin Finck         MESSAGE_HANDLER(WM_CREATE, OnCreate)
3092c2c66affSColin Finck         /*MESSAGE_HANDLER(WM_DESTROY, OnDestroy)*/
3093c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
3094c2c66affSColin Finck         MESSAGE_HANDLER(WM_COMMAND, OnCommand)
3095c2c66affSColin Finck         MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
3096c2c66affSColin Finck         MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
3097c2c66affSColin Finck         MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
3098c2c66affSColin Finck         MESSAGE_HANDLER(WM_TIMER, OnTimer)
3099c2c66affSColin Finck         MESSAGE_HANDLER(WM_DISPLAYCHANGE, OnDisplayChange)
3100c2c66affSColin Finck         MESSAGE_HANDLER(WM_COPYDATA, OnCopyData)
3101c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint)
3102c2c66affSColin Finck         MESSAGE_HANDLER(WM_CTLCOLORBTN, OnCtlColorBtn)
3103c2c66affSColin Finck         MESSAGE_HANDLER(WM_MOVING, OnMoving)
3104c2c66affSColin Finck         MESSAGE_HANDLER(WM_SIZING, OnSizing)
31054238f223SGiannis Adamopoulos         MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
3106c2c66affSColin Finck         MESSAGE_HANDLER(WM_ENTERSIZEMOVE, OnEnterSizeMove)
3107c2c66affSColin Finck         MESSAGE_HANDLER(WM_EXITSIZEMOVE, OnExitSizeMove)
3108c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown)
3109c2c66affSColin Finck         MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar)
3110c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCRBUTTONUP, OnNcRButtonUp)
3111c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClick)
3112c2c66affSColin Finck         MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
3113c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCMOUSEMOVE, OnMouseMove)
3114c2c66affSColin Finck         MESSAGE_HANDLER(WM_APP_TRAYDESTROY, OnAppTrayDestroy)
3115c2c66affSColin Finck         MESSAGE_HANDLER(WM_CLOSE, OnDoExitWindows)
3116c2c66affSColin Finck         MESSAGE_HANDLER(WM_HOTKEY, OnHotkey)
3117c2c66affSColin Finck         MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize)
3118*75b09f3fSKatayama Hirofumi MZ         MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
31192ed535daSGiannis Adamopoulos         MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
3120a882ec7aSKatayama Hirofumi MZ         MESSAGE_HANDLER(TWM_OPENSTARTMENU, OnOpenStartMenu)
3121a882ec7aSKatayama Hirofumi MZ         MESSAGE_HANDLER(TWM_DOEXITWINDOWS, OnDoExitWindows)
3122c2c66affSColin Finck     ALT_MSG_MAP(1)
3123c2c66affSColin Finck     END_MSG_MAP()
3124c2c66affSColin Finck 
3125c2c66affSColin Finck     /*****************************************************************************/
3126c2c66affSColin Finck 
3127c2c66affSColin Finck     VOID TrayProcessMessages()
3128c2c66affSColin Finck     {
3129c2c66affSColin Finck         MSG Msg;
3130c2c66affSColin Finck 
3131c2c66affSColin Finck         /* FIXME: We should keep a reference here... */
3132c2c66affSColin Finck 
3133c2c66affSColin Finck         while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
3134c2c66affSColin Finck         {
3135c2c66affSColin Finck             if (Msg.message == WM_QUIT)
3136c2c66affSColin Finck                 break;
3137c2c66affSColin Finck 
3138c2c66affSColin Finck             if (m_StartMenuBand == NULL ||
3139c2c66affSColin Finck                 m_StartMenuBand->IsMenuMessage(&Msg) != S_OK)
3140c2c66affSColin Finck             {
3141c2c66affSColin Finck                 TranslateMessage(&Msg);
3142c2c66affSColin Finck                 DispatchMessage(&Msg);
3143c2c66affSColin Finck             }
3144c2c66affSColin Finck         }
3145c2c66affSColin Finck     }
3146c2c66affSColin Finck 
3147c2c66affSColin Finck     VOID TrayMessageLoop()
3148c2c66affSColin Finck     {
3149c2c66affSColin Finck         MSG Msg;
3150c2c66affSColin Finck         BOOL Ret;
3151c2c66affSColin Finck 
3152c2c66affSColin Finck         /* FIXME: We should keep a reference here... */
3153c2c66affSColin Finck 
3154c2c66affSColin Finck         while (true)
3155c2c66affSColin Finck         {
3156c2c66affSColin Finck             Ret = GetMessage(&Msg, NULL, 0, 0);
3157c2c66affSColin Finck 
3158c2c66affSColin Finck             if (!Ret || Ret == -1)
3159c2c66affSColin Finck                 break;
3160c2c66affSColin Finck 
3161c2c66affSColin Finck             if (m_StartMenuBand == NULL ||
3162c2c66affSColin Finck                 m_StartMenuBand->IsMenuMessage(&Msg) != S_OK)
3163c2c66affSColin Finck             {
3164c2c66affSColin Finck                 TranslateMessage(&Msg);
3165c2c66affSColin Finck                 DispatchMessage(&Msg);
3166c2c66affSColin Finck             }
3167c2c66affSColin Finck         }
3168c2c66affSColin Finck     }
3169c2c66affSColin Finck 
3170c2c66affSColin Finck     /*
3171c2c66affSColin Finck      * IShellDesktopTray
3172c2c66affSColin Finck      *
3173c2c66affSColin Finck      * NOTE: this is a very windows-specific COM interface used by SHCreateDesktop()!
3174c2c66affSColin Finck      *       These are the calls I observed, it may be wrong/incomplete/buggy!!!
3175c2c66affSColin Finck      *       The reason we implement it is because we have to use SHCreateDesktop() so
3176c2c66affSColin Finck      *       that the shell provides the desktop window and all the features that come
3177c2c66affSColin Finck      *       with it (especially positioning of desktop icons)
3178c2c66affSColin Finck      */
3179c2c66affSColin Finck 
3180c2c66affSColin Finck     virtual ULONG STDMETHODCALLTYPE GetState()
3181c2c66affSColin Finck     {
3182c2c66affSColin Finck         /* FIXME: Return ABS_ flags? */
3183c2c66affSColin Finck         TRACE("IShellDesktopTray::GetState() unimplemented!\n");
3184c2c66affSColin Finck         return 0;
3185c2c66affSColin Finck     }
3186c2c66affSColin Finck 
3187c2c66affSColin Finck     virtual HRESULT STDMETHODCALLTYPE GetTrayWindow(OUT HWND *phWndTray)
3188c2c66affSColin Finck     {
3189c2c66affSColin Finck         TRACE("IShellDesktopTray::GetTrayWindow(0x%p)\n", phWndTray);
3190c2c66affSColin Finck         *phWndTray = m_hWnd;
3191c2c66affSColin Finck         return S_OK;
3192c2c66affSColin Finck     }
3193c2c66affSColin Finck 
3194c2c66affSColin Finck     virtual HRESULT STDMETHODCALLTYPE RegisterDesktopWindow(IN HWND hWndDesktop)
3195c2c66affSColin Finck     {
3196c2c66affSColin Finck         TRACE("IShellDesktopTray::RegisterDesktopWindow(0x%p)\n", hWndDesktop);
3197c2c66affSColin Finck 
3198c2c66affSColin Finck         m_DesktopWnd = hWndDesktop;
3199c2c66affSColin Finck         return S_OK;
3200c2c66affSColin Finck     }
3201c2c66affSColin Finck 
3202c2c66affSColin Finck     virtual HRESULT STDMETHODCALLTYPE Unknown(IN DWORD dwUnknown1, IN DWORD dwUnknown2)
3203c2c66affSColin Finck     {
3204c2c66affSColin Finck         TRACE("IShellDesktopTray::Unknown(%u,%u) unimplemented!\n", dwUnknown1, dwUnknown2);
3205c2c66affSColin Finck         return S_OK;
3206c2c66affSColin Finck     }
3207c2c66affSColin Finck 
3208c2c66affSColin Finck     virtual HRESULT RaiseStartButton()
3209c2c66affSColin Finck     {
3210c2c66affSColin Finck         m_StartButton.SendMessageW(BM_SETSTATE, FALSE, 0);
3211c2c66affSColin Finck         return S_OK;
3212c2c66affSColin Finck     }
3213c2c66affSColin Finck 
3214c2c66affSColin Finck     HRESULT WINAPI GetWindow(HWND* phwnd)
3215c2c66affSColin Finck     {
3216c2c66affSColin Finck         if (!phwnd)
3217c2c66affSColin Finck             return E_INVALIDARG;
3218c2c66affSColin Finck         *phwnd = m_hWnd;
3219c2c66affSColin Finck         return S_OK;
3220c2c66affSColin Finck     }
3221c2c66affSColin Finck 
3222c2c66affSColin Finck     HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
3223c2c66affSColin Finck     {
3224c2c66affSColin Finck         return E_NOTIMPL;
3225c2c66affSColin Finck     }
3226c2c66affSColin Finck 
3227c2c66affSColin Finck     void _Init()
3228c2c66affSColin Finck     {
3229c2c66affSColin Finck         m_Position = (DWORD) -1;
3230c2c66affSColin Finck     }
3231c2c66affSColin Finck 
3232c2c66affSColin Finck     DECLARE_NOT_AGGREGATABLE(CTrayWindow)
3233c2c66affSColin Finck 
3234c2c66affSColin Finck     DECLARE_PROTECT_FINAL_CONSTRUCT()
3235c2c66affSColin Finck     BEGIN_COM_MAP(CTrayWindow)
3236c2c66affSColin Finck         /*COM_INTERFACE_ENTRY_IID(IID_ITrayWindow, ITrayWindow)*/
3237c2c66affSColin Finck         COM_INTERFACE_ENTRY_IID(IID_IShellDesktopTray, IShellDesktopTray)
3238c2c66affSColin Finck         COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
3239c2c66affSColin Finck         COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
3240c2c66affSColin Finck     END_COM_MAP()
3241c2c66affSColin Finck };
3242c2c66affSColin Finck 
3243c2c66affSColin Finck class CTrayWindowCtxMenu :
3244c2c66affSColin Finck     public CComCoClass<CTrayWindowCtxMenu>,
3245c2c66affSColin Finck     public CComObjectRootEx<CComMultiThreadModelNoCS>,
3246c2c66affSColin Finck     public IContextMenu
3247c2c66affSColin Finck {
3248c2c66affSColin Finck     HWND hWndOwner;
3249c2c66affSColin Finck     CComPtr<CTrayWindow> TrayWnd;
3250c2c66affSColin Finck     CComPtr<IContextMenu> pcm;
3251c2c66affSColin Finck     UINT m_idCmdCmFirst;
3252c2c66affSColin Finck 
3253c2c66affSColin Finck public:
3254c2c66affSColin Finck     HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
3255c2c66affSColin Finck     {
3256c2c66affSColin Finck         this->TrayWnd = (CTrayWindow *) pTrayWnd;
3257c2c66affSColin Finck         this->hWndOwner = hWndOwner;
3258c2c66affSColin Finck         this->m_idCmdCmFirst = 0;
3259c2c66affSColin Finck         return S_OK;
3260c2c66affSColin Finck     }
3261c2c66affSColin Finck 
3262c2c66affSColin Finck     virtual HRESULT STDMETHODCALLTYPE
3263c2c66affSColin Finck         QueryContextMenu(HMENU hPopup,
3264c2c66affSColin Finck                          UINT indexMenu,
3265c2c66affSColin Finck                          UINT idCmdFirst,
3266c2c66affSColin Finck                          UINT idCmdLast,
3267c2c66affSColin Finck                          UINT uFlags)
3268c2c66affSColin Finck     {
3269*75b09f3fSKatayama Hirofumi MZ         HMENU hMenuBase;
3270*75b09f3fSKatayama Hirofumi MZ 
3271*75b09f3fSKatayama Hirofumi MZ         hMenuBase = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_TRAYWND));
3272*75b09f3fSKatayama Hirofumi MZ 
3273*75b09f3fSKatayama Hirofumi MZ         if (g_MinimizedAll.GetSize() != 0 && !::IsThereAnyEffectiveWindow(TRUE))
3274*75b09f3fSKatayama Hirofumi MZ         {
3275*75b09f3fSKatayama Hirofumi MZ             CStringW strRestoreAll(MAKEINTRESOURCEW(IDS_RESTORE_ALL));
3276*75b09f3fSKatayama Hirofumi MZ             MENUITEMINFOW mii = { sizeof(mii) };
3277*75b09f3fSKatayama Hirofumi MZ             mii.fMask = MIIM_ID | MIIM_TYPE;
3278*75b09f3fSKatayama Hirofumi MZ             mii.wID = ID_SHELL_CMD_RESTORE_ALL;
3279*75b09f3fSKatayama Hirofumi MZ             mii.fType = MFT_STRING;
3280*75b09f3fSKatayama Hirofumi MZ             mii.dwTypeData = const_cast<LPWSTR>(&strRestoreAll[0]);
3281*75b09f3fSKatayama Hirofumi MZ             SetMenuItemInfoW(hMenuBase, ID_SHELL_CMD_SHOW_DESKTOP, FALSE, &mii);
3282*75b09f3fSKatayama Hirofumi MZ         }
3283*75b09f3fSKatayama Hirofumi MZ 
3284*75b09f3fSKatayama Hirofumi MZ         if (!hMenuBase)
3285c2c66affSColin Finck             return HRESULT_FROM_WIN32(GetLastError());
3286c2c66affSColin Finck 
3287c2c66affSColin Finck         if (SHRestricted(REST_CLASSICSHELL) != 0)
3288c2c66affSColin Finck         {
3289c2c66affSColin Finck             DeleteMenu(hPopup,
3290c2c66affSColin Finck                        ID_LOCKTASKBAR,
3291c2c66affSColin Finck                        MF_BYCOMMAND);
3292c2c66affSColin Finck         }
3293c2c66affSColin Finck 
3294*75b09f3fSKatayama Hirofumi MZ         CheckMenuItem(hMenuBase,
3295c2c66affSColin Finck                       ID_LOCKTASKBAR,
32962ed535daSGiannis Adamopoulos                       MF_BYCOMMAND | (g_TaskbarSettings.bLock ? MF_CHECKED : MF_UNCHECKED));
3297c2c66affSColin Finck 
3298c2c66affSColin Finck         UINT idCmdNext;
3299*75b09f3fSKatayama Hirofumi MZ         idCmdNext = Shell_MergeMenus(hPopup, hMenuBase, indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS | MM_ADDSEPARATOR);
3300c2c66affSColin Finck         m_idCmdCmFirst = idCmdNext - idCmdFirst;
3301c2c66affSColin Finck 
3302*75b09f3fSKatayama Hirofumi MZ         ::DestroyMenu(hMenuBase);
3303c2c66affSColin Finck 
3304c2c66affSColin Finck         if (TrayWnd->m_TrayBandSite != NULL)
3305c2c66affSColin Finck         {
3306c2c66affSColin Finck             if (FAILED(TrayWnd->m_TrayBandSite->AddContextMenus(
3307c2c66affSColin Finck                 hPopup,
3308c2c66affSColin Finck                 indexMenu,
3309c2c66affSColin Finck                 idCmdNext,
3310c2c66affSColin Finck                 idCmdLast,
3311c2c66affSColin Finck                 CMF_NORMAL,
3312c2c66affSColin Finck                 &pcm)))
3313c2c66affSColin Finck             {
3314c2c66affSColin Finck                 WARN("AddContextMenus failed.\n");
3315c2c66affSColin Finck                 pcm = NULL;
3316c2c66affSColin Finck             }
3317c2c66affSColin Finck         }
3318c2c66affSColin Finck 
3319c2c66affSColin Finck         return S_OK;
3320c2c66affSColin Finck     }
3321c2c66affSColin Finck 
3322c2c66affSColin Finck     virtual HRESULT STDMETHODCALLTYPE
3323c2c66affSColin Finck         InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
3324c2c66affSColin Finck     {
3325c2c66affSColin Finck         UINT uiCmdId = (UINT) lpici->lpVerb;
3326c2c66affSColin Finck         if (uiCmdId != 0)
3327c2c66affSColin Finck         {
3328c2c66affSColin Finck             if (uiCmdId >= m_idCmdCmFirst)
3329c2c66affSColin Finck             {
3330c2c66affSColin Finck                 CMINVOKECOMMANDINFO cmici = { 0 };
3331c2c66affSColin Finck 
3332c2c66affSColin Finck                 if (pcm != NULL)
3333c2c66affSColin Finck                 {
3334c2c66affSColin Finck                     /* Setup and invoke the shell command */
3335c2c66affSColin Finck                     cmici.cbSize = sizeof(cmici);
3336c2c66affSColin Finck                     cmici.hwnd = hWndOwner;
3337c2c66affSColin Finck                     cmici.lpVerb = (LPCSTR) MAKEINTRESOURCEW(uiCmdId - m_idCmdCmFirst);
3338c2c66affSColin Finck                     cmici.nShow = SW_NORMAL;
3339c2c66affSColin Finck 
3340c2c66affSColin Finck                     pcm->InvokeCommand(&cmici);
3341c2c66affSColin Finck                 }
3342c2c66affSColin Finck             }
3343c2c66affSColin Finck             else
3344c2c66affSColin Finck             {
3345c2c66affSColin Finck                 TrayWnd->ExecContextMenuCmd(uiCmdId);
3346c2c66affSColin Finck             }
3347c2c66affSColin Finck         }
3348c2c66affSColin Finck 
3349c2c66affSColin Finck         return S_OK;
3350c2c66affSColin Finck     }
3351c2c66affSColin Finck 
3352c2c66affSColin Finck     virtual HRESULT STDMETHODCALLTYPE
3353c2c66affSColin Finck         GetCommandString(UINT_PTR idCmd,
3354c2c66affSColin Finck         UINT uType,
3355c2c66affSColin Finck         UINT *pwReserved,
3356c2c66affSColin Finck         LPSTR pszName,
3357c2c66affSColin Finck         UINT cchMax)
3358c2c66affSColin Finck     {
3359c2c66affSColin Finck         return E_NOTIMPL;
3360c2c66affSColin Finck     }
3361c2c66affSColin Finck 
3362c2c66affSColin Finck     CTrayWindowCtxMenu()
3363c2c66affSColin Finck     {
3364c2c66affSColin Finck     }
3365c2c66affSColin Finck 
3366c2c66affSColin Finck     virtual ~CTrayWindowCtxMenu()
3367c2c66affSColin Finck     {
3368c2c66affSColin Finck     }
3369c2c66affSColin Finck 
3370c2c66affSColin Finck     BEGIN_COM_MAP(CTrayWindowCtxMenu)
3371c2c66affSColin Finck         COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
3372c2c66affSColin Finck     END_COM_MAP()
3373c2c66affSColin Finck };
3374c2c66affSColin Finck 
3375c2c66affSColin Finck HRESULT TrayWindowCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu)
3376c2c66affSColin Finck {
3377c2c66affSColin Finck     CTrayWindowCtxMenu * mnu = new CComObject<CTrayWindowCtxMenu>();
3378c2c66affSColin Finck     mnu->Initialize(TrayWnd, hWndOwner);
3379c2c66affSColin Finck     *ppCtxMenu = mnu;
3380c2c66affSColin Finck     return S_OK;
3381c2c66affSColin Finck }
3382c2c66affSColin Finck 
3383c2c66affSColin Finck HRESULT CreateTrayWindow(ITrayWindow ** ppTray)
3384c2c66affSColin Finck {
3385c2c66affSColin Finck     CComPtr<CTrayWindow> Tray = new CComObject<CTrayWindow>();
3386c2c66affSColin Finck     if (Tray == NULL)
3387c2c66affSColin Finck         return E_OUTOFMEMORY;
3388c2c66affSColin Finck 
3389c2c66affSColin Finck     Tray->_Init();
3390c2c66affSColin Finck     Tray->Open();
3391c2c66affSColin Finck 
3392c2c66affSColin Finck     *ppTray = (ITrayWindow *) Tray;
3393c2c66affSColin Finck 
3394c2c66affSColin Finck     return S_OK;
3395c2c66affSColin Finck }
3396c2c66affSColin Finck 
3397c2c66affSColin Finck HRESULT
3398c2c66affSColin Finck Tray_OnStartMenuDismissed(ITrayWindow* Tray)
3399c2c66affSColin Finck {
3400c2c66affSColin Finck     CTrayWindow * TrayWindow = static_cast<CTrayWindow *>(Tray);
3401c2c66affSColin Finck     return TrayWindow->RaiseStartButton();
3402c2c66affSColin Finck }
3403c2c66affSColin Finck 
3404c2c66affSColin Finck VOID TrayProcessMessages(ITrayWindow *Tray)
3405c2c66affSColin Finck {
3406c2c66affSColin Finck     CTrayWindow * TrayWindow = static_cast<CTrayWindow *>(Tray);
3407c2c66affSColin Finck     TrayWindow->TrayProcessMessages();
3408c2c66affSColin Finck }
3409c2c66affSColin Finck 
3410c2c66affSColin Finck VOID TrayMessageLoop(ITrayWindow *Tray)
3411c2c66affSColin Finck {
3412c2c66affSColin Finck     CTrayWindow * TrayWindow = static_cast<CTrayWindow *>(Tray);
3413c2c66affSColin Finck     TrayWindow->TrayMessageLoop();
3414c2c66affSColin Finck }
3415