windows-nt/Source/XPSP1/NT/shell/browseui/legacy/tbmenu.cpp
2020-09-26 16:20:57 +08:00

288 lines
8.3 KiB
C++

#include "priv.h"
#include "resource.h"
#include "tbmenu.h"
#include "isfband.h"
#include "isfmenu.h"
#include "util.h"
#include "mluisupp.h"
#define SMFORWARD(x) if (!_psm) { return E_FAIL; } else return _psm->x
#define SUPERCLASS CMenuToolbarBase
CToolbarMenu::CToolbarMenu(DWORD dwFlags, HWND hwndTB) :
CMenuToolbarBase(NULL, dwFlags),
_hwndSubject(hwndTB) // this is the toolbar that we are customizing
{
}
void CToolbarMenu::GetSize(SIZE* psize)
{
ASSERT(_hwndMB);
if (SendMessage(_hwndMB, TB_GETTEXTROWS, 0, 0) == 0) {
// no text labels, so set a min width to make menu look
// pretty. use min width of 4 * button width.
LRESULT lButtonSize = SendMessage(_hwndMB, TB_GETBUTTONSIZE, 0, 0);
LONG cxMin = 4 * LOWORD(lButtonSize);
psize->cx = max(psize->cx, cxMin);
}
SUPERCLASS::GetSize(psize);
}
void CToolbarMenu::v_Show(BOOL fShow, BOOL fForceUpdate)
{
if (fShow)
{
_fClickHandled = FALSE;
_FillToolbar();
_pcmb->SetTracked(NULL); // Since hot item is NULL
ToolBar_SetHotItem(_hwndMB, -1);
if (fForceUpdate)
v_UpdateButtons(TRUE);
}
}
void CToolbarMenu::v_Close()
{
_UnsubclassWindow(_hwndMB);
}
void CToolbarMenu::v_UpdateButtons(BOOL fNegotiateSize)
{
}
HRESULT CToolbarMenu::v_CallCBItem(int idtCmd, UINT dwMsg, WPARAM wParam, LPARAM lParam)
{
return S_OK;
}
HRESULT CToolbarMenu::v_GetState(int idtCmd, LPSMDATA psmd)
{
ASSERT(0);
return E_NOTIMPL;
}
HRESULT CToolbarMenu::v_ExecItem(int idCmd)
{
HRESULT hres = E_FAIL;
TraceMsg(TF_TBMENU, "CToolbarMenu::v_ExecItem \tidCmd: %d", idCmd);
return hres;
}
void CToolbarMenu::CreateToolbar(HWND hwndParent)
{
if (!_hwndMB)
{
DWORD dwStyle = (WS_VISIBLE | WS_CHILD | TBSTYLE_FLAT |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER |
CCS_NOPARENTALIGN | CCS_NORESIZE | TBSTYLE_REGISTERDROP | TBSTYLE_TOOLTIPS);
INT_PTR nRows = SendMessage(_hwndSubject, TB_GETTEXTROWS, 0, 0);
if (nRows > 0)
{
// We have text labels; make it TBSTYLE_LIST. The base class will
// set TBSTYLE_EX_VERTICAL for us.
ASSERT(_fHorizInVerticalMB == FALSE);
dwStyle |= TBSTYLE_LIST;
}
else
{
// No text labels; make it horizontal and TBSTYLE_WRAPABLE. Set
// _fHorizInVerticalMB so that the base class does not try and set
// TBSTYLE_EX_VERTICAL.
_fHorizInVerticalMB = TRUE;
dwStyle |= TBSTYLE_WRAPABLE;
}
_hwndMB = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, TEXT("Menu"), dwStyle,
0, 0, 0, 0, hwndParent, (HMENU) FCIDM_TOOLBAR, HINST_THISDLL, NULL);
if (!_hwndMB)
{
TraceMsg(TF_TBMENU, "CToolbarMenu::CreateToolbar: Failed to Create Toolbar");
return;
}
HWND hwndTT = (HWND)SendMessage(_hwndMB, TB_GETTOOLTIPS, 0, 0);
SHSetWindowBits(hwndTT, GWL_STYLE, TTS_ALWAYSTIP, TTS_ALWAYSTIP);
SendMessage(_hwndMB, TB_BUTTONSTRUCTSIZE, SIZEOF(TBBUTTON), 0);
SendMessage(_hwndMB, TB_SETMAXTEXTROWS, nRows, 0);
SendMessage(_hwndMB, CCM_SETVERSION, COMCTL32_VERSION, 0);
SendMessage(_hwndMB, TB_SETEXTENDEDSTYLE, TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_DRAWDDARROWS);
int cPimgs = (int)SendMessage(_hwndSubject, TB_GETIMAGELISTCOUNT, 0, 0);
for (int i = 0; i < cPimgs; i++)
{
HIMAGELIST himl = (HIMAGELIST)SendMessage(_hwndSubject, TB_GETIMAGELIST, i, 0);
SendMessage(_hwndMB, TB_SETIMAGELIST, i, (LPARAM)himl);
HIMAGELIST himlHot = (HIMAGELIST)SendMessage(_hwndSubject, TB_GETHOTIMAGELIST, i, 0);
SendMessage(_hwndMB, TB_SETHOTIMAGELIST, i, (LPARAM)himlHot);
}
_SubclassWindow(_hwndMB);
// Set the format to ANSI
ToolBar_SetUnicodeFormat(_hwndMB, 0);
CMenuToolbarBase::CreateToolbar(hwndParent);
}
else if (GetParent(_hwndMB) != hwndParent)
{
::SetParent(_hwndMB, hwndParent);
}
}
LRESULT CToolbarMenu::_DefWindowProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
{
LRESULT lRes = CMenuToolbarBase::_DefWindowProcMB(hwnd, uMessage, wParam, lParam);
if (lRes == 0)
lRes = CNotifySubclassWndProc::_DefWindowProc(hwnd, uMessage, wParam, lParam);
return lRes;
}
#define MAXLEN 256
void CToolbarMenu::_FillToolbar()
{
RECT rcTB;
TCHAR pszBuf[MAXLEN+1];
LPTSTR psz;
TBBUTTON tb;
INT_PTR i, iCount;
iCount = SendMessage(_hwndSubject, TB_BUTTONCOUNT, 0, 0L);
GetClientRect(_hwndSubject, &rcTB);
for (i = 0; i < iCount; i++) {
if (SHIsButtonObscured(_hwndSubject, &rcTB, i)) {
SendMessage(_hwndSubject, TB_GETBUTTON, i, (LPARAM)&tb);
if (!(tb.fsStyle & BTNS_SEP)) {
// autosize buttons look ugly here
tb.fsStyle &= ~BTNS_AUTOSIZE;
// need to rip off wrap bit; new toolbar will
// figure out where wrapping should happen
tb.fsState &= ~TBSTATE_WRAP;
if (tb.iString == -1) {
// no string
psz = NULL;
} else if (HIWORD(tb.iString)) {
// it's a string pointer
psz = (LPTSTR) tb.iString;
} else {
// it's an index into toolbar string array
SendMessage(_hwndSubject, TB_GETSTRING, MAKELONG(MAXLEN, tb.iString), (LPARAM)pszBuf);
psz = pszBuf;
}
if (psz)
tb.iString = (INT_PTR)psz;
else
tb.iString = -1;
if (tb.iBitmap == -1) {
int id = GetDlgCtrlID(_hwndSubject);
NMTBDISPINFO tbgdi = {0};
tbgdi.hdr.hwndFrom = _hwndSubject;
tbgdi.hdr.idFrom = id;
tbgdi.hdr.code = TBN_GETDISPINFO;
tbgdi.dwMask = TBNF_IMAGE;
tbgdi.idCommand = tb.idCommand;
tbgdi.iImage = 0;
tbgdi.lParam = tb.dwData;
SendMessage(GetParent(_hwndSubject), WM_NOTIFY, (WPARAM)id, (LPARAM)&tbgdi);
if(tbgdi.dwMask & TBNF_DI_SETITEM)
tb.iBitmap = tbgdi.iImage;
}
SendMessage(_hwndMB, TB_ADDBUTTONS, 1, (LPARAM)&tb);
}
}
}
}
STDMETHODIMP CToolbarMenu::IsWindowOwner(HWND hwnd)
{
if ( hwnd == _hwndMB)
return S_OK;
else
return S_FALSE;
}
void CToolbarMenu::_CancelMenu()
{
IMenuPopup* pmp;
if (EVAL(SUCCEEDED(_pcmb->QueryInterface(IID_IMenuPopup, (LPVOID*)&pmp)))) {
// tell menuband it's time to die
pmp->OnSelect(MPOS_FULLCANCEL);
pmp->Release();
}
}
STDMETHODIMP CToolbarMenu::OnWinEvent(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
{
HRESULT hres = S_FALSE;
ASSERT(plres);
switch (uMsg) {
case WM_COMMAND:
PostMessage(GetParent(_hwndSubject), WM_COMMAND, wParam, (LPARAM)_hwndSubject);
_CancelMenu();
hres = S_OK;
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR) lParam;
switch (pnmh->code) {
case TBN_DROPDOWN:
_fTrackingSubMenu = TRUE;
pnmh->hwndFrom = _hwndSubject;
MapWindowPoints(_hwndMB, _hwndSubject, (LPPOINT) &((LPNMTOOLBAR)pnmh)->rcButton, 2);
*plres = SendMessage(GetParent(_hwndSubject), WM_NOTIFY, wParam, (LPARAM)pnmh);
_CancelMenu();
hres = S_OK;
_fTrackingSubMenu = FALSE;
break;
case NM_CUSTOMDRAW:
// override mnbase custom draw shiznits
*plres = 0;
hres = S_OK;
break;
default:
goto DoDefault;
}
break;
}
DoDefault:
default:
hres = SUPERCLASS::OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
}
return hres;
}
CMenuToolbarBase* ToolbarMenu_Create(HWND hwnd)
{
return new CToolbarMenu(0, hwnd);
}