2590 lines
135 KiB
C++
2590 lines
135 KiB
C++
// ==========================================================================
|
||
// Class Implementation : COXBitmapMenuOrganizer
|
||
// ==========================================================================
|
||
|
||
// Version: 9.3
|
||
|
||
// This software along with its related components, documentation and files ("The Libraries")
|
||
// is ?1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
||
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
||
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
||
// to obtain this file, or directly from our office. For a copy of the license governing
|
||
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
||
|
||
// //////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "stdafx.h"
|
||
#include "OXBitmapMenuOrganizer.h"
|
||
|
||
#include "afxpriv.h"
|
||
#include "afxole.h"
|
||
|
||
#ifndef __OXMFCIMPL_H__
|
||
#if _MFC_VER >= 0x0700
|
||
#if _MFC_VER >= 1400
|
||
#include <afxtempl.h>
|
||
#endif
|
||
#include <..\src\mfc\afximpl.h>
|
||
#else
|
||
#include <..\src\afximpl.h>
|
||
#endif
|
||
#define __OXMFCIMPL_H__
|
||
#endif
|
||
|
||
|
||
#ifndef __OX_OLEIMPL2_H__
|
||
#ifdef MAP_LOGHIM_TO_PIX
|
||
#undef MAP_LOGHIM_TO_PIX
|
||
#endif
|
||
#ifdef MAP_PIX_TO_LOGHIM
|
||
#undef MAP_PIX_TO_LOGHIM
|
||
#endif
|
||
|
||
#if _MFC_VER < 0x0700
|
||
#include <..\src\oleimpl2.h>
|
||
#else
|
||
#include <..\src\mfc\oleimpl2.h>
|
||
#endif
|
||
|
||
#define __OX_OLEIMPL2_H__
|
||
#endif
|
||
|
||
#include "UTB64Bit.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[]=__FILE__;
|
||
#endif
|
||
|
||
#ifndef TB_GETIMAGELIST
|
||
#define TB_GETIMAGELIST (WM_USER + 49)
|
||
#endif // TB_GETIMAGELIST
|
||
|
||
#ifndef TB_GETHOTIMAGELIST
|
||
#define TB_GETHOTIMAGELIST (WM_USER + 53)
|
||
#endif // TB_GETHOTIMAGELIST
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Definition of static members
|
||
|
||
// --- A map of all the frame windows that have been subclassed and that are associated with
|
||
// a menu organizer object. This object will handle the windows messages first
|
||
CMap<HWND, HWND, COXBitmapMenuOrganizer*, COXBitmapMenuOrganizer*>
|
||
COXBitmapMenuOrganizer::m_allMenuOrganizers;
|
||
|
||
// handle of the old mouse hook procedure
|
||
HHOOK COXBitmapMenuOrganizer::g_pfnOldMouseHookProc=NULL;
|
||
// handle of the old keyboard hook procedure
|
||
HHOOK COXBitmapMenuOrganizer::g_pfnOldKeyboardHookProc=NULL;
|
||
///////////////////////////////////////////
|
||
|
||
|
||
|
||
// Member functions ---------------------------------------------------------
|
||
// public:
|
||
|
||
COXBitmapMenuOrganizer::COXBitmapMenuOrganizer()
|
||
:
|
||
m_pFrameWnd(NULL),
|
||
m_hWnd(NULL),
|
||
m_pfnSuper(NULL),
|
||
m_bInCutomizationMode(FALSE),
|
||
m_hWndCustomizeOrganizer(NULL),
|
||
m_bShowOnlyRecentlyUsed(TRUE),
|
||
m_bForceToDisplayHiddenItems(FALSE),
|
||
m_bMainMenuIsActive(FALSE),
|
||
m_nActivePopupMenuCount(0),
|
||
m_pDeferedBM(NULL)
|
||
{
|
||
Init();
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::Init(UINT cx, UINT cy, UINT nCheckID, UINT nBulletID)
|
||
{
|
||
CDC memDC;
|
||
VERIFY(memDC.CreateCompatibleDC(NULL));
|
||
|
||
CRect rcCheckMark;
|
||
ASSERT((!cx && !cy) || (cx && cy));
|
||
if(!cx && !cy)
|
||
{
|
||
rcCheckMark=CRect(0,0,
|
||
::GetSystemMetrics(SM_CXMENUCHECK),::GetSystemMetrics(SM_CYMENUCHECK));
|
||
// Convert from device to logical points
|
||
memDC.DPtoLP(&rcCheckMark);
|
||
}
|
||
else
|
||
{
|
||
rcCheckMark=CRect(0, 0, cx, cy);
|
||
}
|
||
|
||
if(m_DefaultImgList.m_hImageList!=NULL)
|
||
{
|
||
m_DefaultImgList.DeleteImageList();
|
||
}
|
||
// The default image list will contain a checkmark and a bulletmark
|
||
VERIFY(m_DefaultImgList.Create(rcCheckMark.right,rcCheckMark.bottom,TRUE,2,0));
|
||
|
||
CBitmap bmTemp;
|
||
VERIFY(bmTemp.CreateCompatibleBitmap(&memDC,rcCheckMark.right,rcCheckMark.bottom));
|
||
|
||
// Create a checkmark bitmap
|
||
|
||
ASSERT((nCheckID==NULL && nBulletID==NULL) || (nCheckID!=NULL && nCheckID!=NULL));
|
||
|
||
CBitmap* pbmTempOld;
|
||
if(!nCheckID)
|
||
{
|
||
pbmTempOld=memDC.SelectObject(&bmTemp);
|
||
memDC.DrawFrameControl(&rcCheckMark, DFC_MENU, DFCS_MENUCHECK);
|
||
memDC.SelectObject(pbmTempOld);
|
||
m_DefaultImgList.Add(&bmTemp, RGB(255,255,255));
|
||
}
|
||
else
|
||
{
|
||
CBitmap bmp;
|
||
VERIFY(bmp.LoadBitmap(nCheckID));
|
||
m_DefaultImgList.Add(&bmp, RGB(255,255,255));
|
||
}
|
||
|
||
// Create a bulletmark bitmap
|
||
if(!nBulletID)
|
||
{
|
||
pbmTempOld=memDC.SelectObject(&bmTemp);
|
||
memDC.DrawFrameControl(&rcCheckMark, DFC_MENU, DFCS_MENUBULLET);
|
||
memDC.SelectObject(pbmTempOld);
|
||
m_DefaultImgList.Add(&bmTemp, RGB(255,255,255));
|
||
}
|
||
else
|
||
{
|
||
CBitmap bmp;
|
||
VERIFY(bmp.LoadBitmap(nBulletID));
|
||
m_DefaultImgList.Add(&bmp, RGB(255,255,255));
|
||
}
|
||
|
||
// Clean up
|
||
memDC.DeleteDC();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void COXBitmapMenuOrganizer::Empty(BOOL bCopyText/*=TRUE*/)
|
||
{
|
||
CString sKey;
|
||
CImageList* pImageList;
|
||
POSITION pos=m_mapStringToImageList.GetStartPosition();
|
||
// Remove all the elements from m_mapStringToImageList and deletes them
|
||
while(pos!=NULL)
|
||
{
|
||
m_mapStringToImageList.GetNextAssoc(pos,sKey,pImageList);
|
||
if(pImageList!=&m_DefaultImgList)
|
||
{
|
||
delete pImageList;
|
||
pImageList = NULL;
|
||
}
|
||
}
|
||
m_mapStringToImageList.RemoveAll();
|
||
|
||
DWORD wKey;
|
||
COXImageInfo* pImageInfo;
|
||
pos=m_mapCommandToImageInfo.GetStartPosition();
|
||
// Remove all the elements from m_mapCommandToImageInfo
|
||
while(pos != NULL)
|
||
{
|
||
m_mapCommandToImageInfo.GetNextAssoc(pos,wKey,pImageInfo);
|
||
delete pImageInfo;
|
||
pImageInfo = NULL;
|
||
}
|
||
m_mapCommandToImageInfo.RemoveAll();
|
||
|
||
// Deletes all the instantiated COXBitmapMenus
|
||
while(!m_BitmapMenuList.IsEmpty())
|
||
{
|
||
|
||
COXBitmapMenu* pBitmapMenu=m_BitmapMenuList.RemoveHead();
|
||
// v9.3 - update 04 fixed gibberish output due to __FILE__ not being UNICODE - AAW 2009-03-29
|
||
//TRACE(_T("\nEmpty: Found bitmapmenu %x - Line: %d, %s"), pBitmapMenu, __LINE__, TEXT( __FILE__ ));
|
||
RestoreBitmapMenu(pBitmapMenu,bCopyText);
|
||
|
||
//delete pBitmapMenu;
|
||
}
|
||
}
|
||
|
||
COXBitmapMenuOrganizer::~COXBitmapMenuOrganizer()
|
||
{
|
||
Empty(FALSE);
|
||
|
||
// delete deferred from RestoreBitmapMenu - 9.3 patch
|
||
if(m_pDeferedBM != NULL) {
|
||
delete m_pDeferedBM;
|
||
}
|
||
|
||
// ... Detach a possible attached frame window
|
||
DetachFrameWnd();
|
||
|
||
for(int nIndex=PtrToInt(m_arrCreatedPopupMenus.GetSize())-1; nIndex>=0; nIndex--)
|
||
{
|
||
::DestroyMenu(m_arrCreatedPopupMenus[nIndex]);
|
||
}
|
||
m_arrCreatedPopupMenus.RemoveAll();
|
||
|
||
ASSERT(g_pfnOldMouseHookProc==NULL);
|
||
ASSERT(g_pfnOldKeyboardHookProc==NULL);
|
||
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::AttachFrameWnd(CFrameWnd* pFrameWnd)
|
||
{
|
||
if((m_pFrameWnd==NULL) && (pFrameWnd != NULL))
|
||
{
|
||
m_pFrameWnd=pFrameWnd;
|
||
VERIFY(SubclassFrameWindow(pFrameWnd));
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::AttachFrameWnd : Failed because already attached or frame wnd is NULL\n");
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
CFrameWnd* COXBitmapMenuOrganizer::DetachFrameWnd()
|
||
{
|
||
CFrameWnd* pFrameWnd=m_pFrameWnd;
|
||
if(pFrameWnd != NULL)
|
||
{
|
||
UnsubclassFrameWindow();
|
||
}
|
||
m_pFrameWnd=NULL;
|
||
Empty();
|
||
return pFrameWnd;
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuImage(UINT nCommandID, LPCTSTR pszBitmapID,
|
||
int nBitmapIndex, int nCx)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::SetMenuImage : Must attach a frame window before calling this function\n");
|
||
return FALSE;
|
||
}
|
||
|
||
CString sUResourse=GetUniqueResourceString(pszBitmapID);
|
||
CImageList* pImageList;
|
||
//Doesn't add if already the resource is asociated with a ImageList
|
||
if(!m_mapStringToImageList.Lookup(sUResourse,pImageList))
|
||
{
|
||
pImageList=new CImageList;
|
||
m_mapStringToImageList[sUResourse]=pImageList;
|
||
}
|
||
else
|
||
{
|
||
VERIFY(pImageList->DeleteImageList());
|
||
}
|
||
pImageList->Create(pszBitmapID,nCx,0,RGB(192,192,192));
|
||
ASSERT(AfxIsValidAddress(pImageList, sizeof(CImageList)));
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
pImageInfo=new COXImageInfo(pImageList,nBitmapIndex);
|
||
m_mapCommandToImageInfo[nCommandID]=pImageInfo;
|
||
}
|
||
else
|
||
{
|
||
pImageInfo->SetImageList(pImageList);
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuImage(UINT nCommandID, HICON hIcon,
|
||
int nCx, int nCy)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::SetMenuImage : Must attach a frame window before calling this function\n");
|
||
return FALSE;
|
||
}
|
||
|
||
CString sUResourse=GetUniqueResourceString((UINT_PTR)hIcon);
|
||
CImageList* pImageList;
|
||
//Doesn't add if already the resource is asociated with a ImageList
|
||
if(!m_mapStringToImageList.Lookup(sUResourse,pImageList))
|
||
{
|
||
pImageList=new CImageList;
|
||
m_mapStringToImageList[sUResourse]=pImageList;
|
||
}
|
||
else
|
||
{
|
||
VERIFY(pImageList->DeleteImageList());
|
||
}
|
||
VERIFY(pImageList->Create(nCx,nCy,ILC_COLOR24|ILC_MASK,0,0));
|
||
VERIFY(pImageList->Add(hIcon)!=-1);
|
||
ASSERT(AfxIsValidAddress(pImageList, sizeof(CImageList)));
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
pImageInfo=new COXImageInfo(pImageList,0);
|
||
m_mapCommandToImageInfo[nCommandID]=pImageInfo;
|
||
}
|
||
else
|
||
{
|
||
pImageInfo->SetImageList(pImageList);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuImage(UINT nCommandID, CBitmap* pbmImage,
|
||
COLORREF crMask, int nCx, int nCy)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::SetMenuImage : Must attach a frame window before calling this function\n");
|
||
return FALSE;
|
||
}
|
||
|
||
CString sUResourse=GetUniqueResourceString((UINT_PTR)pbmImage);
|
||
CImageList* pImageList;
|
||
//Doesn't add if already the resource is asociated with a ImageList
|
||
if(!m_mapStringToImageList.Lookup(sUResourse,pImageList))
|
||
{
|
||
pImageList=new CImageList;
|
||
m_mapStringToImageList[sUResourse]=pImageList;
|
||
}
|
||
else
|
||
{
|
||
VERIFY(pImageList->DeleteImageList());
|
||
}
|
||
VERIFY(pImageList->Create(nCx,nCy,ILC_COLOR24|ILC_MASK,0,0));
|
||
VERIFY(pImageList->Add(pbmImage,crMask)!=-1);
|
||
ASSERT(AfxIsValidAddress(pImageList, sizeof(CImageList)));
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
pImageInfo=new COXImageInfo(pImageList,0);
|
||
m_mapCommandToImageInfo[nCommandID]=pImageInfo;
|
||
}
|
||
else
|
||
{
|
||
pImageInfo->SetImageList(pImageList);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotImage(UINT nCommandID, LPCTSTR pszBitmapID,
|
||
int nBitmapIndex, int nCx)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : Must attach a frame window before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : normal image must be set for the item before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
ASSERT(pImageInfo!=NULL);
|
||
CImageList* pExistingImageList=pImageInfo->GetImageList();
|
||
ASSERT(pExistingImageList!=NULL);
|
||
|
||
CImageList imageList;
|
||
if(!imageList.Create(pszBitmapID,nCx,0,RGB(192,192,192)))
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : failed to load the bitmap\n"));
|
||
return FALSE;
|
||
}
|
||
ASSERT((HIMAGELIST)imageList!=NULL);
|
||
|
||
HICON hIcon=imageList.ExtractIcon(nBitmapIndex);
|
||
ASSERT(hIcon!=NULL);
|
||
|
||
int nIndex=pExistingImageList->Add(hIcon);
|
||
VERIFY(::DestroyIcon(hIcon));
|
||
if(nIndex==-1)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : failed to add bitmap to menu item's image list\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pImageInfo->SetHotIndex(nIndex);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotImage(UINT nCommandID, HICON hIcon)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : Must attach a frame window before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : normal image must be set for the item before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
ASSERT(pImageInfo!=NULL);
|
||
CImageList* pExistingImageList=pImageInfo->GetImageList();
|
||
ASSERT(pExistingImageList!=NULL);
|
||
|
||
ASSERT(hIcon!=NULL);
|
||
|
||
int nIndex=pExistingImageList->Add(hIcon);
|
||
if(nIndex==-1)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : failed to add bitmap to menu item's image list\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pImageInfo->SetHotIndex(nIndex);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotImage(UINT nCommandID, CBitmap* pbmImage,
|
||
COLORREF crMask)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : Must attach a frame window before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : normal image must be set for the item before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
ASSERT(pImageInfo!=NULL);
|
||
CImageList* pExistingImageList=pImageInfo->GetImageList();
|
||
ASSERT(pExistingImageList!=NULL);
|
||
|
||
ASSERT(pbmImage!=NULL);
|
||
|
||
int nIndex=pExistingImageList->Add(pbmImage,crMask);
|
||
if(nIndex==-1)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotImage : failed to add bitmap to menu item's image list\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pImageInfo->SetHotIndex(nIndex);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuBitmap(UINT nCommandID, LPCTSTR pszBitmapID)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::SetMenuBitmap : Must attach a frame window before calling this function\n");
|
||
return FALSE;
|
||
}
|
||
|
||
CBitmap Bitmap;
|
||
//to get the width of the bitmap
|
||
if(!Bitmap.LoadBitmap(pszBitmapID))
|
||
return FALSE;
|
||
BITMAP BitmapInfo;
|
||
Bitmap.GetBitmap(&BitmapInfo);
|
||
Bitmap.DeleteObject();
|
||
return SetMenuImage(nCommandID, pszBitmapID, 0, BitmapInfo.bmWidth);
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuBitmap(UINT nCommandID, UINT nBitmapID)
|
||
{
|
||
return SetMenuBitmap(nCommandID,MAKEINTRESOURCE(nBitmapID));
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotBitmap(UINT nCommandID, LPCTSTR pszBitmapID)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::SetMenuBitmap : Must attach a frame window before calling this function\n");
|
||
return FALSE;
|
||
}
|
||
|
||
CBitmap Bitmap;
|
||
//to get the width of the bitmap
|
||
if(!Bitmap.LoadBitmap(pszBitmapID))
|
||
return FALSE;
|
||
BITMAP BitmapInfo;
|
||
Bitmap.GetBitmap(&BitmapInfo);
|
||
Bitmap.DeleteObject();
|
||
return SetMenuHotImage(nCommandID, pszBitmapID, 0, BitmapInfo.bmWidth);
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotBitmap(UINT nCommandID, UINT nBitmapID)
|
||
{
|
||
return SetMenuHotBitmap(nCommandID,MAKEINTRESOURCE(nBitmapID));
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuIcon(UINT nCommandID, LPCTSTR pszIconID)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuIcon : Must attach a frame window before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
HICON hIcon;
|
||
//Loads Icon
|
||
hIcon=AfxGetApp()->LoadIcon(pszIconID);
|
||
if(hIcon==NULL)
|
||
return FALSE;
|
||
|
||
CImageList* pImageList;
|
||
CString sUResource=GetUniqueResourceString(pszIconID,FALSE);
|
||
//if the Icon resource is not already added
|
||
if(!m_mapStringToImageList.Lookup(sUResource,pImageList))
|
||
{
|
||
pImageList=new CImageList;
|
||
//To differentiate between Icon and bitmap add "Icon" at the end
|
||
m_mapStringToImageList[sUResource]=pImageList;
|
||
}
|
||
else
|
||
{
|
||
VERIFY(pImageList->DeleteImageList());
|
||
}
|
||
VERIFY(pImageList->Create(GetSystemMetrics(SM_CXICON),
|
||
GetSystemMetrics(SM_CYICON),FALSE,1,0));
|
||
VERIFY(pImageList->Add(hIcon)!=-1);
|
||
ASSERT(AfxIsValidAddress(pImageList, sizeof(CImageList)));
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
pImageInfo=new COXImageInfo(pImageList,0);
|
||
m_mapCommandToImageInfo[nCommandID]=pImageInfo;
|
||
}
|
||
else
|
||
{
|
||
pImageInfo->SetImageList(pImageList);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuIcon(UINT nCommandID, UINT nIconID)
|
||
{
|
||
return SetMenuIcon(nCommandID,MAKEINTRESOURCE(nIconID));
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotIcon(UINT nCommandID, LPCTSTR pszIconID)
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotIcon : Must attach a frame window before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo))
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotIcon : normal image must be set for the item before calling this function\n"));
|
||
return FALSE;
|
||
}
|
||
ASSERT(pImageInfo!=NULL);
|
||
CImageList* pExistingImageList=pImageInfo->GetImageList();
|
||
ASSERT(pExistingImageList!=NULL);
|
||
|
||
HICON hIcon;
|
||
//Loads Icon
|
||
hIcon=AfxGetApp()->LoadIcon(pszIconID);
|
||
if(hIcon==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotIcon : failed to load the icon\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
int nIndex=pExistingImageList->Add(hIcon);
|
||
if(nIndex==-1)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::SetMenuHotIcon : failed to add the icon to menu item's image list\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pImageInfo->SetHotIndex(nIndex);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SetMenuHotIcon(UINT nCommandID, UINT nIconID)
|
||
{
|
||
return SetMenuHotIcon(nCommandID,MAKEINTRESOURCE(nIconID));
|
||
}
|
||
|
||
|
||
COXImageInfo* COXBitmapMenuOrganizer::GetMenuItemImageInfo(UINT nCommandID) const
|
||
{
|
||
COXImageInfo* pImageInfo=NULL;
|
||
m_mapCommandToImageInfo.Lookup(nCommandID,pImageInfo);
|
||
return pImageInfo;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::AutoSetMenuImage()
|
||
{
|
||
if(m_pFrameWnd==NULL)
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::AutoSetMenuImage : Must attach a frame window before calling this function\n");
|
||
return FALSE;
|
||
}
|
||
|
||
// Empty previous settings
|
||
Empty();
|
||
|
||
CToolBar* pToolBar=NULL;
|
||
UINT nID=0;
|
||
UINT nStyle=0;
|
||
int iImage=0;
|
||
int iHotImage=0;
|
||
|
||
int nListIndex=0;
|
||
CString sListIndex;
|
||
// Iterate all the control bars and use only the toolbars
|
||
POSITION pos=m_pFrameWnd->m_listControlBars.GetHeadPosition();
|
||
while (pos != NULL)
|
||
{
|
||
pToolBar=DYNAMIC_DOWNCAST(CToolBar,
|
||
(CControlBar*)m_pFrameWnd->m_listControlBars.GetNext(pos));
|
||
//If its a CToolBar
|
||
if(pToolBar!=NULL)
|
||
{
|
||
// Get the original imagelist of the toolbar
|
||
HIMAGELIST hOrigImageList=
|
||
(HIMAGELIST)pToolBar->SendMessage(TB_GETIMAGELIST);
|
||
if(hOrigImageList!=NULL)
|
||
{
|
||
CImageList origImageList;
|
||
CImageList* pOrigImageList=
|
||
CImageList::FromHandlePermanent(hOrigImageList);
|
||
if(pOrigImageList==NULL)
|
||
{
|
||
VERIFY(origImageList.Attach(hOrigImageList));
|
||
pOrigImageList=&origImageList;
|
||
}
|
||
ASSERT(pOrigImageList!=NULL);
|
||
|
||
int nOrigImageCount=pOrigImageList->GetImageCount();
|
||
ASSERT(0<nOrigImageCount);
|
||
|
||
// Get the hot imagelist of the toolbar
|
||
HIMAGELIST hHotImageList=
|
||
(HIMAGELIST)pToolBar->SendMessage(TB_GETHOTIMAGELIST);
|
||
CImageList hotImageList;
|
||
CImageList* pHotImageList=NULL;
|
||
int nHotImageCount=0;
|
||
if(hHotImageList!=NULL)
|
||
{
|
||
pHotImageList=CImageList::FromHandlePermanent(hHotImageList);
|
||
if(pHotImageList==NULL)
|
||
{
|
||
VERIFY(hotImageList.Attach(hHotImageList));
|
||
pHotImageList=&hotImageList;
|
||
}
|
||
ASSERT(pHotImageList!=NULL);
|
||
nHotImageCount=pHotImageList->GetImageCount();
|
||
ASSERT(nHotImageCount==nOrigImageCount);
|
||
}
|
||
|
||
CImageList* pNewImageList=new CImageList;
|
||
CRect buttonRect;
|
||
pToolBar->GetItemRect(0, buttonRect);
|
||
|
||
int nButtonIndex=0;
|
||
#if _MFC_VER > 0x0421
|
||
VERIFY(pNewImageList->Create(pOrigImageList));
|
||
#else
|
||
IMAGEINFO imageInfo;
|
||
VERIFY(pOrigImageList->GetImageInfo(0,&imageInfo));
|
||
VERIFY(pNewImageList->Create(imageInfo.rcImage.right-imageInfo.rcImage.left,
|
||
imageInfo.rcImage.bottom-imageInfo.rcImage.top,
|
||
ILC_COLOR24|ILC_MASK,0,0));
|
||
for(nButtonIndex=0; nButtonIndex<nOrigImageCount; nButtonIndex++)
|
||
{
|
||
HICON hIcon=pOrigImageList->ExtractIcon(nButtonIndex);
|
||
ASSERT(hIcon!=NULL);
|
||
VERIFY(pNewImageList->Add(hIcon)!=-1);
|
||
VERIFY(::DestroyIcon(hIcon));
|
||
}
|
||
#endif
|
||
for(nButtonIndex=0; nButtonIndex<nHotImageCount; nButtonIndex++)
|
||
{
|
||
HICON hIcon=pHotImageList->ExtractIcon(nButtonIndex);
|
||
ASSERT(hIcon!=NULL);
|
||
VERIFY(pNewImageList->Add(hIcon)!=-1);
|
||
VERIFY(::DestroyIcon(hIcon));
|
||
}
|
||
|
||
ASSERT(pNewImageList->GetImageCount()==nHotImageCount+nOrigImageCount);
|
||
|
||
// Close everything
|
||
if((HIMAGELIST)hotImageList!=NULL)
|
||
hotImageList.Detach();
|
||
if((HIMAGELIST)origImageList!=NULL)
|
||
origImageList.Detach();
|
||
|
||
nListIndex++;
|
||
sListIndex.Format(_T("%i"), nListIndex);
|
||
m_mapStringToImageList[sListIndex]=pNewImageList;
|
||
|
||
int nButtonCount=pToolBar->GetToolBarCtrl().GetButtonCount();
|
||
// Iterate all buttons on the toolbar
|
||
for(nButtonIndex=0; nButtonIndex < nButtonCount; nButtonIndex++)
|
||
{
|
||
nID=0;
|
||
nStyle=0;
|
||
iImage=0;
|
||
iHotImage=-1;
|
||
pToolBar->GetButtonInfo(nButtonIndex, nID, nStyle, iImage);
|
||
if(nHotImageCount>0)
|
||
{
|
||
iHotImage=iImage+nOrigImageCount;
|
||
}
|
||
//If the Item is not a button
|
||
if(nStyle&TBBS_SEPARATOR)
|
||
continue;
|
||
|
||
//Sets the mapping
|
||
COXImageInfo* pImageInfo=NULL;
|
||
if(!m_mapCommandToImageInfo.Lookup(nID,pImageInfo))
|
||
{
|
||
pImageInfo=new COXImageInfo(
|
||
pNewImageList,iImage,FALSE,iHotImage);
|
||
// ... Set new value
|
||
m_mapCommandToImageInfo[nID]=pImageInfo;
|
||
}
|
||
else
|
||
{
|
||
ASSERT(pImageInfo!=NULL);
|
||
pImageInfo->SetImageList(pNewImageList);
|
||
pImageInfo->SetIndex(iImage);
|
||
pImageInfo->SetHotIndex(iHotImage);
|
||
pImageInfo->SetDefaultImgList(FALSE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void COXBitmapMenuOrganizer::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex,
|
||
BOOL bSysMenu)
|
||
{
|
||
ASSERT(pPopupMenu->GetSafeHmenu()!=NULL);
|
||
|
||
// Replace the attached CMenu by a new COXBitmapMenu object
|
||
// if necessary (if not done yet)
|
||
CMenu* pMenu=pPopupMenu;
|
||
|
||
COXBitmapMenu* pBitmapMenu=DYNAMIC_DOWNCAST(COXBitmapMenu, pMenu);
|
||
//If a COXBitmapMenu is not already attached to the SubMenu
|
||
BOOL bNewBitmapMenu=FALSE;
|
||
if(pBitmapMenu==NULL)
|
||
{
|
||
pBitmapMenu=new COXBitmapMenu();
|
||
|
||
// Detaches the CMenu
|
||
HMENU hMenu=pMenu->Detach();
|
||
|
||
//Attaches the COXBitmapMenu object to the menu handle
|
||
pBitmapMenu->Attach(hMenu);
|
||
m_BitmapMenuList.AddTail(pBitmapMenu);
|
||
pPopupMenu=pBitmapMenu;
|
||
|
||
bNewBitmapMenu=TRUE;
|
||
}
|
||
|
||
#if _MFC_VER>0x0421
|
||
#ifndef _AFX_NO_OLE_SUPPORT
|
||
BOOL bUpdateCmdUI=TRUE;
|
||
if(m_pFrameWnd->m_pNotifyHook!=NULL)
|
||
{
|
||
if(m_pFrameWnd->m_pNotifyHook->m_pActiveItem!=NULL)
|
||
{
|
||
bUpdateCmdUI=FALSE;
|
||
}
|
||
}
|
||
if(bUpdateCmdUI)
|
||
{
|
||
#endif // _AFX_NO_OLE_SUPPORT
|
||
#endif // _MFC_VER>0x0421
|
||
|
||
// Before we begin iterating the menuitems to make them ownerdrawn, be sure
|
||
// the CmdUI mechanism doesn't want to add or change some menuitems
|
||
// (E.g. MRU list)
|
||
pBitmapMenu->OnUpdateCmdUI(CWnd::FromHandle(m_hWnd), nIndex, bSysMenu);
|
||
|
||
#if _MFC_VER>0x0421
|
||
#ifndef _AFX_NO_OLE_SUPPORT
|
||
}
|
||
#endif // _AFX_NO_OLE_SUPPORT
|
||
#endif // _MFC_VER>0x0421
|
||
|
||
|
||
ConvertBitmapMenu(pBitmapMenu,bNewBitmapMenu);
|
||
|
||
pBitmapMenu->
|
||
SetCutomizationMode(IsInCustomizationMode(),m_hWndCustomizeOrganizer);
|
||
}
|
||
|
||
|
||
LRESULT COXBitmapMenuOrganizer::OnMenuChar(UINT nChar, UINT /* nFlags */,
|
||
CMenu* pMenu)
|
||
{
|
||
//to check wether its a COXBitmapMenu
|
||
COXBitmapMenu* pBitmapMenu=DYNAMIC_DOWNCAST(COXBitmapMenu, pMenu);
|
||
int nLoWord =0;
|
||
int nHiWord =0;
|
||
//if its a COXBitmapMenu
|
||
if(pBitmapMenu != NULL)
|
||
{
|
||
int nIndex=0;
|
||
//sets the index of the menu item for the corresponding char
|
||
if(pBitmapMenu->m_KeyAccessMap.Lookup((TCHAR)nChar,nIndex))
|
||
{
|
||
nHiWord=2;
|
||
nLoWord=nIndex;
|
||
}
|
||
}
|
||
return MAKELRESULT(nLoWord,nHiWord);
|
||
}
|
||
|
||
// Measure item implementation relies on unique control/menu IDs
|
||
BOOL COXBitmapMenuOrganizer::OnMeasureItem(int /*nIDCtl*/,
|
||
LPMEASUREITEMSTRUCT lpMeasureItemStruct)
|
||
{
|
||
// ... Handle the cases we can handle
|
||
BOOL bHandled=TRUE;
|
||
CWnd* pWnd=CWnd::FromHandle(m_hWnd);
|
||
ASSERT(pWnd != NULL);
|
||
if(lpMeasureItemStruct->CtlType==ODT_MENU)
|
||
{
|
||
ASSERT(lpMeasureItemStruct->CtlID==0);
|
||
CMenu* pMenu;
|
||
|
||
_AFX_THREAD_STATE* pThreadState=AfxGetThreadState();
|
||
if(pThreadState->m_hTrackingWindow==m_hWnd)
|
||
{
|
||
// start from popup
|
||
pMenu=CMenu::FromHandle(pThreadState->m_hTrackingMenu);
|
||
}
|
||
else
|
||
{
|
||
// start from menubar
|
||
pMenu=pWnd->GetMenu();
|
||
}
|
||
|
||
pMenu=OwnFindPopupMenuFromID(pMenu, lpMeasureItemStruct->itemID);
|
||
if(pMenu==NULL)
|
||
{
|
||
if(m_arrPopupMenusTrace.GetSize()>0 && m_nActivePopupMenuCount>0)
|
||
{
|
||
OXPOPUPMENUTRACE popupMenu=
|
||
m_arrPopupMenusTrace[m_nActivePopupMenuCount-1];
|
||
pMenu=CMenu::FromHandlePermanent(popupMenu.m_hPopupMenu);
|
||
}
|
||
}
|
||
if(pMenu!=NULL)
|
||
{
|
||
pMenu->MeasureItem(lpMeasureItemStruct);
|
||
}
|
||
else
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::OnMeasureItem: Unknown Menu : passing to Default()\n");
|
||
bHandled=FALSE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
CWnd* pChild=pWnd->GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
|
||
if(pChild != NULL && pChild->SendChildNotifyLastMsg())
|
||
return bHandled; // eaten by child
|
||
}
|
||
return bHandled;
|
||
}
|
||
|
||
CString COXBitmapMenuOrganizer::GetUniqueResourceString(UINT_PTR uResourceID,
|
||
BOOL bBitmapIcon)
|
||
{
|
||
CString sRet;
|
||
CString sNum;
|
||
sNum.Format(_T("%u"), uResourceID);
|
||
sNum.ReleaseBuffer();
|
||
sRet=CString((TCHAR)CHAR_MAX)+sNum+
|
||
CString(bBitmapIcon ? (TCHAR)CHAR_MAX : (TCHAR)CHAR_MIN);
|
||
return sRet;
|
||
}
|
||
|
||
CString COXBitmapMenuOrganizer::GetUniqueResourceString(LPCTSTR pszResource,
|
||
BOOL bBitmapIcon)
|
||
{
|
||
if(HIWORD((DWORD_PTR)pszResource)==0)
|
||
{
|
||
return GetUniqueResourceString(LOWORD((DWORD_PTR)pszResource),bBitmapIcon);
|
||
}
|
||
else
|
||
return CString(pszResource)+
|
||
CString(bBitmapIcon ? (TCHAR)CHAR_MAX : (TCHAR)CHAR_MIN);
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::SubclassFrameWindow(CFrameWnd* pFrameWnd)
|
||
// --- In : pFrameWnd : The frame window
|
||
// --- Out :
|
||
// --- Returns : Whether it was successful or not
|
||
// --- Effect : This function subclasses the frame window
|
||
{
|
||
ASSERT(pFrameWnd != NULL);
|
||
ASSERT(pFrameWnd->GetSafeHwnd() != NULL);
|
||
ASSERT_VALID(pFrameWnd);
|
||
|
||
if(m_pfnSuper != NULL)
|
||
{
|
||
// Already subclasses, check that hWnd and window proc is correct
|
||
if((m_hWnd != pFrameWnd->GetSafeHwnd()) ||
|
||
((WNDPROC)::GetWindowLongPtr(pFrameWnd->GetSafeHwnd(),GWL_WNDPROC)!=
|
||
GlobalMenuOrganizerProc))
|
||
{
|
||
TRACE0("COXBitmapMenuOrganizer::SubclassFrameWindow : Failed because already subclassed by other window proc\n");
|
||
return FALSE;
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
ASSERT(m_hWnd==NULL);
|
||
ASSERT(m_pfnSuper==NULL);
|
||
#ifdef _DEBUG
|
||
COXBitmapMenuOrganizer* pDummyLayoutManager=NULL;
|
||
// ... Should not yet be in list of subclassed frame windows
|
||
ASSERT(!m_allMenuOrganizers.Lookup(m_hWnd, pDummyLayoutManager));
|
||
#endif // _DEBUG
|
||
|
||
// ... Subclass window (Windows way, not MFC : because may already be subclessed by MFC)
|
||
m_hWnd=pFrameWnd->GetSafeHwnd();
|
||
m_pfnSuper=(WNDPROC)::GetWindowLongPtr(pFrameWnd->GetSafeHwnd(), GWL_WNDPROC);
|
||
::SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG_PTR)GlobalMenuOrganizerProc);
|
||
|
||
// ... Store in the global map
|
||
m_allMenuOrganizers.SetAt(m_hWnd, this);
|
||
|
||
ASSERT_VALID(this);
|
||
return (m_hWnd != NULL);;
|
||
}
|
||
|
||
void COXBitmapMenuOrganizer::UnsubclassFrameWindow()
|
||
// --- In :
|
||
// --- Out :
|
||
// --- Returns :
|
||
// --- Effect : This function unsubclasses the window
|
||
// It removes this object from the map
|
||
// When it is the last in the list it restores the original
|
||
// windows procedure
|
||
{
|
||
ASSERT_VALID(this);
|
||
|
||
if(m_hWnd != NULL)
|
||
{
|
||
// Put back original window procedure
|
||
ASSERT(m_pfnSuper != NULL);
|
||
ASSERT(m_pfnSuper != GlobalMenuOrganizerProc);
|
||
// ... GlobalLayoutManagerProc is not used anymore : set WNDPROC back to original value
|
||
::SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG_PTR)m_pfnSuper);
|
||
// ... Remove use from global map
|
||
m_allMenuOrganizers.RemoveKey(m_hWnd);
|
||
m_hWnd=NULL;
|
||
m_pfnSuper=NULL;
|
||
}
|
||
|
||
ASSERT(m_hWnd==NULL);
|
||
ASSERT(m_pfnSuper==NULL);
|
||
|
||
ASSERT_VALID(this);
|
||
}
|
||
|
||
LRESULT CALLBACK COXBitmapMenuOrganizer::GlobalMenuOrganizerProc(HWND hWnd,
|
||
UINT uMsg,
|
||
WPARAM wParam,
|
||
LPARAM lParam)
|
||
// --- In : hWnd :
|
||
// uMsg :
|
||
// wParam :
|
||
// lParam :
|
||
// --- Out :
|
||
// --- Returns : The result of the message
|
||
// --- Effect : This is the global windows procedure of all the menu organizers
|
||
// objects that have subclasses a window
|
||
{
|
||
#if defined (_WINDLL)
|
||
#if defined (_AFXDLL)
|
||
AFX_MANAGE_STATE(AfxGetAppModuleState());
|
||
#else
|
||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||
#endif
|
||
#endif
|
||
|
||
COXBitmapMenuOrganizer* pBitmapMenuOrganizer=NULL;
|
||
|
||
VERIFY(m_allMenuOrganizers.Lookup(hWnd, pBitmapMenuOrganizer));
|
||
ASSERT_VALID(pBitmapMenuOrganizer);
|
||
return pBitmapMenuOrganizer->MenuOrganizerProc(hWnd, uMsg, wParam, lParam);
|
||
}
|
||
|
||
|
||
LRESULT COXBitmapMenuOrganizer::MenuOrganizerProc(HWND hWnd, UINT uMsg,
|
||
WPARAM wParam, LPARAM lParam)
|
||
// --- In : hWnd :
|
||
// uMsg :
|
||
// wParam :
|
||
// lParam :
|
||
// --- Out :
|
||
// --- Returns: The result of the message
|
||
// --- Effect : This is the member function called by the windows procedure of the
|
||
// COXBitmapMenuOrganizer object
|
||
{
|
||
#if defined (_WINDLL)
|
||
#if defined (_AFXDLL)
|
||
AFX_MANAGE_STATE(AfxGetAppModuleState());
|
||
#else
|
||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||
#endif
|
||
#endif
|
||
|
||
ASSERT_VALID(this);
|
||
ASSERT(hWnd==m_hWnd);
|
||
|
||
// Handling before base class
|
||
BOOL bHandled=FALSE;
|
||
LRESULT result=0;
|
||
|
||
// Let the original message procedure handle it first of all
|
||
ASSERT(m_pfnSuper != NULL);
|
||
ASSERT(m_pfnSuper != GlobalMenuOrganizerProc);
|
||
if(uMsg!=WM_MEASUREITEM)
|
||
{
|
||
result=CallWindowProc(m_pfnSuper,hWnd, uMsg, wParam, lParam);
|
||
}
|
||
|
||
if(!::IsWindow(hWnd))
|
||
{
|
||
return result;
|
||
}
|
||
|
||
switch (uMsg)
|
||
{
|
||
case WM_MENUCHAR:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_MENUCHAR\n"));
|
||
{
|
||
CMenu* pMenu=CMenu::FromHandle((HMENU)lParam);
|
||
int nChar=towlower(LOWORD(wParam));
|
||
int nFlags=HIWORD(wParam);
|
||
result=OnMenuChar(nChar, nFlags, pMenu);
|
||
bHandled=TRUE;
|
||
break;
|
||
}
|
||
|
||
case WM_INITMENUPOPUP:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_INITMENUPOPUP\n"));
|
||
{
|
||
CMenu* pPopupMenu=CMenu::FromHandle((HMENU)wParam);
|
||
UINT nIndex=(UINT) LOWORD(lParam);
|
||
BOOL bSysMenu=(BOOL) HIWORD(lParam);
|
||
|
||
UpdateActivePopupMenuCount();
|
||
int nTraceSize=PtrToInt(m_arrPopupMenusTrace.GetSize());
|
||
if(nTraceSize>m_nActivePopupMenuCount)
|
||
{
|
||
for(int nMenuIndex=nTraceSize-1;
|
||
nMenuIndex>=m_nActivePopupMenuCount;
|
||
nMenuIndex--)
|
||
{
|
||
// update map of all popup menu windows
|
||
if(nMenuIndex==m_nActivePopupMenuCount)
|
||
{
|
||
// reuse window object
|
||
HWND hPopupMenuWnd=NULL;
|
||
if(m_mapPopupMenuWindows.Lookup(
|
||
m_arrPopupMenusTrace[nMenuIndex].m_hPopupMenu,
|
||
hPopupMenuWnd))
|
||
{
|
||
m_mapPopupMenuWindows.SetAt((HMENU)wParam,hPopupMenuWnd);
|
||
}
|
||
}
|
||
m_mapPopupMenuWindows.RemoveKey(
|
||
m_arrPopupMenusTrace[nMenuIndex].m_hPopupMenu);
|
||
|
||
m_arrPopupMenusTrace.RemoveAt(nMenuIndex);
|
||
}
|
||
}
|
||
m_nActivePopupMenuCount++;
|
||
|
||
// Don't make system menu's owner-drawn. We can't retrieve them
|
||
// in OnMeasureitem.
|
||
if(bSysMenu)
|
||
{
|
||
TRACE(_T("\nCOXBitmapMenuOrganizer::MenuOrganizerProc: System Menu skipping Ownerdraw\n"));
|
||
bHandled=FALSE;
|
||
break;
|
||
}
|
||
|
||
OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
|
||
|
||
OXPOPUPMENUTRACE pmt;
|
||
pmt.m_hPopupMenu=(HMENU)wParam;
|
||
m_arrPopupMenusTrace.Add(pmt);
|
||
////////////////////////////////
|
||
|
||
// the default msg proc further only deals with CmdUI and that is already
|
||
// done in OnUpdateCmdUI, so halt further processing
|
||
bHandled=TRUE;
|
||
break;
|
||
}
|
||
|
||
case WM_MEASUREITEM:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_MEASUREITEM\n"));
|
||
{
|
||
int nIDCtl=(int)wParam;
|
||
LPMEASUREITEMSTRUCT lpMeasureItemStruct=
|
||
(LPMEASUREITEMSTRUCT)(LPTSTR)lParam;
|
||
result=OnMeasureItem(nIDCtl,lpMeasureItemStruct);
|
||
bHandled=TRUE;
|
||
break;
|
||
}
|
||
|
||
case WM_COMMAND:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_COMMAND\n"));
|
||
{
|
||
if(HIWORD(wParam)==0)
|
||
{
|
||
int nCmdID=LOWORD(wParam);
|
||
|
||
if(nCmdID==ID_OX_SHOWALLITEMS)
|
||
{
|
||
// v9.3 update 01 modification Manfred Drasch
|
||
POSITION pos=m_BitmapMenuList.GetHeadPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
COXBitmapMenu* pBitmapMenu=m_BitmapMenuList.GetNext(pos);
|
||
RestoreBitmapMenu(pBitmapMenu,TRUE);
|
||
}
|
||
// end modification Manfred Drasch
|
||
|
||
m_bForceToDisplayHiddenItems=TRUE;
|
||
|
||
// current menu
|
||
UpdateActivePopupMenuCount();
|
||
|
||
// v9.3 update 01 modification Manfred Drasch
|
||
if (m_nActivePopupMenuCount == 0)
|
||
break;
|
||
// end modification Manfred Drasch
|
||
|
||
ASSERT(m_nActivePopupMenuCount>0);
|
||
OXPOPUPMENUTRACE pmt=
|
||
m_arrPopupMenusTrace[m_nActivePopupMenuCount-1];
|
||
|
||
// handle these event differently for menu bar and standard menu
|
||
// in the case the top level popup menu is being displayed.
|
||
// In the case GetMenu() returns NULL we assume that we deal
|
||
// with menu bar
|
||
BOOL bMenuBar=(m_pFrameWnd->GetMenu()==NULL);
|
||
BOOL bSpecialCase=(bMenuBar && m_nActivePopupMenuCount==1);
|
||
|
||
if(bSpecialCase)
|
||
{
|
||
m_pFrameWnd->LockWindowUpdate();
|
||
}
|
||
|
||
HWND hWndSendRepopulateMsg=NULL;
|
||
if(!bSpecialCase)
|
||
{
|
||
if(m_nActivePopupMenuCount>1)
|
||
{
|
||
VERIFY(m_mapPopupMenuWindows.Lookup(
|
||
m_arrPopupMenusTrace[m_nActivePopupMenuCount-2].
|
||
m_hPopupMenu,hWndSendRepopulateMsg));
|
||
}
|
||
else
|
||
{
|
||
hWndSendRepopulateMsg=m_pFrameWnd->GetSafeHwnd();
|
||
}
|
||
ASSERT(hWndSendRepopulateMsg!=NULL);
|
||
}
|
||
|
||
// hide current menu
|
||
HWND hWnd=NULL;
|
||
VERIFY(m_mapPopupMenuWindows.Lookup(pmt.m_hPopupMenu,hWnd));
|
||
ASSERT(hWnd!=NULL);
|
||
if(bSpecialCase || bMenuBar)
|
||
{
|
||
TRACE(_T("MenuOrganizerProc ::SendMessage(hWnd,WM_KEYDOWN,VK_ESCAPE,0x00010001);"));
|
||
::SendMessage(hWnd,WM_KEYDOWN,VK_ESCAPE,0x00010001);
|
||
}
|
||
else
|
||
{
|
||
TRACE(_T("MenuOrganizerProc ::PostMessage(hWnd,WM_KEYDOWN,VK_ESCAPE,0x00010001);"));
|
||
::PostMessage(hWnd,WM_KEYDOWN,VK_ESCAPE,0x00010001);
|
||
}
|
||
|
||
if(bSpecialCase)
|
||
{
|
||
m_pFrameWnd->UnlockWindowUpdate();
|
||
}
|
||
|
||
// repopulate menus
|
||
// v9.3 update 01 modification Manfred Drasch - POSITION pos declared above
|
||
// POSITION pos=m_BitmapMenuList.GetHeadPosition();
|
||
pos=m_BitmapMenuList.GetHeadPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
COXBitmapMenu* pBitmapMenu=m_BitmapMenuList.GetNext(pos);
|
||
ASSERT(pBitmapMenu!=NULL);
|
||
HWND hWnd=NULL;
|
||
if(!::IsMenu(pBitmapMenu->m_hMenu) ||
|
||
!m_mapPopupMenuWindows.Lookup(
|
||
pBitmapMenu->GetSafeHmenu(),hWnd) || !::IsWindow(hWnd) ||
|
||
pBitmapMenu->GetSafeHmenu()==pmt.m_hPopupMenu)
|
||
{
|
||
// restore the menu
|
||
RestoreBitmapMenu(pBitmapMenu,TRUE);
|
||
}
|
||
}
|
||
|
||
if(!bSpecialCase)
|
||
{
|
||
if(bMenuBar)
|
||
{
|
||
// display the menu again
|
||
::SendMessage(hWndSendRepopulateMsg,
|
||
WM_KEYDOWN,VK_RETURN,0x001c0001);
|
||
}
|
||
else
|
||
{
|
||
// display the menu again
|
||
::PostMessage(hWndSendRepopulateMsg,
|
||
WM_KEYDOWN,VK_RETURN,0x001c0001);
|
||
}
|
||
}
|
||
}
|
||
else if(nCmdID>0 && IsShowOnlyRecentlyUsedItems() &&
|
||
m_arrPopupMenusTrace.GetSize()>0)
|
||
{
|
||
BOOL bMarkMenuAsChanged=FALSE;
|
||
if(!IsRecentlyUsed(nCmdID))
|
||
{
|
||
AddToRecentlyUsed(nCmdID);
|
||
bMarkMenuAsChanged=TRUE;
|
||
}
|
||
for(int nIndex=1;
|
||
nIndex<m_arrPopupMenusTrace.GetSize(); nIndex++)
|
||
{
|
||
HMENU hPopupMenu=m_arrPopupMenusTrace[nIndex].m_hPopupMenu;
|
||
if(!IsSubmenuRecentlyUsed(hPopupMenu))
|
||
{
|
||
AddSubmenuToRecentlyUsed(hPopupMenu);
|
||
bMarkMenuAsChanged=TRUE;
|
||
}
|
||
}
|
||
|
||
if(bMarkMenuAsChanged && IsAttached())
|
||
{
|
||
m_pFrameWnd->SendMessage(WM_OX_MENUCHANGED);
|
||
}
|
||
}
|
||
|
||
bHandled=TRUE;
|
||
}
|
||
break;
|
||
}
|
||
|
||
case WM_ENTERMENULOOP:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_ENTERMENULOOP\n"));
|
||
{
|
||
if(wParam==0)
|
||
{
|
||
m_bMainMenuIsActive=TRUE;
|
||
}
|
||
|
||
bHandled=TRUE;
|
||
|
||
break;
|
||
}
|
||
|
||
case WM_EXITMENULOOP:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_EXITMENULOOP\n"));
|
||
{
|
||
if(wParam==0)
|
||
{
|
||
if(m_bForceToDisplayHiddenItems)
|
||
{
|
||
// repopulate menus
|
||
m_bForceToDisplayHiddenItems=FALSE;
|
||
if(IsShowOnlyRecentlyUsedItems())
|
||
{
|
||
POSITION pos=m_BitmapMenuList.GetHeadPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
COXBitmapMenu* pBitmapMenu=m_BitmapMenuList.GetNext(pos);
|
||
RestoreBitmapMenu(pBitmapMenu,TRUE);
|
||
|
||
TRACE(_T("\n %x menu should be removed by RestoreBitmapMenu"), pBitmapMenu);
|
||
//delete pBitmapMenu;
|
||
}
|
||
}
|
||
}
|
||
|
||
m_bMainMenuIsActive=FALSE;
|
||
|
||
m_nActivePopupMenuCount=0;
|
||
}
|
||
|
||
// unhook mouse messages
|
||
if(g_pfnOldMouseHookProc!=NULL)
|
||
{
|
||
VERIFY(::UnhookWindowsHookEx(g_pfnOldMouseHookProc));
|
||
g_pfnOldMouseHookProc=NULL;
|
||
}
|
||
|
||
// unhook keyboard messages
|
||
if(g_pfnOldKeyboardHookProc!=NULL)
|
||
{
|
||
VERIFY(::UnhookWindowsHookEx(g_pfnOldKeyboardHookProc));
|
||
g_pfnOldKeyboardHookProc=NULL;
|
||
}
|
||
|
||
bHandled=TRUE;
|
||
|
||
break;
|
||
}
|
||
|
||
case WM_MENUSELECT:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_MENUSELECT\n"));
|
||
{
|
||
if(lParam!=NULL && m_arrPopupMenusTrace.GetSize()>0)
|
||
{
|
||
OXPOPUPMENUTRACE& pmt=
|
||
m_arrPopupMenusTrace[m_arrPopupMenusTrace.GetSize()-1];
|
||
if(pmt.m_hPopupMenu==(HMENU)lParam)
|
||
{
|
||
// save Top/Left coordinates of the menu window
|
||
CWnd* pPopupWnd=CWnd::GetDesktopWindow()->GetTopWindow();
|
||
ASSERT(pPopupWnd!=NULL);
|
||
CRect rectPopupWnd;
|
||
pPopupWnd->GetWindowRect(rectPopupWnd);
|
||
pmt.m_ptTopLeft=rectPopupWnd.TopLeft();
|
||
////////////////////////////////
|
||
m_mapPopupMenuWindows.
|
||
SetAt((HMENU)lParam,pPopupWnd->GetSafeHwnd());
|
||
if(IsShowOnlyRecentlyUsedItems())
|
||
{
|
||
// setup hooks for mouse and keyboard messages
|
||
if(g_pfnOldMouseHookProc==NULL)
|
||
{
|
||
g_pfnOldMouseHookProc=::SetWindowsHookEx(WH_MOUSE,
|
||
MenuMouseHookProc,NULL,::GetCurrentThreadId());
|
||
}
|
||
if(g_pfnOldKeyboardHookProc==NULL)
|
||
{
|
||
g_pfnOldKeyboardHookProc=::SetWindowsHookEx(WH_KEYBOARD,
|
||
MenuKeyboardHookProc,NULL,::GetCurrentThreadId());
|
||
}
|
||
//////////////////////////////////////////////
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
UINT nFlags=HIWORD(wParam);
|
||
if((nFlags&MF_HILITE)!=0 && !(nFlags==0xffff && lParam==NULL) &&
|
||
LOWORD(wParam)!=-1)
|
||
{
|
||
while(m_nActivePopupMenuCount>0 && m_arrPopupMenusTrace[
|
||
m_nActivePopupMenuCount-1].m_hPopupMenu!=(HMENU)lParam)
|
||
{
|
||
m_nActivePopupMenuCount--;
|
||
}
|
||
}
|
||
*/
|
||
break;
|
||
}
|
||
|
||
case WM_OX_SAVEMENUSTATE:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc - WM_OX_SAVEMENUSTATE\n"));
|
||
{
|
||
// save info about recently used submenu items
|
||
HMENU hMenu=(HMENU)wParam;
|
||
CString sKey=(LPCTSTR)lParam;
|
||
if(hMenu!=NULL)
|
||
{
|
||
VERIFY(SaveRUSubmenusState(hMenu,
|
||
sKey+_T("_RecentlyUsedSubmenuItems")));
|
||
}
|
||
}
|
||
|
||
case WM_OX_LOADMENUSTATE:
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuOrganizerProc\n"));
|
||
{
|
||
// load info about recently used submenu items
|
||
HMENU hMenu=(HMENU)wParam;
|
||
CString sKey=(LPCTSTR)lParam;
|
||
if(hMenu!=NULL)
|
||
{
|
||
VERIFY(LoadRUSubmenusState(hMenu,
|
||
sKey+_T("_RecentlyUsedSubmenuItems")));
|
||
}
|
||
}
|
||
|
||
default:
|
||
// Do nothing special
|
||
;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
void COXBitmapMenuOrganizer::UpdateActivePopupMenuCount()
|
||
{
|
||
int nTraceLength=PtrToInt(m_arrPopupMenusTrace.GetSize());
|
||
|
||
if(nTraceLength==0)
|
||
{
|
||
m_nActivePopupMenuCount=0;
|
||
return;
|
||
}
|
||
|
||
int nIndex=0;
|
||
for(nIndex=0; nIndex<nTraceLength; nIndex++)
|
||
{
|
||
HWND hWnd=NULL;
|
||
if(!m_mapPopupMenuWindows.
|
||
Lookup(m_arrPopupMenusTrace[nIndex].m_hPopupMenu,hWnd))
|
||
{
|
||
break;
|
||
}
|
||
|
||
if(!::IsWindow(hWnd) || !::IsWindowVisible(hWnd))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(nIndex<m_nActivePopupMenuCount)
|
||
{
|
||
m_nActivePopupMenuCount=nIndex;
|
||
}
|
||
}
|
||
|
||
|
||
CMenu* COXBitmapMenuOrganizer::OwnFindPopupMenuFromID(CMenu* pMenu, UINT nID)
|
||
{
|
||
ASSERT_VALID(pMenu);
|
||
|
||
// walk through all items, looking for ID match
|
||
UINT_PTR nItems=pMenu->GetMenuItemCount();
|
||
UINT_PTR nItemID=0;
|
||
for (int iItem=0; iItem < (int)nItems; iItem++)
|
||
{
|
||
// Always check the menu item itself first
|
||
nItemID=pMenu->GetMenuItemID(iItem);
|
||
if(nItemID==(UINT)-1)
|
||
{
|
||
// ... If it is a cascade menu, use its handle instead of its ID (which is always -1)
|
||
// So appearently Windows passes the HMENU instead of the ID for cascade manus
|
||
// in MEASUREITEMSTRUCT when sending WM_MEASUREITEM
|
||
nItemID=(UINT_PTR)pMenu->GetSubMenu(iItem)->GetSafeHmenu();
|
||
}
|
||
|
||
if(nItemID==nID || nID==-1)
|
||
{
|
||
// ... it is an item inside our popup
|
||
pMenu=CMenu::FromHandlePermanent(pMenu->m_hMenu);
|
||
return pMenu;
|
||
}
|
||
|
||
// Then check child menus
|
||
CMenu* pPopup=pMenu->GetSubMenu(iItem);
|
||
if(pPopup != NULL)
|
||
{
|
||
// ... Recurse to child popup
|
||
pPopup=OwnFindPopupMenuFromID(pPopup, nID);
|
||
// ... Check popups on this popup
|
||
if(pPopup != NULL)
|
||
return pPopup;
|
||
}
|
||
}
|
||
// ... Not found
|
||
return NULL;
|
||
}
|
||
|
||
void COXBitmapMenuOrganizer::ConvertBitmapMenu(COXBitmapMenu* pBitmapMenu,
|
||
BOOL bNewBitmapMenu/*=TRUE*/)
|
||
{
|
||
ASSERT(pBitmapMenu!=NULL);
|
||
|
||
UINT uItemID;
|
||
COXImageInfo* pImageInfo;
|
||
int nCount=pBitmapMenu->GetMenuItemCount();
|
||
|
||
int nAmpIndex;
|
||
MENUITEMINFO miiGet, miiPut;
|
||
CString sText;
|
||
|
||
COXArrSavedMenuItem arrSavedMenuItems;
|
||
BOOL bPrevSepBeforeHidden=TRUE;
|
||
|
||
//Make all the menu items OwnerDrawn
|
||
int nIndex=0;
|
||
for(nIndex=0; nIndex < nCount; nIndex++)
|
||
{
|
||
// Even cascade menu item should be made owner drawn
|
||
// so that the text of these items is aligned properly
|
||
|
||
::ZeroMemory(&miiGet, sizeof(miiGet));
|
||
miiGet.cbSize=sizeof(miiGet);
|
||
miiGet.fMask=MIIM_TYPE|MIIM_ID|MIIM_STATE|MIIM_DATA|
|
||
MIIM_SUBMENU|MIIM_CHECKMARKS;
|
||
miiGet.fType=MFT_STRING;
|
||
miiGet.dwTypeData = NULL;
|
||
::GetMenuItemInfo(pBitmapMenu->GetSafeHmenu(),nIndex,TRUE,&miiGet);
|
||
++miiGet.cch;
|
||
miiGet.dwTypeData=sText.GetBuffer(miiGet.cch + 1);
|
||
// Gets the item info
|
||
miiGet.dwTypeData[0]=_T('\0');
|
||
::GetMenuItemInfo(pBitmapMenu->GetSafeHmenu(),nIndex,TRUE,&miiGet);
|
||
sText.ReleaseBuffer();
|
||
|
||
#if _MFC_VER>0x0421
|
||
#ifndef _AFX_NO_OLE_SUPPORT
|
||
if(miiGet.fType & MFT_SEPARATOR)
|
||
{
|
||
if(m_pFrameWnd->m_pNotifyHook!=NULL)
|
||
{
|
||
if(m_pFrameWnd->m_pNotifyHook->m_pActiveItem!=NULL)
|
||
{
|
||
// continue;
|
||
}
|
||
}
|
||
}
|
||
#endif // _AFX_NO_OLE_SUPPORT
|
||
#endif // _MFC_VER>0x0421
|
||
|
||
if(bNewBitmapMenu && !m_bForceToDisplayHiddenItems &&
|
||
!IsInCustomizationMode() && IsShowOnlyRecentlyUsedItems() &&
|
||
(!IsRecentlyUsed(miiGet.wID) ||
|
||
!IsSubmenuRecentlyUsed(miiGet.hSubMenu) ||
|
||
((miiGet.fType & MFT_SEPARATOR) && bPrevSepBeforeHidden)))
|
||
{
|
||
OXSAVEDMENUITEM smi;
|
||
smi.nIndex=nIndex;
|
||
smi.miInfo=miiGet;
|
||
if(miiGet.hSubMenu!=NULL)
|
||
{
|
||
smi.miInfo.hSubMenu=CopyPopupMenu(miiGet.hSubMenu);
|
||
}
|
||
smi.sText=sText;
|
||
ASSERT(smi.miInfo.wID!=-1 || ::IsMenu(smi.miInfo.hSubMenu));
|
||
arrSavedMenuItems.Add(smi);
|
||
|
||
if(!(miiGet.fType & MFT_SEPARATOR) && !bPrevSepBeforeHidden && nIndex>0)
|
||
{
|
||
if(pBitmapMenu->GetMenuItemID(nIndex-1)==0)
|
||
{
|
||
bPrevSepBeforeHidden=TRUE;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
BOOL bConvertToOwnerdraw=((miiGet.fType & MFT_OWNERDRAW)==0);
|
||
|
||
uItemID=((miiGet.hSubMenu==NULL) ? miiGet.wID : (UINT)-1);
|
||
|
||
//Makes the item owner-drawn and sets the ItemInfo to the ItemData
|
||
// which in turn will be used in COXBitmapMenu while drawing
|
||
::ZeroMemory(&miiPut, sizeof(miiPut));
|
||
miiPut.cbSize=sizeof(miiPut);
|
||
miiPut.fMask=(bConvertToOwnerdraw ? MIIM_TYPE : 0) | MIIM_DATA | MIIM_ID;
|
||
miiPut.fType=(miiGet.fType & ~MFT_STRING) | MFT_OWNERDRAW;
|
||
|
||
switch(miiGet.wID)
|
||
{
|
||
// Restore
|
||
case 61728:
|
||
miiPut.wID = ID_OXBITMAPMENU_RESTORE;
|
||
break;
|
||
// Minimize
|
||
case 61472:
|
||
miiPut.wID = ID_OXBITMAPMENU_MINIMIZE;
|
||
break;
|
||
// Close
|
||
case 61536:
|
||
miiPut.wID = ID_OXBITMAPMENU_CLOSE;
|
||
break;
|
||
default:
|
||
miiPut.wID = miiGet.wID;
|
||
}
|
||
|
||
// Gets the ImageInfo for the command if exist
|
||
if(!m_mapCommandToImageInfo.Lookup(uItemID,pImageInfo))
|
||
{
|
||
CImageList* pImageList;
|
||
CString sUResource=GetUniqueResourceString(uItemID,FALSE);
|
||
|
||
// if the Normal menuitem is not already added
|
||
if(!m_mapStringToImageList.Lookup(sUResource, pImageList))
|
||
{
|
||
m_mapStringToImageList[sUResource]=pImageList=&m_DefaultImgList;
|
||
}
|
||
|
||
ASSERT(AfxIsValidAddress(pImageList, sizeof(CImageList)));
|
||
pImageInfo=new COXImageInfo(pImageList, 0, TRUE);
|
||
//sets the mapping between MenuItem ID and Image Info
|
||
m_mapCommandToImageInfo[uItemID]=pImageInfo;
|
||
}
|
||
|
||
COXItemInfo* pItemInfo=NULL;
|
||
if(miiGet.dwItemData != 0 && !bNewBitmapMenu)
|
||
{
|
||
pItemInfo=(COXItemInfo*)miiGet.dwItemData;
|
||
miiPut.dwItemData=(DWORD_PTR)pItemInfo;
|
||
if(miiGet.fType==MFT_STRING)
|
||
{
|
||
pItemInfo->SetText(sText);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
|
||
pItemInfo=new COXItemInfo(pImageInfo, sText);
|
||
// v9.3 - update 04 fixed gibberish output due to __FILE__ not being UNICODE - AAW 2009-03-29
|
||
TRACE(_T("\nCreated COXItemInfo at %x - Line: %d, %s"), pItemInfo, __LINE__, TEXT( __FILE__ ));
|
||
miiPut.dwItemData=(DWORD_PTR)pItemInfo;
|
||
pBitmapMenu->AddItemInfo(pItemInfo);
|
||
}
|
||
|
||
// Put the menuitem with the new data back in its place
|
||
::SetMenuItemInfo(pBitmapMenu->GetSafeHmenu(),nIndex,TRUE,&miiPut);
|
||
|
||
// A mapping is maintained for keyboard access chars of menu items and
|
||
// the commands IDs.
|
||
nAmpIndex=sText.Find('&');
|
||
TCHAR LoCase=_T('\0');
|
||
if(nAmpIndex!=-1)
|
||
{
|
||
LoCase=(TCHAR)towlower(sText[nAmpIndex+1]);
|
||
(pBitmapMenu->m_KeyAccessMap)[LoCase]=nIndex;
|
||
}
|
||
|
||
bPrevSepBeforeHidden=FALSE;
|
||
}
|
||
}
|
||
|
||
if(bNewBitmapMenu)
|
||
{
|
||
if(arrSavedMenuItems.GetSize()>0)
|
||
{
|
||
// Gets the ImageInfo for the command if exist
|
||
if(!m_mapCommandToImageInfo.Lookup(ID_OX_SHOWALLITEMS,pImageInfo))
|
||
{
|
||
CString sUResource=GetUniqueResourceString(ID_OX_SHOWALLITEMS,FALSE);
|
||
CImageList* pImageList;
|
||
m_mapStringToImageList[sUResource]=pImageList=&m_DefaultImgList;
|
||
ASSERT(AfxIsValidAddress(pImageList, sizeof(CImageList)));
|
||
pImageInfo=new COXImageInfo(pImageList, 0, TRUE);
|
||
//sets the mapping between MenuItem ID and Image Info
|
||
m_mapCommandToImageInfo[ID_OX_SHOWALLITEMS]=pImageInfo;
|
||
}
|
||
|
||
COXItemInfo* pItemInfo=new COXItemInfo(pImageInfo,_T(""));
|
||
pBitmapMenu->AddItemInfo(pItemInfo);
|
||
|
||
// add expansion item
|
||
pBitmapMenu->
|
||
AppendMenu(MF_OWNERDRAW,ID_OX_SHOWALLITEMS,(LPCTSTR)pItemInfo);
|
||
}
|
||
|
||
ASSERT(!m_mapSavedMenuItems.RemoveKey(pBitmapMenu));
|
||
m_mapSavedMenuItems.SetAt(pBitmapMenu,arrSavedMenuItems);
|
||
|
||
for(nIndex= PtrToInt(arrSavedMenuItems.GetSize())-1; nIndex>=0; nIndex--)
|
||
{
|
||
OXSAVEDMENUITEM smi=arrSavedMenuItems[nIndex];
|
||
VERIFY(pBitmapMenu->DeleteMenu(smi.nIndex,MF_BYPOSITION));
|
||
}
|
||
}
|
||
|
||
|
||
//Calculates the various internal extents
|
||
pBitmapMenu->CalcExtents();
|
||
}
|
||
|
||
|
||
void COXBitmapMenuOrganizer::RestoreBitmapMenu(COXBitmapMenu* pBitmapMenu,
|
||
BOOL bCopyText/*=TRUE*/)
|
||
{
|
||
BOOL bDeferDeletion = FALSE;
|
||
|
||
// remove it from the list if it hasn't been removed yet
|
||
POSITION pos=m_BitmapMenuList.GetHeadPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
if(m_BitmapMenuList.GetAt(pos)==pBitmapMenu)
|
||
{
|
||
// v9.3 - update 04 fixed gibberish output due to __FILE__ not being UNICODE - AAW 2009-03-29
|
||
TRACE(_T("\nRemoving bitmapmenu at %x - Line: %d, %s"), pBitmapMenu, __LINE__, TEXT( __FILE__ ));
|
||
m_BitmapMenuList.RemoveAt(pos);
|
||
break;
|
||
}
|
||
m_BitmapMenuList.GetNext(pos);
|
||
}
|
||
|
||
// remove expansion item
|
||
if(::IsMenu(pBitmapMenu->m_hMenu) && pBitmapMenu->GetMenuItemCount()>0)
|
||
{
|
||
if(pBitmapMenu->GetMenuItemID(pBitmapMenu->GetMenuItemCount()-1)==
|
||
ID_OX_SHOWALLITEMS)
|
||
{
|
||
bDeferDeletion = TRUE;
|
||
pBitmapMenu->DeleteMenu(pBitmapMenu->GetMenuItemCount()-1,MF_BYPOSITION);
|
||
}
|
||
}
|
||
|
||
MENUITEMINFO miiGet, miiPut;
|
||
CString sText;
|
||
|
||
if(bCopyText && ::IsMenu(pBitmapMenu->m_hMenu))
|
||
{
|
||
int nCount=pBitmapMenu->GetMenuItemCount();
|
||
|
||
// Put the strings of the menu's back in, the ownerdraw state has emptied them.
|
||
for(int nIndex=0; nIndex < nCount; nIndex++)
|
||
{
|
||
::ZeroMemory(&miiGet, sizeof(miiGet));
|
||
miiGet.cbSize=sizeof(miiGet);
|
||
miiGet.fMask=MIIM_TYPE | MIIM_DATA;
|
||
// Gets the item info
|
||
::GetMenuItemInfo(pBitmapMenu->GetSafeHmenu(), nIndex, TRUE, &miiGet);
|
||
|
||
// all item must have been converted to ownerdraw
|
||
// only the items that has been added programmatically
|
||
// and hasn't been displayed yet won't have ownerdraw style
|
||
if((miiGet.fType&MFT_OWNERDRAW)!=0)
|
||
{
|
||
COXItemInfo* pItemInfo=(COXItemInfo*)miiGet.dwItemData;
|
||
if(pItemInfo!=NULL)
|
||
{
|
||
sText=pItemInfo->GetText();
|
||
|
||
// Put the text text back into the menu
|
||
::ZeroMemory(&miiPut, sizeof(miiPut));
|
||
miiPut.cbSize=sizeof(miiPut);
|
||
miiPut.fMask=MIIM_TYPE|MIIM_DATA;
|
||
if((miiGet.fType&MFT_SEPARATOR)==0)
|
||
{
|
||
miiPut.fType=(miiGet.fType&~MFT_OWNERDRAW)|MFT_STRING;
|
||
}
|
||
else
|
||
{
|
||
miiPut.fType=(miiGet.fType&~MFT_OWNERDRAW);
|
||
}
|
||
miiPut.cch=sText.GetLength();
|
||
miiPut.dwTypeData=sText.GetBuffer(miiPut.cch);
|
||
miiPut.dwItemData=0;
|
||
// Put the menuitem with the new data back in its place
|
||
::SetMenuItemInfo(pBitmapMenu->GetSafeHmenu(),nIndex,TRUE,&miiPut);
|
||
sText.ReleaseBuffer();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
COXArrSavedMenuItem arrSavedMenuItems;
|
||
VERIFY(m_mapSavedMenuItems.Lookup(pBitmapMenu,arrSavedMenuItems));
|
||
if(::IsMenu(pBitmapMenu->m_hMenu))
|
||
{
|
||
for(int nIndex=0; nIndex<arrSavedMenuItems.GetSize(); nIndex++)
|
||
{
|
||
OXSAVEDMENUITEM smi=arrSavedMenuItems[nIndex];
|
||
smi.miInfo.dwTypeData=(LPTSTR)((LPCTSTR)smi.sText);
|
||
VERIFY(::InsertMenuItem(pBitmapMenu->GetSafeHmenu(),
|
||
smi.nIndex,TRUE,&smi.miInfo));
|
||
}
|
||
}
|
||
VERIFY(m_mapSavedMenuItems.RemoveKey(pBitmapMenu));
|
||
|
||
|
||
//TRACE(_T("\npBitmapMenu at %0x\n"),pBitmapMenu);
|
||
|
||
// - 9.3 patch - defer deletion of bitmap till restored bitmap displayed
|
||
if(!bDeferDeletion) {
|
||
pBitmapMenu->Detach();
|
||
delete pBitmapMenu;
|
||
pBitmapMenu = NULL;
|
||
}
|
||
else {
|
||
if( m_pDeferedBM != NULL) {
|
||
delete m_pDeferedBM;
|
||
}
|
||
pBitmapMenu->Detach();
|
||
m_pDeferedBM = pBitmapMenu;
|
||
}
|
||
}
|
||
|
||
|
||
void COXBitmapMenuOrganizer::ShowOnlyRecentlyUsedItems(BOOL bShowOnlyRecentlyUsed)
|
||
{
|
||
if(bShowOnlyRecentlyUsed!=m_bShowOnlyRecentlyUsed)
|
||
{
|
||
m_bShowOnlyRecentlyUsed=bShowOnlyRecentlyUsed;
|
||
|
||
POSITION pos=m_BitmapMenuList.GetHeadPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
COXBitmapMenu* pBitmapMenu=m_BitmapMenuList.GetNext(pos);
|
||
COXBitmapMenuPopupWnd* pPopupWnd=pBitmapMenu->GetPopupWnd();
|
||
if(pPopupWnd!=NULL && ::IsWindow(pPopupWnd->GetSafeHwnd()))
|
||
{
|
||
pPopupWnd->OnMenuChanged();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::ExcludeFromRecentlyUsed(int nCmdID)
|
||
{
|
||
ASSERT(nCmdID>=0);
|
||
|
||
if(nCmdID==0)
|
||
{
|
||
// separators cannot be hidden
|
||
return FALSE;
|
||
}
|
||
|
||
if(!IsRecentlyUsed(nCmdID))
|
||
{
|
||
// not a recently used item
|
||
return FALSE;
|
||
}
|
||
|
||
m_mapHiddenCommands.SetAt(nCmdID,0);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::ExcludeFromRecentlyUsed(CMenu* pMenu, int nItemIndex)
|
||
{
|
||
ASSERT(pMenu!=NULL);
|
||
ASSERT(nItemIndex>=0 && nItemIndex<(int)pMenu->GetMenuItemCount());
|
||
|
||
int nCmdID=(int)pMenu->GetMenuItemID(nItemIndex);
|
||
if(nCmdID==-1)
|
||
{
|
||
// submenu
|
||
ASSERT(pMenu->GetSubMenu(nItemIndex)!=NULL);
|
||
return ExcludeSubmenuFromRecentlyUsed(
|
||
pMenu->GetSubMenu(nItemIndex)->GetSafeHmenu());
|
||
}
|
||
else
|
||
{
|
||
return ExcludeFromRecentlyUsed(nCmdID);
|
||
}
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::ExcludeSubmenuFromRecentlyUsed(HMENU hPopupMenu)
|
||
{
|
||
ASSERT(hPopupMenu!=NULL);
|
||
|
||
if(!IsSubmenuRecentlyUsed(hPopupMenu))
|
||
{
|
||
// not a recently used submenu
|
||
return FALSE;
|
||
}
|
||
|
||
m_mapHiddenSubmenus.SetAt(hPopupMenu,0);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::AddToRecentlyUsed(int nCmdID)
|
||
{
|
||
ASSERT(nCmdID>0);
|
||
|
||
if(!m_mapHiddenCommands.RemoveKey(nCmdID))
|
||
{
|
||
// this command is already marked as recently used
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::AddToRecentlyUsed(CMenu* pMenu, int nItemIndex)
|
||
{
|
||
ASSERT(pMenu!=NULL);
|
||
ASSERT(nItemIndex>=0 && nItemIndex<(int)pMenu->GetMenuItemCount());
|
||
|
||
int nCmdID=(int)pMenu->GetMenuItemID(nItemIndex);
|
||
if(nCmdID==-1)
|
||
{
|
||
// submenu
|
||
ASSERT(pMenu->GetSubMenu(nItemIndex)!=NULL);
|
||
return AddSubmenuToRecentlyUsed(pMenu->GetSubMenu(nItemIndex)->GetSafeHmenu());
|
||
}
|
||
else
|
||
{
|
||
return AddToRecentlyUsed(nCmdID);
|
||
}
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::AddSubmenuToRecentlyUsed(HMENU hPopupMenu)
|
||
{
|
||
ASSERT(hPopupMenu!=NULL);
|
||
|
||
if(!m_mapHiddenSubmenus.RemoveKey(hPopupMenu))
|
||
{
|
||
// this submenu is already marked as recently used
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::IsRecentlyUsed(int nCmdID) const
|
||
{
|
||
int nDummy=-1;
|
||
return (!m_mapHiddenCommands.Lookup(nCmdID,nDummy));
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::IsRecentlyUsed(CMenu* pMenu, int nItemIndex) const
|
||
{
|
||
if (nItemIndex == -1)
|
||
return TRUE;
|
||
ASSERT(pMenu!=NULL);
|
||
ASSERT(nItemIndex>=0 && nItemIndex<(int)pMenu->GetMenuItemCount());
|
||
|
||
int nCmdID=(int)pMenu->GetMenuItemID(nItemIndex);
|
||
if(nCmdID==-1)
|
||
{
|
||
// submenu
|
||
ASSERT(pMenu->GetSubMenu(nItemIndex)!=NULL);
|
||
return IsSubmenuRecentlyUsed(pMenu->GetSubMenu(nItemIndex)->GetSafeHmenu());
|
||
}
|
||
else
|
||
{
|
||
return IsRecentlyUsed(nCmdID);
|
||
}
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::IsSubmenuRecentlyUsed(HMENU hPopupMenu) const
|
||
{
|
||
int nDummy=-1;
|
||
return (!m_mapHiddenSubmenus.Lookup(hPopupMenu,nDummy));
|
||
}
|
||
|
||
|
||
|
||
void COXBitmapMenuOrganizer::SetCutomizationMode(BOOL bInCutomizationMode,
|
||
HWND hWndCustomizeOrganizer/*=NULL*/)
|
||
{
|
||
if(m_bInCutomizationMode!=bInCutomizationMode)
|
||
{
|
||
m_bInCutomizationMode=bInCutomizationMode;
|
||
if(m_bInCutomizationMode)
|
||
{
|
||
if(IsShowOnlyRecentlyUsedItems() && !m_bForceToDisplayHiddenItems)
|
||
{
|
||
POSITION pos=m_BitmapMenuList.GetHeadPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
COXBitmapMenu* pBitmapMenu=m_BitmapMenuList.GetNext(pos);
|
||
RestoreBitmapMenu(pBitmapMenu,TRUE);
|
||
// delete pBitmapMenu;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
m_hWndCustomizeOrganizer=hWndCustomizeOrganizer;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SaveRUCommandsState(LPCTSTR lpszSubKey)
|
||
{
|
||
#ifndef _MAC
|
||
CWinApp* pApp=AfxGetApp();
|
||
CString sProfileName=lpszSubKey;
|
||
if(sProfileName.IsEmpty())
|
||
{
|
||
sProfileName=_T("RecentlyUsedMenuItems");
|
||
}
|
||
CString sValueName=_T("RUContents");
|
||
|
||
CMemFile memFile;
|
||
CArchive ar(&memFile,CArchive::store);
|
||
VERIFY(SaveRUCommandsContents(ar));
|
||
ar.Close();
|
||
int nBufferLength=(int)memFile.GetLength();
|
||
ASSERT(nBufferLength>0);
|
||
BYTE* pBuffer=memFile.Detach();
|
||
|
||
pApp->WriteProfileBinary(sProfileName,sValueName,pBuffer,nBufferLength);
|
||
::free((void*)pBuffer);
|
||
|
||
sValueName=_T("RUItemsDataSize");
|
||
pApp->WriteProfileInt(sProfileName,sValueName,nBufferLength);
|
||
|
||
return TRUE;
|
||
#else
|
||
return FALSE;
|
||
#endif
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::LoadRUCommandsState(LPCTSTR lpszSubKey)
|
||
{
|
||
#ifndef _MAC
|
||
CWinApp* pApp=AfxGetApp();
|
||
CString sProfileName=lpszSubKey;
|
||
if(sProfileName.IsEmpty())
|
||
{
|
||
sProfileName=_T("RecentlyUsedMenuItems");
|
||
}
|
||
CString sValueName=_T("RUItemsDataSize");
|
||
int nSavedBufferLength=
|
||
pApp->GetProfileInt(sProfileName,sValueName,-1);
|
||
sValueName=_T("RUContents");
|
||
if(nSavedBufferLength!=-1)
|
||
{
|
||
ASSERT(nSavedBufferLength>0);
|
||
UINT nBufferLength=0;
|
||
BYTE* pBuffer=NULL;
|
||
if(pApp->GetProfileBinary(sProfileName,sValueName,&pBuffer,&nBufferLength))
|
||
{
|
||
ASSERT(nBufferLength>0);
|
||
ASSERT(pBuffer!=NULL);
|
||
CMemFile memFile(pBuffer,nBufferLength);
|
||
CArchive ar(&memFile,CArchive::load);
|
||
VERIFY(LoadRUCommandsContents(ar));
|
||
ar.Close();
|
||
memFile.Detach();
|
||
delete[] pBuffer;
|
||
}
|
||
}
|
||
return TRUE;
|
||
#else
|
||
return FALSE;
|
||
#endif
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SaveRUCommandsContents(CArchive& ar)
|
||
{
|
||
int nCommandsCount=PtrToInt(m_mapHiddenCommands.GetCount());
|
||
ar<<nCommandsCount;
|
||
POSITION pos=m_mapHiddenCommands.GetStartPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
int nCmdID=-1;
|
||
int nIndex=-1;
|
||
m_mapHiddenCommands.GetNextAssoc(pos,nCmdID,nIndex);
|
||
ASSERT(nCmdID>0);
|
||
ar<<nCmdID;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::LoadRUCommandsContents(CArchive& ar)
|
||
{
|
||
// remove all items from the list of hidden commands
|
||
m_mapHiddenCommands.RemoveAll();
|
||
|
||
DWORD dwCommandsCount=0;
|
||
ar>>dwCommandsCount;
|
||
for(int nIndex=0; nIndex<(int)dwCommandsCount; nIndex++)
|
||
{
|
||
DWORD dwCmdID=0;
|
||
ar>>dwCmdID;
|
||
ASSERT(dwCmdID>0);
|
||
ExcludeFromRecentlyUsed((int)dwCmdID);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SaveRUSubmenusState(HMENU hMenu, LPCTSTR lpszSubKey)
|
||
{
|
||
#ifndef _MAC
|
||
ASSERT(hMenu!=NULL);
|
||
ASSERT(::IsMenu(hMenu));
|
||
|
||
CWinApp* pApp=AfxGetApp();
|
||
CString sProfileName=lpszSubKey;
|
||
if(sProfileName.IsEmpty())
|
||
{
|
||
sProfileName=_T("RecentlyUsedSubmenuItems");
|
||
}
|
||
CString sValueName=_T("RUContents");
|
||
|
||
CMemFile memFile;
|
||
CArchive ar(&memFile,CArchive::store);
|
||
VERIFY(SaveRUSubmenusContents(hMenu,ar));
|
||
ar.Close();
|
||
int nBufferLength=(int)memFile.GetLength();
|
||
ASSERT(nBufferLength>0);
|
||
BYTE* pBuffer=memFile.Detach();
|
||
|
||
pApp->WriteProfileBinary(sProfileName,sValueName,pBuffer,nBufferLength);
|
||
::free((void*)pBuffer);
|
||
|
||
sValueName=_T("RUItemsDataSize");
|
||
pApp->WriteProfileInt(sProfileName,sValueName,nBufferLength);
|
||
|
||
return TRUE;
|
||
#else
|
||
return FALSE;
|
||
#endif
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::LoadRUSubmenusState(HMENU hMenu, LPCTSTR lpszSubKey)
|
||
{
|
||
#ifndef _MAC
|
||
ASSERT(hMenu!=NULL);
|
||
ASSERT(::IsMenu(hMenu));
|
||
|
||
CWinApp* pApp=AfxGetApp();
|
||
CString sProfileName=lpszSubKey;
|
||
if(sProfileName.IsEmpty())
|
||
{
|
||
sProfileName=_T("RecentlyUsedSubmenuItems");
|
||
}
|
||
CString sValueName=_T("RUItemsDataSize");
|
||
int nSavedBufferLength=
|
||
pApp->GetProfileInt(sProfileName,sValueName,-1);
|
||
sValueName=_T("RUContents");
|
||
if(nSavedBufferLength!=-1)
|
||
{
|
||
ASSERT(nSavedBufferLength>0);
|
||
UINT nBufferLength=0;
|
||
BYTE* pBuffer=NULL;
|
||
if(pApp->GetProfileBinary(sProfileName,sValueName,&pBuffer,&nBufferLength))
|
||
{
|
||
ASSERT(nBufferLength>0);
|
||
ASSERT(pBuffer!=NULL);
|
||
CMemFile memFile(pBuffer,nBufferLength);
|
||
CArchive ar(&memFile,CArchive::load);
|
||
VERIFY(LoadRUSubmenusContents(hMenu,ar));
|
||
ar.Close();
|
||
memFile.Detach();
|
||
delete[] pBuffer;
|
||
}
|
||
}
|
||
return TRUE;
|
||
#else
|
||
return FALSE;
|
||
#endif
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::SaveRUSubmenusContents(HMENU hMenu, CArchive& ar)
|
||
{
|
||
ASSERT(hMenu!=NULL);
|
||
ASSERT(::IsMenu(hMenu));
|
||
|
||
int nSubmenusCount=PtrToInt(m_mapHiddenSubmenus.GetCount());
|
||
ar<<nSubmenusCount;
|
||
POSITION pos=m_mapHiddenSubmenus.GetStartPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
HMENU hPopupMenu=NULL;
|
||
int nIndex=-1;
|
||
m_mapHiddenSubmenus.GetNextAssoc(pos,hPopupMenu,nIndex);
|
||
ASSERT(hPopupMenu!=NULL);
|
||
if(::IsMenu(hPopupMenu))
|
||
{
|
||
CArray<int,int> arrPath;
|
||
if(FindPopupMenuPath(hPopupMenu,hMenu,arrPath))
|
||
{
|
||
for(int nIndex=0; nIndex<arrPath.GetSize(); nIndex++)
|
||
{
|
||
ar<<arrPath[nIndex];
|
||
}
|
||
}
|
||
}
|
||
// end of path
|
||
ar<<-1;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOL COXBitmapMenuOrganizer::LoadRUSubmenusContents(HMENU hMenu, CArchive& ar)
|
||
{
|
||
ASSERT(hMenu!=NULL);
|
||
ASSERT(::IsMenu(hMenu));
|
||
|
||
// remove all items from the list of hidden submenus
|
||
m_mapHiddenSubmenus.RemoveAll();
|
||
|
||
DWORD dwSubmenusCount=0;
|
||
ar>>dwSubmenusCount;
|
||
for(int nIndex=0; nIndex<(int)dwSubmenusCount; nIndex++)
|
||
{
|
||
DWORD dwItemIndex;
|
||
CArray<int,int> arrPath;
|
||
do
|
||
{
|
||
ar>>dwItemIndex;
|
||
if(dwItemIndex!=-1)
|
||
{
|
||
arrPath.Add(dwItemIndex);
|
||
}
|
||
} while(dwItemIndex!=-1);
|
||
|
||
HMENU hPopupMenu=NULL;
|
||
if(arrPath.GetSize()>0)
|
||
{
|
||
HMENU hParentMenu=hMenu;
|
||
for(int nPathIndex=0; nPathIndex<arrPath.GetSize(); nPathIndex++)
|
||
{
|
||
hParentMenu=GetSubMenu(hParentMenu,arrPath[nPathIndex]);
|
||
if(hParentMenu==NULL)
|
||
{
|
||
TRACE(_T("COXBitmapMenuOrganizer::LoadRUSubmenusContents: failed to load RU submenu\n"));
|
||
break;
|
||
}
|
||
}
|
||
hPopupMenu=hParentMenu;
|
||
}
|
||
|
||
if(hPopupMenu!=NULL)
|
||
{
|
||
ExcludeSubmenuFromRecentlyUsed(hPopupMenu);
|
||
}
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
COXBitmapMenuOrganizer* COXBitmapMenuOrganizer::FindOrganizer(HWND hWnd)
|
||
{
|
||
COXBitmapMenuOrganizer* pOrganizer=NULL;
|
||
if(!m_allMenuOrganizers.Lookup(hWnd,pOrganizer))
|
||
{
|
||
return NULL;
|
||
}
|
||
else
|
||
{
|
||
return pOrganizer;
|
||
}
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::IsTopLevelPopupMenu(HMENU hPopupMenu)
|
||
{
|
||
ASSERT(hPopupMenu!=NULL);
|
||
ASSERT(::IsMenu(hPopupMenu));
|
||
ASSERT(IsAttached());
|
||
|
||
CMenu* pMenu=m_pFrameWnd->GetMenu();
|
||
if(pMenu==NULL)
|
||
return FALSE;
|
||
|
||
BOOL bFound=FALSE;
|
||
for(int nIndex=0; nIndex<(int)pMenu->GetMenuItemCount(); nIndex++)
|
||
{
|
||
CMenu* pTopLevelPopupMenu=pMenu->GetSubMenu(nIndex);
|
||
if(pTopLevelPopupMenu!=NULL &&
|
||
pTopLevelPopupMenu->GetSafeHmenu()==hPopupMenu)
|
||
{
|
||
bFound=TRUE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return bFound;
|
||
}
|
||
|
||
|
||
HMENU COXBitmapMenuOrganizer::CopyPopupMenu(HMENU hMenuDest)
|
||
{
|
||
HMENU hMenu=::CreatePopupMenu();
|
||
ASSERT(hMenu!=NULL);
|
||
m_arrCreatedPopupMenus.Add(hMenu);
|
||
if(!IsSubmenuRecentlyUsed(hMenuDest))
|
||
{
|
||
AddSubmenuToRecentlyUsed(hMenuDest);
|
||
ExcludeSubmenuFromRecentlyUsed(hMenu);
|
||
}
|
||
|
||
MENUITEMINFO miInfo;
|
||
CString sText;
|
||
|
||
for(int nIndex=0; nIndex<::GetMenuItemCount(hMenuDest); nIndex++)
|
||
{
|
||
// Even cascade menu item should be made owner drawn
|
||
// so that the text of these items is align properly
|
||
|
||
::ZeroMemory(&miInfo,sizeof(miInfo));
|
||
miInfo.cbSize=sizeof(miInfo);
|
||
miInfo.fMask=MIIM_TYPE|MIIM_ID|MIIM_STATE|MIIM_DATA|
|
||
MIIM_SUBMENU|MIIM_CHECKMARKS;
|
||
miInfo.fType=MFT_STRING;
|
||
miInfo.cch=300;
|
||
miInfo.dwTypeData=sText.GetBuffer(miInfo.cch);
|
||
// Gets the item info
|
||
miInfo.dwTypeData[0]=_T('\0');
|
||
::GetMenuItemInfo(hMenuDest,nIndex,TRUE,&miInfo);
|
||
if(miInfo.hSubMenu!=NULL)
|
||
{
|
||
miInfo.hSubMenu=CopyPopupMenu(miInfo.hSubMenu);
|
||
}
|
||
VERIFY(::InsertMenuItem(hMenu,nIndex,TRUE,&miInfo));
|
||
sText.ReleaseBuffer();
|
||
}
|
||
|
||
return hMenu;
|
||
}
|
||
|
||
|
||
BOOL COXBitmapMenuOrganizer::FindPopupMenuPath(HMENU hPopupMenu,
|
||
HMENU hParentMenu,
|
||
CArray<int,int>& arrPath)
|
||
{
|
||
ASSERT(hPopupMenu!=NULL);
|
||
ASSERT(::IsMenu(hPopupMenu));
|
||
ASSERT(hParentMenu!=NULL);
|
||
ASSERT(::IsMenu(hParentMenu));
|
||
|
||
int nItemCount=::GetMenuItemCount(hParentMenu);
|
||
for(int nIndex=0; nIndex<nItemCount; nIndex++)
|
||
{
|
||
HMENU hSubmenu=::GetSubMenu(hParentMenu,nIndex);
|
||
if(hSubmenu==hPopupMenu ||
|
||
(hSubmenu!=NULL && FindPopupMenuPath(hPopupMenu,hSubmenu,arrPath)))
|
||
{
|
||
arrPath.InsertAt(0,nIndex);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
LRESULT CALLBACK COXBitmapMenuOrganizer::
|
||
MenuMouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
#if defined (_WINDLL)
|
||
#if defined (_AFXDLL)
|
||
AFX_MANAGE_STATE(AfxGetAppModuleState());
|
||
#else
|
||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||
#endif
|
||
#endif
|
||
|
||
TRACE(_T("COXBitmapMenuOrganizer::MenuMouseHookProc code: %0X, wParam: %0X, lParam: %0X \n"));
|
||
|
||
ASSERT(g_pfnOldMouseHookProc!=NULL);
|
||
|
||
if(nCode<0)
|
||
{
|
||
// have to call the default implementation
|
||
return ::CallNextHookEx(g_pfnOldMouseHookProc,nCode,wParam,lParam);
|
||
}
|
||
|
||
if(wParam!=WM_LBUTTONDOWN && wParam!=WM_RBUTTONDOWN &&
|
||
wParam!=WM_LBUTTONUP && wParam!=WM_RBUTTONUP &&
|
||
wParam!=WM_LBUTTONDBLCLK && wParam!=WM_RBUTTONDBLCLK)
|
||
{
|
||
// have to call the default implementation
|
||
return ::CallNextHookEx(g_pfnOldMouseHookProc,nCode,wParam,lParam);
|
||
}
|
||
|
||
COXBitmapMenuOrganizer* pBMOrganizer=
|
||
COXBitmapMenuOrganizer::FindOrganizer(AfxGetMainWnd()->GetSafeHwnd());
|
||
ASSERT(pBMOrganizer!=NULL);
|
||
ASSERT(pBMOrganizer->IsShowOnlyRecentlyUsedItems());
|
||
|
||
DWORD dwMessagePos=::GetMessagePos();
|
||
POINTS points=MAKEPOINTS(dwMessagePos);
|
||
CPoint ptLast(points.x,points.y);
|
||
CWnd* pWnd=CWnd::WindowFromPoint(ptLast);
|
||
ASSERT(pWnd!=NULL);
|
||
// find if pWnd is on of the windows that host popup menus
|
||
POSITION pos=pBMOrganizer->m_mapPopupMenuWindows.GetStartPosition();
|
||
while(pos!=NULL)
|
||
{
|
||
HMENU hMenu=NULL;
|
||
HWND hWnd=NULL;
|
||
pBMOrganizer->m_mapPopupMenuWindows.GetNextAssoc(pos,hMenu,hWnd);
|
||
ASSERT(hMenu!=NULL);
|
||
ASSERT(hWnd!=NULL);
|
||
if(pWnd->GetSafeHwnd()==hWnd)
|
||
{
|
||
ASSERT(::IsMenu(hMenu));
|
||
// find the menu in the trace array
|
||
BOOL bFound=FALSE;
|
||
int nIndex=0;
|
||
for(nIndex=0;
|
||
nIndex<pBMOrganizer->m_arrPopupMenusTrace.GetSize(); nIndex++)
|
||
{
|
||
if(pBMOrganizer->m_arrPopupMenusTrace[nIndex].m_hPopupMenu==hMenu)
|
||
{
|
||
bFound=TRUE;
|
||
break;
|
||
}
|
||
}
|
||
ASSERT(bFound);
|
||
if(pBMOrganizer->m_nActivePopupMenuCount>nIndex+1)
|
||
{
|
||
BOOL bFoundPopupMenuToClose=FALSE;
|
||
for(int nIndexPopupWnd=nIndex+1;
|
||
nIndexPopupWnd<pBMOrganizer->m_arrPopupMenusTrace.GetSize();
|
||
nIndexPopupWnd++)
|
||
{
|
||
// try to find and close the remaining popup menus
|
||
HWND hWnd=NULL;
|
||
if(pBMOrganizer->m_mapPopupMenuWindows.Lookup(pBMOrganizer->
|
||
m_arrPopupMenusTrace[nIndexPopupWnd].m_hPopupMenu,hWnd))
|
||
{
|
||
if(::IsWindow(hWnd))
|
||
{
|
||
::SendMessage(hWnd,WM_KEYDOWN,VK_ESCAPE,0x00010001);
|
||
}
|
||
bFoundPopupMenuToClose=TRUE;
|
||
}
|
||
}
|
||
if(bFoundPopupMenuToClose)
|
||
{
|
||
pBMOrganizer->m_nActivePopupMenuCount=nIndex+1;
|
||
}
|
||
}
|
||
|
||
// check if "Show All items" menu item has been clicked
|
||
int nMenuItemIndex=::MenuItemFromPoint(hWnd,hMenu,ptLast);
|
||
if(nMenuItemIndex!=-1)
|
||
{
|
||
int nCmdID=::GetMenuItemID(hMenu,nMenuItemIndex);
|
||
switch(nCmdID)
|
||
{
|
||
case ID_OX_SHOWALLITEMS:
|
||
{
|
||
if(wParam!=WM_LBUTTONDOWN && wParam!=WM_RBUTTONDOWN)
|
||
{
|
||
pBMOrganizer->m_pFrameWnd->PostMessage(WM_COMMAND,
|
||
MAKEWPARAM(ID_OX_SHOWALLITEMS,0));
|
||
}
|
||
// modicication Manfred Drasch - return removed
|
||
// return 1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return ::CallNextHookEx(g_pfnOldMouseHookProc,nCode,wParam,lParam);
|
||
}
|
||
|
||
|
||
LRESULT CALLBACK COXBitmapMenuOrganizer::
|
||
MenuKeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
#if defined (_WINDLL)
|
||
#if defined (_AFXDLL)
|
||
AFX_MANAGE_STATE(AfxGetAppModuleState());
|
||
#else
|
||
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
||
#endif
|
||
#endif
|
||
ASSERT(g_pfnOldKeyboardHookProc!=NULL);
|
||
|
||
// v9.3 update 01 modification - removed by Manfred Drasch
|
||
// avoid crash with return over arrow menu item
|
||
|
||
// if(nCode<0)
|
||
// {
|
||
// // have to call the default implementation
|
||
// return ::CallNextHookEx(g_pfnOldKeyboardHookProc,nCode,wParam,lParam);
|
||
// }
|
||
//
|
||
// if(wParam!=VK_RETURN)
|
||
// {
|
||
// // have to call the default implementation
|
||
// return ::CallNextHookEx(g_pfnOldKeyboardHookProc,nCode,wParam,lParam);
|
||
// }
|
||
//
|
||
// COXBitmapMenuOrganizer* pBMOrganizer=
|
||
// COXBitmapMenuOrganizer::FindOrganizer(AfxGetMainWnd()->GetSafeHwnd());
|
||
// ASSERT(pBMOrganizer!=NULL);
|
||
// ASSERT(pBMOrganizer->IsShowOnlyRecentlyUsedItems());
|
||
//
|
||
// CWnd* pWnd=CWnd::GetDesktopWindow()->GetTopWindow();
|
||
// ASSERT(pWnd!=NULL);
|
||
// // find if pWnd is on of the windows that host popup menus
|
||
// POSITION pos=pBMOrganizer->m_mapPopupMenuWindows.GetStartPosition();
|
||
// while(pos!=NULL)
|
||
// {
|
||
// HMENU hMenu=NULL;
|
||
// HWND hWnd=NULL;
|
||
// pBMOrganizer->m_mapPopupMenuWindows.GetNextAssoc(pos,hMenu,hWnd);
|
||
// ASSERT(hMenu!=NULL);
|
||
// ASSERT(hWnd!=NULL);
|
||
// if(pWnd->GetSafeHwnd()==hWnd)
|
||
// {
|
||
// MENUITEMINFO miInfo={ sizeof(MENUITEMINFO) };
|
||
// miInfo.fMask=MIIM_ID|MIIM_STATE;
|
||
// VERIFY(::GetMenuItemInfo(hMenu,::GetMenuItemCount(hMenu)-1,TRUE,&miInfo));
|
||
// if(miInfo.wID==ID_OX_SHOWALLITEMS && (miInfo.fState&MFS_HILITE))
|
||
// {
|
||
// if((lParam&0xe0000000)==0)
|
||
// {
|
||
// pBMOrganizer->m_pFrameWnd->PostMessage(WM_COMMAND,
|
||
// MAKEWPARAM(ID_OX_SHOWALLITEMS,0));
|
||
// }
|
||
//
|
||
// return 1;
|
||
// }
|
||
// }
|
||
// }
|
||
//
|
||
// end modification Manfred Drasch
|
||
|
||
return ::CallNextHookEx(g_pfnOldKeyboardHookProc,nCode,wParam,lParam);
|
||
}
|
||
|
||
|