mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-31 04:13:37 +00:00
reimplemented start menu as light weight version
svn path=/trunk/; revision=7412
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.x<rect.left || pt.x>rect.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);
|
||||
|
||||
@@ -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<ShellPath> StartMenuFolders;
|
||||
|
||||
@@ -135,17 +149,59 @@ struct StartMenuCreateInfo
|
||||
|
||||
#define STARTMENU_CREATOR(WND_CLASS) WINDOW_CREATOR_INFO(WND_CLASS, StartMenuCreateInfo)
|
||||
|
||||
typedef map<UINT, StartMenuEntry> ShellEntryMap;
|
||||
typedef map<int, StartMenuEntry> 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<SMBtnInfo> SMBtnList;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Startmenu window.
|
||||
To create a start menu call its Create() function.
|
||||
*/
|
||||
struct StartMenu : public OwnerDrawParent<DialogWindow>
|
||||
struct StartMenu :
|
||||
#ifdef _LIGHT_STARTMENU
|
||||
public OwnerDrawParent<Window>
|
||||
#else
|
||||
public OwnerDrawParent<DialogWindow>
|
||||
#endif
|
||||
{
|
||||
#ifdef _LIGHT_STARTMENU
|
||||
typedef OwnerDrawParent<Window> super;
|
||||
#else
|
||||
typedef OwnerDrawParent<DialogWindow> 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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*/);
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user