*/
#include "precomp.h"
#include <windowsx.h>
+#include <CommonControls.h>
#include <shlwapi_undoc.h>
-WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
+extern "C"
+HRESULT WINAPI SHGetImageList(
+ _In_ int iImageList,
+ _In_ REFIID riid,
+ _Out_ void **ppv
+ );
+
#define TBSTYLE_EX_VERTICAL 4
+WINE_DEFAULT_DEBUG_CHANNEL(CMenuBand);
+
#define TIMERID_HOTTRACK 1
#define SUBCLASS_ID_MENUBAND 1
extern "C" BOOL WINAPI Shell_GetImageLists(HIMAGELIST * lpBigList, HIMAGELIST * lpSmallList);
class CMenuBand;
+class CMenuFocusManager;
class CMenuToolbarBase
{
+private:
+ HWND m_hwnd; // May be the pager
+
+protected:
+ CMenuBand * m_menuBand;
+ HWND m_hwndToolbar;
+ DWORD m_dwMenuFlags;
+ INT m_hotItem;
+ WNDPROC m_SubclassOld;
+ BOOL m_hasIdealSize;
+ SIZE m_idealSize;
+ BOOL m_usePager;
+
+private:
+ static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
public:
- CMenuToolbarBase(CMenuBand *menuBand);
+ CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager);
virtual ~CMenuToolbarBase() {}
+ HRESULT IsWindowOwner(HWND hwnd);
HRESULT CreateToolbar(HWND hwndParent, DWORD dwFlags);
HRESULT GetWindow(HWND *phwnd);
HRESULT ShowWindow(BOOL fShow);
HRESULT Close();
- BOOL IsWindowOwner(HWND hwnd) { return m_hwnd && m_hwnd == hwnd; }
-
virtual HRESULT FillToolbar() = 0;
virtual HRESULT PopupItem(UINT uItem) = 0;
virtual HRESULT HasSubMenu(UINT uItem) = 0;
- virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0;
+ virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
- HRESULT OnHotItemChange(const NMTBHOTITEM * hot);
-
- HRESULT PopupSubMenu(UINT index, IShellMenu* childShellMenu);
+ HRESULT PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu);
HRESULT PopupSubMenu(UINT index, HMENU menu);
HRESULT DoContextMenu(IContextMenu* contextMenu);
- static LRESULT CALLBACK s_SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
-protected:
+ HRESULT ChangeHotItem(DWORD changeType);
+ HRESULT OnHotItemChange(const NMTBHOTITEM * hot);
- static const UINT WM_USER_SHOWPOPUPMENU = WM_USER + 1;
+ HRESULT GetIdealSize(SIZE& size);
+ HRESULT SetPosSize(int x, int y, int cx, int cy);
- LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void InvalidateDraw();
- CMenuBand *m_menuBand;
- HWND m_hwnd;
- DWORD m_dwMenuFlags;
- INT m_hotItem;
- WNDPROC m_SubclassOld;
+protected:
+ LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
-class CMenuStaticToolbar : public CMenuToolbarBase
+class CMenuStaticToolbar :
+ public CMenuToolbarBase
{
+private:
+ HMENU m_hmenu;
+
public:
CMenuStaticToolbar(CMenuBand *menuBand);
virtual ~CMenuStaticToolbar() {}
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
-private:
- HMENU m_hmenu;
};
-class CMenuSFToolbar : public CMenuToolbarBase
+class CMenuSFToolbar :
+ public CMenuToolbarBase
{
+private:
+ IShellFolder * m_shellFolder;
+ LPCITEMIDLIST m_idList;
+ HKEY m_hKey;
+
public:
CMenuSFToolbar(CMenuBand *menuBand);
virtual ~CMenuSFToolbar();
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
private:
- LPITEMIDLIST GetPidlFromId(UINT uItem, INT* pIndex);
-
- IShellFolder * m_shellFolder;
- LPCITEMIDLIST m_idList;
- HKEY m_hKey;
+ LPITEMIDLIST GetPidlFromId(UINT uItem, INT* pIndex = NULL);
};
class CMenuBand :
public IWinEventHandler,
public IShellMenuAcc
{
-public:
- CMenuBand();
- ~CMenuBand();
-
private:
- IOleWindow *m_site;
- IShellMenuCallback *m_psmc;
+ CMenuFocusManager * m_focusManager;
+ CMenuStaticToolbar * m_staticToolbar;
+ CMenuSFToolbar * m_SFToolbar;
- CMenuStaticToolbar *m_staticToolbar;
- CMenuSFToolbar *m_SFToolbar;
+ CComPtr<IOleWindow> m_site;
+ CComPtr<IShellMenuCallback> m_psmc;
+ CComPtr<IMenuPopup> m_subMenuChild;
+ CComPtr<IMenuPopup> m_subMenuParent;
- UINT m_uId;
- UINT m_uIdAncestor;
+ UINT m_uId;
+ UINT m_uIdAncestor;
DWORD m_dwFlags;
PVOID m_UserData;
HMENU m_hmenu;
- HWND m_menuOwner;
+ HWND m_menuOwner;
BOOL m_useBigIcons;
-
HWND m_topLevelWindow;
+ CMenuToolbarBase * m_hotBar;
+ INT m_hotItem;
+ INT m_popupItem;
+
+ HFONT m_marlett;
+
public:
+ CMenuBand();
+ ~CMenuBand();
+
+ DECLARE_NOT_AGGREGATABLE(CMenuBand)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ BEGIN_COM_MAP(CMenuBand)
+ COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IMenuPopup)
+ COM_INTERFACE_ENTRY_IID(IID_IShellMenu, IShellMenu)
+ COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
+ COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IDeskBand)
+ COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
+ COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
+ COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
+ COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
+ COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
+ COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersistStream)
+ COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
+ COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
+ COM_INTERFACE_ENTRY_IID(IID_IMenuBand, IMenuBand)
+ COM_INTERFACE_ENTRY_IID(IID_IShellMenu2, IShellMenu2)
+ COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
+ COM_INTERFACE_ENTRY_IID(IID_IShellMenuAcc, IShellMenuAcc)
+ END_COM_MAP()
// *** IDeskBand methods ***
virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi);
virtual HRESULT STDMETHODCALLTYPE DoDefaultAction(THIS);
virtual HRESULT STDMETHODCALLTYPE IsEmpty(THIS);
- HRESULT CallCBWithId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
- HRESULT CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam);
- HRESULT TrackPopup(HMENU popup, INT x, INT y);
+ HRESULT _CallCBWithItemId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ HRESULT _CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ HRESULT _TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y);
+ HRESULT _GetTopLevelWindow(HWND*topLevel);
+ HRESULT _OnHotItemChanged(CMenuToolbarBase * tb, INT id);
+ HRESULT _MenuItemHotTrack(DWORD changeType);
+ HRESULT _OnPopupSubMenu(INT popupItem, IMenuPopup * popup, POINTL * pAt, RECTL * pExclude);
- BOOL UseBigIcons() {
+ BOOL UseBigIcons()
+ {
return m_useBigIcons;
}
- DECLARE_NOT_AGGREGATABLE(CMenuBand)
- DECLARE_PROTECT_FINAL_CONSTRUCT()
+private:
+ HRESULT _CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id = 0, LPITEMIDLIST pidl = NULL);
+};
- BEGIN_COM_MAP(CMenuBand)
- COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IMenuPopup)
- COM_INTERFACE_ENTRY_IID(IID_IShellMenu, IShellMenu)
- COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
- COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IDeskBand)
- COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
- COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
- COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
- COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
- COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
- COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersistStream)
- COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
- COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
- COM_INTERFACE_ENTRY_IID(IID_IMenuBand, IMenuBand)
- COM_INTERFACE_ENTRY_IID(IID_IShellMenu2, IShellMenu2)
- COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
- COM_INTERFACE_ENTRY_IID(IID_IShellMenuAcc, IShellMenuAcc)
- END_COM_MAP()
+class CMenuFocusManager :
+ public CComCoClass<CMenuFocusManager>,
+ public CComObjectRootEx<CComMultiThreadModelNoCS>
+{
+private:
+ static DWORD TlsIndex;
+
+ static CMenuFocusManager * GetManager()
+ {
+ return reinterpret_cast<CMenuFocusManager *>(TlsGetValue(TlsIndex));
+ }
+
+public:
+ static CMenuFocusManager * AcquireManager()
+ {
+ CMenuFocusManager * obj = NULL;
+
+ if (!TlsIndex)
+ {
+ if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return NULL;
+ }
+
+ obj = GetManager();
+
+ if (!obj)
+ {
+ obj = new CComObject<CMenuFocusManager>();
+ TlsSetValue(TlsIndex, obj);
+ }
+
+ obj->AddRef();
+
+ return obj;
+ }
+
+ static void ReleaseManager(CMenuFocusManager * obj)
+ {
+ if (!obj->Release())
+ {
+ TlsSetValue(TlsIndex, NULL);
+ }
+ }
private:
- HRESULT _CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id = 0, LPITEMIDLIST pidl = NULL);
+ static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
+ {
+ return GetManager()->GetMsgHook(nCode, wParam, lParam);
+ }
+
+private:
+ CMenuBand * m_currentBand;
+ HWND m_currentFocus;
+ HHOOK m_hHook;
+ DWORD m_threadId;
+
+ // TODO: make dynamic
+#define MAX_RECURSE 20
+ CMenuBand* m_bandStack[MAX_RECURSE];
+ int m_bandCount;
+
+ HRESULT PushToArray(CMenuBand * item)
+ {
+ if (m_bandCount >= MAX_RECURSE)
+ return E_OUTOFMEMORY;
+
+ m_bandStack[m_bandCount++] = item;
+ return S_OK;
+ }
+
+ HRESULT PopFromArray(CMenuBand ** pItem)
+ {
+ if (pItem)
+ *pItem = NULL;
+
+ if (m_bandCount <= 0)
+ return E_FAIL;
+
+ m_bandCount--;
+
+ if (pItem)
+ *pItem = m_bandStack[m_bandCount];
+
+ m_bandStack[m_bandCount] = NULL;
+
+ return S_OK;
+ }
+
+ HRESULT PeekArray(CMenuBand ** pItem)
+ {
+ if (!pItem)
+ return E_FAIL;
+
+ *pItem = NULL;
+
+ if (m_bandCount <= 0)
+ return E_FAIL;
+
+ *pItem = m_bandStack[m_bandCount - 1];
+
+ return S_OK;
+ }
+
+protected:
+ CMenuFocusManager() :
+ m_currentBand(NULL),
+ m_currentFocus(NULL),
+ m_bandCount(0)
+ {
+ m_threadId = GetCurrentThreadId();
+ }
+
+ ~CMenuFocusManager()
+ {
+ }
+
+public:
+
+ DECLARE_NOT_AGGREGATABLE(CMenuFocusManager)
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(CMenuFocusManager)
+ END_COM_MAP()
+
+ LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
+ {
+ if (nCode < 0)
+ return CallNextHookEx(m_hHook, nCode, wParam, lParam);
+
+ if (nCode == HC_ACTION)
+ {
+ BOOL callNext = TRUE;
+ MSG* msg = reinterpret_cast<MSG*>(lParam);
+
+ // Do whatever is necessary here
+
+ switch (msg->message)
+ {
+ case WM_CLOSE:
+ break;
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ switch (msg->wParam)
+ {
+ case VK_MENU:
+ case VK_LMENU:
+ case VK_RMENU:
+ m_currentBand->_MenuItemHotTrack(MPOS_FULLCANCEL);
+ break;
+ case VK_LEFT:
+ m_currentBand->_MenuItemHotTrack(MPOS_SELECTLEFT);
+ break;
+ case VK_RIGHT:
+ m_currentBand->_MenuItemHotTrack(MPOS_SELECTRIGHT);
+ break;
+ case VK_UP:
+ m_currentBand->_MenuItemHotTrack(VK_UP);
+ break;
+ case VK_DOWN:
+ m_currentBand->_MenuItemHotTrack(VK_DOWN);
+ break;
+ }
+ break;
+ case WM_CHAR:
+ //if (msg->wParam >= 'a' && msg->wParam <= 'z')
+ //{
+ // callNext = FALSE;
+ // PostMessage(m_currentFocus, WM_SYSCHAR, wParam, lParam);
+ //}
+ break;
+ }
+
+ if (!callNext)
+ return 0;
+ }
+
+ return CallNextHookEx(m_hHook, nCode, wParam, lParam);
+ }
+
+ HRESULT PlaceHooks(HWND window)
+ {
+ //SetCapture(window);
+ m_hHook = SetWindowsHookEx(WH_GETMESSAGE, s_GetMsgHook, NULL, m_threadId);
+ return S_OK;
+ }
+
+ HRESULT RemoveHooks(HWND window)
+ {
+ UnhookWindowsHookEx(m_hHook);
+ //ReleaseCapture();
+ return S_OK;
+ }
+
+ HRESULT UpdateFocus(CMenuBand * newBand)
+ {
+ HRESULT hr;
+ HWND newFocus;
+
+ if (newBand == NULL)
+ {
+ hr = RemoveHooks(m_currentFocus);
+ m_currentFocus = NULL;
+ m_currentBand = NULL;
+ return S_OK;
+ }
+
+ hr = newBand->_GetTopLevelWindow(&newFocus);
+ if (FAILED(hr))
+ return hr;
+
+ if (!m_currentBand)
+ {
+ hr = PlaceHooks(newFocus);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ m_currentFocus = newFocus;
+ m_currentBand = newBand;
+
+ return S_OK;
+ }
+
+public:
+ HRESULT PushMenu(CMenuBand * mb)
+ {
+ HRESULT hr;
+
+ hr = PushToArray(mb);
+ if (FAILED(hr))
+ return hr;
+
+ return UpdateFocus(mb);
+ }
+
+ HRESULT PopMenu(CMenuBand * mb)
+ {
+ CMenuBand * mbc;
+ HRESULT hr;
+
+ hr = PopFromArray(&mbc);
+ if (FAILED(hr))
+ return hr;
+
+ if (mb != mbc)
+ return E_FAIL;
+
+ hr = PeekArray(&mbc);
+
+ return UpdateFocus(mbc);
+ }
};
+DWORD CMenuFocusManager::TlsIndex = 0;
+
extern "C"
HRESULT CMenuBand_Constructor(REFIID riid, LPVOID *ppv)
{
return hr;
}
-CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand) :
- m_menuBand(menuBand),
+CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) :
m_hwnd(NULL),
- m_dwMenuFlags(0)
+ m_menuBand(menuBand),
+ m_hwndToolbar(NULL),
+ m_dwMenuFlags(0),
+ m_hasIdealSize(FALSE)
+{
+}
+
+HRESULT CMenuToolbarBase::IsWindowOwner(HWND hwnd)
+{
+ return (m_hwnd && m_hwnd == hwnd) ||
+ (m_hwndToolbar && m_hwndToolbar == hwnd) ? S_OK : S_FALSE;
+}
+
+void CMenuToolbarBase::InvalidateDraw()
{
+ InvalidateRect(m_hwnd, NULL, FALSE);
}
HRESULT CMenuToolbarBase::ShowWindow(BOOL fShow)
if (m_menuBand->UseBigIcons())
{
- SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilBig));
+ SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilBig));
}
else
{
- SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilSmall));
+ SendMessageW(m_hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilSmall));
}
return S_OK;
HRESULT CMenuToolbarBase::Close()
{
- DestroyWindow(m_hwnd);
+ DestroyWindow(m_hwndToolbar);
+ if (m_hwndToolbar != m_hwnd)
+ DestroyWindow(m_hwnd);
+ m_hwndToolbar = NULL;
m_hwnd = NULL;
return S_OK;
}
if (hwndToolbar == NULL)
return E_FAIL;
- ::SetParent(hwndToolbar, hwndParent);
+ if (m_usePager)
+ {
+ LONG pgStyles = PGS_VERT | WS_CHILD | WS_VISIBLE;
+ LONG pgExStyles = 0;
- m_hwnd = hwndToolbar;
+ HWND hwndPager = CreateWindowEx(
+ pgExStyles, WC_PAGESCROLLER, NULL,
+ pgStyles, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
+ hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), 0);
- /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
- SendMessageW(m_hwnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
+ ::SetParent(hwndToolbar, hwndPager);
+ ::SetParent(hwndPager, hwndParent);
- HIMAGELIST ilBig, ilSmall;
- Shell_GetImageLists(&ilBig, &ilSmall);
+ SendMessage(hwndPager, PGM_SETCHILD, 0, reinterpret_cast<LPARAM>(hwndToolbar));
+ m_hwndToolbar = hwndToolbar;
+ m_hwnd = hwndPager;
+ }
+ else
+ {
+ ::SetParent(hwndToolbar, hwndParent);
+ m_hwndToolbar = hwndToolbar;
+ m_hwnd = hwndToolbar;
+ }
+
+ /* Identify the version of the used Common Controls DLL by sending the size of the TBBUTTON structure */
+ SendMessageW(hwndToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
//if (dwFlags & SMINIT_TOPLEVEL)
//{
// SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, 0);
//}
//else
+ int shiml;
if (m_menuBand->UseBigIcons())
{
- SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilBig));
+ shiml = SHIL_LARGE;
+ SendMessageW(hwndToolbar, TB_SETPADDING, 0, MAKELPARAM(0, 0));
+ }
+ else
+ {
+ shiml = SHIL_SMALL;
+ }
+
+ IImageList * piml;
+ HRESULT hr = SHGetImageList(shiml, IID_PPV_ARG(IImageList, &piml));
+ if (SUCCEEDED(hr))
+ {
+ SendMessageW(hwndToolbar, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(piml));
}
else
{
- SendMessageW(m_hwnd, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(ilSmall));
+ SendMessageW(hwndToolbar, TB_SETIMAGELIST, 0, 0);
+ }
+
+ SetWindowLongPtr(hwndToolbar, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
+ m_SubclassOld = (WNDPROC) SetWindowLongPtr(hwndToolbar, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(CMenuToolbarBase::s_SubclassProc));
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::GetIdealSize(SIZE& size)
+{
+ size.cx = size.cy = 0;
+
+ if (m_hwndToolbar && !m_hasIdealSize)
+ {
+ SendMessageW(m_hwndToolbar, TB_AUTOSIZE, 0, 0);
+ SendMessageW(m_hwndToolbar, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&m_idealSize));
+ m_hasIdealSize = TRUE;
}
- SetWindowLongPtr(m_hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
- m_SubclassOld = (WNDPROC) SetWindowLongPtr(m_hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(CMenuToolbarBase::s_SubclassProc));
+ size = m_idealSize;
+
+ return S_OK;
+}
+HRESULT CMenuToolbarBase::SetPosSize(int x, int y, int cx, int cy)
+{
+ if (m_hwnd != m_hwndToolbar)
+ {
+ SetWindowPos(m_hwndToolbar, NULL, x, y, cx, m_idealSize.cy, 0);
+ }
+ SetWindowPos(m_hwnd, NULL, x, y, cx, cy, 0);
+ DWORD btnSize = SendMessage(m_hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
+ SendMessage(m_hwndToolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(cx, HIWORD(btnSize)));
return S_OK;
}
case WM_TIMER:
if (wParam == TIMERID_HOTTRACK)
{
- PopupItem(m_hotItem);
KillTimer(hWnd, TIMERID_HOTTRACK);
+
+ m_menuBand->_OnPopupSubMenu(-1, NULL, NULL, NULL);
+
+ if (HasSubMenu(m_hotItem) == S_OK)
+ {
+ PopupItem(m_hotItem);
+ }
}
}
{
if (hot->dwFlags & HICF_LEAVING)
{
- KillTimer(m_hwnd, TIMERID_HOTTRACK);
+ KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
+ m_hotItem = -1;
+ m_menuBand->_OnHotItemChanged(NULL, -1);
+ m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
}
else if (m_hotItem != hot->idNew)
{
- if (HasSubMenu(hot->idNew) == S_OK)
- {
- DWORD elapsed = 0;
- SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
-
- m_hotItem = hot->idNew;
+ DWORD elapsed = 0;
+ SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &elapsed, 0);
+ SetTimer(m_hwndToolbar, TIMERID_HOTTRACK, elapsed, NULL);
- SetTimer(m_hwnd, TIMERID_HOTTRACK, elapsed, NULL);
- }
+ m_hotItem = hot->idNew;
+ m_menuBand->_OnHotItemChanged(this, m_hotItem);
+ m_menuBand->_MenuItemHotTrack(MPOS_CHILDTRACKING);
}
-
- m_menuBand->OnSelect(MPOS_CHILDTRACKING);
return S_OK;
}
-HRESULT CMenuToolbarBase::PopupSubMenu(UINT index, IShellMenu* childShellMenu)
+HRESULT CMenuToolbarBase::PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu)
{
IBandSite* pBandSite;
IDeskBar* pDeskBar;
HRESULT hr = 0;
RECT rc = { 0 };
- if (!SendMessage(m_hwnd, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
+ if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
return E_FAIL;
POINT a = { rc.left, rc.top };
POINT b = { rc.right, rc.bottom };
- ClientToScreen(m_hwnd, &a);
- ClientToScreen(m_hwnd, &b);
+ ClientToScreen(m_hwndToolbar, &a);
+ ClientToScreen(m_hwndToolbar, &b);
- POINTL pt = { b.x, b.y };
+ POINTL pt = { b.x, a.y };
RECTL rcl = { a.x, a.y, b.x, b.y }; // maybe-TODO: fetch client area of deskbar?
if (FAILED(hr))
return hr;
- popup->Popup(&pt, &rcl, MPPF_TOP | MPPF_RIGHT);
+ m_menuBand->_OnPopupSubMenu(itemId, popup, &pt, &rcl);
return S_OK;
}
{
RECT rc = { 0 };
- if (!SendMessage(m_hwnd, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
+ if (!SendMessage(m_hwndToolbar, TB_GETITEMRECT, index, reinterpret_cast<LPARAM>(&rc)))
return E_FAIL;
POINT b = { rc.right, rc.bottom };
- ClientToScreen(m_hwnd, &b);
+ ClientToScreen(m_hwndToolbar, &b);
HMENU popup = GetSubMenu(menu, index);
- m_menuBand->TrackPopup(popup, b.x, b.y);
+ m_menuBand->_TrackSubMenuUsingTrackPopupMenu(popup, b.x, b.y);
return S_OK;
}
HRESULT CMenuToolbarBase::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
- m_menuBand->OnSelect(MPOS_EXECUTE);
- return S_OK;
+ theResult = 0;
+ if (HasSubMenu(wParam) == S_OK)
+ {
+ KillTimer(m_hwndToolbar, TIMERID_HOTTRACK);
+ PopupItem(wParam);
+ return S_FALSE;
+ }
+ return m_menuBand->_MenuItemHotTrack(MPOS_EXECUTE);
+}
+
+HRESULT CMenuToolbarBase::ChangeHotItem(DWORD dwSelectType)
+{
+ int prev = m_hotItem;
+ int index = -1;
+
+ if (dwSelectType != 0xFFFFFFFF)
+ {
+ int count = SendMessage(m_hwndToolbar, TB_BUTTONCOUNT, 0, 0);
+
+ if (m_hotItem >= 0)
+ {
+ TBBUTTONINFO info = { 0 };
+ info.cbSize = sizeof(TBBUTTONINFO);
+ info.dwMask = 0;
+ index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, m_hotItem, reinterpret_cast<LPARAM>(&info));
+ }
+
+ if (dwSelectType == VK_HOME)
+ {
+ index = 0;
+ dwSelectType = VK_DOWN;
+ }
+ else if (dwSelectType == VK_END)
+ {
+ index = count - 1;
+ dwSelectType = VK_UP;
+ }
+ else if (index < 0)
+ {
+ if (dwSelectType == VK_UP)
+ {
+ index = count - 1;
+ }
+ else if (dwSelectType == VK_DOWN)
+ {
+ index = 0;
+ }
+ }
+ else
+ {
+ if (dwSelectType == VK_UP)
+ {
+ index--;
+ }
+ else if (dwSelectType == VK_DOWN)
+ {
+ index++;
+ }
+ }
+
+ TBBUTTON btn = { 0 };
+ while (index >= 0 && index < count)
+ {
+ DWORD res = SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
+ if (!res)
+ return E_FAIL;
+
+ if (btn.dwData)
+ {
+ m_hotItem = btn.idCommand;
+ if (prev != m_hotItem)
+ {
+ SendMessage(m_hwndToolbar, TB_SETHOTITEM, index, 0);
+ return m_menuBand->_OnHotItemChanged(this, m_hotItem);
+ }
+ return S_OK;
+ }
+
+ if (dwSelectType == VK_UP)
+ {
+ index--;
+ }
+ else if (dwSelectType == VK_DOWN)
+ {
+ index++;
+ }
+ }
+ }
+
+ m_hotItem = -1;
+ if (prev != m_hotItem)
+ {
+ SendMessage(m_hwndToolbar, TB_SETHOTITEM, -1, 0);
+ m_menuBand->_OnHotItemChanged(NULL, -1);
+ }
+ return S_FALSE;
}
BOOL
}
CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
- CMenuToolbarBase(menuBand),
+ CMenuToolbarBase(menuBand, FALSE),
m_hmenu(NULL)
{
}
SMINFO * sminfo = new SMINFO();
sminfo->dwMask = SMIM_ICON | SMIM_FLAGS;
- if (SUCCEEDED(m_menuBand->CallCBWithId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo))))
+ if (SUCCEEDED(m_menuBand->_CallCBWithItemId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo))))
{
tbb.iBitmap = sminfo->iIcon;
tbb.dwData = reinterpret_cast<DWORD_PTR>(sminfo);
tbb.fsStyle |= BTNS_SEP;
}
- SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+ SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
if (MenuString)
HeapFree(GetProcessHeap(), 0, MenuString);
HRESULT CMenuStaticToolbar::OnContextMenu(NMMOUSE * rclick)
{
CComPtr<IContextMenu> contextMenu;
- HRESULT hr = m_menuBand->CallCBWithId(rclick->dwItemSpec, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IContextMenu), reinterpret_cast<LPARAM>(&contextMenu));
+ HRESULT hr = m_menuBand->_CallCBWithItemId(rclick->dwItemSpec, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IContextMenu), reinterpret_cast<LPARAM>(&contextMenu));
if (hr != S_OK)
return hr;
HRESULT CMenuStaticToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
- HRESULT hr = m_menuBand->CallCBWithId(wParam, SMC_EXEC, 0, 0);
+ HRESULT hr;
+ hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
if (FAILED(hr))
return hr;
- return CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
+ // in case the clicked item has a submenu, we do not need to execute the item
+ if (hr == S_FALSE)
+ return hr;
+
+ return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
}
HRESULT CMenuStaticToolbar::PopupItem(UINT uItem)
TBBUTTONINFO info = { 0 };
info.cbSize = sizeof(TBBUTTONINFO);
info.dwMask = 0;
- int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
+ int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
if (index < 0)
return E_FAIL;
-
+
TBBUTTON btn = { 0 };
- SendMessage(m_hwnd, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
+ SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
SMINFO * nfo = reinterpret_cast<SMINFO*>(btn.dwData);
if (!nfo)
else
{
CComPtr<IShellMenu> shellMenu;
- HRESULT hr = m_menuBand->CallCBWithId(uItem, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IShellMenu), reinterpret_cast<LPARAM>(&shellMenu));
+ HRESULT hr = m_menuBand->_CallCBWithItemId(uItem, SMC_GETOBJECT, reinterpret_cast<WPARAM>(&IID_IShellMenu), reinterpret_cast<LPARAM>(&shellMenu));
if (FAILED(hr))
return hr;
- return PopupSubMenu(index, shellMenu);
+ return PopupSubMenu(uItem, index, shellMenu);
}
}
TBBUTTONINFO info = { 0 };
info.cbSize = sizeof(TBBUTTONINFO);
info.dwMask = 0;
- int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
+ int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
if (index < 0)
return E_FAIL;
return ::GetSubMenu(m_hmenu, index) ? S_OK : S_FALSE;
}
CMenuSFToolbar::CMenuSFToolbar(CMenuBand * menuBand) :
- CMenuToolbarBase(menuBand),
+ CMenuToolbarBase(menuBand, TRUE),
m_shellFolder(NULL)
{
}
HRESULT CMenuSFToolbar::FillToolbar()
{
HRESULT hr;
- TBBUTTON tbb = { 0 };
int i = 0;
PWSTR MenuString;
- tbb.fsState = TBSTATE_ENABLED;
- tbb.fsStyle = 0;
-
IEnumIDList * eidl;
- m_shellFolder->EnumObjects(m_hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
+ m_shellFolder->EnumObjects(m_hwndToolbar, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &eidl);
LPITEMIDLIST item = static_cast<LPITEMIDLIST>(CoTaskMemAlloc(sizeof(ITEMIDLIST)));
ULONG fetched;
INT index = 0;
INT indexOpen = 0;
+ TBBUTTON tbb = { 0 };
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = 0;
+
CComPtr<IShellItem> psi;
- SHCreateShellItem(NULL, m_shellFolder, item, &psi);
+ hr = SHCreateShellItem(NULL, m_shellFolder, item, &psi);
+ if (FAILED(hr))
+ return hr;
hr = psi->GetDisplayName(SIGDN_NORMALDISPLAY, &MenuString);
if (FAILED(hr))
tbb.fsStyle |= BTNS_DROPDOWN;
}
- tbb.idCommand = i++;
+ tbb.idCommand = ++i;
tbb.iString = (INT_PTR) MenuString;
tbb.iBitmap = index;
tbb.dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
// FIXME: remove before deleting the toolbar or it will leak
- SendMessageW(m_hwnd, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+ SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
HeapFree(GetProcessHeap(), 0, MenuString);
}
CoTaskMemFree(item);
+ // If no items were added, show the "empty" placeholder
+ if (i == 0)
+ {
+ TBBUTTON tbb = { 0 };
+ PCWSTR MenuString = L"(Empty)";
+
+ tbb.fsState = 0/*TBSTATE_DISABLED*/;
+ tbb.fsStyle = 0;
+ tbb.iString = (INT_PTR) MenuString;
+ tbb.iBitmap = -1;
+
+ SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+
+ return S_OK;
+ }
+
return hr;
}
TBBUTTONINFO info = { 0 };
info.cbSize = sizeof(TBBUTTONINFO);
info.dwMask = 0;
- int index = SendMessage(m_hwnd, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
+ int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
if (index < 0)
return NULL;
*pIndex = index;
TBBUTTON btn = { 0 };
- if (!SendMessage(m_hwnd, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
+ if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
return NULL;
return reinterpret_cast<LPITEMIDLIST>(btn.dwData);
CComPtr<IContextMenu> contextMenu;
LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(rclick->dwItemData);
- hr = m_shellFolder->GetUIObjectOf(m_hwnd, 1, &pidl, IID_IContextMenu, NULL, reinterpret_cast<VOID **>(&contextMenu));
+ hr = m_shellFolder->GetUIObjectOf(m_hwndToolbar, 1, &pidl, IID_IContextMenu, NULL, reinterpret_cast<VOID **>(&contextMenu));
if (hr != S_OK)
return hr;
HRESULT CMenuSFToolbar::OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
- return m_menuBand->CallCBWithPidl(GetPidlFromId(wParam, NULL), SMC_SFEXEC, 0, 0);
+ HRESULT hr;
+ hr = CMenuToolbarBase::OnCommand(wParam, lParam, theResult);
+ if (FAILED(hr))
+ return hr;
+
+ // in case the clicked item has a submenu, we do not need to execute the item
+ if (hr == S_FALSE)
+ return hr;
+
+ return m_menuBand->_CallCBWithItemPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0, 0);
}
HRESULT CMenuSFToolbar::PopupItem(UINT uItem)
int index;
CComPtr<IShellMenuCallback> psmc;
CComPtr<IShellMenu> shellMenu;
-
+
LPITEMIDLIST pidl = GetPidlFromId(uItem, &index);
if (!pidl)
m_menuBand->GetMenuInfo(&psmc, &uId, &uIdAncestor, &flags);
- // FIXME: not sure waht to use as uId/uIdAncestor here
+ // FIXME: not sure what to use as uId/uIdAncestor here
hr = shellMenu->Initialize(psmc, 0, uId, SMINIT_VERTICAL);
if (FAILED(hr))
return hr;
if (FAILED(hr))
return hr;
- return PopupSubMenu(index, shellMenu);
+ return PopupSubMenu(uItem, index, shellMenu);
}
HRESULT CMenuSFToolbar::HasSubMenu(UINT uItem)
{
HRESULT hr;
CComPtr<IShellItem> psi;
- SHCreateShellItem(NULL, m_shellFolder, GetPidlFromId(uItem, NULL), &psi);
+ hr = SHCreateShellItem(NULL, m_shellFolder, GetPidlFromId(uItem), &psi);
+ if (FAILED(hr))
+ return S_FALSE;
SFGAOF attrs;
hr = psi->GetAttributes(SFGAO_FOLDER, &attrs);
}
CMenuBand::CMenuBand() :
- m_site(NULL),
- m_psmc(NULL),
m_staticToolbar(NULL),
m_SFToolbar(NULL),
- m_useBigIcons(FALSE)
+ m_site(NULL),
+ m_psmc(NULL),
+ m_subMenuChild(NULL),
+ m_useBigIcons(FALSE),
+ m_hotBar(NULL),
+ m_hotItem(-1),
+ m_popupItem(-1)
{
+ m_focusManager = CMenuFocusManager::AcquireManager();
+
+ m_marlett = CreateFont(
+ 0, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET,
+ OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY, FF_DONTCARE, L"Marlett");
}
CMenuBand::~CMenuBand()
{
- if (m_site)
- m_site->Release();
-
- if (m_psmc)
- m_psmc->Release();
+ CMenuFocusManager::ReleaseManager(m_focusManager);
if (m_staticToolbar)
delete m_staticToolbar;
if (m_SFToolbar)
delete m_SFToolbar;
+
+ DeleteObject(m_marlett);
}
HRESULT STDMETHODCALLTYPE CMenuBand::Initialize(
UINT uIdAncestor,
DWORD dwFlags)
{
- if (m_psmc)
- m_psmc->Release();
-
- m_psmc = psmc;
+ if (m_psmc != psmc)
+ m_psmc = psmc;
m_uId = uId;
m_uIdAncestor = uIdAncestor;
m_dwFlags = dwFlags;
if (m_psmc)
{
- m_psmc->AddRef();
-
_CallCB(SMC_CREATE, 0, reinterpret_cast<LPARAM>(&m_UserData));
}
HWND hwndParent;
HRESULT hr;
- if (m_site != NULL)
- m_site->Release();
+ m_site = NULL;
if (pUnkSite == NULL)
return S_OK;
hwndParent = NULL;
hr = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &m_site));
- if (SUCCEEDED(hr))
- {
- m_site->Release();
+ if (FAILED(hr))
+ return hr;
- hr = m_site->GetWindow(&hwndParent);
- if (FAILED(hr))
- return hr;
- }
+ hr = m_site->GetWindow(&hwndParent);
+ if (FAILED(hr))
+ return hr;
if (!::IsWindow(hwndParent))
return E_FAIL;
return hr;
}
+ hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_subMenuParent));
+ if (FAILED(hr))
+ return hr;
+
CComPtr<IOleWindow> pTopLevelWindow;
hr = IUnknown_QueryService(m_site, SID_STopLevelBrowser, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
if (FAILED(hr))
HRESULT STDMETHODCALLTYPE CMenuBand::OnPosRectChangeDB(RECT *prc)
{
- SIZE sizeStaticY = { 0 };
- SIZE sizeShlFldY = { 0 };
- HWND hwndStatic = NULL;
- HWND hwndShlFld = NULL;
+ SIZE sizeStatic = { 0 };
+ SIZE sizeShlFld = { 0 };
HRESULT hr = S_OK;
if (m_staticToolbar != NULL)
- hr = m_staticToolbar->GetWindow(&hwndStatic);
+ hr = m_staticToolbar->GetIdealSize(sizeStatic);
if (FAILED(hr))
return hr;
if (m_SFToolbar != NULL)
- hr = m_SFToolbar->GetWindow(&hwndShlFld);
+ hr = m_SFToolbar->GetIdealSize(sizeShlFld);
if (FAILED(hr))
return hr;
- if (hwndStatic == NULL && hwndShlFld == NULL)
+ if (m_staticToolbar == NULL && m_SFToolbar == NULL)
return E_FAIL;
- if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeStaticY));
- if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeShlFldY));
+ int sy = min(prc->bottom - prc->top, sizeStatic.cy + sizeShlFld.cy);
- int sy = max(prc->bottom - prc->top, sizeStaticY.cy + sizeShlFldY.cy);
+ int syStatic = sizeStatic.cy;
+ int syShlFld = sy - syStatic;
- if (hwndShlFld)
+ if (m_SFToolbar)
{
- SetWindowPos(hwndShlFld, NULL,
- prc->left,
- prc->top,
- prc->right - prc->left,
- sizeShlFldY.cy,
- 0);
- DWORD btnSize = SendMessage(hwndShlFld, TB_GETBUTTONSIZE, 0, 0);
- SendMessage(hwndShlFld, TB_SETBUTTONSIZE, 0, MAKELPARAM(prc->right - prc->left, HIWORD(btnSize)));
+ m_SFToolbar->SetPosSize(
+ prc->left,
+ prc->top,
+ prc->right - prc->left,
+ syShlFld);
}
- if (hwndStatic)
+ if (m_staticToolbar)
{
- SetWindowPos(hwndStatic, hwndShlFld,
- prc->left,
- prc->top + sizeShlFldY.cy,
- prc->right - prc->left,
- sy - sizeShlFldY.cy,
- 0);
- DWORD btnSize = SendMessage(hwndStatic, TB_GETBUTTONSIZE, 0, 0);
- SendMessage(hwndStatic, TB_SETBUTTONSIZE, 0, MAKELPARAM(prc->right - prc->left, HIWORD(btnSize)));
+ m_staticToolbar->SetPosSize(
+ prc->left,
+ prc->top + syShlFld,
+ prc->right - prc->left,
+ syStatic);
}
return S_OK;
}
-
HRESULT STDMETHODCALLTYPE CMenuBand::GetBandInfo(
DWORD dwBandID,
DWORD dwViewMode,
DESKBANDINFO *pdbi)
{
- HWND hwndStatic = NULL;
- HWND hwndShlFld = NULL;
+ SIZE sizeStatic = { 0 };
+ SIZE sizeShlFld = { 0 };
+
HRESULT hr = S_OK;
if (m_staticToolbar != NULL)
- hr = m_staticToolbar->GetWindow(&hwndStatic);
+ hr = m_staticToolbar->GetIdealSize(sizeStatic);
if (FAILED(hr))
return hr;
if (m_SFToolbar != NULL)
- hr = m_SFToolbar->GetWindow(&hwndShlFld);
+ hr = m_SFToolbar->GetIdealSize(sizeShlFld);
if (FAILED(hr))
return hr;
- if (hwndStatic == NULL && hwndShlFld == NULL)
+ if (m_staticToolbar == NULL && m_SFToolbar == NULL)
return E_FAIL;
- // HACK (?)
- if (pdbi->dwMask == 0)
- {
- pdbi->dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR;
- }
-
- if (pdbi->dwMask & DBIM_MINSIZE)
- {
- SIZE sizeStatic = { 0 };
- SIZE sizeShlFld = { 0 };
-
- if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeStatic));
- if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeShlFld));
-
- pdbi->ptMinSize.x = 0;
- pdbi->ptMinSize.y = sizeStatic.cy + sizeShlFld.cy;
- }
- if (pdbi->dwMask & DBIM_MAXSIZE)
- {
- SIZE sizeStatic = { 0 };
- SIZE sizeShlFld = { 0 };
-
- if (hwndStatic) SendMessageW(hwndStatic, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&sizeStatic));
- if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETMAXSIZE, 0, reinterpret_cast<LPARAM>(&sizeShlFld));
-
- pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx); // ignored
- pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
- }
- if (pdbi->dwMask & DBIM_INTEGRAL)
- {
- pdbi->ptIntegral.x = 0;
- pdbi->ptIntegral.y = 0;
- }
- if (pdbi->dwMask & DBIM_ACTUAL)
- {
- SIZE sizeStatic = { 0 };
- SIZE sizeShlFld = { 0 };
-
- if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&sizeStatic));
- if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&sizeShlFld));
- pdbi->ptActual.x = max(sizeStatic.cx, sizeShlFld.cx);
+ pdbi->ptMaxSize.x = max(sizeStatic.cx, sizeShlFld.cx) + 20;
+ pdbi->ptMaxSize.y = sizeStatic.cy + sizeShlFld.cy;
- if (hwndStatic) SendMessageW(hwndStatic, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeStatic));
- if (hwndShlFld) SendMessageW(hwndShlFld, TB_GETIDEALSIZE, TRUE, reinterpret_cast<LPARAM>(&sizeShlFld));
- pdbi->ptActual.y = sizeStatic.cy + sizeShlFld.cy;
- }
- if (pdbi->dwMask & DBIM_TITLE)
- wcscpy(pdbi->wszTitle, L"");
- if (pdbi->dwMask & DBIM_MODEFLAGS)
- pdbi->dwModeFlags = DBIMF_UNDELETEABLE;
- if (pdbi->dwMask & DBIM_BKCOLOR)
- pdbi->crBkgnd = 0;
return S_OK;
}
return hr;
if (fShow)
- return _CallCB(SMC_INITMENU, 0, 0);
+ {
+ hr = _CallCB(SMC_INITMENU, 0, 0);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ if (fShow)
+ hr = m_focusManager->PushMenu(this);
+ else
+ hr = m_focusManager->PopMenu(this);
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
{
- UNIMPLEMENTED;
- return S_OK;
+ HRESULT hr;
+
+ hr = m_subMenuParent->SetSubMenu(this, fActivate);
+ if (FAILED(hr))
+ return hr;
+
+ if (fActivate)
+ {
+ CComPtr<IOleWindow> pTopLevelWindow;
+ hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IOleWindow, &pTopLevelWindow));
+ if (FAILED(hr))
+ return hr;
+
+ hr = pTopLevelWindow->GetWindow(&m_topLevelWindow);
+ if (FAILED(hr))
+ return hr;
+ }
+ else
+ {
+ m_topLevelWindow = NULL;
+ }
+
+ return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CMenuBand::HasFocusIO()
{
if (nCmdID == 16) // set (big) icon size
{
- this->m_useBigIcons = TRUE;
+ this->m_useBigIcons = nCmdexecopt == 2;
return S_OK;
}
else if (nCmdID == 19) // popup-related
HRESULT STDMETHODCALLTYPE CMenuBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
{
if (IsEqualIID(guidService, SID_SMenuBandChild) ||
- IsEqualIID(guidService, SID_SMenuBandBottom) ||
+ IsEqualIID(guidService, SID_SMenuBandBottom) ||
IsEqualIID(guidService, SID_SMenuBandBottomSelected))
return this->QueryInterface(riid, ppvObject);
WARN("Unknown service requested %s\n", wine_dbgstr_guid(&guidService));
HRESULT STDMETHODCALLTYPE CMenuBand::OnSelect(DWORD dwSelectType)
{
- CComPtr<IMenuPopup> pmp;
- HRESULT hr = IUnknown_QueryService(m_site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &pmp));
- if (FAILED(hr))
- return hr;
- pmp->OnSelect(dwSelectType);
- return S_OK;
+ switch (dwSelectType)
+ {
+ case MPOS_CHILDTRACKING:
+ // TODO: Cancel timers?
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_SELECTLEFT:
+ if (m_subMenuChild)
+ m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_SELECTRIGHT:
+ if (m_hotBar && m_hotItem >= 0)
+ {
+ // TODO: popup the current child if it has subitems, otherwise spread up.
+ }
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_EXECUTE:
+ case MPOS_FULLCANCEL:
+ if (m_subMenuChild)
+ m_subMenuChild->OnSelect(dwSelectType);
+ return m_subMenuParent->OnSelect(dwSelectType);
+ case MPOS_CANCELLEVEL:
+ if (m_subMenuChild)
+ m_subMenuChild->OnSelect(dwSelectType);
+ break;
+ }
+ return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CMenuBand::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
HRESULT STDMETHODCALLTYPE CMenuBand::GetClient(IUnknown **ppunkClient)
{
- UNIMPLEMENTED;
+ // HACK, so I can test for a submenu in the DeskBar
+ //UNIMPLEMENTED;
+ if (ppunkClient)
+ {
+ if (m_subMenuChild)
+ *ppunkClient = m_subMenuChild;
+ else
+ *ppunkClient = NULL;
+ }
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
+ RECT rc;
+ HDC hdc;
+ HBRUSH bgBrush;
+ HBRUSH hotBrush;
+
*theResult = 0;
switch (uMsg)
{
case WM_COMMAND:
- if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
{
return m_staticToolbar->OnCommand(wParam, lParam, theResult);
}
- if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
{
return m_SFToolbar->OnCommand(wParam, lParam, theResult);
}
NMTBCUSTOMDRAW * cdraw;
NMTBHOTITEM * hot;
NMMOUSE * rclick;
+ NMPGCALCSIZE* csize;
+ TBBUTTONINFO btni;
switch (hdr->code)
{
+ case PGN_CALCSIZE:
+ csize = reinterpret_cast<LPNMPGCALCSIZE>(hdr);
+
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
+ {
+ SIZE tbs;
+ m_staticToolbar->GetIdealSize(tbs);
+ if (csize->dwFlag == PGF_CALCHEIGHT)
+ {
+ csize->iHeight = tbs.cy;
+ }
+ else if (csize->dwFlag == PGF_CALCWIDTH)
+ {
+ csize->iHeight = tbs.cx;
+ }
+ }
+
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
+ {
+ SIZE tbs;
+ m_SFToolbar->GetIdealSize(tbs);
+ if (csize->dwFlag == PGF_CALCHEIGHT)
+ {
+ csize->iHeight = tbs.cy;
+ }
+ else if (csize->dwFlag == PGF_CALCWIDTH)
+ {
+ csize->iHeight = tbs.cx;
+ }
+ }
+ return S_OK;
+
+ case TBN_DROPDOWN:
+
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
+ {
+ WPARAM wp = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
+ return m_staticToolbar->OnCommand(wp, 0, theResult);
+ }
+
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
+ {
+ WPARAM wp = reinterpret_cast<LPNMTOOLBAR>(hdr)->iItem;
+ return m_SFToolbar->OnCommand(wp, 0, theResult);
+ }
+
+ return S_OK;
+
case TBN_HOTITEMCHANGE:
hot = reinterpret_cast<LPNMTBHOTITEM>(hdr);
- if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
{
return m_staticToolbar->OnHotItemChange(hot);
}
- if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
{
return m_SFToolbar->OnHotItemChange(hot);
}
case NM_RCLICK:
rclick = reinterpret_cast<LPNMMOUSE>(hdr);
- if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
{
return m_staticToolbar->OnContextMenu(rclick);
}
- if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
{
return m_SFToolbar->OnContextMenu(rclick);
}
return S_OK;
+
case NM_CUSTOMDRAW:
cdraw = reinterpret_cast<LPNMTBCUSTOMDRAW>(hdr);
switch (cdraw->nmcd.dwDrawStage)
cdraw->clrTextHighlight = GetSysColor(COLOR_HIGHLIGHTTEXT);
cdraw->clrHighlightHotTrack = GetSysColor(COLOR_HIGHLIGHTTEXT);
- RECT rc = cdraw->nmcd.rc;
- HDC hdc = cdraw->nmcd.hdc;
+ bgBrush = GetSysColorBrush(COLOR_MENU);
+ hotBrush = GetSysColorBrush(COLOR_MENUHILIGHT);
- HBRUSH bgBrush = GetSysColorBrush(COLOR_MENU);
- HBRUSH hotBrush = GetSysColorBrush(COLOR_MENUHILIGHT);
+ rc = cdraw->nmcd.rc;
+ hdc = cdraw->nmcd.hdc;
+
+ if (cdraw->nmcd.uItemState != CDIS_DISABLED &&
+ ((INT)cdraw->nmcd.dwItemSpec == m_hotItem ||
+ (m_hotItem < 0 && (INT)cdraw->nmcd.dwItemSpec == m_popupItem)))
+ {
+ cdraw->nmcd.uItemState = CDIS_HOT;
+ }
switch (cdraw->nmcd.uItemState)
{
break;
}
- *theResult = TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOETCHEDEFFECT | TBCDRF_HILITEHOTTRACK | TBCDRF_NOOFFSET;
+ *theResult = CDRF_NOTIFYPOSTPAINT | TBCDRF_NOBACKGROUND | TBCDRF_NOEDGES | TBCDRF_NOOFFSET | TBCDRF_NOMARK | 0x00800000; // FIXME: the last bit is Vista+, for debugging only
+ return S_OK;
+
+ case CDDS_ITEMPOSTPAINT:
+ btni.cbSize = sizeof(btni);
+ btni.dwMask = TBIF_STYLE;
+ SendMessage(hWnd, TB_GETBUTTONINFO, cdraw->nmcd.dwItemSpec, reinterpret_cast<LPARAM>(&btni));
+ if (btni.fsStyle & BTNS_DROPDOWN)
+ {
+ SelectObject(cdraw->nmcd.hdc, m_marlett);
+ WCHAR text [] = L"8";
+ SetBkMode(cdraw->nmcd.hdc, TRANSPARENT);
+ DrawTextEx(cdraw->nmcd.hdc, text, 1, &cdraw->nmcd.rc, DT_NOCLIP | DT_VCENTER | DT_RIGHT | DT_SINGLELINE, NULL);
+ }
+ *theResult = TRUE;
return S_OK;
}
return S_OK;
HRESULT STDMETHODCALLTYPE CMenuBand::IsWindowOwner(HWND hWnd)
{
- if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd))
+ if (m_staticToolbar && m_staticToolbar->IsWindowOwner(hWnd) == S_OK)
return S_OK;
- if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd))
+ if (m_SFToolbar && m_SFToolbar->IsWindowOwner(hWnd) == S_OK)
return S_OK;
return S_FALSE;
return S_OK;
}
-HRESULT CMenuBand::CallCBWithId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
+HRESULT CMenuBand::_CallCBWithItemId(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return _CallCB(uMsg, wParam, lParam, id);
}
-HRESULT CMenuBand::CallCBWithPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
+HRESULT CMenuBand::_CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return _CallCB(uMsg, wParam, lParam, 0, pidl);
}
return hr;
}
-HRESULT CMenuBand::TrackPopup(HMENU popup, INT x, INT y)
+HRESULT CMenuBand::_TrackSubMenuUsingTrackPopupMenu(HMENU popup, INT x, INT y)
{
::TrackPopupMenu(popup, 0, x, y, 0, m_menuOwner, NULL);
return S_OK;
}
+
+HRESULT CMenuBand::_GetTopLevelWindow(HWND*topLevel)
+{
+ *topLevel = m_topLevelWindow;
+ return S_OK;
+}
+
+HRESULT CMenuBand::_OnHotItemChanged(CMenuToolbarBase * tb, INT id)
+{
+ if (m_hotBar && m_hotBar != tb)
+ m_hotBar->ChangeHotItem(-1);
+ m_hotBar = tb;
+ m_hotItem = id;
+ if (m_staticToolbar) m_staticToolbar->InvalidateDraw();
+ if (m_SFToolbar) m_SFToolbar->InvalidateDraw();
+ return S_OK;
+}
+
+HRESULT CMenuBand::_MenuItemHotTrack(DWORD changeType)
+{
+ HRESULT hr;
+
+ if (changeType == VK_DOWN)
+ {
+ if (m_SFToolbar && (m_hotBar == m_SFToolbar || m_hotBar == NULL))
+ {
+ hr = m_SFToolbar->ChangeHotItem(VK_DOWN);
+ if (hr == S_FALSE)
+ {
+ if (m_staticToolbar)
+ return m_staticToolbar->ChangeHotItem(VK_HOME);
+ else
+ return m_SFToolbar->ChangeHotItem(VK_HOME);
+ }
+ return hr;
+ }
+ else if (m_staticToolbar && m_hotBar == m_staticToolbar)
+ {
+ hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
+ if (hr == S_FALSE)
+ {
+ if (m_SFToolbar)
+ return m_SFToolbar->ChangeHotItem(VK_HOME);
+ else
+ return m_staticToolbar->ChangeHotItem(VK_HOME);
+ }
+ return hr;
+ }
+ }
+ else if (changeType == VK_UP)
+ {
+ if (m_staticToolbar && (m_hotBar == m_staticToolbar || m_hotBar == NULL))
+ {
+ hr = m_staticToolbar->ChangeHotItem(VK_DOWN);
+ if (hr == S_FALSE)
+ {
+ if (m_SFToolbar)
+ return m_SFToolbar->ChangeHotItem(VK_END);
+ else
+ return m_staticToolbar->ChangeHotItem(VK_END);
+ }
+ return hr;
+ }
+ else if (m_SFToolbar && m_hotBar == m_SFToolbar)
+ {
+ hr = m_SFToolbar->ChangeHotItem(VK_UP);
+ if (hr == S_FALSE)
+ {
+ if (m_staticToolbar)
+ return m_staticToolbar->ChangeHotItem(VK_END);
+ else
+ return m_SFToolbar->ChangeHotItem(VK_END);
+ }
+ return hr;
+ }
+ }
+ else
+ {
+ m_subMenuParent->OnSelect(changeType);
+ }
+ return S_OK;
+}
+
+HRESULT CMenuBand::_OnPopupSubMenu(INT popupItem, IMenuPopup * popup, POINTL * pAt, RECTL * pExclude)
+{
+ if (m_subMenuChild)
+ {
+ HRESULT hr = m_subMenuChild->OnSelect(MPOS_CANCELLEVEL);
+ if (FAILED(hr))
+ return hr;
+ }
+ m_popupItem = popupItem;
+ m_subMenuChild = popup;
+ if (popup)
+ {
+ IUnknown_SetSite(popup, m_subMenuParent);
+ popup->Popup(pAt, pExclude, MPPF_RIGHT);
+ }
+ if (m_staticToolbar) m_staticToolbar->InvalidateDraw();
+ if (m_SFToolbar) m_SFToolbar->InvalidateDraw();
+ return S_OK;
+}