Index: dll/win32/shell32/lang/en-US.rc =================================================================== --- dll/win32/shell32/lang/en-US.rc (revision 57871) +++ dll/win32/shell32/lang/en-US.rc (working copy) @@ -805,4 +805,13 @@ IDS_BYTES_FORMAT "bytes" IDS_UNKNOWN_APP "Unknown application" IDS_EXE_DESCRIPTION "Description:" + + IDS_SM_PROGRAMS "Programs" + IDS_SM_DOCUMENTS "Documents" + IDS_SM_SETTINGS "Settings" + IDS_SM_SEARCH "Search" + IDS_SM_HELP_AND_SUPPORT "Help and Support" + IDS_SM_RUN "Run..." + IDS_SM_LOGOFF "Log Off" + IDS_SM_TURN_OFF "Turn Off Computer" END Index: dll/win32/shell32/shresdef.h =================================================================== --- dll/win32/shell32/shresdef.h (revision 57871) +++ dll/win32/shell32/shresdef.h (working copy) @@ -184,6 +184,16 @@ #define IDS_DESCRIPTION 331 #define IDS_COPY_OF 332 +/* Start Menu*/ +#define IDS_SM_PROGRAMS 333 +#define IDS_SM_DOCUMENTS 334 +#define IDS_SM_SETTINGS 335 +#define IDS_SM_SEARCH 336 +#define IDS_SM_HELP_AND_SUPPORT 337 +#define IDS_SM_RUN 338 +#define IDS_SM_LOGOFF 340 +#define IDS_SM_TURN_OFF 341 + /* Note: those strings are referenced from the registry */ #define IDS_RECYCLEBIN_FOLDER_NAME 8964 #define IDS_ADMINISTRATIVETOOLS 22982 Index: dll/win32/shell32/startmenu.cpp =================================================================== --- dll/win32/shell32/startmenu.cpp (revision 57871) +++ dll/win32/shell32/startmenu.cpp (working copy) @@ -2,6 +2,7 @@ * Start menu object * * Copyright 2009 Andrew Hill + * Copyright 2012 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,10 +23,643 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell32start); +/* NOTE: The following constants may *NOT* be changed because + they're hardcoded and need to be the exact values + in order to get the start menu to work! */ +#define IDM_PROGRAMS 504 +#define IDM_FAVORITES 507 +#define IDM_DOCUMENTS 501 +#define IDM_SETTINGS 508 +#define IDM_CONTROLPANEL 505 +#define IDM_SECURITY 5001 +#define IDM_NETWORKCONNECTIONS 557 +#define IDM_PRINTERSANDFAXES 510 +#define IDM_TASKBARANDSTARTMENU 413 +#define IDM_SEARCH 520 +#define IDM_HELPANDSUPPORT 503 +#define IDM_RUN 401 +#define IDM_SYNCHRONIZE 553 +#define IDM_LOGOFF 402 +#define IDM_DISCONNECT 5000 +#define IDM_UNDOCKCOMPUTER 410 +#define IDM_SHUTDOWN 506 +#define IDM_LASTSTARTMENU_SEPARATOR 450 + +static const +TCHAR szStartMenuWndClass[] = TEXT("DV2ControlHost"); + +static const INT StartMenuIconIDs[STARTMENUITEM_COUNT] = +{ + IDI_SHELL_PROGRAMS_FOLDER, + IDI_SHELL_RECENT_DOCUMENTS, + IDI_SHELL_RUN, + IDI_SHELL_SEARCH, + IDI_SHELL_HELP, + IDI_SHELL_RUN2, + 0, + IDI_SHELL_LOGOFF, + IDI_SHELL_TURN_OFF, +}; + +static const INT StartMenuTextIDs[STARTMENUITEM_COUNT] = +{ + IDS_SM_PROGRAMS, + IDS_SM_DOCUMENTS, + IDS_SM_SETTINGS, + IDS_SM_SEARCH, + IDS_SM_HELP_AND_SUPPORT, + IDS_SM_RUN, + 0, + IDS_SM_LOGOFF, + IDS_SM_TURN_OFF, +}; + +static const BOOL StartMenuItemHasSubMenu[STARTMENUITEM_COUNT] = +{ + TRUE, + TRUE, + TRUE, + TRUE, + FALSE, + FALSE, + FALSE, + FALSE, + FALSE, +}; + +/* is it a separator index? */ +#define STARTMENU_ISSEPINDEX(i) (!StartMenuIconIDs[i]) + +static VOID +PostTrayCommand(UINT nCommandID) +{ + HWND hTrayWnd; + hTrayWnd = FindWindowExW(NULL, NULL, L"Shell_TrayWnd", NULL); + PostMessage(hTrayWnd, WM_COMMAND, MAKEWPARAM(nCommandID, 0), 0); +} + +static VOID +StartMenu_CalcClientSize(CStartMenu *pMenu, LPSIZE psiz) +{ + HFONT hFont; + HDC hdc; + HGDIOBJ hFontOld; + INT i; + SIZE siz, sizMax; + + sizMax.cx = sizMax.cy = 0; + hdc = CreateCompatibleDC(NULL); + if (hdc != NULL) + { + hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + hFontOld = SelectObject(hdc, hFont); + for(i = 0; i < STARTMENUITEM_COUNT; i++) + { + GetTextExtentPoint32( + hdc, + pMenu->m_aszStartMenuTexts[i], + lstrlen(pMenu->m_aszStartMenuTexts[i]), + &siz); + if (sizMax.cx < siz.cx) sizMax.cx = siz.cx; + if (sizMax.cy < siz.cy) sizMax.cy = siz.cy; + } + SelectObject(hdc, hFontOld); + DeleteDC(hdc); + } + + INT nIconSize; + if (pMenu->m_iIcon == BMICON_LARGE) + nIconSize = 32; + else + nIconSize = 16; + pMenu->m_nMenuHeight = max(nIconSize, (INT)sizMax.cy); + pMenu->m_nSepHeight = 8; + + psiz->cx = pMenu->m_sizBitmap.cx + nIconSize + sizMax.cx + 16; + psiz->cy = pMenu->m_nMenuHeight * 8 + pMenu->m_nSepHeight; +} + +static INT +StartMenu_HitTest(HWND hwnd, CStartMenu *pMenu, POINT pt) +{ + RECT rc, rcBanner, rcClient; + INT i, y, cy; + + GetClientRect(hwnd, &rcClient); + if (pMenu->m_hBitmap != NULL) + { + SetRect(&rcBanner, + 0, 0, + pMenu->m_sizBitmap.cx, rcClient.bottom - rcClient.top); + if (PtInRect(&rcBanner, pt)) + return -2; /* Clicked the banner */ + } + + for(i = y = 0; i < STARTMENUITEM_COUNT; i++) + { + if (STARTMENU_ISSEPINDEX(i)) + { + cy = pMenu->m_nSepHeight; + } + else + { + cy = pMenu->m_nMenuHeight; + SetRect(&rc, + rcClient.left + pMenu->m_sizBitmap.cx, y, + rcClient.right, y + cy); + if (PtInRect(&rc, pt)) + return i; /* index of Start Menu items */ + } + y += cy; + } + + return -1; /* Out of Start Menu */ +} + +static VOID +StartMenu_OnPaint(HWND hwnd, CStartMenu *pMenu) +{ + PAINTSTRUCT ps; + HDC hdc, hdcMem; + RECT rc, rcClient; + POINT pt; + HGDIOBJ hbmOld; + HBRUSH hbr; + INT i, y, cy; + + GetClientRect(hwnd, &rcClient); + GetCursorPos(&pt); + ScreenToClient(hwnd, &pt); + + hdc = BeginPaint(hwnd, &ps); + if (hdc != NULL) + { + if (pMenu->m_hBitmap != NULL) + { + /* fill the banner background */ + hbr = CreateSolidBrush(RGB(138, 178, 219)); + if (hbr != NULL) + { + rcClient.right = rcClient.left + pMenu->m_sizBitmap.cx; + FillRect(hdc, &rcClient, hbr); + DeleteObject(hbr); + } + GetClientRect(hwnd, &rcClient); + + /* draw the banner */ + hdcMem = CreateCompatibleDC(hdc); + if (hdcMem != NULL) + { + hbmOld = SelectObject(hdcMem, pMenu->m_hBitmap); + BitBlt(hdc, + 0, rcClient.bottom - pMenu->m_sizBitmap.cy, + pMenu->m_sizBitmap.cx, pMenu->m_sizBitmap.cy, + hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmOld); + GdiFlush(); + DeleteDC(hdcMem); + } + } + + SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT)); + SetBkMode(hdc, TRANSPARENT); + + /* draw icons and texts */ + HGDIOBJ hPenOld; + HPEN hGrayPen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128)); + HPEN hLtGrayPen = CreatePen(PS_SOLID, 1, RGB(192, 192, 192)); + for(y = i = 0; i < STARTMENUITEM_COUNT; i++) + { + if (STARTMENU_ISSEPINDEX(i)) + { + cy = pMenu->m_nSepHeight; + + /* draw separator */ + hPenOld = SelectObject(hdc, hGrayPen); + MoveToEx(hdc, + rcClient.left + pMenu->m_sizBitmap.cx + 8, + rcClient.top + y + pMenu->m_nSepHeight / 2, + NULL); + LineTo(hdc, + rcClient.right - 8, + rcClient.top + y + pMenu->m_nSepHeight / 2); + + SelectObject(hdc, hLtGrayPen); + MoveToEx(hdc, + rcClient.left + pMenu->m_sizBitmap.cx + 8 + 1, + rcClient.top + y + pMenu->m_nSepHeight / 2 + 1, + NULL); + LineTo(hdc, + rcClient.right - 8 + 1, + rcClient.top + y + pMenu->m_nSepHeight / 2 + 1); + + SelectObject(hdc, hPenOld); + } + else + { + cy = pMenu->m_nMenuHeight; + + /* fill background */ + SetRect(&rc, + rcClient.left + pMenu->m_sizBitmap.cx, y, + rcClient.right, y + cy); + if (pMenu->m_iMenuSelected == i) + { + FillRect(hdc, &rc, (HBRUSH)(COLOR_HIGHLIGHT + 1)); + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else if (PtInRect(&rc, pt)) + { + FillRect(hdc, &rc, (HBRUSH)(COLOR_HIGHLIGHT + 1)); + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + else + { + FillRect(hdc, &rc, (HBRUSH)(COLOR_3DFACE + 1)); + SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT)); + } + + if (StartMenuItemHasSubMenu[i]) + { + /* draw a black triangle */ + POINT apt[3] = + { + {rcClient.right - 8, y + cy / 2}, + {rcClient.right - 12, y + cy / 2 - 4}, + {rcClient.right - 12, y + cy / 2 + 4}, + }; + SelectObject(hdc, GetStockObject(NULL_PEN)); + SelectObject(hdc, GetStockObject(BLACK_BRUSH)); + Polygon(hdc, apt, 3); + } + + /* draw an icon */ + INT nIconSize; + if (pMenu->m_iIcon == BMICON_LARGE) + nIconSize = 32; + else + nIconSize = 16; + DrawIconEx(hdc, pMenu->m_sizBitmap.cx, y, pMenu->m_ahIcons[i], + nIconSize, nIconSize, 0, NULL, DI_NORMAL); + + /* draw a text */ + SetRect(&rc, + rcClient.left + pMenu->m_sizBitmap.cx + nIconSize, y, + rcClient.right, y + cy); + DrawText(hdc, pMenu->m_aszStartMenuTexts[i], -1, + &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE); + } + y += cy; + } + DeleteObject(hGrayPen); + DeleteObject(hLtGrayPen); + + EndPaint(hwnd, &ps); + } +} + +static BOOL +StartMenu_OnCreate(HWND hwnd, CStartMenu *pMenu) +{ + INT i; + + /* load icons and texts */ + for(i = 0; i < STARTMENUITEM_COUNT; i++) + { + if (StartMenuIconIDs[i] != 0) + { + pMenu->m_ahIcons[i] = LoadIcon( + shell32_hInstance, + MAKEINTRESOURCE(StartMenuIconIDs[i])); + LoadString(shell32_hInstance, StartMenuTextIDs[i], + pMenu->m_aszStartMenuTexts[i], + sizeof(pMenu->m_aszStartMenuTexts[i]) / + sizeof(pMenu->m_aszStartMenuTexts[i][0])); + } + else + { + pMenu->m_ahIcons[i] = NULL; + pMenu->m_aszStartMenuTexts[i][0] = 0; + } + } + + return TRUE; +} + +static VOID +StartMenu_PopupSubMenu(CStartMenu *pMenu, INT i) +{ + RECT rcClient; + INT j, x, y, cy; + + GetClientRect(pMenu->m_hWnd, &rcClient); + x = rcClient.right; + for(j = y = 0; j < STARTMENUITEM_COUNT; j++) + { + if (STARTMENU_ISSEPINDEX(j)) + cy = pMenu->m_nSepHeight; + else + cy = pMenu->m_nMenuHeight; + if (j == i) + break; + y += cy; + } + + POINT pt = {x, y}; + ClientToScreen(pMenu->m_hWnd, &pt); + + /* FIXME */ + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, 1, TEXT("Item #1")); + AppendMenu(hMenu, MF_STRING, 2, TEXT("Item #2")); + + pMenu->m_bTracking = TRUE; + UINT nCmdID = (UINT)TrackPopupMenuEx(hMenu, + TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_RETURNCMD, + pt.x, pt.y, pMenu->m_hWnd, NULL); + DestroyMenu(hMenu); + pMenu->m_bTracking = FALSE; + + pMenu->m_iMenuSelected = -1; + InvalidateRect(pMenu->m_hWnd, NULL, FALSE); + + if (nCmdID == 0) + { + /* no item selected */ + if (GetKeyState(VK_LBUTTON) < 0) + { + /* left button pressed */ + GetCursorPos(&pt); + ScreenToClient(pMenu->m_hWnd, &pt); + if (PtInRect(&rcClient, pt)) + { + /* in client area */ + PostMessage(pMenu->m_hWnd, WM_LBUTTONDOWN, + 0, MAKELPARAM(pt.x, pt.y)); + } + else + { + /* out of client area */ + ReleaseCapture(); + ShowWindow(pMenu->m_hWnd, SW_HIDE); + } + } + } + else + { + /* menu item selected */ + ReleaseCapture(); + ShowWindow(pMenu->m_hWnd, SW_HIDE); + } +} + +static VOID +StartMenu_ExecuteItem(HWND hwnd, CStartMenu *pMenu, INT i) +{ + UINT nCommandID; + + switch(i) + { + case 3: nCommandID = IDM_SEARCH; break; + case 4: nCommandID = IDM_HELPANDSUPPORT; break; + case 5: nCommandID = IDM_RUN; break; + case 7: nCommandID = IDM_LOGOFF; break; + case 8: nCommandID = IDM_SHUTDOWN; break; + default: return; + } + ShowWindow(hwnd, SW_HIDE); + PostTrayCommand(nCommandID); +} + +static VOID +StartMenu_OnKeyDown(HWND hwnd, CStartMenu *pMenu, UINT vk) +{ + POINT pt; + RECT rc; + + GetCursorPos(&pt); + GetWindowRect(hwnd, &rc); + + switch(vk) + { + case VK_ESCAPE: + ShowWindow(hwnd, SW_HIDE); + break; + + case VK_UP: + if (PtInRect(&rc, pt)) + return; + if (-1 == pMenu->m_iMenuSelected) + { + pMenu->m_iMenuSelected = STARTMENUITEM_COUNT - 1; + } + else if (pMenu->m_iMenuSelected - 1 >= 0) + { + (pMenu->m_iMenuSelected)--; + if (STARTMENU_ISSEPINDEX(pMenu->m_iMenuSelected)) + (pMenu->m_iMenuSelected)--; + } + else + { + pMenu->m_iMenuSelected = STARTMENUITEM_COUNT - 1; + } + break; + + case VK_DOWN: + if (PtInRect(&rc, pt)) + return; + if (-1 == pMenu->m_iMenuSelected) + { + pMenu->m_iMenuSelected = 0; + } + else if (pMenu->m_iMenuSelected + 1 < STARTMENUITEM_COUNT) + { + (pMenu->m_iMenuSelected)++; + if (STARTMENU_ISSEPINDEX(pMenu->m_iMenuSelected)) + (pMenu->m_iMenuSelected)++; + } + else + { + pMenu->m_iMenuSelected = 0; + } + break; + + case VK_LEFT: + if (PtInRect(&rc, pt)) + return; + if (-1 != pMenu->m_iMenuSelected) + { + if (StartMenuItemHasSubMenu[pMenu->m_iMenuSelected]) + { + StartMenu_PopupSubMenu(pMenu, pMenu->m_iMenuSelected); + } + } + break; + + case VK_SPACE: + case VK_RETURN: /* [Enter] key */ + if (-1 != pMenu->m_iMenuSelected) + { + InvalidateRect(hwnd, NULL, FALSE); + if (StartMenuItemHasSubMenu[pMenu->m_iMenuSelected]) + { + StartMenu_PopupSubMenu(pMenu, pMenu->m_iMenuSelected); + } + else + { + StartMenu_ExecuteItem(hwnd, pMenu, pMenu->m_iMenuSelected); + } + } + break; + } + + InvalidateRect(hwnd, NULL, FALSE); +} + +static VOID +StartMenu_OnLButtonDown(HWND hwnd, CStartMenu *pMenu, LPARAM lParam) +{ + POINT pt; + pt.x = (short)LOWORD(lParam); + pt.y = (short)HIWORD(lParam); + + INT i = StartMenu_HitTest(hwnd, pMenu, pt); + if (i == -1) + { + ShowWindow(hwnd, SW_HIDE); + } + else if (i != -2) + { + pMenu->m_iMenuSelected = i; + InvalidateRect(hwnd, NULL, FALSE); + if (StartMenuItemHasSubMenu[i]) + { + StartMenu_PopupSubMenu(pMenu, i); + } + else + { + StartMenu_ExecuteItem(hwnd, pMenu, i); + } + } +} + +static LRESULT CALLBACK +StartMenu_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static CStartMenu *pMenu = NULL; + + switch(uMsg) + { + case WM_CREATE: + pMenu = (CStartMenu *)((LPCREATESTRUCT)lParam)->lpCreateParams; + pMenu->m_hWnd = hwnd; + if (!StartMenu_OnCreate(hwnd, pMenu)) + return -1; + return 0; + + case WM_SHOWWINDOW: + if (wParam) + SetCapture(hwnd); + else + ReleaseCapture(); + pMenu->m_iMenuSelected = -1; + break; + + case WM_MOUSEMOVE: + InvalidateRect(hwnd, NULL, FALSE); + break; + + case WM_PAINT: + StartMenu_OnPaint(hwnd, pMenu); + break; + + case WM_KEYDOWN: + StartMenu_OnKeyDown(hwnd, pMenu, (UINT)wParam); + break; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + StartMenu_OnLButtonDown(hwnd, pMenu, lParam); + break; + + case WM_MENUCHAR: + /* FIXME: Enable Left key */ + break; + + case WM_MENUSELECT: + /* FIXME: Expand popup menu */ + break; + + case WM_KILLFOCUS: + lParam = wParam; + /* FALL THRU */ + + case WM_CAPTURECHANGED: + if (!pMenu->m_bTracking) + { + TCHAR szClsName[32]; + GetClassName((HWND)lParam, szClsName, 32); + if (lstrcmpi(szClsName, TEXT("BUTTON")) == 0) + { + DWORD PID; + GetWindowThreadProcessId((HWND)lParam, &PID); + if (GetCurrentProcessId() == PID) + break; + } + ShowWindow(hwnd, SW_HIDE); + } + break; + + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + + return 0; +} + +static BOOL +StartMenu_Register(VOID) +{ + WNDCLASSEX wcx; + + wcx.cbSize = sizeof(wcx); + wcx.style = CS_DBLCLKS; + wcx.lpfnWndProc = StartMenu_WndProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(CStartMenu*); + wcx.hInstance = shell32_hInstance; + wcx.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wcx.hCursor = LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = szStartMenuWndClass; + wcx.hIconSm = (HICON)LoadImage(NULL, IDI_WINLOGO, IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0); + + return RegisterClassEx(&wcx) != 0; +} + +static HWND +StartMenu_Create(CStartMenu *pMenu) +{ + DWORD dwStyle, dwExStyle; + + dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_POPUP; + dwExStyle = WS_EX_TOPMOST | WS_EX_WINDOWEDGE; + return CreateWindowEx(dwExStyle, szStartMenuWndClass, TEXT("Start Menu"), + dwStyle, 0, 0, 0, 0, NULL, NULL, shell32_hInstance, pMenu); +} + CStartMenu::CStartMenu() { m_pBandSite = NULL; m_pUnkSite = NULL; + m_hWnd = NULL; + m_iIcon = BMICON_LARGE; + m_hBitmap = NULL; + m_sizBitmap.cx = m_sizBitmap.cy = 0; + m_iMenuSelected = -1; + m_bTracking = FALSE; } CStartMenu::~CStartMenu() @@ -40,8 +674,10 @@ HRESULT STDMETHODCALLTYPE CStartMenu::GetWindow(HWND *phwnd) { - UNIMPLEMENTED; - return E_NOTIMPL; + if (phwnd == NULL) + return E_POINTER; + *phwnd = m_hWnd; + return S_OK; } HRESULT STDMETHODCALLTYPE CStartMenu::GetClient(IUnknown **ppunkClient) @@ -73,8 +709,34 @@ HRESULT STDMETHODCALLTYPE CStartMenu::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags) { - UNIMPLEMENTED; - return E_NOTIMPL; + RECT rc, rcWorkArea; + SIZE siz; + + StartMenu_CalcClientSize(this, &siz); + rc.left = rc.top = 0; + rc.right = siz.cx; rc.bottom = siz.cy; + DWORD dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_POPUP; + DWORD dwExStyle = WS_EX_TOPMOST | WS_EX_WINDOWEDGE; + AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); + siz.cx = rc.right - rc.left; + siz.cy = rc.bottom - rc.top; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); + + /* FIXME: Check ppt and prcExclude */ + MoveWindow(m_hWnd, + 0, rcWorkArea.bottom - (rc.bottom - rc.top), + siz.cx, siz.cy, + TRUE); + + if (IsWindowVisible(m_hWnd)) + ShowWindow(m_hWnd, SW_HIDE); + else + ShowWindow(m_hWnd, SW_SHOW); + + InvalidateRect(m_hWnd, NULL, FALSE); + + return S_OK; } HRESULT STDMETHODCALLTYPE CStartMenu::SetSubMenu(IMenuPopup *pmp, BOOL fSet) @@ -112,6 +774,9 @@ TRACE("(%p)\n", this); + if (!StartMenu_Register() || !StartMenu_Create(this)) + return E_FAIL; + //pBandSiteObj = new CComObject(); ATLTRY (pBandSiteObj = new CComObject); if (pBandSiteObj == NULL) @@ -119,23 +784,84 @@ hr = pBandSiteObj->QueryInterface(IID_IBandSite, (VOID**)&m_pBandSite); if (FAILED(hr)) - return NULL; + return E_FAIL; return m_pBandSite->AddBand((IMenuBand*)this); } HRESULT STDMETHODCALLTYPE CStartMenu::IsMenuMessage(MSG *pmsg) { + if (pmsg->message == WM_CREATE) + return S_OK; + + if (IsWindow(m_hWnd) && pmsg->hwnd == m_hWnd) + { + if (PeekMessage(pmsg, m_hWnd, 0, 0, PM_REMOVE)) + { + TranslateMessage(pmsg); + DispatchMessage(pmsg); + return S_OK; + } + } + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CStartMenu::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet) +{ + if (plRet == NULL) + return S_FALSE; + + if (pmsg->message == WM_CREATE) + return S_OK; + + if (IsWindow(m_hWnd) && pmsg->hwnd == m_hWnd) + { + if (PeekMessage(pmsg, m_hWnd, 0, 0, PM_REMOVE)) + { + TranslateMessage(pmsg); + DispatchMessage(pmsg); + *plRet = 0; + return S_OK; + } + } + + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CStartMenu::SetIconSize(DWORD iIcon) +{ UNIMPLEMENTED; return E_NOTIMPL; } -HRESULT STDMETHODCALLTYPE CStartMenu::TranslateMenuMessage(MSG *pmsg, LRESULT *plRet) +HRESULT STDMETHODCALLTYPE CStartMenu::GetIconSize(DWORD* piIcon) { UNIMPLEMENTED; return E_NOTIMPL; } +HRESULT STDMETHODCALLTYPE CStartMenu::SetBitmap(HBITMAP hBitmap) +{ + BITMAP bm; + if (GetObject(hBitmap, sizeof(BITMAP), &bm)) + { + m_hBitmap = hBitmap; + m_sizBitmap.cx = bm.bmWidth; + m_sizBitmap.cy = bm.bmHeight; + return S_OK; + } + return E_FAIL; +} + +HRESULT STDMETHODCALLTYPE CStartMenu::GetBitmap(HBITMAP* phBitmap) +{ + if (phBitmap == NULL) + return E_FAIL; + *phBitmap = m_hBitmap; + return S_OK; +} + CMenuBandSite::CMenuBandSite() { m_pObjects = NULL; Index: dll/win32/shell32/startmenu.h =================================================================== --- dll/win32/shell32/startmenu.h (revision 57871) +++ dll/win32/shell32/startmenu.h (working copy) @@ -21,22 +21,37 @@ #ifndef _STARTMENU_H_ #define _STARTMENU_H_ +#define STARTMENUITEM_COUNT 9 + class CStartMenu : public CComCoClass, public CComObjectRootEx, public IMenuPopup, public IObjectWithSite, public IInitializeObject, - public IMenuBand // FIXME + public IMenuBand, // FIXME + public IBanneredBar { private: IBandSite *m_pBandSite; IUnknown *m_pUnkSite; public: - CStartMenu(); - ~CStartMenu(); + HWND m_hWnd; + DWORD m_iIcon; /* BMICON_* */ + HBITMAP m_hBitmap; + SIZE m_sizBitmap; + INT m_iMenuSelected; + INT m_nMenuHeight; + INT m_nSepHeight; + HICON m_ahIcons[STARTMENUITEM_COUNT]; + TCHAR m_aszStartMenuTexts[STARTMENUITEM_COUNT][64]; + BOOL m_bTracking; +public: + CStartMenu(); + ~CStartMenu(); + // *** IOleWindow methods *** virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd); @@ -62,6 +77,13 @@ virtual HRESULT STDMETHODCALLTYPE IsMenuMessage(MSG *pmsg); virtual HRESULT STDMETHODCALLTYPE TranslateMenuMessage(MSG *pmsg, LRESULT *plRet); + // *** IBanneredBar methods *** + virtual HRESULT STDMETHODCALLTYPE SetIconSize(DWORD iIcon); + virtual HRESULT STDMETHODCALLTYPE GetIconSize(DWORD* piIcon); + virtual HRESULT STDMETHODCALLTYPE SetBitmap(HBITMAP hBitmap); + virtual HRESULT STDMETHODCALLTYPE GetBitmap(HBITMAP* phBitmap); + + DECLARE_REGISTRY_RESOURCEID(IDR_STARTMENU) DECLARE_NOT_AGGREGATABLE(CStartMenu) @@ -71,9 +93,10 @@ COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IDeskBar) COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup) - COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) - COM_INTERFACE_ENTRY_IID(IID_IInitializeObject, IInitializeObject) - COM_INTERFACE_ENTRY_IID(IID_IMenuBand, IMenuBand) // FIXME: Win does not export it + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + COM_INTERFACE_ENTRY_IID(IID_IInitializeObject, IInitializeObject) + COM_INTERFACE_ENTRY_IID(IID_IMenuBand, IMenuBand) // FIXME: Win does not export it + COM_INTERFACE_ENTRY_IID(IID_IBanneredBar, IBanneredBar) END_COM_MAP() };