////////////////////////////////////////////////////////////////
// CoolMenu 1997 Microsoft Systems Journal.
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
//
// ==========================================================================
// HISTORY:
// ==========================================================================
// 1.01 13 Aug 1998 - Andrew Bancroft [ABancroft@lgc.com] - Since we've already
// added the entire toolbar to the imagelist we need to
// increment nNextImage even if we didn't add this button to
// m_mapIDtoImage in the LoadToolbar() method.
// 1.01a 13 Aug 1998 - Peter Tewkesbury - Added AddSingleBitmap(...)
// method for adding a single bitmap to a pulldown
// menu item.
// 1.02 13 Aug 1998 - Omar L Francisco - Fixed bug with lpds->CtlType
// and lpds->itemData item checking.
// 1.03 12 Nov 1998 - Fixes debug assert in system menu. - Wang Jun
// 1.04 17 Nov 1998 - Fixes debug assert when you maximize a view - Wang Jun
// window, then try to use the system menu for the view.
// 1.05 09 Jan 1998 - Seain B. Conover [sc@tarasoft.com] - Fix for virtual
// key names.
// 1.06 24 Feb 1999 - Michael Lange [michael.home@topdogg.com] - Fix for memory
// leak in CMyItemData structure, added a destructor that
// calls text.Empty().
// - Boris Kartamishev [kbv@omegasoftware.com] - Fix for resource
// ID bug.
// - Jeremy Horgan [jeremyhorgan@hotmail.com] - During
// accelerator key processing OnInitMenuPopup() calls
// ConvertMenu() which allocates a new CMyItemData for each
// menu item. This is memory is normally freed by a call to
// OnMenuSelect(), which is not called when processing
// accelerator keys. This results in a memory leak. This was
// fixed by modifying the ~CCoolMenuManager() destructor.
// 1.07 24 Feb 1999 - Koji MATSUNAMI [kmatsu@inse.co.jp] - Fixed problem with
// popup menus being drawn correctly as cool menus.
// ==========================================================================
//
/////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "CoolMenu.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// helpers
void PLFillRect(CDC& dc, const CRect& rc, COLORREF color);
void PLDrawEmbossed(CDC& dc, CImageList& il, int i,
CPoint p, BOOL bColor=FALSE);
HBITMAP PLLoadSysColorBitmap(LPCTSTR lpResName, BOOL bMono=FALSE);
inline HBITMAP PLLoadSysColorBitmap(UINT nResID, BOOL bMono=FALSE) {
return PLLoadSysColorBitmap(MAKEINTRESOURCE(nResID), bMono);
}
// if you want to see extra TRACE diagnostics, set below to TRUE
BOOL CCoolMenuManager::bTRACE = FALSE;
#define safe_delete(p){if(p){delete p;p=NULL;}}
#ifdef _DEBUG
#define CMTRACEFN \
CTraceFn __fooble; \
if (bTRACE) \
TRACE
#define CMTRACE \
if (bTRACE) \
TRACE
#else
#define CMTRACEFN TRACE
#define CMTRACE TRACE
#endif
// constants used for drawing
const CXGAP = 1; // num pixels between button and text
const CXTEXTMARGIN = 1;//2; // num pixels after hilite to start text
const CXBUTTONMARGIN = 2;//2; // num pixels wider button is than bitmap
const CYBUTTONMARGIN = 2;//2; // ditto for height
// DrawText flags
const DT_MYSTANDARD = DT_SINGLELINE|DT_LEFT|DT_VCENTER;
// identifies owner-draw data as mine
const LONG MYITEMID = MAKELONG(MAKEWORD(_T('m'),_T('i')),MAKEWORD(_T('d'),_T('0')));
// private struct: one of these for each owner-draw menu item
struct CMyItemData {
long magicNum; // magic number identifying me
CString text; // item text
UINT fType; // original item type flags
int iButton; // index of button image in image list
CMyItemData() { magicNum = MYITEMID; }
~CMyItemData() { text.Empty(); }
BOOL IsMyItemData() { return magicNum == MYITEMID; }
};
IMPLEMENT_DYNAMIC(CCoolMenuManager, CSubclassWnd)
CCoolMenuManager::CCoolMenuManager()
{
m_szBitmap = m_szButton = CSize(0,0); // will compute later
m_bShowButtons = TRUE; // show buttons by default
m_bAutoAccel = TRUE; // auto accelerators by default
m_hAccel = NULL; // no accelerators loaded yet
m_pAccel = NULL; // no accelerators loaded yet
m_bUseDrawState = FALSE; // use DrawEmbossed by default
m_bDrawDisabledButtonsInColor = FALSE; // use color for disabled buttons
FixMFCDotBitmap();
}
CCoolMenuManager::~CCoolMenuManager()
{
// Jeremy Horgan [jeremyhorgan@hotmail.com]
while (!m_menuList.IsEmpty())
{
ConvertMenu(CMenu::FromHandle((HMENU)m_menuList.RemoveHead()),0,
FALSE, FALSE);
}
Destroy();
}
//////////////////
// Destroy everything. Called from destructor and Refresh.
//
void CCoolMenuManager::Destroy()
{
m_ilButtons.DeleteImageList();
m_mapIDtoImage.RemoveAll();
m_szBitmap = m_szButton = CSize(0,0);
m_arToolbarID.RemoveAll();
m_fontMenu.DeleteObject();
DestroyAccel();
}
/////////////////
// Destroy accelerators
//
void CCoolMenuManager::DestroyAccel()
{
m_mapIDtoAccel.RemoveAll(); // delete ACCEL entries in map
safe_delete(m_pAccel); // delete current accelerators
}
//////////////////
// Call this to install the menu manager. Install(NULL) to un-install.
//
void CCoolMenuManager::Install(CFrameWnd* pFrame)
{
ASSERT_VALID(pFrame);
m_pFrame = pFrame;
HookWindow(pFrame); // install message hook
}
//////////////////
// Load array of toolbar IDs.
//
BOOL CCoolMenuManager::LoadToolbars(const UINT* arID, int n)
{
ASSERT(arID);
BOOL bRet = TRUE;
for (int i=0; i<n; i++)
bRet |= LoadToolbar(arID[i]);
return bRet;
}
// structure of RT_TOOLBAR resource
struct TOOLBARDATA {
WORD wVersion; // version # should be 1
WORD wWidth; // width of one bitmap
WORD wHeight; // height of one bitmap
WORD wItemCount; // number of items
WORD items[1]; // array of command IDs, actual size is wItemCount
};
//////////////////
// Load one toolbar. Assumes bg color is gray.
//
// * add toolbar bitmap to image list
// * add each button ID to button map
//
BOOL CCoolMenuManager::LoadToolbar(UINT nIDToolbar)
{
// load bitmap
HBITMAP hbmToolbar = PLLoadSysColorBitmap(nIDToolbar);
if (!hbmToolbar) {
TRACE(_T("*** Can't load bitmap for toolbar %d!\n"), nIDToolbar);
return FALSE;
}
CBitmap bmToolbar;
bmToolbar.Attach(hbmToolbar); // destructor will detach & destroy
// load toolbar
LPTSTR lpResName = MAKEINTRESOURCE(nIDToolbar);
HINSTANCE hInst;
HRSRC hRsrc;
TOOLBARDATA* ptbd;
if ((hInst= AfxFindResourceHandle(lpResName, RT_TOOLBAR)) == NULL ||
(hRsrc= FindResource(hInst, lpResName, RT_TOOLBAR)) == NULL ||
(ptbd = (TOOLBARDATA*)LoadResource(hInst, hRsrc)) == NULL) {
TRACE(_T("*** Can't load toolbar %d!\n"), nIDToolbar);
return FALSE;
}
ASSERT(ptbd->wVersion==1);
// OK, I have the bitmap and toolbar.
CSize sz(ptbd->wWidth, ptbd->wHeight);
if (m_szBitmap.cx==0) {
// First toolbar: initialized bitmap/button sizes and create image list.
m_szBitmap = sz;
m_szButton = sz + CSize(CXBUTTONMARGIN<<1, CYBUTTONMARGIN<<1);
VERIFY(m_ilButtons.Create(sz.cx, sz.cy, ILC_MASK, 0, 10));
} else if (m_szBitmap != sz) {
// button sizes different -- oops
TRACE(_T("*** Toolbar %d button size differs!\n"), nIDToolbar);
return FALSE;
}
// I have a good toolbar: now add bitmap to the image list, and each
// command ID to m_mapIDtoImage array. Note that LoadSysColorBitmap will
// change gray -> COLOR_3DFACE, so use that for image list background.
//
int iNextImage = m_ilButtons.GetImageCount();
m_ilButtons.Add(&bmToolbar, GetSysColor(COLOR_3DFACE));
for (int i = 0; i < ptbd->wItemCount; i++) {
UINT nID = p
评论7
最新资源