#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");
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];
&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;
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);
/* 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
break;
default:
- DbgPrint("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
+ TRACE("ITrayWindow::ExecContextMenuCmd(%u): Unhandled Command ID!\n", uiCmd);
bHandled = FALSE;
break;
}
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)
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;
}
break;
case TWM_OPENSTARTMENU:
- SendMessage(This->hWnd, WM_COMMAND, MAKEWPARAM(BN_CLICKED, IDC_STARTBTN), (LPARAM)This->hwndStart);
- break;
+ {
+ HWND hwndStartMenu;
+ HRESULT hr = IUnknown_GetWindow((IUnknown*)This->StartMenuPopup, &hwndStartMenu);
+ if (FAILED(hr))
+ break;
+ if (IsWindowVisible(hwndStartMenu))
+ {
+ IMenuPopup_OnSelect(This->StartMenuPopup, MPOS_CANCELLEVEL);
+ }
+ 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,
{
/* FIXME: Handle these commands as well */
case IDM_TASKBARANDSTARTMENU:
+
+ ITrayWindowImpl_DisplayProperties(ITrayWindow_from_impl(This));
+ break;
+
case IDM_SEARCH:
+ break;
+
case IDM_HELPANDSUPPORT:
+ {
+ /* TODO: Implement properly */
+
+ 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;
+
+ /* 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:
{
}
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;
}
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