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