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