#define TBSTYLE_EX_VERTICAL 4
-
#define TIMERID_HOTTRACK 1
#define SUBCLASS_ID_MENUBAND 1
CMenuToolbarBase::CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager) :
m_hwnd(NULL),
m_useFlatMenus(FALSE),
+ m_SubclassOld(NULL),
m_menuBand(menuBand),
m_hwndToolbar(NULL),
m_dwMenuFlags(0),
- m_SubclassOld(NULL),
m_hasIdealSize(FALSE),
m_usePager(usePager),
m_hotItem(-1),
return S_FALSE;
}
-BOOL
-AllocAndGetMenuString(HMENU hMenu, UINT ItemIDByPosition, WCHAR** String)
+HRESULT CMenuToolbarBase::AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSubMenu, INT iconId, DWORD_PTR buttonData)
+{
+ TBBUTTON tbb = { 0 };
+
+ tbb.fsState = TBSTATE_ENABLED | TBSTATE_WRAP;
+ tbb.fsStyle = 0;
+
+ if (hasSubMenu)
+ tbb.fsStyle |= BTNS_DROPDOWN;
+
+ tbb.iString = (INT_PTR) caption;
+ tbb.idCommand = commandId;
+
+ tbb.iBitmap = iconId;
+ tbb.dwData = buttonData;
+
+ SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::AddSeparator()
+{
+ TBBUTTON tbb = { 0 };
+
+ tbb.fsState = TBSTATE_ENABLED | TBSTATE_WRAP;
+ tbb.fsStyle = BTNS_SEP;
+ tbb.iBitmap = 0;
+
+ SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
+
+ return S_OK;
+}
+
+HRESULT CMenuToolbarBase::AddPlaceholder()
+{
+ TBBUTTON tbb = { 0 };
+ PCWSTR MenuString = L"(Empty)";
+
+ tbb.fsState = TBSTATE_WRAP; // 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;
+}
+
+HRESULT CMenuToolbarBase::GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData)
+{
+ TBBUTTONINFO info = { 0 };
+ info.cbSize = sizeof(TBBUTTONINFO);
+ info.dwMask = 0;
+ int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
+ if (index < 0)
+ return E_FAIL;
+
+ if (pIndex)
+ *pIndex = index;
+
+ if (pData)
+ {
+ TBBUTTON btn = { 0 };
+ if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
+ return E_FAIL;
+ *pData = btn.dwData;
+ }
+
+ return S_OK;
+}
+
+
+HRESULT CMenuToolbarBase::PopupItem(INT uItem)
{
- int Length;
+ INT index;
+ DWORD_PTR dwData;
- Length = GetMenuStringW(hMenu, ItemIDByPosition, NULL, 0, MF_BYPOSITION);
+ GetDataFromId(uItem, &index, &dwData);
- if (!Length)
- return FALSE;
+ return InternalPopupItem(uItem, index, dwData);
+}
- /* Also allocate space for the terminating NULL character */
- ++Length;
- *String = (PWSTR) HeapAlloc(GetProcessHeap(), 0, Length * sizeof(WCHAR));
+HRESULT CMenuToolbarBase::HasSubMenu(INT uItem)
+{
+ INT index;
+ DWORD_PTR dwData;
- GetMenuStringW(hMenu, ItemIDByPosition, *String, Length, MF_BYPOSITION);
+ GetDataFromId(uItem, &index, &dwData);
- return TRUE;
+ return InternalHasSubMenu(uItem, index, dwData);
}
CMenuStaticToolbar::CMenuStaticToolbar(CMenuBand *menuBand) :
for (i = 0; i < ic; i++)
{
MENUITEMINFOW info;
- TBBUTTON tbb = { 0 };
- PWSTR MenuString = NULL;
-
- tbb.fsState = TBSTATE_ENABLED | TBSTATE_WRAP;
- tbb.fsStyle = 0;
info.cbSize = sizeof(info);
- info.fMask = MIIM_FTYPE | MIIM_ID;
+ info.dwTypeData = NULL;
+ info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_SUBMENU;
GetMenuItemInfoW(m_hmenu, i, TRUE, &info);
if (info.fType == MFT_STRING)
{
- if (!AllocAndGetMenuString(m_hmenu, i, &MenuString))
- return E_OUTOFMEMORY;
- if (::GetSubMenu(m_hmenu, i) != NULL)
- tbb.fsStyle |= BTNS_DROPDOWN;
- tbb.iString = (INT_PTR) MenuString;
- tbb.idCommand = info.wID;
+ info.cch++;
+ info.dwTypeData = (PWSTR) HeapAlloc(GetProcessHeap(), 0, (info.cch + 1) * sizeof(WCHAR));
+
+ info.fMask = MIIM_STRING;
+ GetMenuItemInfoW(m_hmenu, i, TRUE, &info);
SMINFO * sminfo = new SMINFO();
sminfo->dwMask = SMIM_ICON | SMIM_FLAGS;
- 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);
- // FIXME: remove before deleting the toolbar or it will leak
- }
+ // FIXME: remove before deleting the toolbar or it will leak
+
+ HRESULT hr = m_menuBand->_CallCBWithItemId(info.wID, SMC_GETINFO, 0, reinterpret_cast<LPARAM>(sminfo));
+ if (FAILED(hr))
+ return hr;
+
+ AddButton(info.wID, info.dwTypeData, info.hSubMenu != NULL, sminfo->iIcon, reinterpret_cast<DWORD_PTR>(sminfo));
+
+ HeapFree(GetProcessHeap(), 0, info.dwTypeData);
}
else
{
- tbb.fsStyle |= BTNS_SEP;
+ AddSeparator();
}
-
- SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
-
- if (MenuString)
- HeapFree(GetProcessHeap(), 0, MenuString);
}
return S_OK;
return m_menuBand->_CallCBWithItemId(wParam, SMC_EXEC, 0, 0);
}
-HRESULT CMenuStaticToolbar::PopupItem(INT uItem)
+HRESULT CMenuStaticToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData)
{
- TBBUTTONINFO info = { 0 };
- info.cbSize = sizeof(TBBUTTONINFO);
- info.dwMask = 0;
- int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
- if (index < 0)
- return E_FAIL;
-
- TBBUTTON btn = { 0 };
- SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn));
-
- SMINFO * nfo = reinterpret_cast<SMINFO*>(btn.dwData);
+ SMINFO * nfo = reinterpret_cast<SMINFO*>(dwData);
if (!nfo)
return E_FAIL;
}
}
-HRESULT CMenuStaticToolbar::HasSubMenu(INT uItem)
+HRESULT CMenuStaticToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData)
{
- TBBUTTONINFO info = { 0 };
- info.cbSize = sizeof(TBBUTTONINFO);
- info.dwMask = 0;
- 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;
}
INT index = 0;
INT indexOpen = 0;
- TBBUTTON tbb = { 0 };
- tbb.fsState = TBSTATE_ENABLED | TBSTATE_WRAP;
- tbb.fsStyle = 0;
-
STRRET sr = { STRRET_CSTR, { 0 } };
hr = m_shellFolder->GetDisplayNameOf(item, SIGDN_NORMALDISPLAY, &sr);
SFGAOF attrs = SFGAO_FOLDER;
hr = m_shellFolder->GetAttributesOf(1, &itemc, &attrs);
- if (attrs & SFGAO_FOLDER)
- {
- tbb.fsStyle |= BTNS_DROPDOWN;
- }
-
- tbb.idCommand = ++i;
- tbb.iString = (INT_PTR) MenuString;
- tbb.iBitmap = index;
- tbb.dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
+ DWORD_PTR dwData = reinterpret_cast<DWORD_PTR>(ILClone(item));
// FIXME: remove before deleting the toolbar or it will leak
- SendMessageW(m_hwndToolbar, TB_ADDBUTTONS, 1, reinterpret_cast<LPARAM>(&tbb));
- CoTaskMemFree(MenuString);
+ AddButton(++i, MenuString, attrs & SFGAO_FOLDER, index, dwData);
+ CoTaskMemFree(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 AddPlaceholder();
}
return hr;
return hr;
}
-LPITEMIDLIST CMenuSFToolbar::GetPidlFromId(INT uItem, INT* pIndex)
-{
- TBBUTTONINFO info = { 0 };
- info.cbSize = sizeof(TBBUTTONINFO);
- info.dwMask = 0;
- int index = SendMessage(m_hwndToolbar, TB_GETBUTTONINFO, uItem, reinterpret_cast<LPARAM>(&info));
- if (index < 0)
- return NULL;
-
- if (pIndex)
- *pIndex = index;
-
- TBBUTTON btn = { 0 };
- if (!SendMessage(m_hwndToolbar, TB_GETBUTTON, index, reinterpret_cast<LPARAM>(&btn)))
- return NULL;
-
- return reinterpret_cast<LPITEMIDLIST>(btn.dwData);
-}
-
HRESULT CMenuSFToolbar::OnContextMenu(NMMOUSE * rclick)
{
HRESULT hr;
if (hr == S_FALSE)
return hr;
- return m_menuBand->_CallCBWithItemPidl(GetPidlFromId(wParam), SMC_SFEXEC, 0, 0);
+ DWORD_PTR data;
+ GetDataFromId(wParam, NULL, &data);
+
+ return m_menuBand->_CallCBWithItemPidl(reinterpret_cast<LPITEMIDLIST>(data), SMC_SFEXEC, 0, 0);
}
-HRESULT CMenuSFToolbar::PopupItem(INT uItem)
+HRESULT CMenuSFToolbar::InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData)
{
HRESULT hr;
UINT uId;
UINT uIdAncestor;
DWORD flags;
- int index;
CComPtr<IShellMenuCallback> psmc;
CComPtr<IShellMenu> shellMenu;
- LPITEMIDLIST pidl = GetPidlFromId(uItem, &index);
+ LPITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
if (!pidl)
return E_FAIL;
return PopupSubMenu(uItem, index, shellMenu);
}
-HRESULT CMenuSFToolbar::HasSubMenu(INT uItem)
+HRESULT CMenuSFToolbar::InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData)
{
HRESULT hr;
- LPCITEMIDLIST pidl = GetPidlFromId(uItem);
+ LPCITEMIDLIST pidl = reinterpret_cast<LPITEMIDLIST>(dwData);
SFGAOF attrs = SFGAO_FOLDER;
hr = m_shellFolder->GetAttributesOf(1, &pidl, &attrs);
HWND m_hwnd; // May be the pager
HFONT m_marlett;
BOOL m_useFlatMenus;
+ WNDPROC m_SubclassOld;
protected:
CMenuBand * m_menuBand;
HWND m_hwndToolbar;
DWORD m_dwMenuFlags;
- WNDPROC m_SubclassOld;
BOOL m_hasIdealSize;
SIZE m_idealSize;
BOOL m_usePager;
void InvalidateDraw();
virtual HRESULT FillToolbar() = 0;
- virtual HRESULT PopupItem(INT uItem) = 0;
- virtual HRESULT HasSubMenu(INT uItem) = 0;
virtual HRESULT OnContextMenu(NMMOUSE * rclick) = 0;
+ HRESULT PopupItem(INT uItem);
+ HRESULT HasSubMenu(INT uItem);
+ HRESULT GetDataFromId(INT uItem, INT* pIndex, DWORD_PTR* pData);
+
protected:
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
+ virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData) = 0;
+ virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData) = 0;
+
LRESULT CALLBACK SubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ HRESULT AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSubMenu, INT iconId, DWORD_PTR buttonData);
+ HRESULT AddSeparator();
+ HRESULT AddPlaceholder();
+
HRESULT UpdateImageLists();
};
HRESULT GetMenu(HMENU *phmenu, HWND *phwnd, DWORD *pdwFlags);
virtual HRESULT FillToolbar();
- virtual HRESULT PopupItem(INT uItem);
- virtual HRESULT HasSubMenu(INT uItem);
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
+protected:
+ virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData);
+ virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData);
};
class CMenuSFToolbar :
HRESULT GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv);
virtual HRESULT FillToolbar();
- virtual HRESULT PopupItem(INT uItem);
- virtual HRESULT HasSubMenu(INT uItem);
virtual HRESULT OnCommand(WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT OnContextMenu(NMMOUSE * rclick);
-private:
- LPITEMIDLIST GetPidlFromId(INT uItem, INT* pIndex = NULL);
+protected:
+ virtual HRESULT InternalPopupItem(INT uItem, INT index, DWORD_PTR dwData);
+ virtual HRESULT InternalHasSubMenu(INT uItem, INT index, DWORD_PTR dwData);
};