288 lines
8.3 KiB
C++
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);
|
||
|
}
|