From 538a9b34e2cedfc9dfddd9b7d78086358c9eded4 Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Fri, 2 Jan 2004 21:09:41 +0000 Subject: [PATCH] reimplemented start menu as light weight version svn path=/trunk/; revision=7412 --- .../subsys/system/explorer/doc/changes.txt | 1 + .../system/explorer/taskbar/startmenu.cpp | 477 ++++++++++++++---- .../system/explorer/taskbar/startmenu.h | 88 +++- .../subsys/system/explorer/utility/utility.h | 19 +- .../subsys/system/explorer/utility/window.cpp | 16 +- .../subsys/system/explorer/utility/window.h | 4 +- 6 files changed, 489 insertions(+), 116 deletions(-) diff --git a/reactos/subsys/system/explorer/doc/changes.txt b/reactos/subsys/system/explorer/doc/changes.txt index 3c71b82bd27..83771a52c21 100644 --- a/reactos/subsys/system/explorer/doc/changes.txt +++ b/reactos/subsys/system/explorer/doc/changes.txt @@ -50,3 +50,4 @@ If you search for more information, look into the CVS repository. 06.12.2003 m. fuchs basic support to display NTFS streams in winefile windows 20.12.2003 m. fuchs context menu implementation for desktop window 01.01.2004 m. fuchs integrated icons of Everaldo (http://www.everaldo.com) into the start menu. +02.01.2004 m. fuchs reimplemented start menu as light weight version diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.cpp b/reactos/subsys/system/explorer/taskbar/startmenu.cpp index ef6307ae872..e8fbac426c9 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.cpp +++ b/reactos/subsys/system/explorer/taskbar/startmenu.cpp @@ -50,6 +50,9 @@ StartMenu::StartMenu(HWND hwnd) _border_left = 0; _border_top = 0; _last_pos = WindowRect(hwnd).pos(); +#ifdef _LIGHT_STARTMENU + _selected_id = 0; +#endif } StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info) @@ -65,6 +68,9 @@ StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info) _border_left = 0; _border_top = create_info._border_top; _last_pos = WindowRect(hwnd).pos(); +#ifdef _LIGHT_STARTMENU + _selected_id = 0; +#endif } StartMenu::~StartMenu() @@ -100,7 +106,11 @@ HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndP top_height = 0; } - RECT rect = {x, y, x+STARTMENU_WIDTH_MIN, y+top_height}; // start height before adding an menu button + RECT rect = {x, y-STARTMENU_LINE_HEIGHT-top_height, x+STARTMENU_WIDTH_MIN, y}; + +#ifndef _LIGHT_STARTMENU + rect.top += STARTMENU_LINE_HEIGHT; +#endif AdjustWindowRectEx(&rect, style, FALSE, ex_style); @@ -140,11 +150,23 @@ LRESULT StartMenu::Init(LPCREATESTRUCT pcs) if ((*it)->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) hasSubmenu = true; +#ifdef _LIGHT_STARTMENU + _buttons.push_back(SMBtnInfo(sme, it->first, hasSubmenu)); +#else AddButton(sme._title, sme._hIcon, hasSubmenu, it->first); +#endif } +#ifdef _LIGHT_STARTMENU + if (_buttons.empty()) +#else if (!GetWindow(_hwnd, GW_CHILD)) - AddButton(ResString(IDS_EMPTY), 0, false, (UINT)-1, WS_VISIBLE|WS_CHILD|BS_OWNERDRAW|WS_DISABLED); +#endif + AddButton(ResString(IDS_EMPTY), 0, false, -1, false); + +#ifdef _LIGHT_STARTMENU + ResizeToButtons(); +#endif } catch(COMException& e) { HandleException(e, pcs->hwndParent); // destroys the start menu window while switching focus } @@ -199,7 +221,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { case WM_PAINT: - DrawFloatingButton(PaintCanvas(_hwnd)); + Paint(PaintCanvas(_hwnd)); break; case WM_SIZE: @@ -247,6 +269,13 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) StartMenu::Create(pos.left+3, pos.bottom-3, _create_info._folders, 0, _create_info._title, _create_info._creator); CloseStartMenu(); } + +#ifdef _LIGHT_STARTMENU + int id = ButtonHitTest(Point(lparam)); + + if (id) + Command(id, BN_CLICKED); +#endif break;} case WM_SYSCOMMAND: @@ -264,6 +293,20 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) CloseStartMenu(); break; +#ifdef _LIGHT_STARTMENU + case WM_MOUSEMOVE: { + // automatically set the focus to startmenu entries when moving the mouse over them + int new_id = ButtonHitTest(Point(lparam)); + + if (new_id != _selected_id) + SelectButton(new_id); + break;} + + case WM_KEYDOWN: + if (wparam==VK_RETURN && _selected_id) + Command(_selected_id, BN_CLICKED); + break; +#else case PM_STARTENTRY_FOCUSED: { ///@todo use TrackMouseEvent() and WM_MOUSEHOVER to wait a bit before opening submenus BOOL hasSubmenu = wparam; HWND hctrl = (HWND)lparam; @@ -278,6 +321,7 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) CloseOtherSubmenus(0); } break;} +#endif case PM_STARTENTRY_LAUNCHED: if (GetWindowStyle(_hwnd) & WS_CAPTION) // don't automatically close floating menus @@ -300,6 +344,154 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) } +void StartMenu::Paint(HDC hdc) +{ + DrawFloatingButton(hdc); + +#ifdef _LIGHT_STARTMENU + ClientRect clnt(_hwnd); + RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; + + int sep_width = rect.right-rect.left - 4; + + FontSelection font(hdc, GetStockFont(DEFAULT_GUI_FONT)); + BkMode bk_mode(hdc, TRANSPARENT); + + for(SMBtnList::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + const SMBtnInfo& info = *it; + + if (info._id == -1) { // a separator? + rect.bottom = rect.top + STARTMENU_SEP_HEIGHT; + + BrushSelection brush_sel(hdc, GetSysColorBrush(COLOR_BTNSHADOW)); + PatBlt(hdc, rect.left+2, rect.top+STARTMENU_SEP_HEIGHT/2-1, sep_width, 1, PATCOPY); + + SelectBrush(hdc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); + PatBlt(hdc, rect.left+2, rect.top+STARTMENU_SEP_HEIGHT/2, sep_width, 1, PATCOPY); + } else { + rect.bottom = rect.top + STARTMENU_LINE_HEIGHT; + + DrawStartMenuButton(hdc, rect, info._title, info._hIcon, + info._hasSubmenu, info._enabled, info._id==_selected_id, false); + } + + rect.top = rect.bottom; + } +#endif +} + +#ifdef _LIGHT_STARTMENU + +int StartMenu::ButtonHitTest(POINT pt) +{ + ClientRect clnt(_hwnd); + RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; + + if (pt.xrect.right) + return 0; + + for(SMBtnList::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + const SMBtnInfo& info = *it; + + if (rect.top > pt.y) + break; + + rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT); + + if (pt.y < rect.bottom) // PtInRect(&rect, pt) + return info._id; + + rect.top = rect.bottom; + } + + return 0; +} + +void StartMenu::InvalidateSelection() +{ + if (!_selected_id) + return; + + ClientRect clnt(_hwnd); + RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; + + for(SMBtnList::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + const SMBtnInfo& info = *it; + + rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT); + + if (info._id == _selected_id) { + InvalidateRect(_hwnd, &rect, TRUE); + break; + } + + rect.top = rect.bottom; + } +} + +const SMBtnInfo* StartMenu::GetButtonInfo(int id) const +{ + for(SMBtnList::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) + if (it->_id == id) + return &*it; + + return NULL; +} + +void StartMenu::SelectButton(int id) +{ + InvalidateSelection(); + + _selected_id = id; + + InvalidateSelection(); + + // automatically open submenus + if (_selected_id) + if (GetButtonInfo(_selected_id)->_hasSubmenu) { + UpdateWindow(_hwnd); // draw focused button before waiting on submenu creation + Command(_selected_id, BN_CLICKED); + } else + CloseOtherSubmenus(0); // close any open submenu +} + +#endif + + +bool StartMenu::GetButtonRect(int id, PRECT prect) +{ +#ifdef _LIGHT_STARTMENU + ClientRect clnt(_hwnd); + RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; + + for(SMBtnList::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + const SMBtnInfo& info = *it; + + rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT); + + if (info._id == _selected_id) { + *prect = rect; + return true; + } + + rect.top = rect.bottom; + } + + return false; +#else + HWND btn = GetDlgItem(_hwnd, id); + + if (btn) { + GetWindowRect(btn, prect); + ScreenToClient(_hwnd, prect); + + return true; + } else + return false; +#endif +} + + void StartMenu::DrawFloatingButton(HDC hdc) { static ResIconEx floatingIcon(IDI_FLOATING, 8, 4); @@ -364,9 +556,9 @@ int StartMenu::Command(int id, int code) } -StartMenuEntry& StartMenu::AddEntry(LPCTSTR title, HICON hIcon, UINT id) +StartMenuEntry& StartMenu::AddEntry(LPCTSTR title, HICON hIcon, int id) { - if (id == (UINT)-1) + if (id == -1) id = ++_next_id; StartMenuEntry& sme = _entries[id]; @@ -409,8 +601,14 @@ StartMenuEntry& StartMenu::AddEntry(const ShellFolder folder, const ShellEntry* } -void StartMenu::AddButton(LPCTSTR title, HICON hIcon, bool hasSubmenu, UINT id, DWORD style) + +void StartMenu::AddButton(LPCTSTR title, HICON hIcon, bool hasSubmenu, int id, bool enabled) { +#ifdef _LIGHT_STARTMENU + _buttons.push_back(SMBtnInfo(title, hIcon, id, hasSubmenu, enabled)); +#else + DWORD style = enabled? WS_VISIBLE|WS_CHILD|BS_OWNERDRAW: WS_VISIBLE|WS_CHILD|BS_OWNERDRAW|WS_DISABLED; + WindowRect rect(_hwnd); ClientRect clnt(_hwnd); @@ -423,8 +621,11 @@ void StartMenu::AddButton(LPCTSTR title, HICON hIcon, bool hasSubmenu, UINT id, rect.bottom += STARTMENU_LINE_HEIGHT; } + WindowCanvas canvas(_hwnd); + FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT)); + // widen window, if it is too small - int text_width = StartMenuButton::GetTextWidth(title,_hwnd) + 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/; + int text_width = GetStartMenuBtnTextWidth(canvas, title, _hwnd) + 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/; int cx = clnt.right - _border_left; if (text_width > cx) @@ -434,10 +635,14 @@ void StartMenu::AddButton(LPCTSTR title, HICON hIcon, bool hasSubmenu, UINT id, StartMenuCtrl(_hwnd, _border_left, clnt.bottom, rect.right-rect.left-_border_left, title, id, hIcon, hasSubmenu, style); +#endif } void StartMenu::AddSeparator() { +#ifdef _LIGHT_STARTMENU + _buttons.push_back(SMBtnInfo(NULL, 0, -1, false)); +#else WindowRect rect(_hwnd); ClientRect clnt(_hwnd); @@ -453,6 +658,7 @@ void StartMenu::AddSeparator() MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); StartMenuSeparator(_hwnd, _border_left, clnt.bottom, rect.right-rect.left-_border_left); +#endif } @@ -519,14 +725,14 @@ void StartMenu::CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTS if (!CloseOtherSubmenus(id)) return; - HWND btn = GetDlgItem(_hwnd, id); + RECT rect; int x, y; - if (btn) { - WindowRect pos(btn); + if (GetButtonRect(id, &rect)) { + ClientToScreen(_hwnd, &rect); - x = pos.right; // Submenus should overlap their parent a bit. - y = pos.top+STARTMENU_LINE_HEIGHT-_border_top; + x = rect.right; // Submenus should overlap their parent a bit. + y = rect.top+STARTMENU_LINE_HEIGHT-_border_top; } else { WindowRect pos(_hwnd); @@ -587,23 +793,115 @@ void StartMenu::CloseStartMenu(int id) } -int StartMenuButton::GetTextWidth(LPCTSTR title, HWND hwnd) +int GetStartMenuBtnTextWidth(HDC hdc, LPCTSTR title, HWND hwnd) { - WindowCanvas canvas(hwnd); - FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT)); - RECT rect = {0, 0, 0, 0}; - DrawText(canvas, title, -1, &rect, DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT); + DrawText(hdc, title, -1, &rect, DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT); return rect.right-rect.left; } +void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon, + bool hasSubmenu, bool enabled, bool has_focus, bool pushed) +{ + UINT style = DFCS_BUTTONPUSH; + + if (!enabled) + style |= DFCS_INACTIVE; + + POINT iconPos = {rect.left+2, (rect.top+rect.bottom-16)/2}; + RECT textRect = {rect.left+16+4, rect.top+2, rect.right-4, rect.bottom-4}; + + if (pushed) { + style |= DFCS_PUSHED; + ++iconPos.x; ++iconPos.y; + ++textRect.left; ++textRect.top; + ++textRect.right; ++textRect.bottom; + } + + int bk_color = COLOR_BTNFACE; + int text_color = COLOR_BTNTEXT; + + if (has_focus) { + bk_color = COLOR_HIGHLIGHT; + text_color = COLOR_HIGHLIGHTTEXT; + } + + HBRUSH bk_brush = GetSysColorBrush(bk_color); + + FillRect(hdc, &rect, bk_brush); + DrawIconEx(hdc, iconPos.x, iconPos.y, hIcon, 16, 16, 0, bk_brush, DI_NORMAL); + + // draw submenu arrow at the right + if (hasSubmenu) { + static SmallIcon arrowIcon(IDI_ARROW); + static SmallIcon selArrowIcon(IDI_ARROW_SELECTED); + + DrawIconEx(hdc, rect.right-16, iconPos.y, + has_focus?selArrowIcon:arrowIcon, 16, 16, 0, bk_brush, DI_NORMAL); + } + + BkMode bk_mode(hdc, TRANSPARENT); + + if (!enabled) // dis->itemState & (ODS_DISABLED|ODS_GRAYED) + DrawGrayText(hdc, &textRect, title, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER); + else { + TextColor lcColor(hdc, GetSysColor(text_color)); + DrawText(hdc, title, -1, &textRect, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER); + } +} + + +#ifdef _LIGHT_STARTMENU + +void StartMenu::ResizeToButtons() +{ + WindowRect rect(_hwnd); + + WindowCanvas canvas(_hwnd); + FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT)); + + int max_width = STARTMENU_WIDTH_MIN; + int height = 0; + + for(SMBtnList::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + int w = GetStartMenuBtnTextWidth(canvas, it->_title, _hwnd); + + if (w > max_width) + max_width = w; + + if (it->_id == -1) + height += STARTMENU_SEP_HEIGHT; + else + height += STARTMENU_LINE_HEIGHT; + } + + // calculate new window size + int text_width = max_width + 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/; + + RECT rt_hgt = {rect.left, rect.bottom-_border_top-height, rect.left+_border_left+text_width, rect.bottom}; + AdjustWindowRectEx(&rt_hgt, GetWindowStyle(_hwnd), FALSE, GetWindowExStyle(_hwnd)); + + // ignore movement, only look at the size change + rect.right = rect.left + (rt_hgt.right-rt_hgt.left); + rect.top = rect.bottom - (rt_hgt.bottom-rt_hgt.top); + + // move down if we are too high + if (rect.top < 0) { + rect.top += STARTMENU_LINE_HEIGHT; + rect.bottom += STARTMENU_LINE_HEIGHT; + } + + MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); +} + +#else // _LIGHT_STARTMENU LRESULT StartMenuButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { case WM_MOUSEMOVE: - // automatically set the focus to startmenu entries when moving the mouse over them + // automatically set the focus to startmenu entries when moving the mouse over them if (GetFocus()!=_hwnd && !(GetWindowStyle(_hwnd)&WS_DISABLED)) SetFocus(_hwnd); break; @@ -625,56 +923,19 @@ LRESULT StartMenuButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) void StartMenuButton::DrawItem(LPDRAWITEMSTRUCT dis) { - UINT style = DFCS_BUTTONPUSH; - - if (dis->itemState & ODS_DISABLED) - style |= DFCS_INACTIVE; - - POINT iconPos = {dis->rcItem.left+2, (dis->rcItem.top+dis->rcItem.bottom-16)/2}; - RECT textRect = {dis->rcItem.left+16+4, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4}; - - if (dis->itemState & ODS_SELECTED) { - style |= DFCS_PUSHED; - ++iconPos.x; ++iconPos.y; - ++textRect.left; ++textRect.top; - ++textRect.right; ++textRect.bottom; - } - - int bk_color = COLOR_BTNFACE; - int text_color = COLOR_BTNTEXT; - - if (dis->itemState & ODS_FOCUS) { - bk_color = COLOR_HIGHLIGHT; - text_color = COLOR_HIGHLIGHTTEXT; - } - - HBRUSH bk_brush = GetSysColorBrush(bk_color); - - FillRect(dis->hDC, &dis->rcItem, bk_brush); - DrawIconEx(dis->hDC, iconPos.x, iconPos.y, _hIcon, 16, 16, 0, bk_brush, DI_NORMAL); - - // draw submenu arrow at the right - if (_hasSubmenu) { - static SmallIcon arrowIcon(IDI_ARROW); - static SmallIcon selArrowIcon(IDI_ARROW_SELECTED); - - DrawIconEx(dis->hDC, dis->rcItem.right-16, iconPos.y, - dis->itemState&ODS_FOCUS?selArrowIcon:arrowIcon, 16, 16, 0, bk_brush, DI_NORMAL); - } - TCHAR title[BUFFER_LEN]; + GetWindowText(_hwnd, title, BUFFER_LEN); - BkMode bk_mode(dis->hDC, TRANSPARENT); - - if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) - DrawGrayText(dis, &textRect, title, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER); - else { - TextColor lcColor(dis->hDC, GetSysColor(text_color)); - DrawText(dis->hDC, title, -1, &textRect, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER); - } + DrawStartMenuButton(dis->hDC, dis->rcItem, title, _hIcon, + _hasSubmenu, + !(dis->itemState & ODS_DISABLED), + dis->itemState&ODS_FOCUS? true: false, + dis->itemState&ODS_SELECTED? true: false); } +#endif + StartMenuRoot::StartMenuRoot(HWND hwnd) : super(hwnd) @@ -712,8 +973,17 @@ HWND StartMenuRoot::Create(HWND hwndDesktopBar) { WindowRect pos(hwndDesktopBar); + RECT rect = {pos.left, pos.top-STARTMENU_LINE_HEIGHT-4, pos.left+STARTMENU_WIDTH_MIN, pos.top}; + +#ifndef _LIGHT_STARTMENU + rect.top += STARTMENU_LINE_HEIGHT; +#endif + + AdjustWindowRectEx(&rect, WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, FALSE, 0); + return Window::Create(WINDOW_CREATOR(StartMenuRoot), 0, GetWndClasss(), TITLE_STARTMENU, - WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, pos.left, pos.top-4, STARTMENU_WIDTH_MIN, 4, hwndDesktopBar); + WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, + rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, hwndDesktopBar); } @@ -852,6 +1122,12 @@ LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs) RegCloseKey(hkey); #endif + +#ifdef _LIGHT_STARTMENU + // set the window size to fit all buttons + ResizeToButtons(); +#endif + return 0; } @@ -867,37 +1143,9 @@ void StartMenuRoot::AddEntries() LRESULT StartMenuRoot::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { switch(nmsg) { - case WM_PAINT: { - int clr_bits; - {WindowCanvas dc(_hwnd); clr_bits=GetDeviceCaps(dc, BITSPIXEL);} - bool logo256 = clr_bits<=8; - - PaintCanvas canvas(_hwnd); - - MemCanvas mem_dc; - ResBitmap bmp(logo256? IDB_LOGOV256: IDB_LOGOV); - BitmapSelection sel(mem_dc, bmp); - - ClientRect clnt(_hwnd); - int h = min(_logo_size.cy, clnt.bottom); - - RECT rect = {0, 0, _logo_size.cx-1, clnt.bottom-h}; - HBRUSH hbr = CreateSolidBrush(logo256? RGB(166,202,240): RGB(255,255,255)); // same color as the background color in the logo bitmap - FillRect(canvas, &rect, hbr); - DeleteObject(hbr); - //PatBlt(canvas, _logo_size.cx-1, 0, 1, clnt.bottom-h, WHITENESS); - PatBlt(canvas, _logo_size.cx-1, 0, 1, clnt.bottom-h, WHITENESS); - - BitBlt(canvas, 0, clnt.bottom-h, _logo_size.cx, h, mem_dc, 0, 0, SRCCOPY); - - if (!logo256) { - rect.left = rect.right++; - rect.bottom = clnt.bottom; - HBRUSH hbr_border = GetStockBrush(GRAY_BRUSH); //CreateSolidBrush(RGB(71,88,85)); - FillRect(canvas, &rect, hbr_border); - //DeleteObject(hbr_border); - } - break;} + case WM_PAINT: + Paint(PaintCanvas(_hwnd)); + break; default: return super::WndProc(nmsg, wparam, lparam); @@ -906,6 +1154,39 @@ LRESULT StartMenuRoot::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) return 0; } +void StartMenuRoot::Paint(HDC hdc) +{ + int clr_bits; + {WindowCanvas dc(_hwnd); clr_bits=GetDeviceCaps(dc, BITSPIXEL);} + bool logo256 = clr_bits<=8; + + MemCanvas mem_dc; + ResBitmap bmp(logo256? IDB_LOGOV256: IDB_LOGOV); + BitmapSelection sel(mem_dc, bmp); + + ClientRect clnt(_hwnd); + int h = min(_logo_size.cy, clnt.bottom); + + RECT rect = {0, 0, _logo_size.cx-1, clnt.bottom-h}; + HBRUSH hbr = CreateSolidBrush(logo256? RGB(166,202,240): RGB(255,255,255)); // same color as the background color in the logo bitmap + FillRect(hdc, &rect, hbr); + DeleteObject(hbr); + //PatBlt(hdc, _logo_size.cx-1, 0, 1, clnt.bottom-h, WHITENESS); + PatBlt(hdc, _logo_size.cx-1, 0, 1, clnt.bottom-h, WHITENESS); + + BitBlt(hdc, 0, clnt.bottom-h, _logo_size.cx, h, mem_dc, 0, 0, SRCCOPY); + + if (!logo256) { + rect.left = rect.right++; + rect.bottom = clnt.bottom; + HBRUSH hbr_border = GetStockBrush(GRAY_BRUSH); //CreateSolidBrush(RGB(71,88,85)); + FillRect(hdc, &rect, hbr_border); + //DeleteObject(hbr_border); + } + + super::Paint(hdc); +} + int StartMenuHandler::Command(int id, int code) { @@ -952,6 +1233,12 @@ int StartMenuHandler::Command(int id, int code) CreateSubmenu(id, ResString(IDS_SEARCH), STARTMENU_CREATOR(SearchMenu)); break; + case IDC_START_HELP: { + HWND hwndDesktopBar = GetWindow(_hwnd, GW_OWNER); + CloseStartMenu(id); + MessageBox(hwndDesktopBar, TEXT("Help not yet implemented"), ResString(IDS_TITLE), MB_OK); + break;} + case IDC_LOGOFF: /* The shell32 Dialog prompts about some system setting change. This is not what we want to display here. HWND hwndDesktopBar = GetWindow(_hwnd, GW_OWNER); diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.h b/reactos/subsys/system/explorer/taskbar/startmenu.h index 33855a425f5..e90ce8094ea 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.h +++ b/reactos/subsys/system/explorer/taskbar/startmenu.h @@ -26,6 +26,9 @@ // +#define _LIGHT_STARTMENU + + #define CLASSNAME_STARTMENU TEXT("ReactosStartmenuClass") #define TITLE_STARTMENU TEXT("Start Menu") @@ -38,8 +41,11 @@ // private message constants #define PM_STARTMENU_CLOSED (WM_APP+0x11) -#define PM_STARTENTRY_FOCUSED (WM_APP+0x12) -#define PM_STARTENTRY_LAUNCHED (WM_APP+0x13) +#define PM_STARTENTRY_LAUNCHED (WM_APP+0x12) + +#ifndef _LIGHT_STARTMENU +#define PM_STARTENTRY_FOCUSED (WM_APP+0x13) +#endif /// StartMenuDirectory is used to store the base directory of start menus. @@ -73,6 +79,14 @@ struct StartMenuEntry }; +extern int GetStartMenuBtnTextWidth(HDC hdc, LPCTSTR title, HWND hwnd); + +extern void DrawStartMenuButton(HDC hdc, const RECT& rect, LPCTSTR title, HICON hIcon, + bool hasSubmenu, bool enabled, bool has_focus, bool pushed); + + +#ifndef _LIGHT_STARTMENU + /** StartMenuButton draws the face of a StartMenuCtrl button control. */ @@ -83,8 +97,6 @@ struct StartMenuButton : public OwnerdrawnButton StartMenuButton(HWND hwnd, HICON hIcon, bool hasSubmenu) : super(hwnd), _hIcon(hIcon), _hasSubmenu(hasSubmenu) {} - static int GetTextWidth(LPCTSTR title, HWND hwnd); - protected: LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); virtual void DrawItem(LPDRAWITEMSTRUCT dis); @@ -119,6 +131,8 @@ struct StartMenuSeparator : public Static } }; +#endif + typedef list StartMenuFolders; @@ -135,17 +149,59 @@ struct StartMenuCreateInfo #define STARTMENU_CREATOR(WND_CLASS) WINDOW_CREATOR_INFO(WND_CLASS, StartMenuCreateInfo) -typedef map ShellEntryMap; +typedef map ShellEntryMap; +#ifdef _LIGHT_STARTMENU + +struct SMBtnInfo +{ + SMBtnInfo(const StartMenuEntry& entry, int id, bool hasSubmenu=false, bool enabled=true) + : _title(entry._title), + _hIcon(entry._hIcon), + _id(id), + _hasSubmenu(hasSubmenu), + _enabled(enabled) + { + } + + SMBtnInfo(LPCTSTR title, HICON hIcon, int id, bool hasSubmenu=false, bool enabled=true) + : _title(title), + _hIcon(hIcon), + _id(id), + _hasSubmenu(hasSubmenu), + _enabled(enabled) + { + } + + String _title; + HICON _hIcon; + int _id; + bool _hasSubmenu; + bool _enabled; +}; + +typedef list SMBtnList; + +#endif + /** Startmenu window. To create a start menu call its Create() function. */ -struct StartMenu : public OwnerDrawParent +struct StartMenu : +#ifdef _LIGHT_STARTMENU + public OwnerDrawParent +#else + public OwnerDrawParent +#endif { +#ifdef _LIGHT_STARTMENU + typedef OwnerDrawParent super; +#else typedef OwnerDrawParent super; +#endif StartMenu(HWND hwnd); StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info); @@ -178,17 +234,28 @@ protected: StartMenuCreateInfo _create_info; // copy of the original create info +#ifdef _LIGHT_STARTMENU + SMBtnList _buttons; + int _selected_id; + + void ResizeToButtons(); + int ButtonHitTest(POINT pt); + void InvalidateSelection(); + const SMBtnInfo* GetButtonInfo(int id) const; + void SelectButton(int id); +#endif + // member functions void ResizeButtons(int cx); virtual void AddEntries(); - StartMenuEntry& AddEntry(LPCTSTR title, HICON hIcon=0, UINT id=(UINT)-1); + StartMenuEntry& AddEntry(LPCTSTR title, HICON hIcon=0, int id=-1); StartMenuEntry& AddEntry(const ShellFolder folder, const ShellEntry* entry); void AddShellEntries(const ShellDirectory& dir, int max=-1, bool subfolders=true); - void AddButton(LPCTSTR title, HICON hIcon=0, bool hasSubmenu=false, UINT id=(UINT)-1, DWORD style=WS_VISIBLE|WS_CHILD|BS_OWNERDRAW); + void AddButton(LPCTSTR title, HICON hIcon=0, bool hasSubmenu=false, int id=-1, bool enabled=true); void AddSeparator(); bool CloseSubmenus() {return CloseOtherSubmenus(0);} @@ -200,8 +267,12 @@ protected: void ActivateEntry(int id, const ShellEntrySet& entries); void CloseStartMenu(int id=0); + bool GetButtonRect(int id, PRECT prect); + void DrawFloatingButton(HDC hdc); void GetFloatingButonRect(LPRECT prect); + + void Paint(HDC hdc); }; @@ -268,6 +339,7 @@ protected: SIZE _logo_size; void AddEntries(); + void Paint(HDC hdc); }; diff --git a/reactos/subsys/system/explorer/utility/utility.h b/reactos/subsys/system/explorer/utility/utility.h index 9482d341ee5..7ca78c4e146 100644 --- a/reactos/subsys/system/explorer/utility/utility.h +++ b/reactos/subsys/system/explorer/utility/utility.h @@ -527,7 +527,7 @@ protected: COLORREF _old_color; }; - /// TextColor locally sets the background mode for drawing. + /// BkMode locally sets the background mode for drawing. struct BkMode { BkMode(HDC hdc, int bkmode) @@ -540,7 +540,7 @@ protected: COLORREF _old_bkmode; }; - /// TextColor locally selects a font for drawing. + /// FontSelection locally selects a font for drawing. struct FontSelection { FontSelection(HDC hdc, HFONT hFont) @@ -553,7 +553,7 @@ protected: HFONT _old_hFont; }; - /// TextColor locally selects a bitmap into a device context. + /// BitmapSelection locally selects a bitmap into a device context. struct BitmapSelection { BitmapSelection(HDC hdc, HBITMAP hBmp) @@ -566,6 +566,19 @@ protected: HBITMAP _old_hBmp; }; + /// BrushSelection locally selects a brush into a device context. +struct BrushSelection +{ + BrushSelection(HDC hdc, HBRUSH hBrush) + : _hdc(hdc), _old_hBrush(SelectBrush(hdc, hBrush)) {} + + ~BrushSelection() {SelectBrush(_hdc, _old_hBrush);} + +protected: + HDC _hdc; + HBRUSH _old_hBrush; +}; + /// string class for convenience struct String diff --git a/reactos/subsys/system/explorer/utility/window.cpp b/reactos/subsys/system/explorer/utility/window.cpp index c1c3e7117bf..3a870f88a9a 100644 --- a/reactos/subsys/system/explorer/utility/window.cpp +++ b/reactos/subsys/system/explorer/utility/window.cpp @@ -792,22 +792,22 @@ static BOOL CALLBACK MyDrawText(HDC hdc, LPARAM data, int cnt) return TRUE; } -void OwnerdrawnButton::DrawGrayText(LPDRAWITEMSTRUCT dis, LPRECT pRect, LPCTSTR title, int dt_flags) +void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR title, int dt_flags) { COLORREF gray = GetSysColor(COLOR_GRAYTEXT); if (gray) { - TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNHIGHLIGHT)); + TextColor lcColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT)); RECT shadowRect = {pRect->left+1, pRect->top+1, pRect->right+1, pRect->bottom+1}; - DrawText(dis->hDC, title, -1, &shadowRect, dt_flags); + DrawText(hdc, title, -1, &shadowRect, dt_flags); - SetTextColor(dis->hDC, gray); - DrawText(dis->hDC, title, -1, pRect, dt_flags); + SetTextColor(hdc, gray); + DrawText(hdc, title, -1, pRect, dt_flags); } else { int old_r = pRect->right; int old_b = pRect->bottom; - DrawText(dis->hDC, title, -1, pRect, dt_flags|DT_CALCRECT); + DrawText(hdc, title, -1, pRect, dt_flags|DT_CALCRECT); int x = pRect->left + (old_r-pRect->right)/2; int y = pRect->top + (old_b-pRect->bottom)/2; @@ -816,7 +816,7 @@ void OwnerdrawnButton::DrawGrayText(LPDRAWITEMSTRUCT dis, LPRECT pRect, LPCTSTR s_MyDrawText_Rect.right = w; s_MyDrawText_Rect.bottom = h; - GrayString(dis->hDC, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)title, -1, x, y, w, h); + GrayString(hdc, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)title, -1, x, y, w, h); } } @@ -910,7 +910,7 @@ void PictureButton::DrawItem(LPDRAWITEMSTRUCT dis) BkMode bk_mode(dis->hDC, TRANSPARENT); if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) - DrawGrayText(dis, &textRect, title, DT_SINGLELINE|DT_VCENTER/*|DT_CENTER*/); + DrawGrayText(dis->hDC, &textRect, title, DT_SINGLELINE|DT_VCENTER/*|DT_CENTER*/); else { TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNTEXT)); DrawText(dis->hDC, title, -1, &textRect, DT_SINGLELINE|DT_VCENTER/*|DT_CENTER*/); diff --git a/reactos/subsys/system/explorer/utility/window.h b/reactos/subsys/system/explorer/utility/window.h index 443463d6cef..0a35c8c503a 100644 --- a/reactos/subsys/system/explorer/utility/window.h +++ b/reactos/subsys/system/explorer/utility/window.h @@ -568,11 +568,11 @@ struct OwnerdrawnButton : public SubclassedWindow protected: LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); - void DrawGrayText(LPDRAWITEMSTRUCT dis, LPRECT pRect, LPCTSTR text, int dt_flags); - virtual void DrawItem(LPDRAWITEMSTRUCT dis) = 0; }; +extern void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR text, int dt_flags); + /** Subclass button controls to paint colored text labels.