Index: base/shell/explorer-new/CMakeLists.txt =================================================================== --- base/shell/explorer-new/CMakeLists.txt (revision 57798) +++ base/shell/explorer-new/CMakeLists.txt (working copy) @@ -32,6 +32,7 @@ shell32 shlwapi version + uxtheme msvcrt kernel32 ntdll) Index: base/shell/explorer-new/explorer.exe.manifest =================================================================== --- base/shell/explorer-new/explorer.exe.manifest (revision 0) +++ base/shell/explorer-new/explorer.exe.manifest (working copy) @@ -0,0 +1,22 @@ + + + +This is ReactOS Explorer + + + + + + \ No newline at end of file Index: base/shell/explorer-new/explorer.exe.manifest =================================================================== --- base/shell/explorer-new/explorer.exe.manifest (revision 0) +++ base/shell/explorer-new/explorer.exe.manifest (working copy) Property changes on: base/shell/explorer-new/explorer.exe.manifest ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: base/shell/explorer-new/explorer.rc =================================================================== --- base/shell/explorer-new/explorer.rc (revision 57798) +++ base/shell/explorer-new/explorer.rc (working copy) @@ -20,6 +20,7 @@ IDB_TASKBARPROP_NOLOCK_NOGROUP_NOQL BITMAP DISCARDABLE res/nolock_nogroup_noql.bmp IDB_TASKBARPROP_NOLOCK_NOGROUP_QL BITMAP DISCARDABLE res/nolock_nogroup_ql.bmp IDB_TASKBARPROP_NOLOCK_GROUP_QL BITMAP DISCARDABLE res/nolock_group_ql.bmp +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "explorer.exe.manifest" // UTF-8 #pragma code_page(65001) Index: base/shell/explorer-new/precomp.h =================================================================== --- base/shell/explorer-new/precomp.h (revision 57798) +++ base/shell/explorer-new/precomp.h (working copy) @@ -17,7 +17,9 @@ #include #include #include +#include +#include "tmschema.h" #include "resource.h" #include "comcsup.h" #include "todo.h" @@ -384,6 +386,11 @@ CreateTrayNotifyWnd(IN OUT ITrayWindow *TrayWindow, IN BOOL bHideClock); +VOID +TrayNotify_NotifyMsg(IN HWND hwnd, + IN WPARAM wParam, + IN LPARAM lParam); + /* * taskswnd.c */ Index: base/shell/explorer-new/taskswnd.c =================================================================== --- base/shell/explorer-new/taskswnd.c (revision 57798) +++ base/shell/explorer-new/taskswnd.c (working copy) @@ -20,10 +20,6 @@ #include -/* By default we don't use DrawCaptionTemp() because it causes some minimal - drawing glitches with the toolbar custom painting code */ -#define TASK_USE_DRAWCAPTIONTEMP 1 - /* Set DUMP_TASKS to 1 to enable a dump of the tasks and task groups every 5 seconds */ #define DUMP_TASKS 0 @@ -47,14 +43,6 @@ struct { -#if TASK_USE_DRAWCAPTIONTEMP != 0 - - /* DisplayTooltip is TRUE when the group button text didn't fit into - the button. */ - DWORD DisplayTooltip : 1; - -#endif - DWORD IsCollapsed : 1; }; }; @@ -65,27 +53,16 @@ HWND hWnd; PTASK_GROUP Group; INT Index; + INT IconIndex; -#if !(TASK_USE_DRAWCAPTIONTEMP != 0) - INT IconIndex; -#endif - union { DWORD dwFlags; struct { -#if TASK_USE_DRAWCAPTIONTEMP != 0 - - /* DisplayTooltip is TRUE when the window text didn't fit into the - button. */ - DWORD DisplayTooltip : 1; - -#endif - /* IsFlashing is TRUE when the task bar item should be flashing. */ DWORD IsFlashing : 1; @@ -113,9 +90,11 @@ PTASK_ITEM TaskItems; PTASK_ITEM ActiveTaskItem; + HTHEME TaskBandTheme; HWND hWndToolbar; UINT TbButtonsPerLine; WORD ToolbarBtnCount; + HIMAGELIST TaskIcons; union { @@ -139,12 +118,6 @@ static VOID TaskSwitchWnd_UpdateButtonsSize(IN OUT PTASK_SWITCH_WND This, IN BOOL bRedrawDisabled); -#if TASK_USE_DRAWCAPTIONTEMP != 0 - -#define TaskSwitchWnd_GetWndTextFromTaskItem(a,b) NULL - -#else /* !TASK_USE_DRAWCAPTIONTEMP */ - static LPTSTR TaskSwitchWnd_GetWndTextFromTaskItem(IN OUT PTASK_SWITCH_WND This, IN PTASK_ITEM TaskItem) @@ -161,7 +134,6 @@ return NULL; } -#endif #if DUMP_TASKS != 0 static VOID @@ -408,20 +380,45 @@ /* FIXME: Implement */ } +static HICON +TaskSwitchWnd_GetWndIcon(HWND hwnd) +{ + HICON hIcon = 0; + + SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon); + + if (!hIcon) + SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon); + + if (!hIcon) + SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon); + + if (!hIcon) + hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM); + + if (!hIcon) + hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON); + + return hIcon; +} static INT TaskSwitchWnd_UpdateTaskItemButton(IN OUT PTASK_SWITCH_WND This, IN PTASK_ITEM TaskItem) { TBBUTTONINFO tbbi; + HICON icon; ASSERT(TaskItem->Index >= 0); tbbi.cbSize = sizeof(tbbi); - tbbi.dwMask = TBIF_BYINDEX | TBIF_STATE | TBIF_TEXT; + tbbi.dwMask = TBIF_BYINDEX | TBIF_STATE | TBIF_TEXT | TBIF_IMAGE; tbbi.fsState = TBSTATE_ENABLED; if (This->ActiveTaskItem == TaskItem) tbbi.fsState |= TBSTATE_CHECKED; + if (TaskItem->RenderFlashed) + tbbi.fsState |= TBSTATE_MARKED; + /* Check if we're updating a button that is the last one in the line. If so, we need to set the TBSTATE_WRAP flag! */ if (This->TbButtonsPerLine != 0 && @@ -433,6 +430,10 @@ tbbi.pszText = TaskSwitchWnd_GetWndTextFromTaskItem(This, TaskItem); + icon = TaskSwitchWnd_GetWndIcon(TaskItem->hWnd); + TaskItem->IconIndex = ImageList_ReplaceIcon(This->TaskIcons,TaskItem->IconIndex,icon); + tbbi.iImage = TaskItem->IconIndex; + if (!SendMessage(This->hWndToolbar, TB_SETBUTTONINFO, (WPARAM)TaskItem->Index, @@ -446,6 +447,39 @@ return TaskItem->Index; } +static VOID +TaskSwitchWnd_RemoveIcon(IN OUT PTASK_SWITCH_WND This, + IN PTASK_ITEM TaskItem) +{ + TBBUTTONINFO tbbi; + PTASK_ITEM currentTaskItem,LastItem; + + if (TaskItem->IconIndex==-1) + return; + + tbbi.cbSize = sizeof(tbbi); + tbbi.dwMask = TBIF_IMAGE; + + currentTaskItem = This->TaskItems; + LastItem = currentTaskItem + This->TaskItemCount; + while (currentTaskItem != LastItem) + { + if (currentTaskItem->IconIndex > TaskItem->IconIndex) + { + currentTaskItem->IconIndex--; + tbbi.iImage = currentTaskItem->IconIndex; + + SendMessage(This->hWndToolbar, + TB_SETBUTTONINFO, + currentTaskItem->Index, + (LPARAM)&tbbi); + } + currentTaskItem++; + } + + ImageList_Remove(This->TaskIcons, TaskItem->IconIndex); +} + static PTASK_ITEM TaskSwitchWnd_FindLastTaskItemOfGroup(IN OUT PTASK_SWITCH_WND This, IN PTASK_GROUP TaskGroup OPTIONAL, @@ -541,6 +575,7 @@ { TBBUTTON tbBtn; INT iIndex; + HICON icon; if (TaskItem->Index >= 0) { @@ -556,7 +591,10 @@ TaskItem->Group); } - tbBtn.iBitmap = 0; + icon = TaskSwitchWnd_GetWndIcon(TaskItem->hWnd); + TaskItem->IconIndex = ImageList_AddIcon(This->TaskIcons, icon); + + tbBtn.iBitmap = TaskItem->IconIndex; tbBtn.fsState = TBSTATE_ENABLED | TBSTATE_ELLIPSES; tbBtn.fsStyle = BTNS_CHECK | BTNS_NOPREFIX | BTNS_SHOWTEXT; tbBtn.dwData = TaskItem->Index; @@ -612,6 +650,7 @@ { TaskSwitchWnd_BeginUpdate(This); + TaskSwitchWnd_RemoveIcon(This, TaskItem); iIndex = TaskItem->Index; if (SendMessage(This->hWndToolbar, TB_DELETEBUTTON, @@ -1107,7 +1146,9 @@ TaskSwitchWnd_FlashTaskItem(IN OUT PTASK_SWITCH_WND This, IN OUT PTASK_ITEM TaskItem) { - /* FIXME: Implement */ + TaskItem->RenderFlashed = 1; + TaskSwitchWnd_UpdateTaskItemButton(This, + TaskItem); } static BOOL @@ -1151,6 +1192,7 @@ else if (TaskItem->Index >= 0) { UpdateTaskItem: + TaskItem->RenderFlashed = 0; TaskSwitchWnd_UpdateTaskItemButton(This, TaskItem); } @@ -1387,6 +1429,18 @@ } static VOID +TaskSwitchWnd_UpdateTheme(IN OUT PTASK_SWITCH_WND This) +{ + if (This->TaskBandTheme) + CloseThemeData(This->TaskBandTheme); + + if (IsThemeActive()) + This->TaskBandTheme = OpenThemeData(This->hWnd, L"TaskBand"); + else + This->TaskBandTheme = NULL; +} + +static VOID TaskSwitchWnd_Create(IN OUT PTASK_SWITCH_WND This) { This->hWndToolbar = CreateWindowEx(0, @@ -1410,12 +1464,17 @@ HMODULE hShell32; SIZE BtnSize; + SetWindowTheme(This->hWndToolbar, L"TaskBand", NULL); + TaskSwitchWnd_UpdateTheme(This); /* Identify the version we're using */ SendMessage(This->hWndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + This->TaskIcons = ImageList_Create(16, 16, ILC_COLOR32, 0, 1000); + SendMessage(This->hWndToolbar, TB_SETIMAGELIST, 0, (LPARAM)This->TaskIcons); + /* Calculate the default button size. Don't save this in This->ButtonSize.cx so that the actual button width gets updated correctly on the first recalculation */ BtnSize.cx = GetSystemMetrics(SM_CXMINIMIZED); @@ -1497,6 +1556,7 @@ } } + CloseThemeData(This->TaskBandTheme); TaskSwitchWnd_DeleteAllTasks(This); } @@ -1729,7 +1789,7 @@ GetCursorPos(&pt); cmd = TrackPopupMenu(hmenu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, This->hWndToolbar, NULL); if (cmd) { - SetForegroundWindow(TaskItem->hWnd); // reactivate window after the context menu has closed + SetForegroundWindow(TaskItem->hWnd); // reactivate window after the context menu has closed PostMessage(TaskItem->hWnd, WM_SYSCOMMAND, cmd, 0); } } @@ -1778,16 +1838,10 @@ TaskSwichWnd_HandleItemPaint(IN OUT PTASK_SWITCH_WND This, IN OUT NMTBCUSTOMDRAW *nmtbcd) { - HFONT hCaptionFont, hBoldCaptionFont; LRESULT Ret = CDRF_DODEFAULT; PTASK_GROUP TaskGroup; PTASK_ITEM TaskItem; -#if TASK_USE_DRAWCAPTIONTEMP != 0 - - UINT uidctFlags = DC_TEXT | DC_ICON | DC_NOSENDMSG; - -#endif TaskItem = FindTaskItemByIndex(This, (INT)nmtbcd->nmcd.dwItemSpec); TaskGroup = FindTaskGroupByIndex(This, @@ -1798,97 +1852,31 @@ if (TaskItem != NULL && IsWindow(TaskItem->hWnd)) { - hCaptionFont = ITrayWindow_GetCaptionFonts(This->Tray, - &hBoldCaptionFont); - if (nmtbcd->nmcd.uItemState & CDIS_CHECKED) - hCaptionFont = hBoldCaptionFont; - -#if TASK_USE_DRAWCAPTIONTEMP != 0 - - /* Make sure we don't draw on the button edges */ - InflateRect(&nmtbcd->nmcd.rc, - -GetSystemMetrics(SM_CXEDGE), - -GetSystemMetrics(SM_CYEDGE)); - - if ((nmtbcd->nmcd.uItemState & CDIS_MARKED) && TaskItem->RenderFlashed) - { - /* This is a slight glitch. We have to move the rectangle so that - the button content appears to be pressed. However, when flashing - is enabled, we can see a light line at the top and left inner - border. We need to fill that area with the flashing color. Note - that since we're using DrawCaptionTemp() the flashing color is - COLOR_ACTIVECAPTION, not COLOR_HIGHLIGHT! */ - FillRect(nmtbcd->nmcd.hdc, - &nmtbcd->nmcd.rc, - (HBRUSH)(COLOR_ACTIVECAPTION + 1)); - - /* Make the button content appear pressed. This however draws a bit - into the right and bottom border of the button edge, making it - look a bit odd. However, selecting a clipping region to prevent - that from happening causes problems with DrawCaptionTemp()! */ - OffsetRect(&nmtbcd->nmcd.rc, - 1, - 1); - - /* Render flashed */ - uidctFlags |= DC_ACTIVE; - } - else - { - uidctFlags |= DC_INBUTTON; - if (nmtbcd->nmcd.uItemState & CDIS_CHECKED) - uidctFlags |= DC_ACTIVE; - } - - if (DrawCapTemp != NULL) - { - /* Draw the button content */ - TaskItem->DisplayTooltip = !DrawCapTemp(TaskItem->hWnd, - nmtbcd->nmcd.hdc, - &nmtbcd->nmcd.rc, - hCaptionFont, - NULL, - NULL, - uidctFlags); - } - - return CDRF_SKIPDEFAULT; - -#else /* !TASK_USE_DRAWCAPTIONTEMP */ - /* Make the entire button flashing if neccessary */ if (nmtbcd->nmcd.uItemState & CDIS_MARKED) { - if (TaskItem->RenderFlashed) + Ret = TBCDRF_NOBACKGROUND; + if (!This->TaskBandTheme){ + SelectObject(nmtbcd->nmcd.hdc, GetSysColorBrush(COLOR_HIGHLIGHT)); + Rectangle(nmtbcd->nmcd.hdc, + nmtbcd->nmcd.rc.left, + nmtbcd->nmcd.rc.top, + nmtbcd->nmcd.rc.right, + nmtbcd->nmcd.rc.bottom); + } + else { - nmtbcd->hbrMonoDither = GetSysColorBrush(COLOR_HIGHLIGHT); - nmtbcd->clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT); - nmtbcd->nHLStringBkMode = TRANSPARENT; - - /* We don't really need to set clrMark because we set the - background mode to TRANSPARENT! */ - nmtbcd->clrMark = GetSysColor(COLOR_HIGHLIGHT); - - Ret |= TBCDRF_USECDCOLORS; + DrawThemeBackground(This->TaskBandTheme, nmtbcd->nmcd.hdc, TDP_FLASHBUTTON, 0, &nmtbcd->nmcd.rc, 0); } - else - Ret |= TBCDRF_NOMARK; + nmtbcd->clrText = GetSysColor(COLOR_HIGHLIGHTTEXT); + return Ret; } - - /* Select the font we want to use */ - SelectObject(nmtbcd->nmcd.hdc, - hCaptionFont); - return Ret | CDRF_NEWFONT; - -#endif - } } else if (TaskGroup != NULL) { /* FIXME: Implement painting for task groups */ } - return Ret; } @@ -1907,22 +1895,7 @@ switch (nmtbcd->nmcd.dwDrawStage) { -#if TASK_USE_DRAWCAPTIONTEMP != 0 - case CDDS_ITEMPREPAINT: - /* We handle drawing in the post-paint stage so that we - don't have to draw the button edges, etc */ - Ret = CDRF_NOTIFYPOSTPAINT; - break; - - case CDDS_ITEMPOSTPAINT: - -#else /* !TASK_USE_DRAWCAPTIONTEMP */ - - case CDDS_ITEMPREPAINT: - -#endif - Ret = TaskSwichWnd_HandleItemPaint(This, nmtbcd); break; @@ -1942,6 +1915,16 @@ return Ret; } +static VOID +TaskSwitchWnd_DrawBackground(HWND hwnd, + HDC hdc) +{ + RECT rect; + + GetClientRect(hwnd, &rect); + DrawThemeParentBackground(hwnd, hdc, &rect); +} + static LRESULT CALLBACK TaskSwitchWndProc(IN HWND hwnd, IN UINT uMsg, @@ -1961,6 +1944,12 @@ { switch (uMsg) { + case WM_THEMECHANGED: + TaskSwitchWnd_UpdateTheme(This); + break; + case WM_ERASEBKGND: + TaskSwitchWnd_DrawBackground(hwnd, (HDC)wParam); + break; case WM_SIZE: { SIZE szClient; Index: base/shell/explorer-new/trayntfy.c =================================================================== --- base/shell/explorer-new/trayntfy.c (revision 57798) +++ base/shell/explorer-new/trayntfy.c (working copy) @@ -19,10 +19,679 @@ */ #include +#include /* + * SysPagerWnd + */ +static const TCHAR szSysPagerWndClass[] = TEXT("SysPager"); + +typedef struct _NOTIFY_ITEM +{ + struct _NOTIFY_ITEM *next; + INT Index; + INT IconIndex; + NOTIFYICONDATA iconData; +} NOTIFY_ITEM, *PNOTIFY_ITEM, **PPNOTIFY_ITEM; + +typedef struct _SYS_PAGER_DATA +{ + HWND hWnd; + HWND hWndToolbar; + HIMAGELIST SysIcons; + PNOTIFY_ITEM NotifyItems; + INT ButtonCount; + INT VisibleButtonCount; +} SYS_PAGER_WND_DATA, *PSYS_PAGER_WND_DATA; + + +static PNOTIFY_ITEM +SysPagerWnd_CreateNotifyItemData(IN OUT PSYS_PAGER_WND_DATA This) +{ + PNOTIFY_ITEM *findNotifyPointer = &This->NotifyItems; + PNOTIFY_ITEM notifyItem; + + notifyItem = malloc(sizeof(*notifyItem)); + if (notifyItem == NULL) + return NULL; + + ZeroMemory(notifyItem, sizeof(*notifyItem)); + notifyItem->next = NULL; + + while (*findNotifyPointer != NULL) + { + findNotifyPointer = &(*findNotifyPointer)->next; + } + + *findNotifyPointer = notifyItem; + + return notifyItem; +} + +static PPNOTIFY_ITEM +SysPagerWnd_FindPPNotifyItemByIconData(IN OUT PSYS_PAGER_WND_DATA This, + IN CONST NOTIFYICONDATA *iconData) +{ + PPNOTIFY_ITEM findNotifyPointer = &This->NotifyItems; + + while (*findNotifyPointer != NULL) + { + if ((*findNotifyPointer)->iconData.hWnd == iconData->hWnd && + (*findNotifyPointer)->iconData.uID == iconData->uID) + { + return findNotifyPointer; + } + findNotifyPointer = &(*findNotifyPointer)->next; + } + + return NULL; +} + +static PPNOTIFY_ITEM +SysPagerWnd_FindPPNotifyItemByIndex(IN OUT PSYS_PAGER_WND_DATA This, + IN WORD wIndex) +{ + PPNOTIFY_ITEM findNotifyPointer = &This->NotifyItems; + + while (*findNotifyPointer != NULL) + { + if ((*findNotifyPointer)->Index == wIndex) + { + return findNotifyPointer; + } + findNotifyPointer = &(*findNotifyPointer)->next; + } + + return NULL; +} + +static VOID +SysPagerWnd_UpdateButton(IN OUT PSYS_PAGER_WND_DATA This, + IN CONST NOTIFYICONDATA *iconData) +{ + TBBUTTONINFO tbbi; + PNOTIFY_ITEM notifyItem; + PPNOTIFY_ITEM NotifyPointer; + + NotifyPointer = SysPagerWnd_FindPPNotifyItemByIconData(This, iconData); + notifyItem = *NotifyPointer; + + tbbi.cbSize = sizeof(tbbi); + tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND; + tbbi.idCommand = notifyItem->Index; + + if (iconData->uFlags & NIF_MESSAGE) + { + notifyItem->iconData.uCallbackMessage = iconData->uCallbackMessage; + } + + if (iconData->uFlags & NIF_ICON) + { + tbbi.dwMask |= TBIF_IMAGE; + notifyItem->IconIndex = tbbi.iImage = ImageList_AddIcon(This->SysIcons, iconData->hIcon); + } + + /* TODO: support NIF_TIP */ + + if (iconData->uFlags & NIF_STATE) + { + if (iconData->dwStateMask & NIS_HIDDEN && + (notifyItem->iconData.dwState & NIS_HIDDEN) != (iconData->dwState & NIS_HIDDEN)) + { + tbbi.dwMask |= TBIF_STATE; + if (iconData->dwState & NIS_HIDDEN) + { + tbbi.fsState |= TBSTATE_HIDDEN; + This->VisibleButtonCount--; + } + else + { + tbbi.fsState &= ~TBSTATE_HIDDEN; + This->VisibleButtonCount++; + } + } + + notifyItem->iconData.dwState &= ~iconData->dwStateMask; + notifyItem->iconData.dwState |= (iconData->dwState & iconData->dwStateMask); + } + + /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */ + + SendMessage(This->hWndToolbar, + TB_SETBUTTONINFO, + (WPARAM)notifyItem->Index, + (LPARAM)&tbbi); +} + + +static VOID +SysPagerWnd_AddButton(IN OUT PSYS_PAGER_WND_DATA This, + IN CONST NOTIFYICONDATA *iconData) +{ + TBBUTTON tbBtn; + PNOTIFY_ITEM notifyItem; + TCHAR text[] = TEXT(""); + + notifyItem = SysPagerWnd_CreateNotifyItemData(This); + + notifyItem->next = NULL; + notifyItem->Index = This->ButtonCount; + This->ButtonCount++; + This->VisibleButtonCount++; + + notifyItem->iconData.hWnd = iconData->hWnd; + notifyItem->iconData.uID = iconData->uID; + + tbBtn.fsState = TBSTATE_ENABLED; + tbBtn.fsStyle = BTNS_NOPREFIX; + tbBtn.dwData = notifyItem->Index; + + tbBtn.iString = (INT_PTR)text; + tbBtn.idCommand=notifyItem->Index; + + + if (iconData->uFlags & NIF_MESSAGE) + { + notifyItem->iconData.uCallbackMessage = iconData->uCallbackMessage; + } + + if (iconData->uFlags & NIF_ICON) + { + notifyItem->IconIndex = tbBtn.iBitmap = ImageList_AddIcon(This->SysIcons, iconData->hIcon); + } + + /* TODO: support NIF_TIP */ + + if (iconData->uFlags & NIF_STATE) + { + notifyItem->iconData.dwState &= ~iconData->dwStateMask; + notifyItem->iconData.dwState |= (iconData->dwState & iconData->dwStateMask); + if (notifyItem->iconData.dwState & NIS_HIDDEN) + { + tbBtn.fsState |= TBSTATE_HIDDEN; + This->VisibleButtonCount--; + } + + } + + /* TODO: support NIF_INFO, NIF_GUID, NIF_REALTIME, NIF_SHOWTIP */ + + SendMessage(This->hWndToolbar, + TB_INSERTBUTTON, + notifyItem->Index, + (LPARAM)&tbBtn); + + SendMessage(This->hWndToolbar, + TB_SETBUTTONSIZE, + 0, + MAKELONG(16, 16)); +} + + +static VOID +SysPagerWnd_RemoveButton(IN OUT PSYS_PAGER_WND_DATA This, + IN CONST NOTIFYICONDATA *iconData) +{ + PPNOTIFY_ITEM NotifyPointer; + + NotifyPointer = SysPagerWnd_FindPPNotifyItemByIconData(This, iconData); + if (NotifyPointer) + { + PNOTIFY_ITEM deleteItem; + PNOTIFY_ITEM updateItem; + deleteItem=*NotifyPointer; + + + SendMessage(This->hWndToolbar, + TB_DELETEBUTTON, + deleteItem->Index, + 0); + + *NotifyPointer=updateItem=deleteItem->next; + + if (!(deleteItem->iconData.dwState & NIS_HIDDEN)) + This->VisibleButtonCount--; + free(deleteItem); + This->ButtonCount--; + + while (updateItem != NULL) + { + TBBUTTONINFO tbbi; + updateItem->Index--; + tbbi.cbSize = sizeof(tbbi); + tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND; + tbbi.idCommand = updateItem->Index; + + SendMessage(This->hWndToolbar, + TB_SETBUTTONINFO, + updateItem->Index, + (LPARAM)&tbbi); + + updateItem = updateItem->next; + } + } +} + +static VOID +SysPagerWnd_HandleButtonClick(IN OUT PSYS_PAGER_WND_DATA This, + IN WORD wIndex, + IN UINT uMsg, + IN WPARAM wParam) +{ + PPNOTIFY_ITEM NotifyPointer; + + NotifyPointer = SysPagerWnd_FindPPNotifyItemByIndex(This, wIndex); + if (NotifyPointer) + { + PNOTIFY_ITEM notifyItem; + notifyItem = *NotifyPointer; + + if (IsWindow(notifyItem->iconData.hWnd)) + { + if (uMsg == WM_MOUSEMOVE || + uMsg == WM_LBUTTONDOWN || + uMsg == WM_MBUTTONDOWN || + uMsg == WM_RBUTTONDOWN) + { + PostMessage(notifyItem->iconData.hWnd, + notifyItem->iconData.uCallbackMessage, + notifyItem->iconData.uID, + uMsg); + } + else + { + DWORD pid; + GetWindowThreadProcessId(notifyItem->iconData.hWnd, &pid); + if (pid == GetCurrentProcessId()) + { + PostMessage(notifyItem->iconData.hWnd, + notifyItem->iconData.uCallbackMessage, + notifyItem->iconData.uID, + uMsg); + } + else + { + SendMessage(notifyItem->iconData.hWnd, + notifyItem->iconData.uCallbackMessage, + notifyItem->iconData.uID, + uMsg); + } + } + } + } +} + +static VOID +SysPagerWnd_DrawBackground(IN HWND hwnd, + IN HDC hdc) +{ + RECT rect; + + GetClientRect(hwnd, &rect); + DrawThemeParentBackground(hwnd, hdc, &rect); +} + +static LRESULT CALLBACK +SysPagerWnd_ToolbarSubclassedProc(IN HWND hWnd, + IN UINT msg, + IN WPARAM wParam, + IN LPARAM lParam, + IN UINT_PTR uIdSubclass, + IN DWORD_PTR dwRefData) +{ + if (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) + { + HWND parent = GetParent(hWnd); + + if (!parent) + return 0; + + return SendMessage(parent, msg, wParam, lParam); + } + + return DefSubclassProc(hWnd, msg, wParam, lParam); +} + +static VOID +SysPagerWnd_Create(IN OUT PSYS_PAGER_WND_DATA This) +{ + This->hWndToolbar = CreateWindowEx(0, + TOOLBARCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | + TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_WRAPABLE | + TBSTYLE_TRANSPARENT | + CCS_TOP | CCS_NORESIZE | CCS_NODIVIDER, + 0, + 0, + 0, + 0, + This->hWnd, + NULL, + hExplorerInstance, + NULL); + if (This->hWndToolbar != NULL) + { + SIZE BtnSize; + SetWindowTheme(This->hWndToolbar, L"TrayNotify", NULL); + /* Identify the version we're using */ + SendMessage(This->hWndToolbar, + TB_BUTTONSTRUCTSIZE, + sizeof(TBBUTTON), + 0); + + This->SysIcons = ImageList_Create(16, 16, ILC_COLOR32, 0, 1000); + SendMessage(This->hWndToolbar, TB_SETIMAGELIST, 0, (LPARAM)This->SysIcons); + + BtnSize.cx = BtnSize.cy = 18; + //BtnSize.cx = GetSystemMetrics(SM_CXMINIMIZED); + //This->ButtonSize.cy = BtnSize.cy = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE)); + SendMessage(This->hWndToolbar, + TB_SETBUTTONSIZE, + 0, + MAKELONG(BtnSize.cx, BtnSize.cy)); + /*SysPagerWnd_AddButton(This);*/ + + SetWindowSubclass(This->hWndToolbar, + SysPagerWnd_ToolbarSubclassedProc, + 2, + (DWORD_PTR)This); + } +} + +static VOID +SysPagerWnd_NCDestroy(IN OUT PSYS_PAGER_WND_DATA This) +{ + /* Free allocated resources */ + SetWindowLongPtr(This->hWnd, + 0, + 0); + HeapFree(hProcessHeap, + 0, + This); +} + +static VOID +SysPagerWnd_NotifyMsg(IN HWND hwnd, + IN WPARAM wParam, + IN LPARAM lParam) +{ + PSYS_PAGER_WND_DATA This = (PSYS_PAGER_WND_DATA)GetWindowLongPtr(hwnd, 0); + + PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT)lParam; + if (cpData->dwData == 1) + { + DWORD trayCommand; + NOTIFYICONDATA *iconData; + HWND parentHWND; + RECT windowRect; + parentHWND = GetParent(This->hWnd); + parentHWND = GetParent(parentHWND); + GetClientRect(parentHWND, &windowRect); + + trayCommand = *(DWORD *) (((BYTE *)cpData->lpData) + 4); + iconData = (NOTIFYICONDATA *) (((BYTE *)cpData->lpData) + 8); + + switch (trayCommand) + { + case NIM_ADD: + { + PPNOTIFY_ITEM NotifyPointer; + NotifyPointer = SysPagerWnd_FindPPNotifyItemByIconData(This, + iconData); + if (!NotifyPointer) + { + SysPagerWnd_AddButton(This, iconData); + } + break; + } + case NIM_MODIFY: + { + PPNOTIFY_ITEM NotifyPointer; + NotifyPointer = SysPagerWnd_FindPPNotifyItemByIconData(This, + iconData); + if(!NotifyPointer) + { + SysPagerWnd_AddButton(This, iconData); + } + else + { + SysPagerWnd_UpdateButton(This, iconData); + } + break; + } + case NIM_DELETE: + { + SysPagerWnd_RemoveButton(This, iconData); + break; + } + } + SendMessage(parentHWND, + WM_SIZE, + 0, + MAKELONG(windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top)); + } +} + +static void +SysPagerWnd_GetSize(IN HWND hwnd, + IN WPARAM wParam, + IN PSIZE size) +{ + PSYS_PAGER_WND_DATA This = (PSYS_PAGER_WND_DATA)GetWindowLongPtr(hwnd, 0); + INT rows = 0; + TBMETRICS tbm; + + if (wParam) /* horizontal */ + { + rows = size->cy / 24; + if (rows == 0) + rows++; + size->cx = (This->VisibleButtonCount+rows - 1) / rows * 24; + } + else + { + rows = size->cx / 24; + if (rows == 0) + rows++; + size->cy = (This->VisibleButtonCount+rows - 1) / rows * 24; + } + + tbm.cbSize = sizeof(tbm); + tbm.dwMask = TBMF_BARPAD | TBMF_BUTTONSPACING; + tbm.cxBarPad = tbm.cyBarPad = 0; + tbm.cxButtonSpacing = 0; + tbm.cyButtonSpacing = 0; + + SendMessage(This->hWndToolbar, + TB_SETMETRICS, + 0, + (LPARAM)&tbm); +} + +static LRESULT CALLBACK +SysPagerWndProc(IN HWND hwnd, + IN UINT uMsg, + IN WPARAM wParam, + IN LPARAM lParam) +{ + PSYS_PAGER_WND_DATA This = NULL; + LRESULT Ret = FALSE; + + if (uMsg != WM_NCCREATE) + { + This = (PSYS_PAGER_WND_DATA)GetWindowLongPtr(hwnd, 0); + } + + if (This != NULL || uMsg == WM_NCCREATE) + { + switch (uMsg) + { + case WM_ERASEBKGND: + SysPagerWnd_DrawBackground(hwnd,(HDC)wParam); + return 0; + + case WM_NCCREATE: + { + LPCREATESTRUCT CreateStruct = (LPCREATESTRUCT)lParam; + This = CreateStruct->lpCreateParams; + This->hWnd = hwnd; + This->NotifyItems = NULL; + This->ButtonCount = 0; + This->VisibleButtonCount = 0; + + SetWindowLongPtr(hwnd, + 0, + (LONG_PTR)This); + + return TRUE; + } + case WM_CREATE: + SysPagerWnd_Create(This); + break; + case WM_NCDESTROY: + SysPagerWnd_NCDestroy(This); + break; + + case WM_SIZE: + { + SIZE szClient; + szClient.cx = LOWORD(lParam); + szClient.cy = HIWORD(lParam); + + Ret = DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + + + if (This->hWndToolbar != NULL && This->hWndToolbar != hwnd) + { + SetWindowPos(This->hWndToolbar, + NULL, + 0, + 0, + szClient.cx, + szClient.cy, + SWP_NOZORDER); + } + } + + default: + if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST) + { + POINT pt; + INT iBtn; + + pt.x = LOWORD(lParam); + pt.y = HIWORD(lParam); + + iBtn = (INT)SendMessage(This->hWndToolbar, + TB_HITTEST, + 0, + (LPARAM)&pt); + + if (iBtn >= 0) + { + SysPagerWnd_HandleButtonClick(This,iBtn,uMsg,wParam); + } + + return 0; + } + + Ret = DefWindowProc(hwnd, + uMsg, + wParam, + lParam); + break; + } + } + + return Ret; +} + +static HWND +CreateSysPagerWnd(IN HWND hWndParent, + IN BOOL bVisible) +{ + PSYS_PAGER_WND_DATA TcData; + DWORD dwStyle; + HWND hWnd = NULL; + + TcData = HeapAlloc(hProcessHeap, + 0, + sizeof(*TcData)); + if (TcData != NULL) + { + ZeroMemory(TcData, + sizeof(*TcData)); + + //TcData->IsHorizontal = TRUE; + /* Create the window. The tray window is going to move it to the correct + position and resize it as needed. */ + dwStyle = WS_CHILD | WS_CLIPSIBLINGS; + if (bVisible) + dwStyle |= WS_VISIBLE; + + hWnd = CreateWindowEx(0, + szSysPagerWndClass, + NULL, + dwStyle, + 0, + 0, + 0, + 0, + hWndParent, + NULL, + hExplorerInstance, + TcData); + + if (hWnd == NULL) + { + HeapFree(hProcessHeap, + 0, + TcData); + } + } + + SetWindowTheme(hWnd, L"TrayNotify", NULL); + + return hWnd; + +} + +static BOOL +RegisterSysPagerWndClass(VOID) +{ + WNDCLASS wcTrayClock; + + wcTrayClock.style = CS_DBLCLKS; + wcTrayClock.lpfnWndProc = SysPagerWndProc; + wcTrayClock.cbClsExtra = 0; + wcTrayClock.cbWndExtra = sizeof(PSYS_PAGER_WND_DATA); + wcTrayClock.hInstance = hExplorerInstance; + wcTrayClock.hIcon = NULL; + wcTrayClock.hCursor = LoadCursor(NULL, + IDC_ARROW); + wcTrayClock.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wcTrayClock.lpszMenuName = NULL; + wcTrayClock.lpszClassName = szSysPagerWndClass; + + return RegisterClass(&wcTrayClock) != 0; +} + +static VOID +UnregisterSysPagerWndClass(VOID) +{ + UnregisterClass(szSysPagerWndClass, + hExplorerInstance); +} + + +/* * TrayClockWnd - */ + */ static const TCHAR szTrayClockWndClass[] = TEXT("TrayClockWClass"); static LPCTSTR s_szRegistryKey = _T("Software\\ReactOS\\Features\\Explorer"); @@ -40,46 +709,46 @@ {TRUE, 0, NULL}, {FALSE, 0, TEXT("dddd")}, {FALSE, DATE_SHORTDATE, NULL} -}; +}; -HRESULT RegGetDWord(HKEY hKey, LPCTSTR szValueName, DWORD * lpdwResult) +HRESULT RegGetDWord(HKEY hKey, LPCTSTR szValueName, DWORD * lpdwResult) { - LONG lResult; - DWORD dwDataSize = sizeof(DWORD); - DWORD dwType = 0; + LONG lResult; + DWORD dwDataSize = sizeof(DWORD); + DWORD dwType = 0; - // Check input parameters... - if (hKey == NULL || lpdwResult == NULL) return E_INVALIDARG; + // Check input parameters... + if (hKey == NULL || lpdwResult == NULL) return E_INVALIDARG; - // Get dword value from the registry... - lResult = RegQueryValueEx(hKey, szValueName, 0, &dwType, (LPBYTE) lpdwResult, &dwDataSize ); + // Get dword value from the registry... + lResult = RegQueryValueEx(hKey, szValueName, 0, &dwType, (LPBYTE) lpdwResult, &dwDataSize ); - // Check result and make sure the registry value is a DWORD(REG_DWORD)... - if (lResult != ERROR_SUCCESS) return HRESULT_FROM_WIN32(lResult); - else if (dwType != REG_DWORD) return DISP_E_TYPEMISMATCH; + // Check result and make sure the registry value is a DWORD(REG_DWORD)... + if (lResult != ERROR_SUCCESS) return HRESULT_FROM_WIN32(lResult); + else if (dwType != REG_DWORD) return DISP_E_TYPEMISMATCH; - return NOERROR; + return NOERROR; } void LoadSettings(void) { - HKEY hKey = NULL; - DWORD dwValue; + HKEY hKey = NULL; + DWORD dwValue; - if (RegOpenKey(HKEY_CURRENT_USER, s_szRegistryKey, &hKey) == ERROR_SUCCESS) - { - RegGetDWord(hKey, TEXT("blShowSeconds"), &dwValue); - if (dwValue == 1) - { - blShowSeconds = TRUE; - } - else - { - blShowSeconds = FALSE; - } + if (RegOpenKey(HKEY_CURRENT_USER, s_szRegistryKey, &hKey) == ERROR_SUCCESS) + { + RegGetDWord(hKey, TEXT("blShowSeconds"), &dwValue); + if (dwValue == 1) + { + blShowSeconds = TRUE; + } + else + { + blShowSeconds = FALSE; + } - RegCloseKey(hKey); - } + RegCloseKey(hKey); + } } #define CLOCKWND_FORMAT_COUNT (sizeof(ClockWndFormats) / sizeof(ClockWndFormats[0])) @@ -92,9 +761,10 @@ HWND hWnd; HWND hWndNotify; HFONT hFont; + COLORREF textColor; RECT rcText; SYSTEMTIME LocalTime; - + union { DWORD dwFlags; @@ -113,6 +783,49 @@ TCHAR szLines[CLOCKWND_FORMAT_COUNT][48]; } TRAY_CLOCK_WND_DATA, *PTRAY_CLOCK_WND_DATA; +static VOID +TrayClockWnd_SetFont(IN OUT PTRAY_CLOCK_WND_DATA This, + IN HFONT hNewFont, + IN BOOL bRedraw); + +static VOID +TrayClockWnd_UpdateTheme(IN OUT PTRAY_CLOCK_WND_DATA This) +{ + LOGFONTW clockFont; + HTHEME clockTheme; + HFONT hFont; + + clockTheme = OpenThemeData(This->hWnd, L"Clock"); + + if (clockTheme) + { + GetThemeFont(clockTheme, + NULL, + CLP_TIME, + 0, + TMT_FONT, + &clockFont); + + hFont = CreateFontIndirect(&clockFont); + + TrayClockWnd_SetFont(This, + hFont, + FALSE); + + GetThemeColor(clockTheme, + CLP_TIME, + 0, + TMT_TEXTCOLOR, + &This->textColor); + } + else + { + This->textColor = RGB(0,0,0); + } + + CloseThemeData(clockTheme); +} + static BOOL TrayClockWnd_MeasureLines(IN OUT PTRAY_CLOCK_WND_DATA This) { @@ -276,11 +989,11 @@ if (iRet != 0 && i == 0) { - if (blShowSeconds == FALSE) - { - (This->szLines[0][5] = '\0'); - }; - + if (blShowSeconds == FALSE) + { + This->szLines[0][5] = '\0'; + }; + /* Set the window text to the time only */ SetWindowText(This->hWnd, This->szLines[i]); @@ -344,10 +1057,10 @@ /* Calculate the due time */ GetLocalTime(&This->LocalTime); uiDueTime = 1000 - (UINT)This->LocalTime.wMilliseconds; - if (blShowSeconds == TRUE) - uiDueTime += ( (UINT)This->LocalTime.wSecond) * 100; - else - uiDueTime += (59 - (UINT)This->LocalTime.wSecond) * 1000; + if (blShowSeconds == TRUE) + uiDueTime += ( (UINT)This->LocalTime.wSecond) * 100; + else + uiDueTime += (59 - (UINT)This->LocalTime.wSecond) * 1000; if (uiDueTime < USER_TIMER_MINIMUM || uiDueTime > USER_TIMER_MAXIMUM) uiDueTime = 1000; @@ -401,7 +1114,7 @@ { UINT uiDueTime; BOOL Ret; - int intWait1, intWait2; + UINT uiWait1, uiWait2; /* Kill the initialization timer */ KillTimer(This->hWnd, @@ -409,26 +1122,26 @@ This->IsInitTimerEnabled = FALSE; uiDueTime = TrayClockWnd_CalculateDueTime(This); - - if (blShowSeconds == TRUE) - { - intWait1 = 1000-200; - intWait2 = 1000; - } - else - { - intWait1 = 60*1000-200; - intWait2 = 60*1000; - } - if (uiDueTime > intWait1) + if (blShowSeconds == TRUE) { + uiWait1 = 1000 - 200; + uiWait2 = 1000; + } + else + { + uiWait1 = 60 * 1000 - 200; + uiWait2 = 60 * 1000; + } + + if (uiDueTime > uiWait1) + { /* The update of the clock will be up to 200 ms late, but that's acceptable. We're going to setup a timer that fires depending - intWait2. */ + uiWait2. */ Ret = SetTimer(This->hWnd, ID_TRAYCLOCK_TIMER, - intWait2, + uiWait2, NULL) != 0; This->IsTimerEnabled = Ret; @@ -483,6 +1196,8 @@ iPrevBkMode = SetBkMode(hDC, TRANSPARENT); + SetTextColor(hDC, This->textColor); + hPrevFont = SelectObject(hDC, This->hFont); @@ -532,6 +1247,16 @@ } } +static VOID +TrayClockWnd_DrawBackground(IN HWND hwnd, + IN HDC hdc) +{ + RECT rect; + + GetClientRect(hwnd, &rect); + DrawThemeParentBackground(hwnd, hdc, &rect); +} + static LRESULT CALLBACK TrayClockWndProc(IN HWND hwnd, IN UINT uMsg, @@ -551,6 +1276,12 @@ { switch (uMsg) { + case WM_THEMECHANGED: + TrayClockWnd_UpdateTheme(This); + break; + case WM_ERASEBKGND: + TrayClockWnd_DrawBackground(hwnd, (HDC)wParam); + break; case WM_PAINT: case WM_PRINTCLIENT: { @@ -621,6 +1352,7 @@ SetWindowLongPtr(hwnd, 0, (LONG_PTR)This); + TrayClockWnd_UpdateTheme(This); return TRUE; } @@ -677,7 +1409,7 @@ PTRAY_CLOCK_WND_DATA TcData; DWORD dwStyle; HWND hWnd = NULL; - LoadSettings(); + LoadSettings(); TcData = HeapAlloc(hProcessHeap, 0, @@ -714,6 +1446,7 @@ TcData); } } + SetWindowTheme(hWnd, L"TrayNotify", NULL); return hWnd; @@ -760,9 +1493,13 @@ HWND hWnd; HWND hWndTrayClock; HWND hWndNotify; + HWND hWndSysPager; + HTHEME TrayTheme; SIZE szTrayClockMin; - SIZE szNonClient; + SIZE szTrayNotify; + MARGINS ContentMargin; ITrayWindow *TrayWindow; + HFONT hFontClock; union { DWORD dwFlags; @@ -775,22 +1512,43 @@ } TRAY_NOTIFY_WND_DATA, *PTRAY_NOTIFY_WND_DATA; static VOID -TrayNotifyWnd_UpdateStyle(IN OUT PTRAY_NOTIFY_WND_DATA This) +TrayNotifyWnd_UpdateTheme(IN OUT PTRAY_NOTIFY_WND_DATA This) { - RECT rcClient = { 0, 0, 0, 0 }; + LONG_PTR style; - if (AdjustWindowRectEx(&rcClient, - GetWindowLongPtr(This->hWnd, - GWL_STYLE), - FALSE, - GetWindowLongPtr(This->hWnd, - GWL_EXSTYLE))) + if (This->TrayTheme) + CloseThemeData(This->TrayTheme); + + if (IsThemeActive()) + This->TrayTheme = OpenThemeData(This->hWnd, L"TrayNotify"); + else + This->TrayTheme = 0; + + if (This->TrayTheme) { - This->szNonClient.cx = rcClient.right - rcClient.left; - This->szNonClient.cy = rcClient.bottom - rcClient.top; + style = GetWindowLongPtr(This->hWnd, GWL_EXSTYLE); + style = style & ~WS_EX_STATICEDGE; + SetWindowLongPtr(This->hWnd, GWL_EXSTYLE, style); + + GetThemeMargins(This->TrayTheme, + NULL, + TNP_BACKGROUND, + 0, + TMT_CONTENTMARGINS, + NULL, + &This->ContentMargin); } else - This->szNonClient.cx = This->szNonClient.cy = 0; + { + style = GetWindowLongPtr(This->hWnd, GWL_EXSTYLE); + style = style | WS_EX_STATICEDGE; + SetWindowLongPtr(This->hWnd, GWL_EXSTYLE, style); + + This->ContentMargin.cxLeftWidth = 0; + This->ContentMargin.cxRightWidth = 0; + This->ContentMargin.cyTopHeight = 0; + This->ContentMargin.cyBottomHeight = 0; + } } static VOID @@ -799,7 +1557,10 @@ This->hWndTrayClock = CreateTrayClockWnd(This->hWnd, !This->HideClock); - TrayNotifyWnd_UpdateStyle(This); + This->hWndSysPager = CreateSysPagerWnd(This->hWnd, + !This->HideClock); + + TrayNotifyWnd_UpdateTheme(This); } static VOID @@ -818,21 +1579,26 @@ IN BOOL Horizontal, IN OUT PSIZE pSize) { + SIZE szClock = { 0, 0 }; + SIZE szTray = { 0, 0 }; + This->IsHorizontal = Horizontal; + if (This->IsHorizontal) + SetWindowTheme(This->hWnd, L"TrayNotifyHoriz", NULL); + else + SetWindowTheme(This->hWnd, L"TrayNotifyVert", NULL); if (!This->HideClock) { - SIZE szClock = { 0, 0 }; - if (Horizontal) { - szClock.cy = pSize->cy - This->szNonClient.cy - (2 * TRAY_NOTIFY_WND_SPACING_Y); + szClock.cy = pSize->cy - (2 * TRAY_NOTIFY_WND_SPACING_Y); if (szClock.cy <= 0) goto NoClock; } else { - szClock.cx = pSize->cx - This->szNonClient.cx - (2 * TRAY_NOTIFY_WND_SPACING_X); + szClock.cx = pSize->cx - (2 * TRAY_NOTIFY_WND_SPACING_X); if (szClock.cx <= 0) goto NoClock; } @@ -846,23 +1612,45 @@ } else NoClock: - This->szTrayClockMin = This->szNonClient; + This->szTrayClockMin = szClock; if (Horizontal) { - pSize->cx = This->szNonClient.cx + (2 * TRAY_NOTIFY_WND_SPACING_X); + szTray.cy = pSize->cy - (2 * TRAY_NOTIFY_WND_SPACING_Y); + } + else + { + szTray.cx = pSize->cx - (2 * TRAY_NOTIFY_WND_SPACING_X); + } + SysPagerWnd_GetSize(This->hWndSysPager, + Horizontal, + &szTray); + + This->szTrayNotify = szTray; + + if (Horizontal) + { + pSize->cx = (2 * TRAY_NOTIFY_WND_SPACING_X); + if (!This->HideClock) pSize->cx += TRAY_NOTIFY_WND_SPACING_X + This->szTrayClockMin.cx; + + pSize->cx += szTray.cx; } else { - pSize->cy = This->szNonClient.cy + (2 * TRAY_NOTIFY_WND_SPACING_Y); + pSize->cy = (2 * TRAY_NOTIFY_WND_SPACING_Y); if (!This->HideClock) pSize->cy += TRAY_NOTIFY_WND_SPACING_Y + This->szTrayClockMin.cy; + + pSize->cy += szTray.cy; } + pSize->cy += This->ContentMargin.cyTopHeight + This->ContentMargin.cyBottomHeight; + pSize->cx += This->ContentMargin.cxLeftWidth + This->ContentMargin.cxRightWidth; + return TRUE; } @@ -897,9 +1685,60 @@ szClock.cx, szClock.cy, SWP_NOZORDER); + + if (This->IsHorizontal) + { + //szClock.cx *=2; + ptClock.x -= This->szTrayNotify.cx; + } + else + { + //szClock.cy *=2; + ptClock.y -= This->szTrayNotify.cy; + } + + SetWindowPos(This->hWndSysPager, + NULL, + ptClock.x, + ptClock.y, + This->szTrayNotify.cx, + This->szTrayNotify.cy, + SWP_NOZORDER); } } +static LRESULT +TrayNotifyWnd_DrawBackground(IN HWND hwnd, + IN UINT uMsg, + IN WPARAM wParam, + IN LPARAM lParam) +{ + PTRAY_NOTIFY_WND_DATA This = (PTRAY_NOTIFY_WND_DATA)GetWindowLongPtr(hwnd, 0); + RECT rect; + HDC hdc = (HDC)wParam; + + GetClientRect(hwnd, &rect); + + DrawThemeParentBackground(hwnd, hdc, &rect); + DrawThemeBackground(This->TrayTheme, hdc, TNP_BACKGROUND, 0, &rect, 0); + + return 0; +} + +VOID +TrayNotify_NotifyMsg(IN HWND hwnd, + IN WPARAM wParam, + IN LPARAM lParam) +{ + PTRAY_NOTIFY_WND_DATA This = (PTRAY_NOTIFY_WND_DATA)GetWindowLongPtr(hwnd, 0); + if (This->hWndSysPager) + { + SysPagerWnd_NotifyMsg(This->hWndSysPager, + wParam, + lParam); + } +} + static LRESULT CALLBACK TrayNotifyWndProc(IN HWND hwnd, IN UINT uMsg, @@ -919,6 +1758,14 @@ { switch (uMsg) { + case WM_THEMECHANGED: + TrayNotifyWnd_UpdateTheme(This); + return 0; + case WM_ERASEBKGND: + return TrayNotifyWnd_DrawBackground(hwnd, + uMsg, + wParam, + lParam); case TNWM_GETMINIMUMSIZE: { Ret = (LRESULT)TrayNotifyWnd_GetMinimumSize(This, @@ -1112,6 +1959,7 @@ UnregisterClass(szTrayNotifyWndClass, hExplorerInstance); } + RegisterSysPagerWndClass(); } return Ret; @@ -1122,6 +1970,8 @@ { UnregisterTrayClockWndClass(); + UnregisterSysPagerWndClass(); + UnregisterClass(szTrayNotifyWndClass, hExplorerInstance); } Index: base/shell/explorer-new/traywnd.c =================================================================== --- base/shell/explorer-new/traywnd.c (revision 57798) +++ base/shell/explorer-new/traywnd.c (working copy) @@ -43,6 +43,7 @@ const IShellDesktopTrayVtbl *lpVtblShellDesktopTray; LONG Ref; + HTHEME TaskbarTheme; HWND hWnd; HWND hWndDesktop; @@ -1027,6 +1028,12 @@ This->TrayBandSite = NULL; } + if(This->TaskbarTheme) + { + CloseThemeData(This->TaskbarTheme); + This->TaskbarTheme = NULL; + } + ITrayWindowImpl_Release(ITrayWindow_from_impl(This)); if (InterlockedDecrement(&TrayWndCount) == 0) @@ -1113,6 +1120,8 @@ BOOL Horizontal; HDWP dwp; + ITrayWindowImpl_UpdateStartButton(This, + NULL); if (prcClient != NULL) { rcClient = *prcClient; @@ -1402,10 +1411,25 @@ } 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, @@ -1458,6 +1482,7 @@ NULL); if (This->hwndStart) { + SetWindowTheme(This->hwndStart, L"Start", NULL); SendMessage(This->hwndStart, WM_SETFONT, (WPARAM)This->hStartBtnFont, @@ -1538,6 +1563,7 @@ 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), @@ -1883,6 +1909,108 @@ 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); + + hShell32 = GetModuleHandle(TEXT("SHELL32.DLL")); + RunFileDlg = (RUNFILEDLG)GetProcAddress(hShell32, (LPCSTR)61); + + RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY); + + DestroyWindow(hwnd); + + return 0; +} + static LRESULT CALLBACK TrayWndProc(IN HWND hwnd, IN UINT uMsg, @@ -1923,6 +2051,32 @@ switch (uMsg) { + 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; @@ -1936,12 +2090,15 @@ return HTBORDER; } + /* 0 is a possible valid response for MapWindowPoints. + While the default error code is 0. An extra check needs to be done */ + SetLastError(-1); if (GetClientRect(hwnd, &rcClient) && - MapWindowPoints(hwnd, - NULL, - (LPPOINT)&rcClient, - 2) != 0) + (MapWindowPoints(hwnd, + NULL, + (LPPOINT)&rcClient, + 2) != 0 || GetLastError() != 0)) { pt.x = (SHORT)LOWORD(lParam); pt.y = (SHORT)HIWORD(lParam); @@ -1961,30 +2118,23 @@ 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; @@ -2037,7 +2187,7 @@ case WM_SIZE: { RECT rcClient; - + InvalidateRect(This->hWnd, NULL, TRUE); if (wParam == SIZE_RESTORED && lParam == 0) { ITrayWindowImpl_ResizeWorkArea(This); @@ -2382,13 +2532,13 @@ case IDM_RUN: { - HANDLE hShell32; - RUNFILEDLG RunFileDlg; + CloseHandle(CreateThread(NULL, + 0, + RunFileDlgThread, + This, + 0, + NULL)); - hShell32 = GetModuleHandle(TEXT("SHELL32.DLL")); - RunFileDlg = (RUNFILEDLG)GetProcAddress(hShell32, (LPCSTR)61); - - RunFileDlg(hwnd, NULL, NULL, NULL, NULL, RFF_CALCDIRECTORY); break; }