306 lines
7.6 KiB
C++
306 lines
7.6 KiB
C++
|
//
|
||
|
// Menu- and menuband- related utility functions
|
||
|
//
|
||
|
|
||
|
#include "local.h"
|
||
|
#include "dochost.h"
|
||
|
|
||
|
// this goes away when the split is done **and** dochost goes away
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Replace the contents of hmenuDst with hmenuSrc. Note any
|
||
|
submenus in hmenuDst will be deleted.
|
||
|
|
||
|
Call Menu_RemoveAllSubMenus if you don't want this to
|
||
|
happen.
|
||
|
*/
|
||
|
void Menu_Replace(HMENU hmenuDst, HMENU hmenuSrc)
|
||
|
{
|
||
|
int cItems = GetMenuItemCount(hmenuDst);
|
||
|
int i;
|
||
|
|
||
|
for (i=0; i<cItems; i++)
|
||
|
DeleteMenu(hmenuDst, 0, MF_BYPOSITION);
|
||
|
|
||
|
cItems = GetMenuItemCount(hmenuSrc);
|
||
|
for (i=0; i<cItems; i++)
|
||
|
{
|
||
|
MENUITEMINFO mii;
|
||
|
TCHAR szText[MAX_PATH];
|
||
|
mii.cbSize = SIZEOF(MENUITEMINFO);
|
||
|
mii.dwTypeData = szText;
|
||
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_STATE;
|
||
|
mii.cch = ARRAYSIZE(szText);
|
||
|
mii.fType = MFT_SEPARATOR;
|
||
|
mii.hSubMenu = NULL;
|
||
|
mii.dwItemData = 0;
|
||
|
if (GetMenuItemInfo(hmenuSrc, i, TRUE, &mii))
|
||
|
{
|
||
|
HMENU hMenuOldSub = NULL;
|
||
|
if (mii.hSubMenu != NULL)
|
||
|
{
|
||
|
hMenuOldSub = mii.hSubMenu;
|
||
|
mii.hSubMenu = CreateMenu();
|
||
|
Menu_Replace(mii.hSubMenu, hMenuOldSub);
|
||
|
}
|
||
|
InsertMenuItem(hmenuDst, i, TRUE, &mii);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifndef POSTPOSTSPLIT
|
||
|
//----------------------------------------------------------------------
|
||
|
//
|
||
|
// CMenuList
|
||
|
//
|
||
|
//----------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
HMENU hmenu;
|
||
|
BITBOOL bObject:1; // TRUE: menu belongs to object
|
||
|
} MLITEM; // CMenuList item
|
||
|
|
||
|
|
||
|
CMenuList::CMenuList(void)
|
||
|
{
|
||
|
ASSERT(NULL == _hdsa);
|
||
|
}
|
||
|
|
||
|
|
||
|
CMenuList::~CMenuList(void)
|
||
|
{
|
||
|
if (_hdsa)
|
||
|
{
|
||
|
DSA_Destroy(_hdsa);
|
||
|
_hdsa = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Set the menu list (comparable to HOLEMENU) so we can
|
||
|
dispatch commands to the frame or the object correctly.
|
||
|
We do this since menu bands bypass OLE's FrameFilterWndProc.
|
||
|
|
||
|
We build the menu list by comparing the given hmenuShared
|
||
|
with hmenuFrame. Anything in hmenuShared that is not
|
||
|
in hmenuFrame belongs to the object.
|
||
|
|
||
|
*/
|
||
|
void CMenuList::Set(HMENU hmenuShared, HMENU hmenuFrame)
|
||
|
{
|
||
|
ASSERT(NULL == hmenuShared || IS_VALID_HANDLE(hmenuShared, MENU));
|
||
|
ASSERT(NULL == hmenuFrame || IS_VALID_HANDLE(hmenuFrame, MENU));
|
||
|
|
||
|
if (_hdsa)
|
||
|
{
|
||
|
ASSERT(IS_VALID_HANDLE(_hdsa, DSA));
|
||
|
|
||
|
DSA_DeleteAllItems(_hdsa);
|
||
|
}
|
||
|
else
|
||
|
_hdsa = DSA_Create(sizeof(MLITEM), 10);
|
||
|
|
||
|
if (_hdsa && hmenuShared && hmenuFrame)
|
||
|
{
|
||
|
int i;
|
||
|
int iFrame = 0;
|
||
|
int cmenu = GetMenuItemCount(hmenuShared);
|
||
|
int cmenuFrame = GetMenuItemCount(hmenuFrame);
|
||
|
BOOL bMatched;
|
||
|
int iSaveFrame;
|
||
|
int iHaveFrame = -1;
|
||
|
|
||
|
TCHAR sz[64];
|
||
|
TCHAR szFrame[64];
|
||
|
MENUITEMINFO miiFrame;
|
||
|
MENUITEMINFO mii;
|
||
|
MLITEM mlitem;
|
||
|
|
||
|
miiFrame.cbSize = sizeof(miiFrame);
|
||
|
mii.cbSize = sizeof(mii);
|
||
|
|
||
|
for (i = 0; i < cmenu; i++)
|
||
|
{
|
||
|
|
||
|
mii.cch = SIZECHARS(sz);
|
||
|
mii.fMask = MIIM_SUBMENU | MIIM_TYPE;
|
||
|
mii.dwTypeData = sz;
|
||
|
EVAL(GetMenuItemInfo(hmenuShared, i, TRUE, &mii));
|
||
|
|
||
|
ASSERT(IS_VALID_HANDLE(mii.hSubMenu, MENU));
|
||
|
|
||
|
mlitem.hmenu = mii.hSubMenu;
|
||
|
|
||
|
iSaveFrame = iFrame;
|
||
|
bMatched = FALSE;
|
||
|
|
||
|
// DocObject might have dropped some of our menus, like edit and view
|
||
|
// Need to be able to skip over dropped frame menus
|
||
|
while (1)
|
||
|
{
|
||
|
if (iHaveFrame != iFrame)
|
||
|
{
|
||
|
iHaveFrame = iFrame;
|
||
|
if (iFrame < cmenuFrame)
|
||
|
{
|
||
|
miiFrame.cch = SIZECHARS(szFrame);
|
||
|
miiFrame.fMask = MIIM_SUBMENU | MIIM_TYPE;
|
||
|
miiFrame.dwTypeData = szFrame;
|
||
|
EVAL(GetMenuItemInfo(hmenuFrame, iFrame, TRUE, &miiFrame));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Make it so it won't compare
|
||
|
miiFrame.hSubMenu = NULL;
|
||
|
*szFrame = 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
ASSERT(iFrame >= cmenuFrame || IS_VALID_HANDLE(miiFrame.hSubMenu, MENU));
|
||
|
|
||
|
// The browser may have a menu that was not merged into
|
||
|
// the shared menu because the object put one in with
|
||
|
// the same name. Have we hit this case? Check by comparing
|
||
|
// sz and szFrame
|
||
|
|
||
|
if (mii.hSubMenu == miiFrame.hSubMenu || 0 == StrCmp(sz, szFrame))
|
||
|
{
|
||
|
bMatched = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (iFrame >= cmenuFrame)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
iFrame++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Is this one of our menus?
|
||
|
mlitem.bObject = (mii.hSubMenu == miiFrame.hSubMenu) ? FALSE:TRUE;
|
||
|
if (bMatched)
|
||
|
{
|
||
|
iFrame++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iFrame = iSaveFrame;
|
||
|
}
|
||
|
DSA_SetItem(_hdsa, i, &mlitem);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Adds the given hmenu to the list.
|
||
|
|
||
|
*/
|
||
|
void CMenuList::AddMenu(HMENU hmenu)
|
||
|
{
|
||
|
ASSERT(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
|
||
|
|
||
|
if (_hdsa && hmenu)
|
||
|
{
|
||
|
MLITEM mlitem;
|
||
|
|
||
|
mlitem.hmenu = hmenu;
|
||
|
mlitem.bObject = TRUE;
|
||
|
|
||
|
DSA_AppendItem(_hdsa, &mlitem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Removes the given hmenu from the list.
|
||
|
|
||
|
*/
|
||
|
void CMenuList::RemoveMenu(HMENU hmenu)
|
||
|
{
|
||
|
ASSERT(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
|
||
|
|
||
|
if (_hdsa && hmenu)
|
||
|
{
|
||
|
int i = DSA_GetItemCount(_hdsa) - 1;
|
||
|
|
||
|
for (; i >= 0; i--)
|
||
|
{
|
||
|
MLITEM * pmlitem = (MLITEM *)DSA_GetItemPtr(_hdsa, i);
|
||
|
ASSERT(pmlitem);
|
||
|
|
||
|
if (hmenu == pmlitem->hmenu)
|
||
|
{
|
||
|
DSA_DeleteItem(_hdsa, i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------
|
||
|
Purpose: Returns TRUE if the given hmenu belongs to the object.
|
||
|
|
||
|
*/
|
||
|
BOOL CMenuList::IsObjectMenu(HMENU hmenu)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
ASSERT(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
|
||
|
|
||
|
if (_hdsa && hmenu)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < DSA_GetItemCount(_hdsa); i++)
|
||
|
{
|
||
|
MLITEM * pmlitem = (MLITEM *)DSA_GetItemPtr(_hdsa, i);
|
||
|
ASSERT(pmlitem);
|
||
|
|
||
|
if (hmenu == pmlitem->hmenu)
|
||
|
{
|
||
|
bRet = pmlitem->bObject;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
|
||
|
void CMenuList::Dump(LPCTSTR pszMsg)
|
||
|
{
|
||
|
if (IsFlagSet(g_dwDumpFlags, DF_DEBUGMENU))
|
||
|
{
|
||
|
TraceMsg(TF_ALWAYS, "CMenuList: Dumping menus for %#08x %s", (LPVOID)this, pszMsg);
|
||
|
|
||
|
if (_hdsa)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < DSA_GetItemCount(_hdsa); i++)
|
||
|
{
|
||
|
MLITEM * pmlitem = (MLITEM *)DSA_GetItemPtr(_hdsa, i);
|
||
|
ASSERT(pmlitem);
|
||
|
|
||
|
TraceMsg(TF_ALWAYS, " [%d] = %x", i, pmlitem->hmenu);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#endif
|