* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <precomp.h>
+#include "precomp.h"
+
+extern HRESULT InitShellServices(HDPA * phdpa);
+extern HRESULT ShutdownShellServices(HDPA hdpa);
static const TRAYWINDOW_CTXMENU TrayWindowCtxMenu;
#define WM_APP_TRAYDESTROY (WM_APP + 0x100)
+#define TIMER_ID_AUTOHIDE 1
+#define TIMER_ID_MOUSETRACK 2
+#define MOUSETRACK_INTERVAL 100
+#define AUTOHIDE_DELAY_HIDE 2000
+#define AUTOHIDE_DELAY_SHOW 50
+#define AUTOHIDE_INTERVAL_ANIMATING 10
+
+#define AUTOHIDE_SPEED_SHOW 10
+#define AUTOHIDE_SPEED_HIDE 1
+
+#define AUTOHIDE_HIDDEN 0
+#define AUTOHIDE_SHOWING 1
+#define AUTOHIDE_SHOWN 2
+#define AUTOHIDE_HIDING 3
+
static LONG TrayWndCount = 0;
static const TCHAR szTrayWndClass[] = TEXT("Shell_TrayWnd");
const IShellDesktopTrayVtbl *lpVtblShellDesktopTray;
LONG Ref;
+ HTHEME TaskbarTheme;
HWND hWnd;
HWND hWndDesktop;
IMenuPopup *StartMenuPopup;
HBITMAP hbmStartMenu;
- HWND hWndTrayProperties;
+ HWND hwndTrayPropertiesOwner;
+ HWND hwndRunFileDlgOwner;
+
+ UINT AutoHideState;
+ SIZE AutoHideOffset;
+ TRACKMOUSEEVENT MouseTrackingInfo;
+
+ HDPA hdpaShellServices;
} ITrayWindowImpl;
+static ITrayWindowImpl * g_TrayWindow;
+
+BOOL LaunchCPanel(HWND hwnd, LPCTSTR applet)
+{
+ TCHAR szParams[MAX_PATH];
+
+ StringCbCopy(szParams, sizeof(szParams),
+ TEXT("shell32.dll,Control_RunDLL "));
+ if (FAILED(StringCbCat(szParams, sizeof(szParams),
+ applet)))
+ return FALSE;
+
+ return (ShellExecute(hwnd, TEXT("open"), TEXT("rundll32.exe"), szParams, NULL, SW_SHOWDEFAULT) > (HINSTANCE)32);
+}
+
static IUnknown *
IUnknown_from_impl(ITrayWindowImpl *This)
{
RECT rcMin = {0};
AdjustWindowRectEx(&rcMin,
- GetWindowLongPtr(This->hWnd,
- GWL_STYLE),
+ GetWindowLong(This->hWnd,
+ GWL_STYLE),
FALSE,
- GetWindowLongPtr(This->hWnd,
- GWL_EXSTYLE));
+ GetWindowLong(This->hWnd,
+ GWL_EXSTYLE));
*pRect = rcMin;
}
&rcScreen,
&szTray,
pRect);
-
+ if (This->AutoHide)
+ {
+ pRect->left += This->AutoHideOffset.cx;
+ pRect->right += This->AutoHideOffset.cx;
+ pRect->top += This->AutoHideOffset.cy;
+ pRect->bottom += This->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 = This->rcTrayWnd[Pos];
+ if (This->AutoHide)
+ {
+ pRect->left += This->AutoHideOffset.cx;
+ pRect->right += This->AutoHideOffset.cx;
+ pRect->top += This->AutoHideOffset.cy;
+ pRect->bottom += This->AutoHideOffset.cy;
+ }
}
*phMonitor = hMon;
rcTray.top = pwp->y;
rcTray.right = rcTray.left + pwp->cx;
rcTray.bottom = rcTray.top + pwp->cy;
+ if (This->AutoHide)
+ {
+ rcTray.left -= This->AutoHideOffset.cx;
+ rcTray.right -= This->AutoHideOffset.cx;
+ rcTray.top -= This->AutoHideOffset.cy;
+ rcTray.bottom -= This->AutoHideOffset.cy;
+ }
if (!EqualRect(&rcTray,
&This->rcTrayWnd[This->DraggingPosition]))
&rcTray);
}
+ if (This->AutoHide)
+ {
+ rcTray.left -= This->AutoHideOffset.cx;
+ rcTray.right -= This->AutoHideOffset.cx;
+ rcTray.top -= This->AutoHideOffset.cy;
+ rcTray.bottom -= This->AutoHideOffset.cy;
+ }
This->rcTrayWnd[This->Position] = rcTray;
}
else
This->TraySize.cx = rcTray.right - rcTray.left;
This->TraySize.cy = rcTray.bottom - rcTray.top;
+ if (This->AutoHide)
+ {
+ rcTray.left += This->AutoHideOffset.cx;
+ rcTray.right += This->AutoHideOffset.cx;
+ rcTray.top += This->AutoHideOffset.cy;
+ rcTray.bottom += This->AutoHideOffset.cy;
+ }
+
pwp->flags &= ~(SWP_NOMOVE | SWP_NOSIZE);
pwp->x = rcTray.left;
pwp->y = rcTray.top;
RECT rcTray,rcWorkArea;
/* If monitor has changed then fix the previous monitors work area */
- if(This->PreviousMonitor!=This->Monitor)
+ if (This->PreviousMonitor != This->Monitor)
{
ITrayWindowImpl_GetScreenRect(This,
This->PreviousMonitor,
ITrayWindowImpl_GetScreenRect(This,
This->Monitor,
&rcWorkArea);
- This->PreviousMonitor=This->Monitor;
+ This->PreviousMonitor = This->Monitor;
/* If AutoHide is false then change the workarea to exclude the area that
the taskbar covers. */
- if(!This->AutoHide)
+ if (!This->AutoHide)
{
- switch(This->Position)
+ switch (This->Position)
{
case ABE_TOP:
- rcWorkArea.top=rcTray.bottom;
+ rcWorkArea.top = rcTray.bottom;
break;
case ABE_LEFT:
- rcWorkArea.left=rcTray.right;
+ rcWorkArea.left = rcTray.right;
break;
case ABE_RIGHT:
- rcWorkArea.right=rcTray.left;
+ rcWorkArea.right = rcTray.left;
break;
case ABE_BOTTOM:
- rcWorkArea.bottom=rcTray.top;
+ rcWorkArea.bottom = rcTray.top;
break;
}
}
RECT rcTray;
rcTray = This->rcTrayWnd[This->Position];
-// DbgPrint("CheckTray: %d: %d,%d,%d,%d\n", This->Position, rcTray.left, rcTray.top, rcTray.right, rcTray.bottom);
+
+ if (This->AutoHide)
+ {
+ rcTray.left += This->AutoHideOffset.cx;
+ rcTray.right += This->AutoHideOffset.cx;
+ rcTray.top += This->AutoHideOffset.cy;
+ rcTray.bottom += This->AutoHideOffset.cy;
+ }
+
+// TRACE("CheckTray: %d: %d,%d,%d,%d\n", This->Position, rcTray.left, rcTray.top, rcTray.right, rcTray.bottom);
/* Move the tray window */
SetWindowPos(This->hWnd,
/* FIXME: Are there more flags? */
- if (This->hWnd != NULL)
- SetWindowPos (This->hWnd,
- This->AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
- 0,
- 0,
- 0,
- 0,
- SWP_NOMOVE | SWP_NOSIZE);
-
if (sr.Position > ABE_BOTTOM)
This->Position = ABE_BOTTOM;
else
else
{
This->Position = ABE_BOTTOM;
+ This->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
MONITOR_DEFAULTTOPRIMARY);
}
+ if (This->hWnd != NULL)
+ SetWindowPos(This->hWnd,
+ This->AlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
+ 0,
+ 0,
+ 0,
+ 0,
+ SWP_NOMOVE | SWP_NOSIZE);
+
/* 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
&rcScreen,
&This->TraySize,
&This->rcTrayWnd[Pos]);
-// DbgPrint("rcTrayWnd[%d(%d)]: %d,%d,%d,%d\n", Pos, This->Position, This->rcTrayWnd[Pos].left, This->rcTrayWnd[Pos].top, This->rcTrayWnd[Pos].right, This->rcTrayWnd[Pos].bottom);
+// TRACE("rcTrayWnd[%d(%d)]: %d,%d,%d,%d\n", Pos, This->Position, This->rcTrayWnd[Pos].left, This->rcTrayWnd[Pos].top, This->rcTrayWnd[Pos].right, This->rcTrayWnd[Pos].bottom);
}
/* Determine which monitor we are on. It shouldn't matter which docked
cmdId,
pcmContext,
Context);
+
+ DestroyMenu(hPopup);
}
return cmdId;
(void)InterlockedExchangePointer((PVOID*)&This->hWnd,
NULL);
+
+ if (This->hdpaShellServices != NULL)
+ {
+ ShutdownShellServices(This->hdpaShellServices);
+ This->hdpaShellServices = NULL;
+ }
+
if (This->himlStartBtn != NULL)
{
ImageList_Destroy(This->himlStartBtn);
This->TrayBandSite = NULL;
}
+ if (This->TaskbarTheme)
+ {
+ CloseThemeData(This->TaskbarTheme);
+ This->TaskbarTheme = NULL;
+ }
+
ITrayWindowImpl_Release(ITrayWindow_from_impl(This));
if (InterlockedDecrement(&TrayWndCount) == 0)
BOOL Horizontal;
HDWP dwp;
+ ITrayWindowImpl_UpdateStartButton(This, NULL);
if (prcClient != NULL)
{
rcClient = *prcClient;
return hBitmap;
}
+static VOID
+ITrayWindowImpl_UpdateTheme(IN OUT ITrayWindowImpl *This)
+{
+ if (This->TaskbarTheme)
+ CloseThemeData(This->TaskbarTheme);
+
+ if (IsThemeActive())
+ This->TaskbarTheme = OpenThemeData(This->hWnd, L"Taskbar");
+ else
+ This->TaskbarTheme = 0;
+}
+
static VOID
ITrayWindowImpl_Create(IN OUT ITrayWindowImpl *This)
{
TCHAR szStartCaption[32];
+ SetWindowTheme(This->hWnd, L"TaskBar", NULL);
+ ITrayWindowImpl_UpdateTheme(This);
+
InterlockedIncrement(&TrayWndCount);
if (!LoadString(hExplorerInstance,
NULL);
if (This->hwndStart)
{
+ SetWindowTheme(This->hwndStart, L"Start", NULL);
SendMessage(This->hwndStart,
WM_SETFONT,
(WPARAM)This->hStartBtnFont,
This->TrayBandSite = CreateTrayBandSite(ITrayWindow_from_impl(This),
&This->hwndRebar,
&This->hwndTaskSwitch);
+ SetWindowTheme(This->hwndRebar, L"TaskBar", NULL);
/* Create the tray notification window */
This->hwndTrayNotify = CreateTrayNotifyWnd(ITrayWindow_from_impl(This),
/* Align all controls on the tray window */
ITrayWindowImpl_AlignControls(This,
NULL);
+
+ InitShellServices(&(This->hdpaShellServices));
+
+ if (This->AutoHide)
+ {
+ This->AutoHideState = AUTOHIDE_HIDING;
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
+ }
}
static HRESULT STDMETHODCALLTYPE
ITrayWindowImpl *This;
This = HeapAlloc(hProcessHeap,
- 0,
+ HEAP_ZERO_MEMORY,
sizeof(*This));
if (This == NULL)
return NULL;
- ZeroMemory(This,
- sizeof(*This));
This->lpVtbl = &ITrayWindowImpl_Vtbl;
This->lpVtblShellDesktopTray = &IShellDesktopTrayImpl_Vtbl;
This->Ref = 1;
return This->hCaptionFont;
}
+static DWORD WINAPI
+TrayPropertiesThread(IN OUT PVOID pParam)
+{
+ ITrayWindowImpl *This = pParam;
+ HWND hwnd;
+ RECT posRect;
+
+ GetWindowRect(This->hwndStart, &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);
+
+ This->hwndTrayPropertiesOwner = hwnd;
+
+ DisplayTrayProperties(hwnd);
+
+ This->hwndTrayPropertiesOwner = NULL;
+ DestroyWindow(hwnd);
+
+ return 0;
+}
+
static HWND STDMETHODCALLTYPE
ITrayWindowImpl_DisplayProperties(IN OUT ITrayWindow *iface)
{
ITrayWindowImpl *This = impl_from_ITrayWindow(iface);
+ HWND hTrayProp;
- if (This->hWndTrayProperties != NULL)
+ if (This->hwndTrayPropertiesOwner)
{
- BringWindowToTop(This->hWndTrayProperties);
- return This->hWndTrayProperties;
+ hTrayProp = GetLastActivePopup(This->hwndTrayPropertiesOwner);
+ if (hTrayProp != NULL &&
+ hTrayProp != This->hwndTrayPropertiesOwner)
+ {
+ SetForegroundWindow(hTrayProp);
+ return NULL;
+ }
}
- This->hWndTrayProperties = DisplayTrayProperties(ITrayWindow_from_impl(This));
- return This->hWndTrayProperties;
+ CloseHandle(CreateThread(NULL, 0, TrayPropertiesThread, This, 0, NULL));
+ return NULL;
}
static VOID
OpenTaskManager(This->hWnd);
break;
+ case ID_SHELL_CMD_UNDO_ACTION:
+ break;
+
+ case ID_SHELL_CMD_SHOW_DESKTOP:
+ break;
+
+ case ID_SHELL_CMD_TILE_WND_H:
+ TileWindows(NULL, MDITILE_HORIZONTAL, NULL, 0, NULL);
+ break;
+
+ case ID_SHELL_CMD_TILE_WND_V:
+ TileWindows(NULL, MDITILE_VERTICAL, NULL, 0, NULL);
+ break;
+
+ case ID_SHELL_CMD_CASCADE_WND:
+ CascadeWindows(NULL, MDITILE_SKIPDISABLED, NULL, 0, NULL);
+ break;
+
+ case ID_SHELL_CMD_CUST_NOTIF:
+ break;
+
+ case ID_SHELL_CMD_ADJUST_DAT:
+ LaunchCPanel(NULL, TEXT("timedate.cpl"));
+ break;
default:
- DbgPrint("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
+ TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
bHandled = FALSE;
break;
}
ITrayWindowImpl_Lock
};
+static int
+ITrayWindowImpl_DrawBackground(IN ITrayWindowImpl *This,
+ IN HDC dc)
+{
+ int backoundPart;
+ RECT rect;
+
+ GetClientRect(This->hWnd, &rect);
+ switch (This->Position)
+ {
+ case ABE_LEFT:
+ backoundPart = TBP_BACKGROUNDLEFT;
+ break;
+ case ABE_TOP:
+ backoundPart = TBP_BACKGROUNDTOP;
+ break;
+ case ABE_RIGHT:
+ backoundPart = TBP_BACKGROUNDRIGHT;
+ break;
+ case ABE_BOTTOM:
+ default:
+ backoundPart = TBP_BACKGROUNDBOTTOM;
+ break;
+ }
+ DrawThemeBackground(This->TaskbarTheme, dc, backoundPart, 0, &rect, 0);
+ return 0;
+}
+
+static int
+ITrayWindowImpl_DrawSizer(IN ITrayWindowImpl *This,
+ IN HRGN hRgn)
+{
+ HDC hdc;
+ RECT rect;
+ int backoundPart;
+
+ GetWindowRect(This->hWnd, &rect);
+ OffsetRect(&rect, -rect.left, -rect.top);
+
+ hdc = GetDCEx(This->hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_PARENTCLIP);
+
+ switch (This->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;
+ }
+
+ DrawThemeBackground(This->TaskbarTheme, hdc, backoundPart, 0, &rect, 0);
+
+ ReleaseDC(This->hWnd, hdc);
+ return 0;
+}
+
+static DWORD WINAPI
+RunFileDlgThread(IN OUT PVOID pParam)
+{
+ ITrayWindowImpl *This = pParam;
+ HANDLE hShell32;
+ RUNFILEDLG RunFileDlg;
+ HWND hwnd;
+ RECT posRect;
+
+ GetWindowRect(This->hwndStart,&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);
+
+ This->hwndRunFileDlgOwner = hwnd;
+
+ hShell32 = GetModuleHandle(TEXT("SHELL32.DLL"));
+ RunFileDlg = (RUNFILEDLG)GetProcAddress(hShell32, (LPCSTR)61);
+
+ RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
+
+ This->hwndRunFileDlgOwner = NULL;
+ DestroyWindow(hwnd);
+
+ return 0;
+}
+
+static void
+ITrayWindowImpl_DisplayRunFileDlg(IN ITrayWindowImpl *This)
+{
+ HWND hRunDlg;
+ if (This->hwndRunFileDlgOwner)
+ {
+ hRunDlg = GetLastActivePopup(This->hwndRunFileDlgOwner);
+ if (hRunDlg != NULL &&
+ hRunDlg != This->hwndRunFileDlgOwner)
+ {
+ SetForegroundWindow(hRunDlg);
+ return;
+ }
+ }
+
+ CloseHandle(CreateThread(NULL, 0, RunFileDlgThread, This, 0, NULL));
+}
+
+static void PopupStartMenu(IN ITrayWindowImpl *This)
+{
+ if (This->StartMenuPopup != NULL)
+ {
+ POINTL pt;
+ RECTL rcExclude;
+ DWORD dwFlags = 0;
+
+ if (GetWindowRect(This->hwndStart,
+ (RECT*) &rcExclude))
+ {
+ switch (This->Position)
+ {
+ case ABE_BOTTOM:
+ pt.x = rcExclude.left;
+ pt.y = rcExclude.top;
+ dwFlags |= MPPF_BOTTOM;
+ break;
+ case ABE_TOP:
+ case ABE_LEFT:
+ pt.x = rcExclude.left;
+ pt.y = rcExclude.bottom;
+ dwFlags |= MPPF_TOP | MPPF_ALIGN_RIGHT;
+ break;
+ case ABE_RIGHT:
+ pt.x = rcExclude.right;
+ pt.y = rcExclude.bottom;
+ dwFlags |= MPPF_TOP | MPPF_ALIGN_LEFT;
+ break;
+ }
+
+ IMenuPopup_Popup(This->StartMenuPopup,
+ &pt,
+ &rcExclude,
+ dwFlags);
+
+ SendMessageW(This->hwndStart, BM_SETSTATE, TRUE, 0);
+ }
+ }
+}
+
+static void
+ProcessMouseTracking(ITrayWindowImpl * This)
+{
+ RECT rcCurrent;
+ POINT pt;
+ BOOL over;
+ UINT state = This->AutoHideState;
+
+ GetCursorPos(&pt);
+ GetWindowRect(This->hWnd, &rcCurrent);
+ over = PtInRect(&rcCurrent, pt);
+
+ if (SendMessage(This->hwndStart, BM_GETSTATE, 0, 0) != BST_UNCHECKED)
+ {
+ over = TRUE;
+ }
+
+ if (over)
+ {
+ if (state == AUTOHIDE_HIDING)
+ {
+ TRACE("AutoHide cancelling hide.\n");
+ This->AutoHideState = AUTOHIDE_SHOWING;
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+ }
+ else if (state == AUTOHIDE_HIDDEN)
+ {
+ TRACE("AutoHide starting show.\n");
+ This->AutoHideState = AUTOHIDE_SHOWING;
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_SHOW, NULL);
+ }
+ }
+ else
+ {
+ if (state == AUTOHIDE_SHOWING)
+ {
+ TRACE("AutoHide cancelling show.\n");
+ This->AutoHideState = AUTOHIDE_HIDING;
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+ }
+ else if (state == AUTOHIDE_SHOWN)
+ {
+ TRACE("AutoHide starting hide.\n");
+ This->AutoHideState = AUTOHIDE_HIDING;
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_DELAY_HIDE, NULL);
+ }
+
+ KillTimer(This->hWnd, TIMER_ID_MOUSETRACK);
+ }
+}
+
+static void
+ProcessAutoHide(ITrayWindowImpl * This)
+{
+ RECT rc = This->rcTrayWnd[This->Position];
+ INT w = This->TraySize.cx - GetSystemMetrics(SM_CXBORDER) * 2 - 1;
+ INT h = This->TraySize.cy - GetSystemMetrics(SM_CYBORDER) * 2 - 1;
+
+ TRACE("AutoHide Timer received for %u, rc=(%d, %d, %d, %d), w=%d, h=%d.\n", This->AutoHideState, rc.left, rc.top, rc.right, rc.bottom, w, h);
+
+ switch (This->AutoHideState)
+ {
+ case AUTOHIDE_HIDING:
+ switch (This->Position)
+ {
+ case ABE_LEFT:
+ This->AutoHideOffset.cy = 0;
+ This->AutoHideOffset.cx -= AUTOHIDE_SPEED_HIDE;
+ if (This->AutoHideOffset.cx < -w)
+ This->AutoHideOffset.cx = -w;
+ break;
+ case ABE_TOP:
+ This->AutoHideOffset.cx = 0;
+ This->AutoHideOffset.cy -= AUTOHIDE_SPEED_HIDE;
+ if (This->AutoHideOffset.cy < -h)
+ This->AutoHideOffset.cy = -h;
+ break;
+ case ABE_RIGHT:
+ This->AutoHideOffset.cy = 0;
+ This->AutoHideOffset.cx += AUTOHIDE_SPEED_HIDE;
+ if (This->AutoHideOffset.cx > w)
+ This->AutoHideOffset.cx = w;
+ break;
+ case ABE_BOTTOM:
+ This->AutoHideOffset.cx = 0;
+ This->AutoHideOffset.cy += AUTOHIDE_SPEED_HIDE;
+ if (This->AutoHideOffset.cy > h)
+ This->AutoHideOffset.cy = h;
+ break;
+ }
+
+ if (This->AutoHideOffset.cx != w && This->AutoHideOffset.cy != h)
+ {
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+ break;
+ }
+
+ /* fallthrough */
+ case AUTOHIDE_HIDDEN:
+
+ switch (This->Position)
+ {
+ case ABE_LEFT:
+ This->AutoHideOffset.cx = -w;
+ This->AutoHideOffset.cy = 0;
+ break;
+ case ABE_TOP:
+ This->AutoHideOffset.cx = 0;
+ This->AutoHideOffset.cy = -h;
+ break;
+ case ABE_RIGHT:
+ This->AutoHideOffset.cx = w;
+ This->AutoHideOffset.cy = 0;
+ break;
+ case ABE_BOTTOM:
+ This->AutoHideOffset.cx = 0;
+ This->AutoHideOffset.cy = h;
+ break;
+ }
+
+ KillTimer(This->hWnd, TIMER_ID_AUTOHIDE);
+ This->AutoHideState = AUTOHIDE_HIDDEN;
+ break;
+
+ case AUTOHIDE_SHOWING:
+ if (This->AutoHideOffset.cx >= AUTOHIDE_SPEED_SHOW)
+ {
+ This->AutoHideOffset.cx -= AUTOHIDE_SPEED_SHOW;
+ }
+ else if (This->AutoHideOffset.cx <= -AUTOHIDE_SPEED_SHOW)
+ {
+ This->AutoHideOffset.cx += AUTOHIDE_SPEED_SHOW;
+ }
+ else
+ {
+ This->AutoHideOffset.cx = 0;
+ }
+
+ if (This->AutoHideOffset.cy >= AUTOHIDE_SPEED_SHOW)
+ {
+ This->AutoHideOffset.cy -= AUTOHIDE_SPEED_SHOW;
+ }
+ else if (This->AutoHideOffset.cy <= -AUTOHIDE_SPEED_SHOW)
+ {
+ This->AutoHideOffset.cy += AUTOHIDE_SPEED_SHOW;
+ }
+ else
+ {
+ This->AutoHideOffset.cy = 0;
+ }
+
+ if (This->AutoHideOffset.cx != 0 || This->AutoHideOffset.cy != 0)
+ {
+ SetTimer(This->hWnd, TIMER_ID_AUTOHIDE, AUTOHIDE_INTERVAL_ANIMATING, NULL);
+ break;
+ }
+
+ /* fallthrough */
+ case AUTOHIDE_SHOWN:
+
+ KillTimer(This->hWnd, TIMER_ID_AUTOHIDE);
+ This->AutoHideState = AUTOHIDE_SHOWN;
+ break;
+ }
+
+ rc.left += This->AutoHideOffset.cx;
+ rc.right += This->AutoHideOffset.cx;
+ rc.top += This->AutoHideOffset.cy;
+ rc.bottom += This->AutoHideOffset.cy;
+
+ TRACE("AutoHide Changing position to (%d, %d, %d, %d) and state=%u.\n", rc.left, rc.top, rc.right, rc.bottom, This->AutoHideState);
+ SetWindowPos(This->hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
static LRESULT CALLBACK
TrayWndProc(IN HWND hwnd,
IN UINT uMsg,
switch (uMsg)
{
+ case WM_DISPLAYCHANGE:
+
+ /* Load the saved tray window settings */
+ ITrayWindowImpl_RegLoadSettings(This);
+
+ /* Move the tray window to the right position and resize it if neccessary */
+ ITrayWindowImpl_CheckTrayWndPosition(This);
+
+ /* Align all controls on the tray window */
+ ITrayWindowImpl_AlignControls(This, NULL);
+
+ break;
+
+ case WM_COPYDATA:
+ {
+ if (This->hwndTrayNotify)
+ {
+ TrayNotify_NotifyMsg(This->hwndTrayNotify,
+ wParam,
+ lParam);
+ }
+ return TRUE;
+ }
+ case WM_THEMECHANGED:
+ ITrayWindowImpl_UpdateTheme(This);
+ return 0;
+ case WM_NCPAINT:
+ if (!This->TaskbarTheme)
+ goto DefHandler;
+ return ITrayWindowImpl_DrawSizer(This,
+ (HRGN)wParam);
+ case WM_ERASEBKGND:
+ if (!This->TaskbarTheme)
+ goto DefHandler;
+ return ITrayWindowImpl_DrawBackground(This,
+ (HDC)wParam);
+ case WM_CTLCOLORBTN:
+ SetBkMode((HDC)wParam, TRANSPARENT);
+ return (LRESULT)GetStockObject(HOLLOW_BRUSH);
case WM_NCHITTEST:
{
RECT rcClient;
return HTBORDER;
}
+ SetLastError(ERROR_SUCCESS);
if (GetClientRect(hwnd,
&rcClient) &&
- MapWindowPoints(hwnd,
- NULL,
- (LPPOINT)&rcClient,
- 2) != 0)
+ (MapWindowPoints(hwnd,
+ NULL,
+ (LPPOINT)&rcClient,
+ 2) != 0 || GetLastError() == ERROR_SUCCESS))
{
pt.x = (SHORT)LOWORD(lParam);
pt.y = (SHORT)HIWORD(lParam);
if (pt.y > rcClient.bottom)
return HTBOTTOM;
break;
-
- case ABE_BOTTOM:
- if (pt.y < rcClient.top)
- return HTTOP;
- break;
-
case ABE_LEFT:
if (pt.x > rcClient.right)
return HTRIGHT;
break;
-
case ABE_RIGHT:
if (pt.x < rcClient.left)
return HTLEFT;
break;
-
+ case ABE_BOTTOM:
default:
+ if (pt.y < rcClient.top)
+ return HTTOP;
break;
}
}
-
return HTBORDER;
}
-
case WM_MOVING:
{
POINT ptCursor;
else
{
*pRect = This->rcTrayWnd[This->Position];
+
+ if (This->AutoHide)
+ {
+ pRect->left += This->AutoHideOffset.cx;
+ pRect->right += This->AutoHideOffset.cx;
+ pRect->top += This->AutoHideOffset.cy;
+ pRect->bottom += This->AutoHideOffset.cy;
+ }
}
return TRUE;
}
else
{
*pRect = This->rcTrayWnd[This->Position];
+
+ if (This->AutoHide)
+ {
+ pRect->left += This->AutoHideOffset.cx;
+ pRect->right += This->AutoHideOffset.cx;
+ pRect->top += This->AutoHideOffset.cy;
+ pRect->bottom += This->AutoHideOffset.cy;
+ }
}
return TRUE;
}
case WM_SIZE:
{
RECT rcClient;
-
+ InvalidateRect(This->hWnd, NULL, TRUE);
if (wParam == SIZE_RESTORED && lParam == 0)
{
ITrayWindowImpl_ResizeWorkArea(This);
}
case WM_NCLBUTTONDBLCLK:
+ {
/* We "handle" this message so users can't cause a weird maximize/restore
window animation when double-clicking the tray window! */
+
+ /* We should forward mouse messages to child windows here.
+ Right now, this is only clock double-click */
+ RECT rcClock;
+ if (TrayNotify_GetClockRect(This->hwndTrayNotify, &rcClock))
+ {
+ POINT ptClick;
+ ptClick.x = MAKEPOINTS(lParam).x;
+ ptClick.y = MAKEPOINTS(lParam).y;
+ if (PtInRect(&rcClock, ptClick))
+ LaunchCPanel(NULL, TEXT("timedate.cpl"));
+ }
break;
+ }
case WM_NCCREATE:
{
DestroyWindow(hwnd);
break;
+ case TWM_OPENSTARTMENU:
+ {
+ HWND hwndStartMenu;
+ HRESULT hr = IUnknown_GetWindow((IUnknown*)This->StartMenuPopup, &hwndStartMenu);
+ if (FAILED(hr))
+ break;
+
+ if (IsWindowVisible(hwndStartMenu))
+ SetWindowPos(hwndStartMenu, 0,0,0,0,0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
+ else
+ SendMessage(This->hWnd, WM_COMMAND, MAKEWPARAM(BN_CLICKED, IDC_STARTBTN), (LPARAM)This->hwndStart);
+
+ break;
+ }
case WM_COMMAND:
if ((HWND)lParam == This->hwndStart)
{
- if (This->StartMenuPopup != NULL)
- {
- POINTL pt;
- RECTL rcExclude;
- DWORD dwFlags = 0;
-
- if (GetWindowRect(This->hwndStart,
- (RECT*)&rcExclude))
- {
- if (ITrayWindowImpl_IsPosHorizontal(This))
- {
- pt.x = rcExclude.left;
- pt.y = rcExclude.top;
- dwFlags |= MPPF_BOTTOM;
- }
- else
- {
- if (This->Position == ABE_LEFT)
- pt.x = rcExclude.left;
- else
- pt.x = rcExclude.right;
-
- pt.y = rcExclude.bottom;
- dwFlags |= MPPF_BOTTOM;
- }
-
- IMenuPopup_Popup(This->StartMenuPopup,
- &pt,
- &rcExclude,
- dwFlags);
- }
- }
+ PopupStartMenu(This);
break;
}
if (This->TrayBandSite == NULL ||
- !SUCCEEDED(ITrayBandSite_ProcessMessage(This->TrayBandSite,
+ FAILED(ITrayBandSite_ProcessMessage(This->TrayBandSite,
hwnd,
uMsg,
wParam,
lParam,
&Ret)))
{
- switch(LOWORD(wParam))
+ switch (LOWORD(wParam))
{
/* FIXME: Handle these commands as well */
case IDM_TASKBARANDSTARTMENU:
+
+ ITrayWindowImpl_DisplayProperties(ITrayWindow_from_impl(This));
+ break;
+
case IDM_SEARCH:
- case IDM_HELPANDSUPPORT:
break;
- case IDM_RUN:
+ case IDM_HELPANDSUPPORT:
{
- HANDLE hShell32;
- RUNFILEDLG RunFileDlg;
+ /* TODO: Implement properly */
- hShell32 = GetModuleHandle(TEXT("SHELL32.DLL"));
- RunFileDlg = (RUNFILEDLG)GetProcAddress(hShell32, (LPCSTR)61);
+ LPCWSTR strSite = L"http://www.reactos.org/";
+
+ /* TODO: Make localizable */
+ LPCWSTR strCaption = L"Sorry";
+ LPCWSTR strMessage = L"ReactOS could not browse to '%s' (error %d). Please make sure there is a web browser installed.";
+ WCHAR tmpMessage[512];
+
+ /* TODO: Read from the registry */
+ LPCWSTR strVerb = NULL; /* default */
+ LPCWSTR strPath = strSite;
+ LPCWSTR strParams = NULL;
- RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY);
+ /* The return value is defined as HINSTANCE for backwards compatibility only, the cast is needed */
+ int result = (int) ShellExecuteW(hwnd, strVerb, strPath, strParams, NULL, SW_SHOWNORMAL);
+ if (result <= 32)
+ {
+ StringCchPrintfW(tmpMessage, 512, strMessage, strSite, result);
+ MessageBoxExW(hwnd, tmpMessage, strCaption, MB_OK, 0);
+ }
+ break;
+ }
+
+ case IDM_RUN:
+ {
+ ITrayWindowImpl_DisplayRunFileDlg(This);
break;
}
}
break;
+ case WM_MOUSEMOVE:
+ case WM_NCMOUSEMOVE:
+
+ if (This->AutoHide)
+ {
+ SetTimer(This->hWnd, TIMER_ID_MOUSETRACK, MOUSETRACK_INTERVAL, NULL);
+ }
+
+ break;
+ case WM_TIMER:
+ if (wParam == TIMER_ID_MOUSETRACK)
+ {
+ ProcessMouseTracking(This);
+ }
+ else if (wParam == TIMER_ID_AUTOHIDE)
+ {
+ ProcessAutoHide(This);
+ }
+
+ goto DefHandler;
+
default:
goto DefHandler;
}
CMF_NORMAL,
&pcm)))
{
- DbgPrint("ITrayBandSite::AddContextMenus succeeded!\n");
+ TRACE("ITrayBandSite::AddContextMenus succeeded!\n");
*(IContextMenu **)ppcmContext = pcm;
}
}
ITrayWindowImpl_Open(TrayWindow);
+ g_TrayWindow = This;
+
return TrayWindow;
}
while (1)
{
- Ret = (GetMessage(&Msg,
- NULL,
- 0,
- 0) != 0);
+ Ret = GetMessage(&Msg,
+ NULL,
+ 0,
+ 0);
- if (Ret != -1)
- {
- if (!Ret)
- break;
+ if (!Ret || Ret == -1)
+ break;
- if (This->StartMenuBand == NULL ||
- IMenuBand_IsMenuMessage(This->StartMenuBand,
- &Msg) != S_OK)
+ if (Msg.message == WM_HOTKEY)
+ {
+ switch (Msg.wParam)
{
- TranslateMessage(&Msg);
- DispatchMessage(&Msg);
+ case IDHK_RUN: /* Win+R */
+ ITrayWindowImpl_DisplayRunFileDlg(This);
+ break;
}
}
+
+ if (This->StartMenuBand == NULL ||
+ IMenuBand_IsMenuMessage(This->StartMenuBand,
+ &Msg) != S_OK)
+ {
+ TranslateMessage(&Msg);
+ DispatchMessage(&Msg);
+ }
}
}
ITrayWindowImpl *This = impl_from_IShellDesktopTray(iface);
ITrayWindow *tray = ITrayWindow_from_impl(This);
- DbgPrint("IShellDesktopTray::QueryInterface(0x%p, 0x%p)\n", riid, ppvObj);
+ TRACE("IShellDesktopTray::QueryInterface(0x%p, 0x%p)\n", riid, ppvObj);
return ITrayWindowImpl_QueryInterface(tray,
riid,
ppvObj);
ITrayWindowImpl *This = impl_from_IShellDesktopTray(iface);
ITrayWindow *tray = ITrayWindow_from_impl(This);
- DbgPrint("IShellDesktopTray::Release()\n");
+ TRACE("IShellDesktopTray::Release()\n");
return ITrayWindowImpl_Release(tray);
}
ITrayWindowImpl *This = impl_from_IShellDesktopTray(iface);
ITrayWindow *tray = ITrayWindow_from_impl(This);
- DbgPrint("IShellDesktopTray::AddRef()\n");
+ TRACE("IShellDesktopTray::AddRef()\n");
return ITrayWindowImpl_AddRef(tray);
}
ITrayWindowImpl_IShellDesktopTray_GetState(IN OUT IShellDesktopTray *iface)
{
/* FIXME: Return ABS_ flags? */
- DbgPrint("IShellDesktopTray::GetState() unimplemented!\n");
+ TRACE("IShellDesktopTray::GetState() unimplemented!\n");
return 0;
}
OUT HWND *phWndTray)
{
ITrayWindowImpl *This = impl_from_IShellDesktopTray(iface);
- DbgPrint("IShellDesktopTray::GetTrayWindow(0x%p)\n", phWndTray);
+ TRACE("IShellDesktopTray::GetTrayWindow(0x%p)\n", phWndTray);
*phWndTray = This->hWnd;
return S_OK;
}
IN HWND hWndDesktop)
{
ITrayWindowImpl *This = impl_from_IShellDesktopTray(iface);
- DbgPrint("IShellDesktopTray::RegisterDesktopWindow(0x%p)\n", hWndDesktop);
+ TRACE("IShellDesktopTray::RegisterDesktopWindow(0x%p)\n", hWndDesktop);
This->hWndDesktop = hWndDesktop;
return S_OK;
IN DWORD dwUnknown1,
IN DWORD dwUnknown2)
{
- DbgPrint("IShellDesktopTray::Unknown(%u,%u) unimplemented!\n", dwUnknown1, dwUnknown2);
+ TRACE("IShellDesktopTray::Unknown(%u,%u) unimplemented!\n", dwUnknown1, dwUnknown2);
return S_OK;
}
ITrayWindowImpl_IShellDesktopTray_RegisterDesktopWindow,
ITrayWindowImpl_IShellDesktopTray_Unknown
};
+
+HRESULT
+ITrayWindowImpl_RaiseStartButton(ITrayWindowImpl * This)
+{
+ SendMessageW(This->hwndStart, BM_SETSTATE, FALSE, 0);
+ return S_OK;
+}
+
+HRESULT
+Tray_OnStartMenuDismissed()
+{
+ return ITrayWindowImpl_RaiseStartButton(g_TrayWindow);
+}
\ No newline at end of file