From 84970bfa09e8d92e144efaadbdd83eb027553c49 Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Sun, 20 Jun 2004 21:42:59 +0000 Subject: [PATCH] scroll mode for very long start menus svn path=/trunk/; revision=9773 --- reactos/subsys/system/explorer/doc/TODO.txt | 5 +- reactos/subsys/system/explorer/explorer.dsp | 12 ++ .../subsys/system/explorer/explorer_intres.h | 2 + .../subsys/system/explorer/explorer_intres.rc | 2 + .../subsys/system/explorer/res/arrow_dwn.ico | Bin 0 -> 158 bytes .../subsys/system/explorer/res/arrow_up.ico | Bin 0 -> 158 bytes .../system/explorer/taskbar/startmenu.cpp | 160 ++++++++++++++++-- .../system/explorer/taskbar/startmenu.h | 10 ++ 8 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 reactos/subsys/system/explorer/res/arrow_dwn.ico create mode 100644 reactos/subsys/system/explorer/res/arrow_up.ico diff --git a/reactos/subsys/system/explorer/doc/TODO.txt b/reactos/subsys/system/explorer/doc/TODO.txt index 3dbafff6367..982daa9c2b7 100644 --- a/reactos/subsys/system/explorer/doc/TODO.txt +++ b/reactos/subsys/system/explorer/doc/TODO.txt @@ -18,14 +18,11 @@ - close start start menu when resizing explorer bar - adjust already open windows of all running applications when resizing explorer bar - implement blink effect in task bar for SetForegoundWindow() requests -- implement more than one column or scrolling in start menus for very crowded start menus - Execute selected programs with additional command line options ("Run" dialog with pre-filled edit field) - switch background images with desktop switcher - Desktop Manager: Desktop Names; Speicherung der Verteilung von Applikations-Fenstern auf die verschiedenen Desktops -> config file - autostart doesn't work on NT4 ? - hide desktop bar when showing full screen applications - new start menu entry "Filemanager" close to "Explore" -> display C: and D: drive in MDI window - -- Startmenu: You can't close the start menu with pressing Win-key You can open the start menu - with pressing Win-key, but can't close with another hit of Win-key. +- Startmenu: You can open the start menu by pressing Win-key, but can't close with another hit of Win-key. diff --git a/reactos/subsys/system/explorer/explorer.dsp b/reactos/subsys/system/explorer/explorer.dsp index 075c4f81b3d..62facffc7f3 100644 --- a/reactos/subsys/system/explorer/explorer.dsp +++ b/reactos/subsys/system/explorer/explorer.dsp @@ -361,6 +361,18 @@ SOURCE=.\res\arrow.ico # End Source File # Begin Source File +SOURCE=.\res\arrow_do.ico +# End Source File +# Begin Source File + +SOURCE=.\res\arrow_dwn.ico +# End Source File +# Begin Source File + +SOURCE=.\res\arrow_up.ico +# End Source File +# Begin Source File + SOURCE=.\res\arrowsel.ico # End Source File # Begin Source File diff --git a/reactos/subsys/system/explorer/explorer_intres.h b/reactos/subsys/system/explorer/explorer_intres.h index 1e9a4e0b1d1..caef1ea3d68 100644 --- a/reactos/subsys/system/explorer/explorer_intres.h +++ b/reactos/subsys/system/explorer/explorer_intres.h @@ -106,6 +106,8 @@ #define IDB_LOGOV16 164 #define IDI_DOT_TRANS 164 #define IDI_DOT_RED 165 +#define IDI_ARROW_UP 166 +#define IDI_ARROW_DOWN 167 #define ID_VIEW_NAME 401 #define ID_VIEW_ALL_ATTRIBUTES 402 #define ID_VIEW_SELECTED_ATTRIBUTES 403 diff --git a/reactos/subsys/system/explorer/explorer_intres.rc b/reactos/subsys/system/explorer/explorer_intres.rc index 52c550ed81e..5a6241bb229 100644 --- a/reactos/subsys/system/explorer/explorer_intres.rc +++ b/reactos/subsys/system/explorer/explorer_intres.rc @@ -947,6 +947,8 @@ IDI_SPEAKER ICON DISCARDABLE "res/speaker.ico" IDI_DOT ICON DISCARDABLE "res/dot.ico" IDI_DOT_TRANS ICON DISCARDABLE "res/dot_trans.ico" IDI_DOT_RED ICON DISCARDABLE "res/dot_red.ico" +IDI_ARROW_UP ICON DISCARDABLE "res/arrow_up.ico" +IDI_ARROW_DOWN ICON DISCARDABLE "res/arrow_dwn.ico" ///////////////////////////////////////////////////////////////////////////// // diff --git a/reactos/subsys/system/explorer/res/arrow_dwn.ico b/reactos/subsys/system/explorer/res/arrow_dwn.ico new file mode 100644 index 0000000000000000000000000000000000000000..e6a982ddad1cf1e577eb7fab3abcd201c251ed06 GIT binary patch literal 158 zcmZvRF%E!02n3hpiYu+GEqx}5jnAU 0) { + --_scroll_pos; + InvalidateRect(_hwnd, NULL, TRUE); + } + } else { + if (_scroll_pos <= _invisible_lines) { + ++_scroll_pos; + InvalidateRect(_hwnd, NULL, TRUE); + } + } + break; + case WM_KEYDOWN: ProcessKey(wparam); break; @@ -379,7 +437,7 @@ int StartMenu::ButtonHitTest(POINT pt) if (pt.xrect.right) return 0; - for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) { const SMBtnInfo& info = *it; if (rect.top > pt.y) @@ -387,6 +445,9 @@ int StartMenu::ButtonHitTest(POINT pt) rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT); + if (rect.bottom > _bottom_max) + break; + if (pt.y < rect.bottom) // PtInRect(&rect, pt) return info._id; @@ -404,7 +465,7 @@ void StartMenu::InvalidateSelection() ClientRect clnt(_hwnd); RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; - for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) { const SMBtnInfo& info = *it; rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT); @@ -629,7 +690,7 @@ bool StartMenu::GetButtonRect(int id, PRECT prect) const ClientRect clnt(_hwnd); RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; - for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) { const SMBtnInfo& info = *it; rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT); @@ -676,12 +737,44 @@ void StartMenu::GetFloatingButtonRect(LPRECT prect) } +void StartMenu::DrawArrows(HDC hdc) +{ + static ResIconEx arrowUpIcon(IDI_ARROW_UP, 8, 4); + static ResIconEx arrowDownIcon(IDI_ARROW_DOWN, 8, 4); + + ClientRect clnt(_hwnd); + + DrawIconEx(hdc, clnt.right/2-4, _floating_btn?3:1, arrowUpIcon, 8, 4, 0, 0, DI_NORMAL); + DrawIconEx(hdc, clnt.right/2-4, clnt.bottom-5, arrowDownIcon, 8, 4, 0, 0, DI_NORMAL); +} + +void StartMenu::GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down) +{ + GetClientRect(_hwnd, prect_up); + *prect_down = *prect_up; + +// prect_up->left = prect_up->right/2 - 4; +// prect_up->right = prect_up->left + 8; + prect_up->right -= 8; + prect_up->top = _floating_btn? 3: 1; + prect_up->bottom = prect_up->top + 4; + +// prect_down->left = prect_down->right/2 - 4; +// prect_down->right = prect_down->left + 8; + prect_down->right -= 8; + prect_down->top = prect_down->bottom - 5; +} + + void StartMenu::Paint(PaintCanvas& canvas) { - if (_border_top) + if (_floating_btn) DrawFloatingButton(canvas); #ifdef _LIGHT_STARTMENU + if (_arrow_btns) + DrawArrows(canvas); + ClientRect clnt(_hwnd); RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT}; @@ -690,7 +783,7 @@ void StartMenu::Paint(PaintCanvas& canvas) FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT)); BkMode bk_mode(canvas, TRANSPARENT); - for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) { + for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) { const SMBtnInfo& btn = *it; if (rect.top > canvas.rcPaint.bottom) @@ -699,6 +792,9 @@ void StartMenu::Paint(PaintCanvas& canvas) if (btn._id == -1) { // a separator? rect.bottom = rect.top + STARTMENU_SEP_HEIGHT; + if (rect.bottom > _bottom_max) + break; + BrushSelection brush_sel(canvas, GetSysColorBrush(COLOR_BTNSHADOW)); PatBlt(canvas, rect.left+2, rect.top+STARTMENU_SEP_HEIGHT/2-1, sep_width, 1, PATCOPY); @@ -707,6 +803,9 @@ void StartMenu::Paint(PaintCanvas& canvas) } else { rect.bottom = rect.top + STARTMENU_LINE_HEIGHT; + if (rect.bottom > _bottom_max) + break; + if (rect.top >= canvas.rcPaint.top) DrawStartMenuButton(canvas, rect, btn._title, btn, btn._id==_selected_id, false); } @@ -724,7 +823,7 @@ void StartMenu::UpdateIcons(/*int idx*/) #ifdef _SINGLE_ICONEXTRACT //if (idx >= 0) - int idx = 0; + int idx = _scroll_pos; for(; idx<(int)_buttons.size(); ++idx) { SMBtnInfo& btn = _buttons[idx]; @@ -738,7 +837,11 @@ void StartMenu::UpdateIcons(/*int idx*/) Entry* entry = *it; if (entry->_icon_id == ICID_UNKNOWN) - entry->extract_icon(); + try { + entry->extract_icon(); + } catch(COMException&) { + // ignore unexpected exceptions while extracting icons + } if (entry->_icon_id > ICID_NONE) { btn._icon_id = (ICON_ID)/*@@*/ entry->_icon_id; @@ -746,6 +849,10 @@ void StartMenu::UpdateIcons(/*int idx*/) RECT rect; GetButtonRect(btn._id, &rect); + + if (rect.bottom > _bottom_max) + break; + WindowCanvas canvas(_hwnd); DrawStartMenuButton(canvas, rect, NULL, btn, btn._id==_selected_id, false); @@ -1066,7 +1173,7 @@ void StartMenu::CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTS ClientToScreen(_hwnd, &rect); x = rect.right; // Submenus should overlap their parent a bit. - y = rect.top+STARTMENU_LINE_HEIGHT-_border_top; + y = rect.top+STARTMENU_LINE_HEIGHT +_border_top/*own border*/ -STARTMENU_TOP_BTN_SPACE/*border of new submenu*/; } else { WindowRect pos(_hwnd); @@ -1103,7 +1210,7 @@ void StartMenu::ActivateEntry(int id, const ShellEntrySet& entries) if (title.empty()) title = entry->_display_name; } else { - // If the entry is no subdirectory, there can only be one shell entry. + // The entry is no subdirectory, so there can only be one shell entry. assert(entries.size()==1); HWND hparent = GetParent(_hwnd); @@ -1264,11 +1371,40 @@ void StartMenu::ResizeToButtons() // move down if we are too high if (rect.top < 0) { - rect.top += STARTMENU_LINE_HEIGHT; - rect.bottom += STARTMENU_LINE_HEIGHT; + int dy = -rect.top; + rect.top += dy; + rect.bottom += dy; + } + + // enable scroll mode for long start menus, which span more than the whole screen height + int cyscreen = GetSystemMetrics(SM_CYSCREEN); + int bottom_max = 0; + + if (rect.bottom > cyscreen) { + _arrow_btns = true; + + _invisible_lines = (rect.bottom-cyscreen+(STARTMENU_LINE_HEIGHT-1))/STARTMENU_LINE_HEIGHT + 1; + rect.bottom -= _invisible_lines * STARTMENU_LINE_HEIGHT; + + bottom_max = rect.bottom; + + if (_floating_btn) + rect.bottom += 6; // lower scroll arrow + else { + _border_top += 6; // upper scroll arrow + rect.bottom += 2*6; // upper+lower scroll arrow + } } MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); + + if (bottom_max) { + POINT pt = {0, bottom_max}; + + ScreenToClient(_hwnd, &pt); + + _bottom_max = pt.y; + } } #else // _LIGHT_STARTMENU diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.h b/reactos/subsys/system/explorer/taskbar/startmenu.h index 6402029e224..c5b42487cab 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.h +++ b/reactos/subsys/system/explorer/taskbar/startmenu.h @@ -240,8 +240,15 @@ protected: int _border_left; // left border in pixels int _border_top; // top border in pixels + int _bottom_max; // limit display area for long start menus + + bool _floating_btn; + bool _arrow_btns; POINT _last_pos; + enum SCROLL_MODE {SCROLL_NOT, SCROLL_UP, SCROLL_DOWN} _scroll_mode; + int _scroll_pos; + int _invisible_lines; StartMenuCreateInfo _create_info; // copy of the original create info @@ -291,6 +298,9 @@ protected: void DrawFloatingButton(HDC hdc); void GetFloatingButtonRect(LPRECT prect); + void GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down); + + void DrawArrows(HDC hdc); void Paint(PaintCanvas& canvas); void UpdateIcons(/*int idx*/);