Author: gadamopoulos
Date: Tue Aug 23 16:52:05 2016
New Revision: 72440
URL:
http://svn.reactos.org/svn/reactos?rev=72440&view=rev
Log:
[EXPLORER]
- CTrayWindow: Reorganise the code in logical groups to make it more readable. Move
command handlers at the top of the file followed by the code that manages moving and
resizing the taskbar. After that is code that paints the taskbar and the implementation of
the ITrayWindow interface which I really doubt if it is needed. Finally at the bottom are
the message handlers.
Modified:
trunk/reactos/base/shell/explorer/traywnd.cpp
Modified: trunk/reactos/base/shell/explorer/traywnd.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/explorer/traywn…
==============================================================================
--- trunk/reactos/base/shell/explorer/traywnd.cpp [iso-8859-1] (original)
+++ trunk/reactos/base/shell/explorer/traywnd.cpp [iso-8859-1] Tue Aug 23 16:52:05 2016
@@ -502,1135 +502,95 @@
PostQuitMessage(0);
}
- /*
- * ITrayWindow
+
+
+
+
+ /**********************************************************
+ * ##### command handling #####
*/
- BOOL UpdateNonClientMetrics()
- {
- NONCLIENTMETRICS ncm;
- ncm.cbSize = sizeof(ncm);
- if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
- {
- if (m_Font != NULL)
- DeleteObject(m_Font);
-
- m_Font = CreateFontIndirect(&ncm.lfMessageFont);
- return TRUE;
- }
-
- return FALSE;
- }
-
- VOID SetWindowsFont()
- {
- if (m_TrayNotify != NULL)
- {
- SendMessage(m_TrayNotify, WM_SETFONT, (WPARAM) m_Font, TRUE);
- }
- }
-
- HMONITOR GetScreenRectFromRect(
- IN OUT RECT *pRect,
- IN DWORD dwFlags)
- {
- MONITORINFO mi;
- HMONITOR hMon;
-
- mi.cbSize = sizeof(mi);
- hMon = MonitorFromRect(pRect, dwFlags);
- if (hMon != NULL &&
- GetMonitorInfo(hMon, &mi))
- {
- *pRect = mi.rcMonitor;
- }
- else
- {
- pRect->left = 0;
- pRect->top = 0;
- pRect->right = GetSystemMetrics(SM_CXSCREEN);
- pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
-
- hMon = NULL;
- }
-
- return hMon;
- }
-
- HMONITOR GetMonitorFromRect(
- IN const RECT *pRect)
- {
- HMONITOR hMon;
-
- /* In case the monitor sizes or saved sizes differ a bit (probably
- not a lot, only so the tray window overlaps into another monitor
- now), minimize the risk that we determine a wrong monitor by
- using the center point of the tray window if we can't determine
- it using the rectangle. */
- hMon = MonitorFromRect(pRect, MONITOR_DEFAULTTONULL);
- if (hMon == NULL)
- {
- POINT pt;
-
- pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
- pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
-
- /* be less error-prone, find the nearest monitor */
- hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
- }
-
- return hMon;
- }
-
- HMONITOR GetScreenRect(
- IN HMONITOR hMonitor,
- IN OUT RECT *pRect)
- {
- HMONITOR hMon = NULL;
-
- if (hMonitor != NULL)
- {
- MONITORINFO mi;
-
- mi.cbSize = sizeof(mi);
- if (!GetMonitorInfo(hMonitor, &mi))
- {
- /* Hm, the monitor is gone? Try to find a monitor where it
- could be located now */
- hMon = GetMonitorFromRect(pRect);
- if (hMon == NULL ||
- !GetMonitorInfo(hMon, &mi))
- {
- hMon = NULL;
- goto GetPrimaryRect;
- }
- }
-
- *pRect = mi.rcMonitor;
- }
- else
- {
-GetPrimaryRect:
- pRect->left = 0;
- pRect->top = 0;
- pRect->right = GetSystemMetrics(SM_CXSCREEN);
- pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
- }
-
- return hMon;
- }
-
- VOID MakeTrayRectWithSize(IN DWORD Position,
- IN const SIZE *pTraySize,
- IN OUT RECT *pRect)
- {
- switch (Position)
- {
- case ABE_LEFT:
- pRect->right = pRect->left + pTraySize->cx;
- break;
-
- case ABE_TOP:
- pRect->bottom = pRect->top + pTraySize->cy;
- break;
-
- case ABE_RIGHT:
- pRect->left = pRect->right - pTraySize->cx;
- break;
-
- case ABE_BOTTOM:
- default:
- pRect->top = pRect->bottom - pTraySize->cy;
- break;
- }
- }
-
- VOID GetTrayRectFromScreenRect(IN DWORD Position,
- IN const RECT *pScreen,
- IN const SIZE *pTraySize OPTIONAL,
- OUT RECT *pRect)
- {
- if (pTraySize == NULL)
- pTraySize = &m_TraySize;
-
- *pRect = *pScreen;
-
- /* Move the border outside of the screen */
- InflateRect(pRect,
- GetSystemMetrics(SM_CXEDGE),
- GetSystemMetrics(SM_CYEDGE));
-
- MakeTrayRectWithSize(Position, pTraySize, pRect);
- }
-
- BOOL IsPosHorizontal()
- {
- return m_Position == ABE_TOP || m_Position == ABE_BOTTOM;
- }
-
- HMONITOR CalculateValidSize(
- IN DWORD Position,
- IN OUT RECT *pRect)
- {
- RECT rcScreen;
- //BOOL Horizontal;
- HMONITOR hMon;
- SIZE szMax, szWnd;
-
- //Horizontal = IsPosHorizontal();
-
- szWnd.cx = pRect->right - pRect->left;
- szWnd.cy = pRect->bottom - pRect->top;
-
- rcScreen = *pRect;
- hMon = GetScreenRectFromRect(
- &rcScreen,
- MONITOR_DEFAULTTONEAREST);
-
- /* Calculate the maximum size of the tray window and limit the window
- size to half of the screen's size. */
- szMax.cx = (rcScreen.right - rcScreen.left) / 2;
- szMax.cy = (rcScreen.bottom - rcScreen.top) / 2;
- if (szWnd.cx > szMax.cx)
- szWnd.cx = szMax.cx;
- if (szWnd.cy > szMax.cy)
- szWnd.cy = szMax.cy;
-
- /* FIXME - calculate */
-
- GetTrayRectFromScreenRect(Position,
- &rcScreen,
- &szWnd,
- pRect);
-
- return hMon;
- }
-
-#if 0
- VOID
- GetMinimumWindowSize(
- OUT RECT *pRect)
- {
- RECT rcMin = {0};
-
- AdjustWindowRectEx(&rcMin,
- GetWindowLong(m_hWnd,
- GWL_STYLE),
- FALSE,
- GetWindowLong(m_hWnd,
- GWL_EXSTYLE));
-
- *pRect = rcMin;
- }
-#endif
-
-
- DWORD GetDraggingRectFromPt(
- IN POINT pt,
- OUT RECT *pRect,
- OUT HMONITOR *phMonitor)
- {
- HMONITOR hMon, hMonNew;
- DWORD PosH, PosV, Pos;
- SIZE DeltaPt, ScreenOffset;
- RECT rcScreen;
-
- rcScreen.left = 0;
- rcScreen.top = 0;
-
- /* Determine the screen rectangle */
- hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
- if (hMon != NULL)
- {
- MONITORINFO mi;
-
- mi.cbSize = sizeof(mi);
- if (!GetMonitorInfo(hMon, &mi))
- {
- hMon = NULL;
- goto GetPrimaryScreenRect;
- }
-
- /* make left top corner of the screen zero based to
- make calculations easier */
- pt.x -= mi.rcMonitor.left;
- pt.y -= mi.rcMonitor.top;
-
- ScreenOffset.cx = mi.rcMonitor.left;
- ScreenOffset.cy = mi.rcMonitor.top;
- rcScreen.right = mi.rcMonitor.right - mi.rcMonitor.left;
- rcScreen.bottom = mi.rcMonitor.bottom - mi.rcMonitor.top;
- }
- else
- {
-GetPrimaryScreenRect:
- ScreenOffset.cx = 0;
- ScreenOffset.cy = 0;
- rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
- rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
- }
-
- /* Calculate the nearest screen border */
- if (pt.x < rcScreen.right / 2)
- {
- DeltaPt.cx = pt.x;
- PosH = ABE_LEFT;
- }
- else
- {
- DeltaPt.cx = rcScreen.right - pt.x;
- PosH = ABE_RIGHT;
- }
-
- if (pt.y < rcScreen.bottom / 2)
- {
- DeltaPt.cy = pt.y;
- PosV = ABE_TOP;
- }
- else
- {
- DeltaPt.cy = rcScreen.bottom - pt.y;
- PosV = ABE_BOTTOM;
- }
-
- Pos = (DeltaPt.cx * rcScreen.bottom < DeltaPt.cy * rcScreen.right) ? PosH :
PosV;
-
- /* Fix the screen origin to be relative to the primary monitor again */
- OffsetRect(&rcScreen,
- ScreenOffset.cx,
- ScreenOffset.cy);
-
- RECT rcPos = m_TrayRects[Pos];
-
- hMonNew = GetMonitorFromRect(&rcPos);
- if (hMon != hMonNew)
- {
- SIZE szTray;
-
- /* Recalculate the rectangle, we're dragging to another monitor.
- We don't need to recalculate the rect on single monitor systems. */
- szTray.cx = rcPos.right - rcPos.left;
- szTray.cy = rcPos.bottom - rcPos.top;
-
- GetTrayRectFromScreenRect(Pos, &rcScreen, &szTray, pRect);
- if (AutoHide)
- {
- pRect->left += m_AutoHideOffset.cx;
- pRect->right += m_AutoHideOffset.cx;
- pRect->top += m_AutoHideOffset.cy;
- pRect->bottom += m_AutoHideOffset.cy;
- }
- hMon = hMonNew;
- }
- else
- {
- /* The user is dragging the tray window on the same monitor. We don't
need
- to recalculate the rectangle */
- *pRect = rcPos;
- if (AutoHide)
- {
- pRect->left += m_AutoHideOffset.cx;
- pRect->right += m_AutoHideOffset.cx;
- pRect->top += m_AutoHideOffset.cy;
- pRect->bottom += m_AutoHideOffset.cy;
- }
- }
-
- *phMonitor = hMon;
-
- return Pos;
- }
-
- DWORD GetDraggingRectFromRect(
- IN OUT RECT *pRect,
- OUT HMONITOR *phMonitor)
- {
- POINT pt;
-
- /* Calculate the center of the rectangle. We call
- GetDraggingRectFromPt to calculate a valid
- dragging rectangle */
- pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
- pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
-
- return GetDraggingRectFromPt(
- pt,
- pRect,
- phMonitor);
- }
-
- VOID ChangingWinPos(IN OUT LPWINDOWPOS pwp)
- {
- RECT rcTray;
-
- if (IsDragging)
- {
- rcTray.left = pwp->x;
- rcTray.top = pwp->y;
- rcTray.right = rcTray.left + pwp->cx;
- rcTray.bottom = rcTray.top + pwp->cy;
- if (AutoHide)
- {
- rcTray.left -= m_AutoHideOffset.cx;
- rcTray.right -= m_AutoHideOffset.cx;
- rcTray.top -= m_AutoHideOffset.cy;
- rcTray.bottom -= m_AutoHideOffset.cy;
- }
-
- if (!EqualRect(&rcTray,
- &m_TrayRects[m_DraggingPosition]))
- {
- /* Recalculate the rectangle, the user dragged the tray
- window to another monitor or the window was somehow else
- moved or resized */
- m_DraggingPosition = GetDraggingRectFromRect(
- &rcTray,
- &m_DraggingMonitor);
- //m_TrayRects[DraggingPosition] = rcTray;
- }
-
- //Monitor = CalculateValidSize(DraggingPosition,
- // &rcTray);
-
- m_Monitor = m_DraggingMonitor;
- m_Position = m_DraggingPosition;
- IsDragging = FALSE;
-
- m_TrayRects[m_Position] = rcTray;
- goto ChangePos;
- }
- else if (GetWindowRect(&rcTray))
- {
- if (InSizeMove)
- {
- if (!(pwp->flags & SWP_NOMOVE))
- {
- rcTray.left = pwp->x;
- rcTray.top = pwp->y;
- }
-
- if (!(pwp->flags & SWP_NOSIZE))
- {
- rcTray.right = rcTray.left + pwp->cx;
- rcTray.bottom = rcTray.top + pwp->cy;
- }
-
- m_Position = GetDraggingRectFromRect(&rcTray, &m_Monitor);
-
- if (!(pwp->flags & (SWP_NOMOVE | SWP_NOSIZE)))
- {
- SIZE szWnd;
-
- szWnd.cx = pwp->cx;
- szWnd.cy = pwp->cy;
-
- MakeTrayRectWithSize(m_Position, &szWnd, &rcTray);
- }
-
- if (AutoHide)
- {
- rcTray.left -= m_AutoHideOffset.cx;
- rcTray.right -= m_AutoHideOffset.cx;
- rcTray.top -= m_AutoHideOffset.cy;
- rcTray.bottom -= m_AutoHideOffset.cy;
- }
- m_TrayRects[m_Position] = rcTray;
- }
- else
- {
- /* If the user isn't resizing the tray window we need to make sure
the
- new size or position is valid. this is to prevent changes to the
window
- without user interaction. */
- rcTray = m_TrayRects[m_Position];
- }
-
-ChangePos:
- m_TraySize.cx = rcTray.right - rcTray.left;
- m_TraySize.cy = rcTray.bottom - rcTray.top;
-
- if (AutoHide)
- {
- rcTray.left += m_AutoHideOffset.cx;
- rcTray.right += m_AutoHideOffset.cx;
- rcTray.top += m_AutoHideOffset.cy;
- rcTray.bottom += m_AutoHideOffset.cy;
- }
-
- pwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
- pwp->x = rcTray.left;
- pwp->y = rcTray.top;
- pwp->cx = m_TraySize.cx;
- pwp->cy = m_TraySize.cy;
- }
- }
-
- VOID ApplyClipping(IN BOOL Clip)
- {
- RECT rcClip, rcWindow;
- HRGN hClipRgn;
-
- if (GetWindowRect(&rcWindow))
- {
- /* Disable clipping on systems with only one monitor */
- if (GetSystemMetrics(SM_CMONITORS) <= 1)
- Clip = FALSE;
-
- if (Clip)
- {
- rcClip = rcWindow;
-
- GetScreenRect(m_Monitor, &rcClip);
-
- if (!IntersectRect(&rcClip, &rcClip, &rcWindow))
- {
- rcClip = rcWindow;
- }
-
- OffsetRect(&rcClip,
- -rcWindow.left,
- -rcWindow.top);
-
- hClipRgn = CreateRectRgnIndirect(&rcClip);
- }
- else
- hClipRgn = NULL;
-
- /* Set the clipping region or make sure the window isn't clipped
- by disabling it explicitly. */
- SetWindowRgn(hClipRgn, TRUE);
- }
- }
-
- VOID ResizeWorkArea()
- {
-#if !WIN7_DEBUG_MODE
- RECT rcTray, rcWorkArea;
-
- /* If monitor has changed then fix the previous monitors work area */
- if (m_PreviousMonitor != m_Monitor)
- {
- GetScreenRect(m_PreviousMonitor, &rcWorkArea);
- SystemParametersInfoW(SPI_SETWORKAREA,
- 1,
- &rcWorkArea,
- SPIF_SENDCHANGE);
- }
-
- rcTray = m_TrayRects[m_Position];
-
- GetScreenRect(m_Monitor, &rcWorkArea);
- m_PreviousMonitor = m_Monitor;
-
- /* If AutoHide is false then change the workarea to exclude
- the area that the taskbar covers. */
- if (!AutoHide)
- {
- switch (m_Position)
- {
- case ABE_TOP:
- rcWorkArea.top = rcTray.bottom;
- break;
- case ABE_LEFT:
- rcWorkArea.left = rcTray.right;
- break;
- case ABE_RIGHT:
- rcWorkArea.right = rcTray.left;
- break;
- case ABE_BOTTOM:
- rcWorkArea.bottom = rcTray.top;
- break;
- }
- }
-
- /*
- * Resize the current monitor work area. Win32k will also send
- * a WM_SIZE message to automatically resize the desktop.
- */
- SystemParametersInfoW(SPI_SETWORKAREA,
- 1,
- &rcWorkArea,
- SPIF_SENDCHANGE);
-#endif
- }
-
- VOID CheckTrayWndPosition()
- {
- RECT rcTray;
-
- rcTray = m_TrayRects[m_Position];
-
- if (AutoHide)
- {
- rcTray.left += m_AutoHideOffset.cx;
- rcTray.right += m_AutoHideOffset.cx;
- rcTray.top += m_AutoHideOffset.cy;
- rcTray.bottom += m_AutoHideOffset.cy;
- }
-
- /* Move the tray window */
- SetWindowPos(NULL,
- rcTray.left,
- rcTray.top,
- rcTray.right - rcTray.left,
- rcTray.bottom - rcTray.top,
- SWP_NOZORDER | SWP_NOACTIVATE);
-
- ResizeWorkArea();
-
- ApplyClipping(TRUE);
- }
-
- typedef struct _TW_STUCKRECTS2
- {
- DWORD cbSize;
- LONG Unknown;
- DWORD dwFlags;
- DWORD Position;
- SIZE Size;
- RECT Rect;
- } TW_STRUCKRECTS2, *PTW_STUCKRECTS2;
-
- VOID RegLoadSettings()
- {
- DWORD Pos;
- TW_STRUCKRECTS2 sr;
- RECT rcScreen;
- SIZE WndSize, EdgeSize, DlgFrameSize;
- DWORD cbSize = sizeof(sr);
- SIZE StartBtnSize = m_StartButton.GetSize();
-
- EdgeSize.cx = GetSystemMetrics(SM_CXEDGE);
- EdgeSize.cy = GetSystemMetrics(SM_CYEDGE);
- DlgFrameSize.cx = GetSystemMetrics(SM_CXDLGFRAME);
- DlgFrameSize.cy = GetSystemMetrics(SM_CYDLGFRAME);
-
- if (SHGetValue(hkExplorer,
- TEXT("StuckRects2"),
- TEXT("Settings"),
- NULL,
- &sr,
- &cbSize) == ERROR_SUCCESS &&
- sr.cbSize == sizeof(sr))
- {
- AutoHide = (sr.dwFlags & ABS_AUTOHIDE) != 0;
- AlwaysOnTop = (sr.dwFlags & ABS_ALWAYSONTOP) != 0;
- SmSmallIcons = (sr.dwFlags & 0x4) != 0;
- HideClock = (sr.dwFlags & 0x8) != 0;
-
- /* FIXME: Are there more flags? */
-
-#if WIN7_DEBUG_MODE
- m_Position = ABE_LEFT;
-#else
- if (sr.Position > ABE_BOTTOM)
- m_Position = ABE_BOTTOM;
- else
- m_Position = sr.Position;
-#endif
-
- /* Try to find out which monitor the tray window was located on last.
- Here we're only interested in the monitor screen that we think
- is the last one used. We're going to determine on which monitor
- we really are after calculating the docked position. */
- rcScreen = sr.Rect;
- GetScreenRectFromRect(
- &rcScreen,
- MONITOR_DEFAULTTONEAREST);
- }
- else
- {
- m_Position = ABE_BOTTOM;
- AlwaysOnTop = TRUE;
-
- /* Use the minimum size of the taskbar, we'll use the start
- button as a minimum for now. Make sure we calculate the
- entire window size, not just the client size. However, we
- use a thinner border than a standard thick border, so that
- the start button and bands are not stuck to the screen border. */
- sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
- sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
-
- /* Use the primary screen by default */
- rcScreen.left = 0;
- rcScreen.top = 0;
- rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
- rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
- GetScreenRectFromRect(
- &rcScreen,
- MONITOR_DEFAULTTOPRIMARY);
- }
-
- if (m_hWnd != NULL)
- SetWindowPos(
- AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
- 0,
- 0,
- 0,
- 0,
- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
-
- /* Determine a minimum tray window rectangle. The "client" height is
- zero here since we cannot determine an optimal minimum width when
- loaded as a vertical tray window. We just need to make sure the values
- loaded from the registry are at least. The windows explorer behaves
- the same way, it allows the user to save a zero width vertical tray
- window, but not a zero height horizontal tray window. */
- WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
- WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
-
- if (WndSize.cx < sr.Size.cx)
- WndSize.cx = sr.Size.cx;
- if (WndSize.cy < sr.Size.cy)
- WndSize.cy = sr.Size.cy;
-
- /* Save the calculated size */
- m_TraySize = WndSize;
-
- /* Calculate all docking rectangles. We need to do this here so they're
- initialized and dragging the tray window to another position gives
- usable results */
- for (Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
- {
- GetTrayRectFromScreenRect(Pos,
- &rcScreen,
- &m_TraySize,
- &m_TrayRects[Pos]);
- // 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);
- }
-
- /* Determine which monitor we are on. It shouldn't matter which docked
- position rectangle we use */
- m_Monitor = GetMonitorFromRect(&m_TrayRects[ABE_LEFT]);
- }
-
- UINT TrackMenu(
- IN HMENU hMenu,
- IN POINT *ppt OPTIONAL,
- IN HWND hwndExclude OPTIONAL,
- IN BOOL TrackUp,
- IN BOOL IsContextMenu)
- {
- TPMPARAMS tmp, *ptmp = NULL;
- POINT pt;
- UINT cmdId;
- UINT fuFlags;
-
- if (hwndExclude != NULL)
- {
- /* Get the client rectangle and map it to screen coordinates */
- if (::GetClientRect(hwndExclude,
- &tmp.rcExclude) &&
- ::MapWindowPoints(hwndExclude,
- NULL,
- (LPPOINT) &tmp.rcExclude,
- 2) != 0)
- {
- ptmp = &tmp;
- }
- }
-
- if (ppt == NULL)
- {
- if (ptmp == NULL &&
- GetClientRect(&tmp.rcExclude) &&
- MapWindowPoints(
- NULL,
- (LPPOINT) &tmp.rcExclude,
- 2) != 0)
- {
- ptmp = &tmp;
- }
-
- if (ptmp != NULL)
- {
- /* NOTE: TrackPopupMenuEx will eventually align the track position
- for us, no need to take care of it here as long as the
- coordinates are somewhere within the exclusion rectangle */
- pt.x = ptmp->rcExclude.left;
- pt.y = ptmp->rcExclude.top;
- }
- else
- pt.x = pt.y = 0;
- }
- else
- pt = *ppt;
-
- tmp.cbSize = sizeof(tmp);
-
- fuFlags = TPM_RETURNCMD | TPM_VERTICAL;
- fuFlags |= (TrackUp ? TPM_BOTTOMALIGN : TPM_TOPALIGN);
- if (IsContextMenu)
- fuFlags |= TPM_RIGHTBUTTON;
- else
- fuFlags |= (TrackUp ? TPM_VERNEGANIMATION : TPM_VERPOSANIMATION);
-
- cmdId = TrackPopupMenuEx(hMenu,
- fuFlags,
- pt.x,
- pt.y,
- m_hWnd,
- ptmp);
-
- return cmdId;
- }
-
- HRESULT TrackCtxMenu(
- IN IContextMenu * contextMenu,
- IN POINT *ppt OPTIONAL,
- IN HWND hwndExclude OPTIONAL,
- IN BOOL TrackUp,
- IN PVOID Context OPTIONAL)
- {
- INT x = ppt->x;
- INT y = ppt->y;
- HRESULT hr;
- UINT uCommand;
- HMENU popup = CreatePopupMenu();
-
- if (popup == NULL)
+ HRESULT ExecResourceCmd(int id)
+ {
+ WCHAR szCommand[256];
+ WCHAR *pszParameters;
+
+ if (!LoadStringW(hExplorerInstance,
+ id,
+ szCommand,
+ _countof(szCommand)))
+ {
return E_FAIL;
-
- TRACE("Before Query\n");
- hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
- if (FAILED_UNEXPECTEDLY(hr))
- {
- TRACE("Query failed\n");
- DestroyMenu(popup);
- return hr;
- }
-
- TRACE("Before Tracking\n");
- uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_hWnd, NULL);
-
- if (uCommand != 0)
- {
- TRACE("Before InvokeCommand\n");
- CMINVOKECOMMANDINFO cmi = { 0 };
- cmi.cbSize = sizeof(cmi);
- cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
- cmi.hwnd = m_hWnd;
- hr = contextMenu->InvokeCommand(&cmi);
- }
- else
- {
- TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand,
GetLastError());
- hr = S_FALSE;
- }
-
- DestroyMenu(popup);
- return hr;
- }
-
- VOID AlignControls(IN PRECT prcClient OPTIONAL)
- {
- RECT rcClient;
- SIZE TraySize, StartSize;
- POINT ptTrayNotify = { 0, 0 };
- BOOL Horizontal;
- HDWP dwp;
-
- m_StartButton.UpdateSize();
- if (prcClient != NULL)
- {
- rcClient = *prcClient;
- }
- else
- {
- if (!GetClientRect(&rcClient))
- {
- ERR("Could not get client rect lastErr=%d\n", GetLastError());
+ }
+
+ pszParameters = wcschr(szCommand, L'>');
+ if (pszParameters)
+ {
+ *pszParameters = 0;
+ pszParameters++;
+ }
+
+ ShellExecuteW(m_hWnd, NULL, szCommand, pszParameters, NULL, SW_SHOWNORMAL);
+ return S_OK;
+ }
+
+ LRESULT DoExitWindows()
+ {
+ ExitWindowsDialog(m_hWnd);
+ return 0;
+ }
+
+ DWORD WINAPI RunFileDlgThread()
+ {
+ HWND hwnd;
+ RECT posRect;
+
+ m_StartButton.GetWindowRect(&posRect);
+
+ hwnd = CreateWindowEx(0,
+ WC_STATIC,
+ NULL,
+ WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER |
SS_LEFT,
+ posRect.left,
+ posRect.top,
+ posRect.right - posRect.left,
+ posRect.bottom - posRect.top,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ m_RunFileDlgOwner = hwnd;
+
+ RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
+
+ m_RunFileDlgOwner = NULL;
+ ::DestroyWindow(hwnd);
+
+ return 0;
+ }
+
+ static DWORD WINAPI s_RunFileDlgThread(IN OUT PVOID pParam)
+ {
+ CTrayWindow * This = (CTrayWindow*) pParam;
+ return This->RunFileDlgThread();
+ }
+
+ void DisplayRunFileDlg()
+ {
+ HWND hRunDlg;
+ if (m_RunFileDlgOwner)
+ {
+ hRunDlg = ::GetLastActivePopup(m_RunFileDlgOwner);
+ if (hRunDlg != NULL &&
+ hRunDlg != m_RunFileDlgOwner)
+ {
+ SetForegroundWindow(hRunDlg);
return;
}
}
- Horizontal = IsPosHorizontal();
-
- /* We're about to resize/move the start button, the rebar control and
- the tray notification control */
- dwp = BeginDeferWindowPos(3);
- if (dwp == NULL)
- {
- ERR("BeginDeferWindowPos failed. lastErr=%d\n", GetLastError());
- return;
- }
-
- /* Limit the Start button width to the client width, if neccessary */
- StartSize = m_StartButton.GetSize();
- if (StartSize.cx > rcClient.right)
- StartSize.cx = rcClient.right;
-
- if (m_StartButton.m_hWnd != NULL)
- {
- /* Resize and reposition the button */
- dwp = m_StartButton.DeferWindowPos(dwp,
- NULL,
- 0,
- 0,
- StartSize.cx,
- StartSize.cy,
- SWP_NOZORDER | SWP_NOACTIVATE);
- if (dwp == NULL)
- {
- ERR("DeferWindowPos for start button failed. lastErr=%d\n",
GetLastError());
- return;
- }
- }
-
- /* Determine the size that the tray notification window needs */
- if (Horizontal)
- {
- TraySize.cx = 0;
- TraySize.cy = rcClient.bottom;
- }
- else
- {
- TraySize.cx = rcClient.right;
- TraySize.cy = 0;
- }
-
- if (m_TrayNotify != NULL &&
- SendMessage(m_TrayNotify,
- TNWM_GETMINIMUMSIZE,
- (WPARAM)Horizontal,
- (LPARAM)&TraySize))
- {
- /* Move the tray notification window to the desired location */
- if (Horizontal)
- ptTrayNotify.x = rcClient.right - TraySize.cx;
- else
- ptTrayNotify.y = rcClient.bottom - TraySize.cy;
-
- dwp = ::DeferWindowPos(dwp,
- m_TrayNotify,
- NULL,
- ptTrayNotify.x,
- ptTrayNotify.y,
- TraySize.cx,
- TraySize.cy,
- SWP_NOZORDER | SWP_NOACTIVATE);
- if (dwp == NULL)
- {
- ERR("DeferWindowPos for notification area failed.
lastErr=%d\n", GetLastError());
- return;
- }
- }
-
- /* Resize/Move the rebar control */
- if (m_Rebar != NULL)
- {
- POINT ptRebar = { 0, 0 };
- SIZE szRebar;
-
- SetWindowStyle(m_Rebar, CCS_VERT, Horizontal ? 0 : CCS_VERT);
-
- if (Horizontal)
- {
- ptRebar.x = StartSize.cx + GetSystemMetrics(SM_CXSIZEFRAME);
- szRebar.cx = ptTrayNotify.x - ptRebar.x;
- szRebar.cy = rcClient.bottom;
- }
- else
- {
- ptRebar.y = StartSize.cy + GetSystemMetrics(SM_CYSIZEFRAME);
- szRebar.cx = rcClient.right;
- szRebar.cy = ptTrayNotify.y - ptRebar.y;
- }
-
- dwp = ::DeferWindowPos(dwp,
- m_Rebar,
- NULL,
- ptRebar.x,
- ptRebar.y,
- szRebar.cx,
- szRebar.cy,
- SWP_NOZORDER | SWP_NOACTIVATE);
- }
-
- if (dwp != NULL)
- EndDeferWindowPos(dwp);
-
- if (m_TaskSwitch != NULL)
- {
- /* Update the task switch window configuration */
- SendMessage(m_TaskSwitch, TSWM_UPDATETASKBARPOS, 0, 0);
- }
- }
-
- LRESULT OnThemeChanged()
- {
- if (m_Theme)
- CloseThemeData(m_Theme);
-
- if (IsThemeActive())
- m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
- else
- m_Theme = NULL;
-
- if (Locked && m_Theme)
- {
- SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
- }
- else
- {
- SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME |
WS_BORDER);
- }
- SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
-
- return TRUE;
- }
-
- LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- return OnThemeChanged();
- }
-
- LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
- ((ITrayWindow*)this)->AddRef();
-
- SetWindowTheme(m_hWnd, L"TaskBar", NULL);
-
- InterlockedIncrement(&TrayWndCount);
-
- if (m_CaptionFont == NULL)
- {
- NONCLIENTMETRICS ncm;
-
- /* Get the system fonts, we use the caption font,
- always bold, though. */
- ncm.cbSize = sizeof(ncm);
- if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm,
FALSE))
- {
- if (m_CaptionFont == NULL)
- {
- ncm.lfCaptionFont.lfWeight = FW_NORMAL;
- m_CaptionFont = CreateFontIndirect(&ncm.lfCaptionFont);
- }
- }
- }
-
- /* Create the Start button */
- m_StartButton.Create(m_hWnd);
-
- /* Load the saved tray window settings */
- RegLoadSettings();
-
- /* Create and initialize the start menu */
- HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance,
MAKEINTRESOURCEW(IDB_STARTMENU));
- m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
-
- /* Load the tray band site */
- m_TrayBandSite = CreateTrayBandSite(this, &m_Rebar, &m_TaskSwitch);
- SetWindowTheme(m_Rebar, L"TaskBar", NULL);
-
- /* Create the tray notification window */
- m_TrayNotify = CreateTrayNotifyWnd(this, HideClock, &m_TrayNotifyInstance);
-
- if (UpdateNonClientMetrics())
- {
- SetWindowsFont();
- }
-
- /* Move the tray window to the right position and resize it if neccessary */
- CheckTrayWndPosition();
-
- /* Align all controls on the tray window */
- AlignControls(NULL);
-
- InitShellServices(&m_ShellServices);
-
- if (AutoHide)
- {
- m_AutoHideState = AUTOHIDE_HIDING;
- SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
- }
-
- RegisterHotKey(m_hWnd, IDHK_RUN, MOD_WIN, 'R');
- RegisterHotKey(m_hWnd, IDHK_MINIMIZE_ALL, MOD_WIN, 'M');
- RegisterHotKey(m_hWnd, IDHK_RESTORE_ALL, MOD_WIN|MOD_SHIFT, 'M');
- RegisterHotKey(m_hWnd, IDHK_HELP, MOD_WIN, VK_F1);
- RegisterHotKey(m_hWnd, IDHK_EXPLORE, MOD_WIN, 'E');
- RegisterHotKey(m_hWnd, IDHK_FIND, MOD_WIN, 'F');
- RegisterHotKey(m_hWnd, IDHK_FIND_COMPUTER, MOD_WIN|MOD_CONTROL, 'F');
- RegisterHotKey(m_hWnd, IDHK_NEXT_TASK, MOD_WIN, VK_TAB);
- RegisterHotKey(m_hWnd, IDHK_PREV_TASK, MOD_WIN|MOD_SHIFT, VK_TAB);
- RegisterHotKey(m_hWnd, IDHK_SYS_PROPERTIES, MOD_WIN, VK_PAUSE);
- RegisterHotKey(m_hWnd, IDHK_DESKTOP, MOD_WIN, 'D');
- RegisterHotKey(m_hWnd, IDHK_PAGER, MOD_WIN, 'B');
-
- return TRUE;
- }
-
- HRESULT STDMETHODCALLTYPE Open()
- {
- RECT rcWnd;
-
- /* Check if there's already a window created and try to show it.
- If it was somehow destroyed just create a new tray window. */
- if (m_hWnd != NULL && IsWindow())
- {
- if (!IsWindowVisible())
- {
- CheckTrayWndPosition();
-
- ShowWindow(SW_SHOW);
- }
-
- return S_OK;
- }
-
- DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
- if (AlwaysOnTop)
- dwExStyle |= WS_EX_TOPMOST;
-
- DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
- WS_BORDER | WS_THICKFRAME;
-
- ZeroMemory(&rcWnd, sizeof(rcWnd));
- if (m_Position != (DWORD) -1)
- rcWnd = m_TrayRects[m_Position];
-
- if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
- return E_FAIL;
-
- return S_OK;
- }
-
- HRESULT STDMETHODCALLTYPE Close()
- {
- if (m_hWnd != NULL)
- {
- SendMessage(m_hWnd,
- WM_APP_TRAYDESTROY,
- 0,
- 0);
- }
-
- return S_OK;
- }
-
- HWND STDMETHODCALLTYPE GetHWND()
- {
- return m_hWnd;
- }
-
- BOOL STDMETHODCALLTYPE IsSpecialHWND(IN HWND hWnd)
- {
- return (m_hWnd == hWnd ||
- (m_DesktopWnd != NULL && m_hWnd == m_DesktopWnd));
- }
-
- BOOL STDMETHODCALLTYPE IsHorizontal()
- {
- return IsPosHorizontal();
- }
-
- HFONT STDMETHODCALLTYPE GetCaptionFonts(OUT HFONT *phBoldCaption OPTIONAL)
- {
- if (phBoldCaption != NULL)
- *phBoldCaption = m_StartButton.GetFont();
-
- return m_CaptionFont;
+ CloseHandle(CreateThread(NULL, 0, s_RunFileDlgThread, this, 0, NULL));
}
DWORD WINAPI TrayPropertiesThread()
@@ -1718,8 +678,6 @@
BOOL STDMETHODCALLTYPE ExecContextMenuCmd(IN UINT uiCmd)
{
- BOOL bHandled = TRUE;
-
switch (uiCmd)
{
case ID_SHELL_CMD_PROPERTIES:
@@ -1775,185 +733,1049 @@
default:
TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command
ID!\n", uiCmd);
- bHandled = FALSE;
- break;
- }
-
- return bHandled;
- }
-
- BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
- {
- BOOL bPrevLock = Locked;
-
- if (Locked != bLock)
- {
- Locked = bLock;
-
- if (m_TrayBandSite != NULL)
- {
- if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ LRESULT HandleHotKey(DWORD id)
+ {
+ switch (id)
+ {
+ case IDHK_RUN:
+ DisplayRunFileDlg();
+ break;
+ case IDHK_HELP:
+ ExecResourceCmd(IDS_HELP_COMMAND);
+ break;
+ case IDHK_EXPLORE:
+ //FIXME: We don't support this yet:
+ //ShellExecuteW(0, L"explore", NULL, NULL, NULL, 1);
+ ShellExecuteW(0, NULL, L"explorer.exe", NULL, NULL, 1);
+ break;
+ case IDHK_FIND:
+ SHFindFiles(NULL, NULL);
+ break;
+ case IDHK_FIND_COMPUTER:
+ SHFindComputer(NULL, NULL);
+ break;
+ case IDHK_SYS_PROPERTIES:
+ //FIXME: Use SHRunControlPanel
+ ShellExecuteW(m_hWnd, NULL, L"sysdm.cpl", NULL, NULL, SW_NORMAL);
+ break;
+ case IDHK_NEXT_TASK:
+ break;
+ case IDHK_PREV_TASK:
+ break;
+ case IDHK_MINIMIZE_ALL:
+ break;
+ case IDHK_RESTORE_ALL:
+ break;
+ case IDHK_DESKTOP:
+ break;
+ case IDHK_PAGER:
+ break;
+ }
+
+ return 0;
+ }
+
+ LRESULT HandleCommand(UINT uCommand)
+ {
+ switch (uCommand)
+ {
+ case IDM_TASKBARANDSTARTMENU:
+ DisplayProperties();
+ break;
+
+ case IDM_SEARCH:
+ SHFindFiles(NULL, NULL);
+ break;
+
+ case IDM_HELPANDSUPPORT:
+ ExecResourceCmd(IDS_HELP_COMMAND);
+ break;
+
+ case IDM_RUN:
+ DisplayRunFileDlg();
+ break;
+
+ /* FIXME: Handle these commands as well */
+ case IDM_SYNCHRONIZE:
+ case IDM_DISCONNECT:
+ case IDM_UNDOCKCOMPUTER:
+ break;
+
+ case IDM_LOGOFF:
+ LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way as
DoExitWindows?
+ break;
+
+ case IDM_SHUTDOWN:
+ DoExitWindows();
+ break;
+ }
+
+ return FALSE;
+ }
+
+
+ UINT TrackMenu(
+ IN HMENU hMenu,
+ IN POINT *ppt OPTIONAL,
+ IN HWND hwndExclude OPTIONAL,
+ IN BOOL TrackUp,
+ IN BOOL IsContextMenu)
+ {
+ TPMPARAMS tmp, *ptmp = NULL;
+ POINT pt;
+ UINT cmdId;
+ UINT fuFlags;
+
+ if (hwndExclude != NULL)
+ {
+ /* Get the client rectangle and map it to screen coordinates */
+ if (::GetClientRect(hwndExclude,
+ &tmp.rcExclude) &&
+ ::MapWindowPoints(hwndExclude,
+ NULL,
+ (LPPOINT) &tmp.rcExclude,
+ 2) != 0)
+ {
+ ptmp = &tmp;
+ }
+ }
+
+ if (ppt == NULL)
+ {
+ if (ptmp == NULL &&
+ GetClientRect(&tmp.rcExclude) &&
+ MapWindowPoints(
+ NULL,
+ (LPPOINT) &tmp.rcExclude,
+ 2) != 0)
+ {
+ ptmp = &tmp;
+ }
+
+ if (ptmp != NULL)
+ {
+ /* NOTE: TrackPopupMenuEx will eventually align the track position
+ for us, no need to take care of it here as long as the
+ coordinates are somewhere within the exclusion rectangle */
+ pt.x = ptmp->rcExclude.left;
+ pt.y = ptmp->rcExclude.top;
+ }
+ else
+ pt.x = pt.y = 0;
+ }
+ else
+ pt = *ppt;
+
+ tmp.cbSize = sizeof(tmp);
+
+ fuFlags = TPM_RETURNCMD | TPM_VERTICAL;
+ fuFlags |= (TrackUp ? TPM_BOTTOMALIGN : TPM_TOPALIGN);
+ if (IsContextMenu)
+ fuFlags |= TPM_RIGHTBUTTON;
+ else
+ fuFlags |= (TrackUp ? TPM_VERNEGANIMATION : TPM_VERPOSANIMATION);
+
+ cmdId = TrackPopupMenuEx(hMenu,
+ fuFlags,
+ pt.x,
+ pt.y,
+ m_hWnd,
+ ptmp);
+
+ return cmdId;
+ }
+
+ HRESULT TrackCtxMenu(
+ IN IContextMenu * contextMenu,
+ IN POINT *ppt OPTIONAL,
+ IN HWND hwndExclude OPTIONAL,
+ IN BOOL TrackUp,
+ IN PVOID Context OPTIONAL)
+ {
+ INT x = ppt->x;
+ INT y = ppt->y;
+ HRESULT hr;
+ UINT uCommand;
+ HMENU popup = CreatePopupMenu();
+
+ if (popup == NULL)
+ return E_FAIL;
+
+ TRACE("Before Query\n");
+ hr = contextMenu->QueryContextMenu(popup, 0, 0, UINT_MAX, CMF_NORMAL);
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ TRACE("Query failed\n");
+ DestroyMenu(popup);
+ return hr;
+ }
+
+ TRACE("Before Tracking\n");
+ uCommand = ::TrackPopupMenuEx(popup, TPM_RETURNCMD, x, y, m_hWnd, NULL);
+
+ if (uCommand != 0)
+ {
+ TRACE("Before InvokeCommand\n");
+ CMINVOKECOMMANDINFO cmi = { 0 };
+ cmi.cbSize = sizeof(cmi);
+ cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+ cmi.hwnd = m_hWnd;
+ hr = contextMenu->InvokeCommand(&cmi);
+ }
+ else
+ {
+ TRACE("TrackPopupMenu failed. Code=%d, LastError=%d\n", uCommand,
GetLastError());
+ hr = S_FALSE;
+ }
+
+ DestroyMenu(popup);
+ return hr;
+ }
+
+
+
+
+
+ /**********************************************************
+ * ##### moving and sizing handling #####
+ */
+
+ BOOL UpdateNonClientMetrics()
+ {
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = sizeof(ncm);
+ if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
+ {
+ if (m_Font != NULL)
+ DeleteObject(m_Font);
+
+ m_Font = CreateFontIndirect(&ncm.lfMessageFont);
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ VOID SetWindowsFont()
+ {
+ if (m_TrayNotify != NULL)
+ {
+ SendMessage(m_TrayNotify, WM_SETFONT, (WPARAM) m_Font, TRUE);
+ }
+ }
+
+ HMONITOR GetScreenRectFromRect(
+ IN OUT RECT *pRect,
+ IN DWORD dwFlags)
+ {
+ MONITORINFO mi;
+ HMONITOR hMon;
+
+ mi.cbSize = sizeof(mi);
+ hMon = MonitorFromRect(pRect, dwFlags);
+ if (hMon != NULL &&
+ GetMonitorInfo(hMon, &mi))
+ {
+ *pRect = mi.rcMonitor;
+ }
+ else
+ {
+ pRect->left = 0;
+ pRect->top = 0;
+ pRect->right = GetSystemMetrics(SM_CXSCREEN);
+ pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
+
+ hMon = NULL;
+ }
+
+ return hMon;
+ }
+
+ HMONITOR GetMonitorFromRect(
+ IN const RECT *pRect)
+ {
+ HMONITOR hMon;
+
+ /* In case the monitor sizes or saved sizes differ a bit (probably
+ not a lot, only so the tray window overlaps into another monitor
+ now), minimize the risk that we determine a wrong monitor by
+ using the center point of the tray window if we can't determine
+ it using the rectangle. */
+ hMon = MonitorFromRect(pRect, MONITOR_DEFAULTTONULL);
+ if (hMon == NULL)
+ {
+ POINT pt;
+
+ pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
+ pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
+
+ /* be less error-prone, find the nearest monitor */
+ hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+ }
+
+ return hMon;
+ }
+
+ HMONITOR GetScreenRect(
+ IN HMONITOR hMonitor,
+ IN OUT RECT *pRect)
+ {
+ HMONITOR hMon = NULL;
+
+ if (hMonitor != NULL)
+ {
+ MONITORINFO mi;
+
+ mi.cbSize = sizeof(mi);
+ if (!GetMonitorInfo(hMonitor, &mi))
+ {
+ /* Hm, the monitor is gone? Try to find a monitor where it
+ could be located now */
+ hMon = GetMonitorFromRect(pRect);
+ if (hMon == NULL ||
+ !GetMonitorInfo(hMon, &mi))
{
- /* Reset?? */
- Locked = bPrevLock;
- return bPrevLock;
+ hMon = NULL;
+ goto GetPrimaryRect;
}
}
- if (Locked && m_Theme)
- {
- SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
+ *pRect = mi.rcMonitor;
+ }
+ else
+ {
+GetPrimaryRect:
+ pRect->left = 0;
+ pRect->top = 0;
+ pRect->right = GetSystemMetrics(SM_CXSCREEN);
+ pRect->bottom = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ return hMon;
+ }
+
+ VOID MakeTrayRectWithSize(IN DWORD Position,
+ IN const SIZE *pTraySize,
+ IN OUT RECT *pRect)
+ {
+ switch (Position)
+ {
+ case ABE_LEFT:
+ pRect->right = pRect->left + pTraySize->cx;
+ break;
+
+ case ABE_TOP:
+ pRect->bottom = pRect->top + pTraySize->cy;
+ break;
+
+ case ABE_RIGHT:
+ pRect->left = pRect->right - pTraySize->cx;
+ break;
+
+ case ABE_BOTTOM:
+ default:
+ pRect->top = pRect->bottom - pTraySize->cy;
+ break;
+ }
+ }
+
+ VOID GetTrayRectFromScreenRect(IN DWORD Position,
+ IN const RECT *pScreen,
+ IN const SIZE *pTraySize OPTIONAL,
+ OUT RECT *pRect)
+ {
+ if (pTraySize == NULL)
+ pTraySize = &m_TraySize;
+
+ *pRect = *pScreen;
+
+ /* Move the border outside of the screen */
+ InflateRect(pRect,
+ GetSystemMetrics(SM_CXEDGE),
+ GetSystemMetrics(SM_CYEDGE));
+
+ MakeTrayRectWithSize(Position, pTraySize, pRect);
+ }
+
+ BOOL IsPosHorizontal()
+ {
+ return m_Position == ABE_TOP || m_Position == ABE_BOTTOM;
+ }
+
+ HMONITOR CalculateValidSize(
+ IN DWORD Position,
+ IN OUT RECT *pRect)
+ {
+ RECT rcScreen;
+ //BOOL Horizontal;
+ HMONITOR hMon;
+ SIZE szMax, szWnd;
+
+ //Horizontal = IsPosHorizontal();
+
+ szWnd.cx = pRect->right - pRect->left;
+ szWnd.cy = pRect->bottom - pRect->top;
+
+ rcScreen = *pRect;
+ hMon = GetScreenRectFromRect(
+ &rcScreen,
+ MONITOR_DEFAULTTONEAREST);
+
+ /* Calculate the maximum size of the tray window and limit the window
+ size to half of the screen's size. */
+ szMax.cx = (rcScreen.right - rcScreen.left) / 2;
+ szMax.cy = (rcScreen.bottom - rcScreen.top) / 2;
+ if (szWnd.cx > szMax.cx)
+ szWnd.cx = szMax.cx;
+ if (szWnd.cy > szMax.cy)
+ szWnd.cy = szMax.cy;
+
+ /* FIXME - calculate */
+
+ GetTrayRectFromScreenRect(Position,
+ &rcScreen,
+ &szWnd,
+ pRect);
+
+ return hMon;
+ }
+
+#if 0
+ VOID
+ GetMinimumWindowSize(
+ OUT RECT *pRect)
+ {
+ RECT rcMin = {0};
+
+ AdjustWindowRectEx(&rcMin,
+ GetWindowLong(m_hWnd,
+ GWL_STYLE),
+ FALSE,
+ GetWindowLong(m_hWnd,
+ GWL_EXSTYLE));
+
+ *pRect = rcMin;
+ }
+#endif
+
+
+ DWORD GetDraggingRectFromPt(
+ IN POINT pt,
+ OUT RECT *pRect,
+ OUT HMONITOR *phMonitor)
+ {
+ HMONITOR hMon, hMonNew;
+ DWORD PosH, PosV, Pos;
+ SIZE DeltaPt, ScreenOffset;
+ RECT rcScreen;
+
+ rcScreen.left = 0;
+ rcScreen.top = 0;
+
+ /* Determine the screen rectangle */
+ hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
+ if (hMon != NULL)
+ {
+ MONITORINFO mi;
+
+ mi.cbSize = sizeof(mi);
+ if (!GetMonitorInfo(hMon, &mi))
+ {
+ hMon = NULL;
+ goto GetPrimaryScreenRect;
+ }
+
+ /* make left top corner of the screen zero based to
+ make calculations easier */
+ pt.x -= mi.rcMonitor.left;
+ pt.y -= mi.rcMonitor.top;
+
+ ScreenOffset.cx = mi.rcMonitor.left;
+ ScreenOffset.cy = mi.rcMonitor.top;
+ rcScreen.right = mi.rcMonitor.right - mi.rcMonitor.left;
+ rcScreen.bottom = mi.rcMonitor.bottom - mi.rcMonitor.top;
+ }
+ else
+ {
+GetPrimaryScreenRect:
+ ScreenOffset.cx = 0;
+ ScreenOffset.cy = 0;
+ rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
+ rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ /* Calculate the nearest screen border */
+ if (pt.x < rcScreen.right / 2)
+ {
+ DeltaPt.cx = pt.x;
+ PosH = ABE_LEFT;
+ }
+ else
+ {
+ DeltaPt.cx = rcScreen.right - pt.x;
+ PosH = ABE_RIGHT;
+ }
+
+ if (pt.y < rcScreen.bottom / 2)
+ {
+ DeltaPt.cy = pt.y;
+ PosV = ABE_TOP;
+ }
+ else
+ {
+ DeltaPt.cy = rcScreen.bottom - pt.y;
+ PosV = ABE_BOTTOM;
+ }
+
+ Pos = (DeltaPt.cx * rcScreen.bottom < DeltaPt.cy * rcScreen.right) ? PosH :
PosV;
+
+ /* Fix the screen origin to be relative to the primary monitor again */
+ OffsetRect(&rcScreen,
+ ScreenOffset.cx,
+ ScreenOffset.cy);
+
+ RECT rcPos = m_TrayRects[Pos];
+
+ hMonNew = GetMonitorFromRect(&rcPos);
+ if (hMon != hMonNew)
+ {
+ SIZE szTray;
+
+ /* Recalculate the rectangle, we're dragging to another monitor.
+ We don't need to recalculate the rect on single monitor systems. */
+ szTray.cx = rcPos.right - rcPos.left;
+ szTray.cy = rcPos.bottom - rcPos.top;
+
+ GetTrayRectFromScreenRect(Pos, &rcScreen, &szTray, pRect);
+ if (AutoHide)
+ {
+ pRect->left += m_AutoHideOffset.cx;
+ pRect->right += m_AutoHideOffset.cx;
+ pRect->top += m_AutoHideOffset.cy;
+ pRect->bottom += m_AutoHideOffset.cy;
+ }
+ hMon = hMonNew;
+ }
+ else
+ {
+ /* The user is dragging the tray window on the same monitor. We don't
need
+ to recalculate the rectangle */
+ *pRect = rcPos;
+ if (AutoHide)
+ {
+ pRect->left += m_AutoHideOffset.cx;
+ pRect->right += m_AutoHideOffset.cx;
+ pRect->top += m_AutoHideOffset.cy;
+ pRect->bottom += m_AutoHideOffset.cy;
+ }
+ }
+
+ *phMonitor = hMon;
+
+ return Pos;
+ }
+
+ DWORD GetDraggingRectFromRect(
+ IN OUT RECT *pRect,
+ OUT HMONITOR *phMonitor)
+ {
+ POINT pt;
+
+ /* Calculate the center of the rectangle. We call
+ GetDraggingRectFromPt to calculate a valid
+ dragging rectangle */
+ pt.x = pRect->left + ((pRect->right - pRect->left) / 2);
+ pt.y = pRect->top + ((pRect->bottom - pRect->top) / 2);
+
+ return GetDraggingRectFromPt(
+ pt,
+ pRect,
+ phMonitor);
+ }
+
+ VOID ChangingWinPos(IN OUT LPWINDOWPOS pwp)
+ {
+ RECT rcTray;
+
+ if (IsDragging)
+ {
+ rcTray.left = pwp->x;
+ rcTray.top = pwp->y;
+ rcTray.right = rcTray.left + pwp->cx;
+ rcTray.bottom = rcTray.top + pwp->cy;
+ if (AutoHide)
+ {
+ rcTray.left -= m_AutoHideOffset.cx;
+ rcTray.right -= m_AutoHideOffset.cx;
+ rcTray.top -= m_AutoHideOffset.cy;
+ rcTray.bottom -= m_AutoHideOffset.cy;
+ }
+
+ if (!EqualRect(&rcTray,
+ &m_TrayRects[m_DraggingPosition]))
+ {
+ /* Recalculate the rectangle, the user dragged the tray
+ window to another monitor or the window was somehow else
+ moved or resized */
+ m_DraggingPosition = GetDraggingRectFromRect(
+ &rcTray,
+ &m_DraggingMonitor);
+ //m_TrayRects[DraggingPosition] = rcTray;
+ }
+
+ //Monitor = CalculateValidSize(DraggingPosition,
+ // &rcTray);
+
+ m_Monitor = m_DraggingMonitor;
+ m_Position = m_DraggingPosition;
+ IsDragging = FALSE;
+
+ m_TrayRects[m_Position] = rcTray;
+ goto ChangePos;
+ }
+ else if (GetWindowRect(&rcTray))
+ {
+ if (InSizeMove)
+ {
+ if (!(pwp->flags & SWP_NOMOVE))
+ {
+ rcTray.left = pwp->x;
+ rcTray.top = pwp->y;
+ }
+
+ if (!(pwp->flags & SWP_NOSIZE))
+ {
+ rcTray.right = rcTray.left + pwp->cx;
+ rcTray.bottom = rcTray.top + pwp->cy;
+ }
+
+ m_Position = GetDraggingRectFromRect(&rcTray, &m_Monitor);
+
+ if (!(pwp->flags & (SWP_NOMOVE | SWP_NOSIZE)))
+ {
+ SIZE szWnd;
+
+ szWnd.cx = pwp->cx;
+ szWnd.cy = pwp->cy;
+
+ MakeTrayRectWithSize(m_Position, &szWnd, &rcTray);
+ }
+
+ if (AutoHide)
+ {
+ rcTray.left -= m_AutoHideOffset.cx;
+ rcTray.right -= m_AutoHideOffset.cx;
+ rcTray.top -= m_AutoHideOffset.cy;
+ rcTray.bottom -= m_AutoHideOffset.cy;
+ }
+ m_TrayRects[m_Position] = rcTray;
}
else
{
- SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME |
WS_BORDER);
- }
- SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE
| SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
-
- }
-
- return bPrevLock;
- }
-
-
- LRESULT DrawBackground(HDC hdc)
- {
- RECT rect;
- int partId;
- HRESULT res;
-
- GetClientRect(&rect);
-
- if (m_Theme)
- {
- GetClientRect(&rect);
+ /* If the user isn't resizing the tray window we need to make sure
the
+ new size or position is valid. this is to prevent changes to the
window
+ without user interaction. */
+ rcTray = m_TrayRects[m_Position];
+ }
+
+ChangePos:
+ m_TraySize.cx = rcTray.right - rcTray.left;
+ m_TraySize.cy = rcTray.bottom - rcTray.top;
+
+ if (AutoHide)
+ {
+ rcTray.left += m_AutoHideOffset.cx;
+ rcTray.right += m_AutoHideOffset.cx;
+ rcTray.top += m_AutoHideOffset.cy;
+ rcTray.bottom += m_AutoHideOffset.cy;
+ }
+
+ pwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
+ pwp->x = rcTray.left;
+ pwp->y = rcTray.top;
+ pwp->cx = m_TraySize.cx;
+ pwp->cy = m_TraySize.cy;
+ }
+ }
+
+ VOID ApplyClipping(IN BOOL Clip)
+ {
+ RECT rcClip, rcWindow;
+ HRGN hClipRgn;
+
+ if (GetWindowRect(&rcWindow))
+ {
+ /* Disable clipping on systems with only one monitor */
+ if (GetSystemMetrics(SM_CMONITORS) <= 1)
+ Clip = FALSE;
+
+ if (Clip)
+ {
+ rcClip = rcWindow;
+
+ GetScreenRect(m_Monitor, &rcClip);
+
+ if (!IntersectRect(&rcClip, &rcClip, &rcWindow))
+ {
+ rcClip = rcWindow;
+ }
+
+ OffsetRect(&rcClip,
+ -rcWindow.left,
+ -rcWindow.top);
+
+ hClipRgn = CreateRectRgnIndirect(&rcClip);
+ }
+ else
+ hClipRgn = NULL;
+
+ /* Set the clipping region or make sure the window isn't clipped
+ by disabling it explicitly. */
+ SetWindowRgn(hClipRgn, TRUE);
+ }
+ }
+
+ VOID ResizeWorkArea()
+ {
+#if !WIN7_DEBUG_MODE
+ RECT rcTray, rcWorkArea;
+
+ /* If monitor has changed then fix the previous monitors work area */
+ if (m_PreviousMonitor != m_Monitor)
+ {
+ GetScreenRect(m_PreviousMonitor, &rcWorkArea);
+ SystemParametersInfoW(SPI_SETWORKAREA,
+ 1,
+ &rcWorkArea,
+ SPIF_SENDCHANGE);
+ }
+
+ rcTray = m_TrayRects[m_Position];
+
+ GetScreenRect(m_Monitor, &rcWorkArea);
+ m_PreviousMonitor = m_Monitor;
+
+ /* If AutoHide is false then change the workarea to exclude
+ the area that the taskbar covers. */
+ if (!AutoHide)
+ {
switch (m_Position)
{
+ case ABE_TOP:
+ rcWorkArea.top = rcTray.bottom;
+ break;
case ABE_LEFT:
- partId = TBP_BACKGROUNDLEFT;
- break;
- case ABE_TOP:
- partId = TBP_BACKGROUNDTOP;
+ rcWorkArea.left = rcTray.right;
break;
case ABE_RIGHT:
- partId = TBP_BACKGROUNDRIGHT;
+ rcWorkArea.right = rcTray.left;
break;
case ABE_BOTTOM:
- default:
- partId = TBP_BACKGROUNDBOTTOM;
+ rcWorkArea.bottom = rcTray.top;
break;
}
- res = DrawThemeBackground(m_Theme, hdc, partId, 0, &rect, 0);
- }
-
- return res;
- }
-
- LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled)
- {
- HDC hdc = (HDC) wParam;
-
- if (!m_Theme)
- {
- bHandled = FALSE;
- return 0;
- }
-
- return DrawBackground(hdc);
- }
-
- int DrawSizer(IN HRGN hRgn)
- {
- HDC hdc;
- RECT rect;
- int backoundPart;
-
- GetWindowRect(&rect);
- OffsetRect(&rect, -rect.left, -rect.top);
-
- hdc = GetDCEx(hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_PARENTCLIP);
-
- switch (m_Position)
- {
- case ABE_LEFT:
- backoundPart = TBP_SIZINGBARLEFT;
- rect.left = rect.right - GetSystemMetrics(SM_CXSIZEFRAME);
- break;
- case ABE_TOP:
- backoundPart = TBP_SIZINGBARTOP;
- rect.top = rect.bottom - GetSystemMetrics(SM_CYSIZEFRAME);
- break;
- case ABE_RIGHT:
- backoundPart = TBP_SIZINGBARRIGHT;
- rect.right = rect.left + GetSystemMetrics(SM_CXSIZEFRAME);
- break;
- case ABE_BOTTOM:
- default:
- backoundPart = TBP_SIZINGBARBOTTOM;
- rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZEFRAME);
- break;
- }
- if (IsThemeBackgroundPartiallyTransparent(m_Theme, backoundPart, 0))
- {
- DrawThemeParentBackground(m_hWnd, hdc, &rect);
- }
- DrawThemeBackground(m_Theme, hdc, backoundPart, 0, &rect, 0);
-
- ReleaseDC(hdc);
- return 0;
- }
-
- DWORD WINAPI RunFileDlgThread()
- {
- HWND hwnd;
- RECT posRect;
-
- m_StartButton.GetWindowRect(&posRect);
-
- hwnd = CreateWindowEx(0,
- WC_STATIC,
- NULL,
- WS_OVERLAPPED | WS_DISABLED | WS_CLIPSIBLINGS | WS_BORDER |
SS_LEFT,
- posRect.left,
- posRect.top,
- posRect.right - posRect.left,
- posRect.bottom - posRect.top,
- NULL,
- NULL,
- NULL,
- NULL);
-
- m_RunFileDlgOwner = hwnd;
-
- RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
-
- m_RunFileDlgOwner = NULL;
- ::DestroyWindow(hwnd);
-
- return 0;
- }
-
- static DWORD WINAPI s_RunFileDlgThread(IN OUT PVOID pParam)
- {
- CTrayWindow * This = (CTrayWindow*) pParam;
- return This->RunFileDlgThread();
- }
-
- void DisplayRunFileDlg()
- {
- HWND hRunDlg;
- if (m_RunFileDlgOwner)
- {
- hRunDlg = ::GetLastActivePopup(m_RunFileDlgOwner);
- if (hRunDlg != NULL &&
- hRunDlg != m_RunFileDlgOwner)
- {
- SetForegroundWindow(hRunDlg);
+ }
+
+ /*
+ * Resize the current monitor work area. Win32k will also send
+ * a WM_SIZE message to automatically resize the desktop.
+ */
+ SystemParametersInfoW(SPI_SETWORKAREA,
+ 1,
+ &rcWorkArea,
+ SPIF_SENDCHANGE);
+#endif
+ }
+
+ VOID CheckTrayWndPosition()
+ {
+ RECT rcTray;
+
+ rcTray = m_TrayRects[m_Position];
+
+ if (AutoHide)
+ {
+ rcTray.left += m_AutoHideOffset.cx;
+ rcTray.right += m_AutoHideOffset.cx;
+ rcTray.top += m_AutoHideOffset.cy;
+ rcTray.bottom += m_AutoHideOffset.cy;
+ }
+
+ /* Move the tray window */
+ SetWindowPos(NULL,
+ rcTray.left,
+ rcTray.top,
+ rcTray.right - rcTray.left,
+ rcTray.bottom - rcTray.top,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+
+ ResizeWorkArea();
+
+ ApplyClipping(TRUE);
+ }
+
+ typedef struct _TW_STUCKRECTS2
+ {
+ DWORD cbSize;
+ LONG Unknown;
+ DWORD dwFlags;
+ DWORD Position;
+ SIZE Size;
+ RECT Rect;
+ } TW_STRUCKRECTS2, *PTW_STUCKRECTS2;
+
+ VOID RegLoadSettings()
+ {
+ DWORD Pos;
+ TW_STRUCKRECTS2 sr;
+ RECT rcScreen;
+ SIZE WndSize, EdgeSize, DlgFrameSize;
+ DWORD cbSize = sizeof(sr);
+ SIZE StartBtnSize = m_StartButton.GetSize();
+
+ EdgeSize.cx = GetSystemMetrics(SM_CXEDGE);
+ EdgeSize.cy = GetSystemMetrics(SM_CYEDGE);
+ DlgFrameSize.cx = GetSystemMetrics(SM_CXDLGFRAME);
+ DlgFrameSize.cy = GetSystemMetrics(SM_CYDLGFRAME);
+
+ if (SHGetValue(hkExplorer,
+ TEXT("StuckRects2"),
+ TEXT("Settings"),
+ NULL,
+ &sr,
+ &cbSize) == ERROR_SUCCESS &&
+ sr.cbSize == sizeof(sr))
+ {
+ AutoHide = (sr.dwFlags & ABS_AUTOHIDE) != 0;
+ AlwaysOnTop = (sr.dwFlags & ABS_ALWAYSONTOP) != 0;
+ SmSmallIcons = (sr.dwFlags & 0x4) != 0;
+ HideClock = (sr.dwFlags & 0x8) != 0;
+
+ /* FIXME: Are there more flags? */
+
+#if WIN7_DEBUG_MODE
+ m_Position = ABE_LEFT;
+#else
+ if (sr.Position > ABE_BOTTOM)
+ m_Position = ABE_BOTTOM;
+ else
+ m_Position = sr.Position;
+#endif
+
+ /* Try to find out which monitor the tray window was located on last.
+ Here we're only interested in the monitor screen that we think
+ is the last one used. We're going to determine on which monitor
+ we really are after calculating the docked position. */
+ rcScreen = sr.Rect;
+ GetScreenRectFromRect(
+ &rcScreen,
+ MONITOR_DEFAULTTONEAREST);
+ }
+ else
+ {
+ m_Position = ABE_BOTTOM;
+ AlwaysOnTop = TRUE;
+
+ /* Use the minimum size of the taskbar, we'll use the start
+ button as a minimum for now. Make sure we calculate the
+ entire window size, not just the client size. However, we
+ use a thinner border than a standard thick border, so that
+ the start button and bands are not stuck to the screen border. */
+ sr.Size.cx = StartBtnSize.cx + (2 * (EdgeSize.cx + DlgFrameSize.cx));
+ sr.Size.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
+
+ /* Use the primary screen by default */
+ rcScreen.left = 0;
+ rcScreen.top = 0;
+ rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
+ rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
+ GetScreenRectFromRect(
+ &rcScreen,
+ MONITOR_DEFAULTTOPRIMARY);
+ }
+
+ if (m_hWnd != NULL)
+ SetWindowPos(
+ AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
+ 0,
+ 0,
+ 0,
+ 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+ /* Determine a minimum tray window rectangle. The "client" height is
+ zero here since we cannot determine an optimal minimum width when
+ loaded as a vertical tray window. We just need to make sure the values
+ loaded from the registry are at least. The windows explorer behaves
+ the same way, it allows the user to save a zero width vertical tray
+ window, but not a zero height horizontal tray window. */
+ WndSize.cx = 2 * (EdgeSize.cx + DlgFrameSize.cx);
+ WndSize.cy = StartBtnSize.cy + (2 * (EdgeSize.cy + DlgFrameSize.cy));
+
+ if (WndSize.cx < sr.Size.cx)
+ WndSize.cx = sr.Size.cx;
+ if (WndSize.cy < sr.Size.cy)
+ WndSize.cy = sr.Size.cy;
+
+ /* Save the calculated size */
+ m_TraySize = WndSize;
+
+ /* Calculate all docking rectangles. We need to do this here so they're
+ initialized and dragging the tray window to another position gives
+ usable results */
+ for (Pos = ABE_LEFT; Pos <= ABE_BOTTOM; Pos++)
+ {
+ GetTrayRectFromScreenRect(Pos,
+ &rcScreen,
+ &m_TraySize,
+ &m_TrayRects[Pos]);
+ // 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);
+ }
+
+ /* Determine which monitor we are on. It shouldn't matter which docked
+ position rectangle we use */
+ m_Monitor = GetMonitorFromRect(&m_TrayRects[ABE_LEFT]);
+ }
+
+ VOID AlignControls(IN PRECT prcClient OPTIONAL)
+ {
+ RECT rcClient;
+ SIZE TraySize, StartSize;
+ POINT ptTrayNotify = { 0, 0 };
+ BOOL Horizontal;
+ HDWP dwp;
+
+ m_StartButton.UpdateSize();
+ if (prcClient != NULL)
+ {
+ rcClient = *prcClient;
+ }
+ else
+ {
+ if (!GetClientRect(&rcClient))
+ {
+ ERR("Could not get client rect lastErr=%d\n", GetLastError());
return;
}
}
- CloseHandle(CreateThread(NULL, 0, s_RunFileDlgThread, this, 0, NULL));
+ Horizontal = IsPosHorizontal();
+
+ /* We're about to resize/move the start button, the rebar control and
+ the tray notification control */
+ dwp = BeginDeferWindowPos(3);
+ if (dwp == NULL)
+ {
+ ERR("BeginDeferWindowPos failed. lastErr=%d\n", GetLastError());
+ return;
+ }
+
+ /* Limit the Start button width to the client width, if neccessary */
+ StartSize = m_StartButton.GetSize();
+ if (StartSize.cx > rcClient.right)
+ StartSize.cx = rcClient.right;
+
+ if (m_StartButton.m_hWnd != NULL)
+ {
+ /* Resize and reposition the button */
+ dwp = m_StartButton.DeferWindowPos(dwp,
+ NULL,
+ 0,
+ 0,
+ StartSize.cx,
+ StartSize.cy,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ if (dwp == NULL)
+ {
+ ERR("DeferWindowPos for start button failed. lastErr=%d\n",
GetLastError());
+ return;
+ }
+ }
+
+ /* Determine the size that the tray notification window needs */
+ if (Horizontal)
+ {
+ TraySize.cx = 0;
+ TraySize.cy = rcClient.bottom;
+ }
+ else
+ {
+ TraySize.cx = rcClient.right;
+ TraySize.cy = 0;
+ }
+
+ if (m_TrayNotify != NULL &&
+ SendMessage(m_TrayNotify,
+ TNWM_GETMINIMUMSIZE,
+ (WPARAM)Horizontal,
+ (LPARAM)&TraySize))
+ {
+ /* Move the tray notification window to the desired location */
+ if (Horizontal)
+ ptTrayNotify.x = rcClient.right - TraySize.cx;
+ else
+ ptTrayNotify.y = rcClient.bottom - TraySize.cy;
+
+ dwp = ::DeferWindowPos(dwp,
+ m_TrayNotify,
+ NULL,
+ ptTrayNotify.x,
+ ptTrayNotify.y,
+ TraySize.cx,
+ TraySize.cy,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ if (dwp == NULL)
+ {
+ ERR("DeferWindowPos for notification area failed.
lastErr=%d\n", GetLastError());
+ return;
+ }
+ }
+
+ /* Resize/Move the rebar control */
+ if (m_Rebar != NULL)
+ {
+ POINT ptRebar = { 0, 0 };
+ SIZE szRebar;
+
+ SetWindowStyle(m_Rebar, CCS_VERT, Horizontal ? 0 : CCS_VERT);
+
+ if (Horizontal)
+ {
+ ptRebar.x = StartSize.cx + GetSystemMetrics(SM_CXSIZEFRAME);
+ szRebar.cx = ptTrayNotify.x - ptRebar.x;
+ szRebar.cy = rcClient.bottom;
+ }
+ else
+ {
+ ptRebar.y = StartSize.cy + GetSystemMetrics(SM_CYSIZEFRAME);
+ szRebar.cx = rcClient.right;
+ szRebar.cy = ptTrayNotify.y - ptRebar.y;
+ }
+
+ dwp = ::DeferWindowPos(dwp,
+ m_Rebar,
+ NULL,
+ ptRebar.x,
+ ptRebar.y,
+ szRebar.cx,
+ szRebar.cy,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+
+ if (dwp != NULL)
+ EndDeferWindowPos(dwp);
+
+ if (m_TaskSwitch != NULL)
+ {
+ /* Update the task switch window configuration */
+ SendMessage(m_TaskSwitch, TSWM_UPDATETASKBARPOS, 0, 0);
+ }
}
void PopupStartMenu()
@@ -2169,17 +1991,333 @@
SetWindowPos(NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
- LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
- {
+
+
+
+
+ /**********************************************************
+ * ##### taskbar drawing #####
+ */
+
+ LRESULT EraseBackgroundWithTheme(HDC hdc)
+ {
+ RECT rect;
+ int partId;
+ HRESULT res;
+
+ GetClientRect(&rect);
+
+ if (m_Theme)
+ {
+ GetClientRect(&rect);
+ switch (m_Position)
+ {
+ case ABE_LEFT:
+ partId = TBP_BACKGROUNDLEFT;
+ break;
+ case ABE_TOP:
+ partId = TBP_BACKGROUNDTOP;
+ break;
+ case ABE_RIGHT:
+ partId = TBP_BACKGROUNDRIGHT;
+ break;
+ case ABE_BOTTOM:
+ default:
+ partId = TBP_BACKGROUNDBOTTOM;
+ break;
+ }
+ res = DrawThemeBackground(m_Theme, hdc, partId, 0, &rect, 0);
+ }
+
+ return res;
+ }
+
+ int DrawSizerWithTheme(IN HRGN hRgn)
+ {
+ HDC hdc;
+ RECT rect;
+ int backoundPart;
+
+ GetWindowRect(&rect);
+ OffsetRect(&rect, -rect.left, -rect.top);
+
+ hdc = GetDCEx(hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_PARENTCLIP);
+
+ switch (m_Position)
+ {
+ case ABE_LEFT:
+ backoundPart = TBP_SIZINGBARLEFT;
+ rect.left = rect.right - GetSystemMetrics(SM_CXSIZEFRAME);
+ break;
+ case ABE_TOP:
+ backoundPart = TBP_SIZINGBARTOP;
+ rect.top = rect.bottom - GetSystemMetrics(SM_CYSIZEFRAME);
+ break;
+ case ABE_RIGHT:
+ backoundPart = TBP_SIZINGBARRIGHT;
+ rect.right = rect.left + GetSystemMetrics(SM_CXSIZEFRAME);
+ break;
+ case ABE_BOTTOM:
+ default:
+ backoundPart = TBP_SIZINGBARBOTTOM;
+ rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZEFRAME);
+ break;
+ }
+ if (IsThemeBackgroundPartiallyTransparent(m_Theme, backoundPart, 0))
+ {
+ DrawThemeParentBackground(m_hWnd, hdc, &rect);
+ }
+ DrawThemeBackground(m_Theme, hdc, backoundPart, 0, &rect, 0);
+
+ ReleaseDC(hdc);
+ return 0;
+ }
+
+
+
+
+
+ /*
+ * ITrayWindow
+ */
+ HRESULT STDMETHODCALLTYPE Open()
+ {
+ RECT rcWnd;
+
+ /* Check if there's already a window created and try to show it.
+ If it was somehow destroyed just create a new tray window. */
+ if (m_hWnd != NULL && IsWindow())
+ {
+ if (!IsWindowVisible())
+ {
+ CheckTrayWndPosition();
+
+ ShowWindow(SW_SHOW);
+ }
+
+ return S_OK;
+ }
+
+ DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE;
+ if (AlwaysOnTop)
+ dwExStyle |= WS_EX_TOPMOST;
+
+ DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
+ WS_BORDER | WS_THICKFRAME;
+
+ ZeroMemory(&rcWnd, sizeof(rcWnd));
+ if (m_Position != (DWORD) -1)
+ rcWnd = m_TrayRects[m_Position];
+
+ if (!Create(NULL, rcWnd, NULL, dwStyle, dwExStyle))
+ return E_FAIL;
+
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE Close()
+ {
+ if (m_hWnd != NULL)
+ {
+ SendMessage(m_hWnd,
+ WM_APP_TRAYDESTROY,
+ 0,
+ 0);
+ }
+
+ return S_OK;
+ }
+
+ HWND STDMETHODCALLTYPE GetHWND()
+ {
+ return m_hWnd;
+ }
+
+ BOOL STDMETHODCALLTYPE IsSpecialHWND(IN HWND hWnd)
+ {
+ return (m_hWnd == hWnd ||
+ (m_DesktopWnd != NULL && m_hWnd == m_DesktopWnd));
+ }
+
+ BOOL STDMETHODCALLTYPE IsHorizontal()
+ {
+ return IsPosHorizontal();
+ }
+
+ HFONT STDMETHODCALLTYPE GetCaptionFonts(OUT HFONT *phBoldCaption OPTIONAL)
+ {
+ if (phBoldCaption != NULL)
+ *phBoldCaption = m_StartButton.GetFont();
+
+ return m_CaptionFont;
+ }
+
+ BOOL STDMETHODCALLTYPE Lock(IN BOOL bLock)
+ {
+ BOOL bPrevLock = Locked;
+
+ if (Locked != bLock)
+ {
+ Locked = bLock;
+
+ if (m_TrayBandSite != NULL)
+ {
+ if (!SUCCEEDED(m_TrayBandSite->Lock(bLock)))
+ {
+ /* Reset?? */
+ Locked = bPrevLock;
+ return bPrevLock;
+ }
+ }
+
+ if (Locked && m_Theme)
+ {
+ SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
+ }
+ else
+ {
+ SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME |
WS_BORDER);
+ }
+ SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE
| SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+
+ }
+
+ return bPrevLock;
+ }
+
+
+
+
+
+
+ /**********************************************************
+ * ##### message handling #####
+ */
+
+ LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ ((ITrayWindow*)this)->AddRef();
+
+ SetWindowTheme(m_hWnd, L"TaskBar", NULL);
+
+ InterlockedIncrement(&TrayWndCount);
+
+ if (m_CaptionFont == NULL)
+ {
+ NONCLIENTMETRICS ncm;
+
+ /* Get the system fonts, we use the caption font,
+ always bold, though. */
+ ncm.cbSize = sizeof(ncm);
+ if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm,
FALSE))
+ {
+ if (m_CaptionFont == NULL)
+ {
+ ncm.lfCaptionFont.lfWeight = FW_NORMAL;
+ m_CaptionFont = CreateFontIndirect(&ncm.lfCaptionFont);
+ }
+ }
+ }
+
+ /* Create the Start button */
+ m_StartButton.Create(m_hWnd);
+
/* Load the saved tray window settings */
RegLoadSettings();
+ /* Create and initialize the start menu */
+ HBITMAP hbmBanner = LoadBitmapW(hExplorerInstance,
MAKEINTRESOURCEW(IDB_STARTMENU));
+ m_StartMenuPopup = CreateStartMenu(this, &m_StartMenuBand, hbmBanner, 0);
+
+ /* Load the tray band site */
+ m_TrayBandSite = CreateTrayBandSite(this, &m_Rebar, &m_TaskSwitch);
+ SetWindowTheme(m_Rebar, L"TaskBar", NULL);
+
+ /* Create the tray notification window */
+ m_TrayNotify = CreateTrayNotifyWnd(this, HideClock, &m_TrayNotifyInstance);
+
+ if (UpdateNonClientMetrics())
+ {
+ SetWindowsFont();
+ }
+
/* Move the tray window to the right position and resize it if neccessary */
CheckTrayWndPosition();
/* Align all controls on the tray window */
AlignControls(NULL);
+ InitShellServices(&m_ShellServices);
+
+ if (AutoHide)
+ {
+ m_AutoHideState = AUTOHIDE_HIDING;
+ SetTimer(TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
+ }
+
+ RegisterHotKey(m_hWnd, IDHK_RUN, MOD_WIN, 'R');
+ RegisterHotKey(m_hWnd, IDHK_MINIMIZE_ALL, MOD_WIN, 'M');
+ RegisterHotKey(m_hWnd, IDHK_RESTORE_ALL, MOD_WIN|MOD_SHIFT, 'M');
+ RegisterHotKey(m_hWnd, IDHK_HELP, MOD_WIN, VK_F1);
+ RegisterHotKey(m_hWnd, IDHK_EXPLORE, MOD_WIN, 'E');
+ RegisterHotKey(m_hWnd, IDHK_FIND, MOD_WIN, 'F');
+ RegisterHotKey(m_hWnd, IDHK_FIND_COMPUTER, MOD_WIN|MOD_CONTROL, 'F');
+ RegisterHotKey(m_hWnd, IDHK_NEXT_TASK, MOD_WIN, VK_TAB);
+ RegisterHotKey(m_hWnd, IDHK_PREV_TASK, MOD_WIN|MOD_SHIFT, VK_TAB);
+ RegisterHotKey(m_hWnd, IDHK_SYS_PROPERTIES, MOD_WIN, VK_PAUSE);
+ RegisterHotKey(m_hWnd, IDHK_DESKTOP, MOD_WIN, 'D');
+ RegisterHotKey(m_hWnd, IDHK_PAGER, MOD_WIN, 'B');
+
+ return TRUE;
+ }
+
+ LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ if (m_Theme)
+ CloseThemeData(m_Theme);
+
+ if (IsThemeActive())
+ m_Theme = OpenThemeData(m_hWnd, L"TaskBar");
+ else
+ m_Theme = NULL;
+
+ if (Locked && m_Theme)
+ {
+ SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, 0);
+ }
+ else
+ {
+ SetWindowStyle(m_hWnd, WS_THICKFRAME | WS_BORDER, WS_THICKFRAME |
WS_BORDER);
+ }
+ SetWindowPos(NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+
+ return TRUE;
+ }
+
+ LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled)
+ {
+ HDC hdc = (HDC) wParam;
+
+ if (!m_Theme)
+ {
+ bHandled = FALSE;
+ return 0;
+ }
+
+ return EraseBackgroundWithTheme(hdc);
+ }
+
+ LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ {
+ /* Load the saved tray window settings */
+ RegLoadSettings();
+
+ /* Move the tray window to the right position and resize it if neccessary */
+ CheckTrayWndPosition();
+
+ /* Align all controls on the tray window */
+ AlignControls(NULL);
+
return TRUE;
}
@@ -2201,7 +2339,7 @@
return 0;
}
- return DrawSizer((HRGN) wParam);
+ return DrawSizerWithTheme((HRGN) wParam);
}
LRESULT OnCtlColorBtn(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -2627,12 +2765,6 @@
return TRUE;
}
- LRESULT DoExitWindows()
- {
- ExitWindowsDialog(m_hWnd);
- return 0;
- }
-
LRESULT OnDoExitWindows(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
/*
@@ -2654,70 +2786,9 @@
return TRUE;
}
- HRESULT ExecResourceCmd(int id)
- {
- WCHAR szCommand[256];
- WCHAR *pszParameters;
-
- if (!LoadStringW(hExplorerInstance,
- id,
- szCommand,
- _countof(szCommand)))
- {
- return E_FAIL;
- }
-
- pszParameters = wcschr(szCommand, L'>');
- if (pszParameters)
- {
- *pszParameters = 0;
- pszParameters++;
- }
-
- ShellExecuteW(m_hWnd, NULL, szCommand, pszParameters, NULL, SW_SHOWNORMAL);
- return S_OK;
- }
-
LRESULT OnHotkey(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
- switch (wParam)
- {
- case IDHK_RUN:
- DisplayRunFileDlg();
- break;
- case IDHK_HELP:
- ExecResourceCmd(IDS_HELP_COMMAND);
- break;
- case IDHK_EXPLORE:
- //FIXME: We don't support this yet:
- //ShellExecuteW(0, L"explore", NULL, NULL, NULL, 1);
- ShellExecuteW(0, NULL, L"explorer.exe", NULL, NULL, 1);
- break;
- case IDHK_FIND:
- SHFindFiles(NULL, NULL);
- break;
- case IDHK_FIND_COMPUTER:
- SHFindComputer(NULL, NULL);
- break;
- case IDHK_SYS_PROPERTIES:
- //FIXME: Use SHRunControlPanel
- ShellExecuteW(m_hWnd, NULL, L"sysdm.cpl", NULL, NULL, SW_NORMAL);
- break;
- case IDHK_NEXT_TASK:
- break;
- case IDHK_PREV_TASK:
- break;
- case IDHK_MINIMIZE_ALL:
- break;
- case IDHK_RESTORE_ALL:
- break;
- case IDHK_DESKTOP:
- break;
- case IDHK_PAGER:
- break;
- }
-
- return 0;
+ return HandleHotKey(wParam);
}
LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
@@ -2732,38 +2803,7 @@
if (m_TrayBandSite == NULL ||
FAILED_UNEXPECTEDLY(m_TrayBandSite->ProcessMessage(m_hWnd, uMsg, wParam, lParam,
&Ret)))
{
- switch (LOWORD(wParam))
- {
- case IDM_TASKBARANDSTARTMENU:
- DisplayProperties();
- break;
-
- case IDM_SEARCH:
- SHFindFiles(NULL, NULL);
- break;
-
- case IDM_HELPANDSUPPORT:
- ExecResourceCmd(IDS_HELP_COMMAND);
- break;
-
- case IDM_RUN:
- DisplayRunFileDlg();
- break;
-
- /* FIXME: Handle these commands as well */
- case IDM_SYNCHRONIZE:
- case IDM_DISCONNECT:
- case IDM_UNDOCKCOMPUTER:
- break;
-
- case IDM_LOGOFF:
- LogoffWindowsDialog(m_hWnd); // FIXME: Maybe handle it in a similar way
as DoExitWindows?
- break;
-
- case IDM_SHUTDOWN:
- DoExitWindows();
- break;
- }
+ return HandleCommand(LOWORD(wParam));
}
return Ret;
}