Files
FC1/Editor/Controls/NewMenu.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

6186 lines
158 KiB
C++

//------------------------------------------------------------------------------
// File : NewMenu.cpp
// Version : 1.10
// Date : 30. July 2002
// Author : Bruno Podetti
// Email : Podetti@gmx.net
// Systems : VC6.0 and VC7.0 (Run under (Window 98/ME), Windows Nt 2000/XP)
//
// Special
// Compiled version with visual studio V7.0 doesn't run correctly on WinNt 4.0
// nor Windows 95. For those platforms, you have to compile it with
// visual studio V6.0
//
// ToDo's
// checking GDI-Leaks, are there some more?
// Shade-Drawing, when underground is changing
// XP-changing settings Border Style => to fix border painting without restarting
// Border repainting after menu closing!!!
//
// (30. July 2002) Bug Fixes or nice hints from 1.03
// Color of checked icons / selection marks more XP-look
// Updating images 16 color by changing systems colors
// Icon drawing with more highlighting and half transparency
// Scroller for large menu correcting (but the overlapping border is not corrected)
// Resource-problem on windows 95/98/ME?, when using too much bitmaps in menus
// changing the kind of storing bitmaps (images list)
// Calculating the size for a menuitem (specially submenuitem) corrected.
// Recentfilelist corrected (Seperator gots a wrong ID number)
//
// (25. June 2002) Bug Fixes or nice hints from 1.02
// Adding removing menu corrected for drawing the shade in menubar
// Draw the menuborder corrected under win 98 at the bottom side
// Highlighting under 98 for menu corrected (Assert), Neville Franks
// Works also on Windows 95
// Changing styles on XP menucolor of the bar now corrected.
//
// (18. June 2002) Bug Fixes or nice hints from 1.01
// Popup menu which has more items than will fit, better
// LoadMenu changed for better languagessuport, SnowCat
// Bordercolor & Drawing of XP-Style-Menu changed to more XP-Look
// Added some functions for setting/reading MenuItemData and MenuData
// Menubar highlighting now supported under 98/ME (NT 4.0 and 95?)
// Font for menutitle can be changed
// Bugs for popupmenu by adding submenu corrected, no autodestroy
//
// (6. June 2002) Bug Fixes or nice hints from 1.00
// Loading Icons from a resource dll expanded (LoadToolBar) Jonathan de Halleux, Belgium.
// Minimized resource leak of User and Gdi objects
// Problem of disabled windows button on 98/Me solved
// Gradient-drawing without Msimg32.dll now supported especially for win 95
// Using solid colors for drawing menu items
// GetSubMenu changed to const
// Added helper function for setting popup-flag for popup menu (centered text)
// Redraw menu bar corrected after canceling popup menu in old style menu
//
// (23. Mai 2002) Bug Fixes and portions of code from previous version supplied by:
// Brent Corkum, Ben Ashley, Girish Bharadwaj, Jean-Edouard Lachand-Robert,
// Robert Edward Caldecott, Kenny Goers, Leonardo Zide, Stefan Kuhr,
// Reiner Jung, Martin Vladic, Kim Yoo Chul, Oz Solomonovich, Tongzhe Cui,
// Stephane Clog, Warren Stevens, Damir Valiulin
//
// You are free to use/modify this code but leave this header intact.
// This class is public domain so you are free to use it any of your
// applications (Freeware, Shareware, Commercial).
// All I ask is that you let me know so that if you have a real winner I can
// brag to my buddies that some of my code is in your app. I also wouldn't
// mind if you sent me a copy of your application since I like to play with
// new stuff.
//------------------------------------------------------------------------------
#include "stdafx.h" // Standard windows header file
#include "NewMenu.h" // CNewMenu class declaration
//#define _TRACE_MENU_
#ifdef _TRACE_MENU_
#include "MyTrace.h"
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
#ifndef IS_INTRESOURCE
#define IS_INTRESOURCE(hh) (HIWORD(hh)==NULL)
#endif
#define GAP 2
#ifndef COLOR_MENUBAR
#define COLOR_MENUBAR 30
#endif
#ifndef SPI_GETDROPSHADOW
#define SPI_GETDROPSHADOW 0x1024
#endif
#ifndef SPI_GETFLATMENU
#define SPI_GETFLATMENU 0x1022
#endif
// Count of menu icons normal gloomed and grayed
#define MENU_ICONS 3
#ifdef TRACE
#undef TRACE
#endif
//Timur[8/27/2002]
#define TRACE(x,y,z)
/////////////////////////////////////////////////////////////////////////////
// Helper datatypes
class CToolBarData
{
public:
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
//WORD aItems[wItemCount]
WORD* items()
{ return (WORD*)(this+1); }
};
class CNewMenuIconInfo
{
public:
WORD wBitmapID;
WORD wWidth;
WORD wHeight;
WORD* ids(){ return (WORD*)(this+1); }
};
// Helpers for casting
__inline HMENU UIntToHMenu(const unsigned int ui )
{
return( (HMENU)(UINT_PTR)ui );
}
__inline HMENU HWndToHMenu(const HWND hWnd )
{
return( (HMENU)hWnd );
}
__inline HWND HMenuToHWnd(const HMENU hMenu)
{
return( (HWND)hMenu );
}
__inline UINT HWndToUInt(const HWND hWnd )
{
return( (UINT)(UINT_PTR) hWnd);
}
__inline HWND UIntToHWnd(const UINT hWnd )
{
return( (HWND)(UINT_PTR) hWnd);
}
__inline UINT HMenuToUInt(const HMENU hMenu )
{
return( (UINT)(UINT_PTR) hMenu);
}
static void ShowLastError()
{
DWORD error = GetLastError();
if(error)
{
LPVOID lpMsgBuf=NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
if(lpMsgBuf)
{
// Display the string.
MessageBox( NULL, (LPCTSTR)lpMsgBuf, _T("Error"), MB_OK | MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
}
else
{
CString temp;
temp.Format(_T("Error message 0x%lx not found"),error);
// Display the string.
MessageBox( NULL,temp, _T("Error"), MB_OK | MB_ICONINFORMATION );
}
}
}
UINT GetSafeTimerID(HWND hWnd, const UINT uiElapse)
{
UINT nNewTimerId = NULL;
if(IsWindow(hWnd))
{ // Try to start with TimerID 31, normaly is used 1, 10, or 100
for(UINT nTimerId=31; nTimerId<100 && nNewTimerId==NULL; nTimerId++)
{ // Try to set a timer each uiElapse ms
nNewTimerId = (UINT)::SetTimer(hWnd,nTimerId,uiElapse,NULL);
}
// Wow you have more than 69 timers!!!
// Try to increase nTimerId<100 to nTimerId<1000;
ASSERT(nNewTimerId);
}
return nNewTimerId;
}
WORD NumBitmapColors(LPBITMAPINFOHEADER lpBitmap)
{
if ( lpBitmap->biClrUsed != 0)
return (WORD)lpBitmap->biClrUsed;
switch (lpBitmap->biBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
}
return 0;
}
HBITMAP LoadColorBitmap(LPCTSTR lpszResourceName, HMODULE hInst, int* pNumcol)
{
if(hInst==0)
{
hInst = AfxFindResourceHandle(lpszResourceName, RT_BITMAP);
}
HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(lpszResourceName),RT_BITMAP);
if (hRsrc == NULL)
return NULL;
// determine how many colors in the bitmap
HGLOBAL hglb;
if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
return NULL;
LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
if (lpBitmap == NULL)
return NULL;
WORD numcol = NumBitmapColors(lpBitmap);
if(pNumcol)
{
*pNumcol = numcol;
}
UnlockResource(hglb);
FreeResource(hglb);
if(numcol!=16)
{
return LoadBitmap(hInst,lpszResourceName);
// (HBITMAP)LoadImage(hInst,lpszResourceName,IMAGE_BITMAP,0,0,LR_DEFAULTCOLOR|LR_CREATEDIBSECTION|LR_SHARED);
}
else
{
// mapping from color in DIB to system color
// { RGB_TO_RGBQUAD(0x00, 0x00, 0x00), COLOR_BTNTEXT }, // black
// { RGB_TO_RGBQUAD(0x80, 0x80, 0x80), COLOR_BTNSHADOW }, // dark gray
// { RGB_TO_RGBQUAD(0xC0, 0xC0, 0xC0), COLOR_BTNFACE }, // bright gray
// { RGB_TO_RGBQUAD(0xFF, 0xFF, 0xFF), COLOR_BTNHIGHLIGHT } // white
return (HBITMAP)AfxLoadSysColorBitmap(hInst,hRsrc,FALSE);
}
}
BOOL DrawMenubarItem(CWnd* pWnd,CMenu* pMenu, UINT nItemIndex,UINT nState)
{
CRect itemRect;
if (nItemIndex!=UINT(-1) && GetMenuItemRect(pWnd->m_hWnd,pMenu->m_hMenu, nItemIndex, &itemRect))
{
MENUITEMINFO menuInfo;
ZeroMemory(&menuInfo,sizeof(menuInfo));
menuInfo.cbSize = sizeof(menuInfo);
menuInfo.fMask = MIIM_DATA|MIIM_TYPE|MIIM_ID;
if(pMenu->GetMenuItemInfo(nItemIndex,&menuInfo,TRUE))
{
// Only ownerdrawn were allowed
if(menuInfo.fType&MF_OWNERDRAW)
{
CWindowDC dc(pWnd);
CFont m_fontMenu;
NONCLIENTMETRICS nm;
ZeroMemory(&nm,sizeof(nm));
nm.cbSize = sizeof (NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm,0));
m_fontMenu.CreateFontIndirect (&nm.lfMenuFont);
CFont* pOldFont = dc.SelectObject(&m_fontMenu);
CRect wndRect;
GetWindowRect(*pWnd,wndRect);
itemRect.OffsetRect(-wndRect.TopLeft());
DRAWITEMSTRUCT drwItem;
ZeroMemory(&drwItem,sizeof(drwItem));
drwItem.CtlType = ODT_MENU;
drwItem.hwndItem = HMenuToHWnd(pMenu->m_hMenu);
drwItem.itemID = menuInfo.wID;
drwItem.itemData = menuInfo.dwItemData;
drwItem.rcItem = itemRect;
drwItem.hDC = dc.m_hDC;
drwItem.itemState = nState;
drwItem.itemAction = ODA_DRAWENTIRE;
ASSERT(menuInfo.dwItemData);
CNewMenu::m_dwLastActiveItem = (DWORD)menuInfo.dwItemData;
SendMessage(pWnd->GetSafeHwnd(),WM_DRAWITEM,NULL,(LPARAM)&drwItem);
dc.SelectObject(pOldFont);
return TRUE;
}
}
}
return FALSE;
}
Win32Type IsShellType()
{
OSVERSIONINFO osvi;
ZeroMemory(&osvi,sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
DWORD winVer=GetVersion();
if(winVer<0x80000000)
{/*NT */
if(!GetVersionEx(&osvi))
{
ShowLastError();
}
if(osvi.dwMajorVersion==4L)
{
return WinNT4;
}
else if(osvi.dwMajorVersion==5L && osvi.dwMinorVersion==0L)
{
return Win2000;
}
else if(osvi.dwMajorVersion==5L && osvi.dwMinorVersion==1L)
{
return WinXP;
}
return WinNT3;
}
else if (LOBYTE(LOWORD(winVer))<4)
{
return Win32s;
}
if(!GetVersionEx(&osvi))
{
ShowLastError();
}
if(osvi.dwMajorVersion==4L && osvi.dwMinorVersion==10L)
{
return Win98;
}
else if(osvi.dwMajorVersion==4L && osvi.dwMinorVersion==90L)
{
return WinME;
}
return Win95;
}
BOOL IsShadowEnabled()
{
BOOL bEnabled=FALSE;
if(SystemParametersInfo(SPI_GETDROPSHADOW,0,&bEnabled,0))
{
return bEnabled;
}
return FALSE;
}
COLORREF DarkenColorXP(COLORREF ColA)
{
return RGB( MulDiv(GetRValue(ColA),7,10),
MulDiv(GetGValue(ColA),7,10),
MulDiv(GetBValue(ColA)+55,7,10));
}
// Function splits a color into its RGB components and
// transforms the color using a scale 0..255
COLORREF DarkenColor( long lScale, COLORREF lColor)
{
long R = MulDiv(GetRValue(lColor),(255-lScale),255);
long G = MulDiv(GetGValue(lColor),(255-lScale),255);
long B = MulDiv(GetBValue(lColor),(255-lScale),255);
return RGB(R, G, B);
}
COLORREF MixedColor(COLORREF ColA,COLORREF ColB)
{
// ( 86a + 14b ) / 100
int Red = MulDiv(86,GetRValue(ColA),100) + MulDiv(14,GetRValue(ColB),100);
int Green = MulDiv(86,GetGValue(ColA),100) + MulDiv(14,GetGValue(ColB),100);
int Blue = MulDiv(86,GetBValue(ColA),100) + MulDiv(14,GetBValue(ColB),100);
return RGB( Red,Green,Blue);
}
COLORREF MidColor(COLORREF ColA,COLORREF ColB)
{
// (7a + 3b)/10
int Red = MulDiv(7,GetRValue(ColA),10) + MulDiv(3,GetRValue(ColB),10);
int Green = MulDiv(7,GetGValue(ColA),10) + MulDiv(3,GetGValue(ColB),10);
int Blue = MulDiv(7,GetBValue(ColA),10) + MulDiv(3,GetBValue(ColB),10);
return RGB( Red,Green,Blue);
}
COLORREF GrayColor(COLORREF crColor)
{
int Gray = (((int)GetRValue(crColor)) + GetGValue(crColor) + GetBValue(crColor))/3;
return RGB( Gray,Gray,Gray);
}
// Function splits a color into its RGB components and
// transforms the color using a scale 0..255
COLORREF LightenColor( long lScale, COLORREF lColor)
{
long R = MulDiv(255-GetRValue(lColor),lScale,255)+GetRValue(lColor);
long G = MulDiv(255-GetGValue(lColor),lScale,255)+GetGValue(lColor);
long B = MulDiv(255-GetBValue(lColor),lScale,255)+GetBValue(lColor);
return RGB(R, G, B);
}
typedef BOOL (WINAPI* FktGradientFill)( IN HDC, IN PTRIVERTEX, IN ULONG, IN PVOID, IN ULONG, IN ULONG);
FktGradientFill pGradientFill = NULL;
void DrawGradient(CDC* pDC,CRect& Rect,
COLORREF StartColor,COLORREF EndColor,
BOOL bHorizontal)
{
// for running under win95 and WinNt 4.0 without loading Msimg32.dll
if(pGradientFill)
{
TRIVERTEX vert[2] ;
GRADIENT_RECT gRect;
vert [0].y = Rect.top;
vert [0].x = Rect.left;
vert [0].Red = COLOR16(COLOR16(GetRValue(StartColor))<<8);
vert [0].Green = COLOR16(COLOR16(GetGValue(StartColor))<<8);
vert [0].Blue = COLOR16(COLOR16(GetBValue(StartColor))<<8);
vert [0].Alpha = 0x0000;
vert [1].y = Rect.bottom;
vert [1].x = Rect.right;
vert [1].Red = COLOR16(COLOR16(GetRValue(EndColor))<<8);
vert [1].Green = COLOR16(COLOR16(GetGValue(EndColor))<<8);
vert [1].Blue = COLOR16(COLOR16(GetBValue(EndColor))<<8);
vert [1].Alpha = 0x0000;
gRect.UpperLeft = 0;
gRect.LowerRight = 1;
if(bHorizontal)
pGradientFill(pDC->m_hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_H);
else
pGradientFill(pDC->m_hDC,vert,2,&gRect,1,GRADIENT_FILL_RECT_V);
}
else
{
BYTE StartRed = GetRValue(StartColor);
BYTE StartGreen = GetGValue(StartColor);
BYTE StartBlue = GetBValue(StartColor);
BYTE EndRed = GetRValue(EndColor);
BYTE EndGreen = GetGValue(EndColor);
BYTE EndBlue = GetBValue(EndColor);
int n = (bHorizontal)?Rect.Width():Rect.Height();
// only need for the rest, can be optimized
{
// We need a brush (can be doted)
CBrush TempBrush(EndColor);
pDC->FillRect(Rect,&TempBrush);
}
n-=4;
for(int dn=0;dn<=n;dn+=4)
{
BYTE ActRed = (BYTE)(MulDiv(int(EndRed)-StartRed,dn,n)+StartRed);
BYTE ActGreen = (BYTE)(MulDiv(int(EndGreen)-StartGreen,dn,n)+StartGreen);
BYTE ActBlue = (BYTE)(MulDiv(int(EndBlue)-StartBlue,dn,n)+StartBlue);
CRect TempRect;
if(bHorizontal)
{
TempRect = CRect(CPoint(Rect.left+dn,Rect.top),CSize(4,Rect.Height()));
}
else
{
TempRect = CRect(CPoint(Rect.left,Rect.top+dn),CSize(Rect.Width(),4));
}
CBrush TempBrush(RGB(ActRed,ActGreen,ActBlue));
pDC->FillRect(TempRect,&TempBrush);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CMenuTheme for drawing border and the rest
typedef void (CNewMenu::*pItemMeasureFkt) (LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenubar);
typedef void (CNewMenu::*pItemDrawFkt) (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenubar);
typedef BOOL (CNewMenu::*pEraseBkgndFkt) (HWND hWnd, HDC hDC);
typedef void (CMenuTheme::*pDrawMenuBorder)( HWND hWnd, HDC hDC, CPoint screen);
class CMenuTheme
{
public:
CMenuTheme();
CMenuTheme(DWORD dwThemeId,
pItemMeasureFkt pMeasureItem,
pItemDrawFkt pDrawItem,
pItemDrawFkt pDrawTitle,
DWORD dwFlags=0);
virtual ~CMenuTheme();
virtual BOOL OnInitWnd(HWND hWnd);
virtual BOOL OnUnInitWnd(HWND hWnd);
virtual BOOL DoDrawBorder();
virtual BOOL OnDrawBorder(HWND hWnd, HDC hDC);
virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC);
virtual BOOL OnNcCalcSize(HWND hWnd, NCCALCSIZE_PARAMS* pCalc);
virtual BOOL OnWindowPosChanging(HWND hWnd, LPWINDOWPOS pPos);
virtual BOOL OnCalcFrameRect(HWND hWnd,LPRECT pRect);
void DrawShade( HWND hWnd, HDC hDC, CPoint screen);
void DrawSmalBorder( HWND hWnd, HDC hDC);
void DrawFrame(CDC* pDC, CRect rectOuter, CRect rectInner, COLORREF crBorder);
public:
DWORD m_dwThemeId;
DWORD m_dwFlags;
pItemMeasureFkt m_pMeasureItem;
pItemDrawFkt m_pDrawItem;
pItemDrawFkt m_pDrawTitle;
CSize m_BorderTopLeft;
CSize m_BorderBottomRight;
};
/////////////////////////////////////////////////////////////////////////////
// CMenuThemeXP for drawing border and the rest
class CMenuThemeXP :public CMenuTheme
{
public:
CMenuThemeXP(DWORD dwThemeId,
pItemMeasureFkt pMeasureItem,
pItemDrawFkt pDrawItem,
pItemDrawFkt pDrawTitle,
DWORD dwFlags=0);
virtual BOOL OnDrawBorder(HWND hWnd, HDC hDC);
virtual BOOL OnEraseBkgnd(HWND hWnd, HDC hDC);
};
/////////////////////////////////////////////////////////////////////////////
// CNewMenuHook important class for subclassing menus!
class CNewMenuHook
{
public:
class CMenuHookData
{
public:
CMenuHookData(HWND hWnd,BOOL bSpecialWnd)
: m_dwData(bSpecialWnd),m_bDrawBorder(TRUE),m_Point(0,0)
{
// Safe actual menu
m_hMenu = CNewMenuHook::m_hLastMenu;
// Reset for the next menu
CNewMenuHook::m_hLastMenu = NULL;
// Save actual border setting etc.
m_dwStyle = GetWindowLong(hWnd, GWL_STYLE) ;
m_dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
}
DWORD m_dwStyle;
DWORD m_dwExStyle;
CPoint m_Point;
DWORD m_dwData;
BOOL m_bDrawBorder;
HMENU m_hMenu;
};
public:
CNewMenuHook();
~CNewMenuHook();
public:
static CMenuHookData* GetMenuHookData(HWND hWnd);
static BOOL AddTheme(CMenuTheme*);
static CMenuTheme* RemoveTheme(DWORD dwThemeId);
static CMenuTheme* FindTheme(DWORD dwThemeId);
private:
static LRESULT CALLBACK NewMenuHook(int code, WPARAM wParam, LPARAM lParam);
static BOOL CheckSubclassing(HWND hWnd,BOOL bSpecialWnd);
static LRESULT CALLBACK SubClassMenu(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
static void UnsubClassMenu(HWND hWnd);
static BOOL SubClassMenu2(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, DWORD* pResult);
public:
static HMENU m_hLastMenu;
static DWORD m_dwMsgPos;
private:
static HMODULE m_hLibrary;
static HHOOK HookOldMenuCbtFilter;
// an map of actual opened Menu and submenu
static CTypedPtrMap<CMapPtrToPtr,HWND,CMenuHookData*> m_MenuHookData;
// Stores list of all defined Themes
static CTypedPtrList<CPtrList, CMenuTheme*>* m_pRegisteredThemesList;
};
/////////////////////////////////////////////////////////////////////////////
// CNewMenuIconLock Helperclass for reference-counting !
class CNewMenuIconLock
{
CNewMenuIcons* m_pIcons;
public:
CNewMenuIconLock(CNewMenuIcons* pIcons):m_pIcons(pIcons)
{
m_pIcons->AddRef();
}
~CNewMenuIconLock()
{
m_pIcons->Release();
}
operator CNewMenuIcons*(){return m_pIcons;}
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewMenuIcons,CObject);
CNewMenuIcons::CNewMenuIcons()
: m_lpszResourceName(NULL),
m_hInst(NULL),
m_nColors(0),
m_crTransparent(CLR_NONE),
m_dwRefCount(0)
{
}
CNewMenuIcons::~CNewMenuIcons()
{
if(m_lpszResourceName && !IS_INTRESOURCE(m_lpszResourceName))
{
delete (LPTSTR)m_lpszResourceName;
}
}
int CNewMenuIcons::AddRef()
{
if(this==NULL)
return NULL;
return ++m_dwRefCount;
}
int CNewMenuIcons::Release()
{
if(this==NULL)
return NULL;
DWORD dwCount = --m_dwRefCount;
if(m_dwRefCount==0)
{
if(CNewMenu::m_pSharedMenuIcons)
{
POSITION pos = CNewMenu::m_pSharedMenuIcons->Find(this);
if(pos)
{
CNewMenu::m_pSharedMenuIcons->RemoveAt(pos);
}
}
delete this;
}
return dwCount;
}
#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
void CNewMenuIcons::AssertValid() const
{
CObject::AssertValid();
}
void CNewMenuIcons::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << _T("NewMenuIcons: ") << _T("\n");
}
#endif
BOOL CNewMenuIcons::DoMatch(LPCTSTR lpszResourceName, HMODULE hInst)
{
if(hInst==m_hInst && lpszResourceName)
{
if(IS_INTRESOURCE(m_lpszResourceName))
return (lpszResourceName==m_lpszResourceName);
return (_tcscmp(lpszResourceName,m_lpszResourceName)==0);
}
return FALSE;
}
BOOL CNewMenuIcons::DoMatch(WORD* pIconInfo, COLORREF crTransparent)
{
if(m_crTransparent==crTransparent && pIconInfo!=NULL)
{
CNewMenuIconInfo* pInfo = (CNewMenuIconInfo*)pIconInfo;
// Check for the same resource ID
if( pInfo->wBitmapID && IS_INTRESOURCE(m_lpszResourceName) &&
((UINT)(UINT_PTR)m_lpszResourceName)==pInfo->wBitmapID)
{
int nCount = (int)m_IDs.GetSize();
WORD* pID = pInfo->ids();
for(int nIndex=0 ; nIndex<nCount ; nIndex++,pID++)
{
if( (*pID)==0 || m_IDs.GetAt(nIndex)!=(*pID) )
{
return FALSE;
}
}
return TRUE;
}
}
return FALSE;
}
int CNewMenuIcons::FindIndex(UINT nID)
{
int nIndex = (int)m_IDs.GetSize();
while(nIndex--)
{
if(m_IDs.GetAt(nIndex)==nID)
{
return nIndex*MENU_ICONS;
}
}
return -1;
}
BOOL CNewMenuIcons::GetIconSize(int* cx, int* cy)
{
return ::ImageList_GetIconSize(m_IconsList,cx,cy);
}
CSize CNewMenuIcons::GetIconSize()
{
int cx=0;
int cy=0;
if(::ImageList_GetIconSize(m_IconsList,&cx,&cy))
{
return CSize(cx,cy);
}
return CSize(0,0);
}
void CNewMenuIcons::OnSysColorChange()
{
if(m_lpszResourceName!=NULL)
{
int cx=16,cy=16;
if(GetIconSize(&cx, &cy) && LoadBitmap(cx,cy,m_lpszResourceName,m_hInst))
{
MakeImages();
}
}
}
BOOL CNewMenuIcons::LoadBitmap(int nWidth, int nHeight, LPCTSTR lpszResourceName, HMODULE hInst)
{
m_nColors = 0;
HBITMAP hBitmap = LoadColorBitmap(lpszResourceName,hInst,&m_nColors);
if(hBitmap!=NULL)
{
CBitmap bitmap;
bitmap.Attach(hBitmap);
if(m_IconsList.GetSafeHandle())
{
m_IconsList.DeleteImageList();
}
m_IconsList.Create(nWidth,nHeight,ILC_COLORDDB|ILC_MASK,0,10);
m_IconsList.Add(&bitmap,m_crTransparent);
return TRUE;
}
return FALSE;
}
BOOL CNewMenuIcons::LoadToolBar(WORD* pIconInfo, COLORREF crTransparent)
{
BOOL bResult = FALSE;
m_crTransparent = crTransparent;
CNewMenuIconInfo* pInfo = (CNewMenuIconInfo*)pIconInfo;
if (LoadBitmap(pInfo->wWidth,pInfo->wHeight,MAKEINTRESOURCE(pInfo->wBitmapID)))
{
SetResourceName(MAKEINTRESOURCE(pInfo->wBitmapID));
WORD* pID = pInfo->ids();
while(*pID)
{
UINT nID = *(pID++);
m_IDs.Add(nID);
bResult = TRUE;
}
MakeImages();
}
return bResult;
}
void CNewMenuIcons::SetResourceName(LPCTSTR lpszResourceName)
{
ASSERT_VALID(this);
ASSERT(lpszResourceName != NULL);
if(m_lpszResourceName && !IS_INTRESOURCE(m_lpszResourceName))
{
delete (LPTSTR)m_lpszResourceName;
}
if( lpszResourceName && !IS_INTRESOURCE(lpszResourceName))
{
m_lpszResourceName = new TCHAR[_tcslen(lpszResourceName)+1];
_tcscpy((LPTSTR)m_lpszResourceName,lpszResourceName);
}
else
{
m_lpszResourceName = lpszResourceName;
}
}
BOOL CNewMenuIcons::LoadToolBar(LPCTSTR lpszResourceName, HMODULE hInst)
{
ASSERT_VALID(this);
SetResourceName(lpszResourceName);
m_hInst = hInst;
// determine location of the bitmap in resource
if(hInst==0)
{
hInst = AfxFindResourceHandle(lpszResourceName, RT_TOOLBAR);
}
HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);
if (hRsrc == NULL)
{ // Special purpose when you try to load it from a dll 30.05.2002
if(AfxGetResourceHandle()!=hInst)
{
hInst = AfxGetResourceHandle();
hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);
}
if (hRsrc == NULL)
return FALSE;
}
HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
if (hGlobal == NULL)
return FALSE;
CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
if (pData == NULL)
return FALSE;
BOOL bResult = FALSE;
ASSERT(pData->wVersion == 1);
if(LoadBitmap(pData->wWidth,pData->wHeight,lpszResourceName,hInst))
{
// Remove all previous ID's
m_IDs.RemoveAll();
for (int i = 0; i < pData->wItemCount; i++)
{
UINT nID = pData->items()[i];
if (nID)
{
m_IDs.Add(nID);
bResult = TRUE;
}
}
}
UnlockResource(hGlobal);
FreeResource(hGlobal);
MakeImages();
return bResult;
}
int CNewMenuIcons::AddGloomIcon(HICON hIcon, int nIndex)
{
ICONINFO iconInfo;
ZeroMemory(&iconInfo,sizeof(iconInfo));
if(!GetIconInfo(hIcon,&iconInfo))
return -1;
CSize size = GetIconSize();
CDC myDC;
myDC.CreateCompatibleDC(0);
CBitmap bmColor;
bmColor.Attach(iconInfo.hbmColor);
CBitmap bmMask;
bmMask.Attach(iconInfo.hbmMask);
CBitmap* pOldBitmap = myDC.SelectObject(&bmColor);
COLORREF crPixel;
for(int i=0;i<size.cx;++i)
{
for(int j=0;j<size.cy;++j)
{
crPixel = myDC.GetPixel(i,j);
myDC.SetPixel(i,j,DarkenColor(50,crPixel));
}
}
myDC.SelectObject(pOldBitmap);
if(nIndex==-1)
return m_IconsList.Add(&bmColor,&bmMask);
return (m_IconsList.Replace(nIndex,&bmColor,&bmMask)) ? nIndex: -1;
}
int CNewMenuIcons::AddGrayIcon(HICON hIcon, int nIndex)
{
ICONINFO iconInfo;
ZeroMemory(&iconInfo,sizeof(iconInfo));
if(!GetIconInfo(hIcon,&iconInfo))
return -1;
CSize size = GetIconSize();
CDC myDC;
myDC.CreateCompatibleDC(0);
CBitmap bmColor;
bmColor.Attach(iconInfo.hbmColor);
CBitmap bmMask;
bmMask.Attach(iconInfo.hbmMask);
CBitmap* pOldBitmap = myDC.SelectObject(&bmColor);
COLORREF crMenu = CNewMenu::GetMenuBarColor();
COLORREF crPixel;
for(int i=0;i<size.cx;++i)
{
for(int j=0;j<size.cy;++j)
{
crPixel = myDC.GetPixel(i,j);
//myDC.SetPixel(i,j,GrayColor(crPixel));
//myDC.SetPixel(i,j,MidColor(GrayColor(crPixel),crMenu));
myDC.SetPixel(i,j,MixedColor(LightenColor(100,GrayColor(crPixel)),crMenu));
}
}
myDC.SelectObject(pOldBitmap);
if(nIndex==-1)
return m_IconsList.Add(&bmColor,&bmMask);
return (m_IconsList.Replace(nIndex,&bmColor,&bmMask)) ? nIndex: -1;
}
BOOL CNewMenuIcons::MakeImages()
{
int nCount = m_IconsList.GetImageCount();
if(!nCount)
return FALSE;
CSize size = GetIconSize();
CImageList ilTemp;
ilTemp.Attach(m_IconsList.Detach());
m_IconsList.Create(size.cx,size.cy,ILC_COLORDDB|ILC_MASK,0,10);
for(int nIndex=0;nIndex<nCount;nIndex++)
{
HICON hIcon = ilTemp.ExtractIcon(nIndex);
m_IconsList.Add(hIcon);
AddGloomIcon(hIcon);
AddGrayIcon(hIcon);
DestroyIcon(hIcon);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewMenuBitmaps,CNewMenuIcons);
CNewMenuBitmaps::CNewMenuBitmaps()
{
}
CNewMenuBitmaps::~CNewMenuBitmaps()
{
}
int CNewMenuBitmaps::Add(UINT nID, COLORREF crTransparent)
{
int nIndex = (int)m_IDs.GetSize();
while(nIndex--)
{
if(m_IDs.GetAt(nIndex)==nID)
{
return nIndex*MENU_ICONS;
}
}
// Try to load the bitmap for getting dimension
HBITMAP hBitmap = LoadColorBitmap(MAKEINTRESOURCE(nID),0);
if(hBitmap!=NULL)
{
CBitmap temp;
temp.Attach(hBitmap);
BITMAP bitmap;
ZeroMemory(&bitmap,sizeof(bitmap));
if(!temp.GetBitmap(&bitmap))
return -1;
if(m_IconsList.GetSafeHandle()==NULL)
{
m_IconsList.Create(bitmap.bmWidth,bitmap.bmHeight,ILC_COLORDDB|ILC_MASK,0,10);
}
else
{
CSize size = GetIconSize();
// Wrong size?
if(size.cx!=bitmap.bmWidth || size.cy!=bitmap.bmHeight)
return -1;
}
m_TranspColors.Add(crTransparent);
m_IDs.Add(nID);
nIndex = m_IconsList.Add(&temp,crTransparent);
HICON hIcon = m_IconsList.ExtractIcon(nIndex);
AddGloomIcon(hIcon);
AddGrayIcon(hIcon);
DestroyIcon(hIcon);
//SetBlendImage();
return nIndex;
}
return -1;
}
void CNewMenuBitmaps::OnSysColorChange()
{
int nCount = (int)m_IDs.GetSize();
for(int nIndex=0;nIndex<nCount;nIndex+=MENU_ICONS)
{
//Todo reload icons
HICON hIcon = m_IconsList.ExtractIcon(nIndex);
AddGloomIcon(hIcon,nIndex+1);
AddGrayIcon(hIcon,nIndex+2);
DestroyIcon(hIcon);
}
}
int CNewMenuBitmaps::Add(HICON hIcon, UINT nID)
{
ICONINFO iconInfo;
ZeroMemory(&iconInfo,sizeof(iconInfo));
if(!GetIconInfo(hIcon,&iconInfo))
return -1;
CBitmap temp;
temp.Attach(iconInfo.hbmColor);
::DeleteObject(iconInfo.hbmMask);
BITMAP bitmap;
ZeroMemory(&bitmap,sizeof(bitmap));
if(!temp.GetBitmap(&bitmap))
return -1;
if(m_IconsList.GetSafeHandle()==NULL)
{
m_IconsList.Create(bitmap.bmWidth,bitmap.bmHeight,ILC_COLORDDB|ILC_MASK,0,10);
}
else
{
CSize size = GetIconSize();
// Wrong size?
if(size.cx!=bitmap.bmWidth || size.cy!=bitmap.bmHeight)
return -1;
}
if(nID)
{
int nIndex = (int)m_IDs.GetSize();
while(nIndex--)
{
if(m_IDs.GetAt(nIndex)==nID)
{
// We found the index also replace the icon
nIndex = nIndex*MENU_ICONS;
m_IconsList.Replace(nIndex,hIcon);
AddGloomIcon(hIcon,nIndex+1);
AddGrayIcon(hIcon,nIndex+2);
return nIndex;
}
}
}
COLORREF clr = CLR_NONE;
m_TranspColors.Add(clr);
m_IDs.Add(nID);
int nIndex = m_IconsList.Add(hIcon);
AddGloomIcon(hIcon);
AddGrayIcon(hIcon);
return nIndex;
}
int CNewMenuBitmaps::Add(CBitmap* pBitmap, COLORREF crTransparent)
{
ASSERT(pBitmap);
BITMAP bitmap;
ZeroMemory(&bitmap,sizeof(bitmap));
if(!pBitmap->GetBitmap(&bitmap))
return -1;
if(m_IconsList.GetSafeHandle()==NULL)
{
m_IconsList.Create(bitmap.bmWidth,bitmap.bmHeight,ILC_COLORDDB|ILC_MASK,0,10);
}
else
{
CSize size = GetIconSize();
// Wrong size?
if(size.cx!=bitmap.bmWidth || size.cy!=bitmap.bmHeight)
return -1;
}
UINT nID = 0;
m_TranspColors.Add(crTransparent);
m_IDs.Add(nID);
int nIndex = m_IconsList.Add(pBitmap,crTransparent);
HICON hIcon = m_IconsList.ExtractIcon(nIndex);
AddGloomIcon(hIcon);
AddGrayIcon(hIcon);
DestroyIcon(hIcon);
//SetBlendImage();
return nIndex;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewMenuItemData,CObject);
CNewMenuItemData::CNewMenuItemData()
: m_nTitleFlags(0),
m_nFlags(0),
m_nID(0),
m_nSyncFlag(0),
m_pData(NULL),
m_pMenuIcon(NULL),
m_nMenuIconOffset(-1)
{
}
CNewMenuItemData::~CNewMenuItemData()
{
// it's a safe release. Do not care for NULL pointers.
m_pMenuIcon->Release();
}
LPCTSTR CNewMenuItemData::GetString()
{
return m_szMenuText;
}
void CNewMenuItemData::SetString(LPCTSTR szMenuText)
{
m_szMenuText = szMenuText;
}
#if defined(_DEBUG) || defined(_AFXDLL)
// Diagnostic Support
void CNewMenuItemData::AssertValid() const
{
CObject::AssertValid();
}
void CNewMenuItemData::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << _T("MenuItem: ") << m_szMenuText << _T("\n");
}
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewMenu,CMenu);
// actual selectet menu-draw mode
CMenuTheme* CNewMenu::m_pActMenuDrawing = NULL;
CTypedPtrList<CPtrList, CNewMenuIcons*>* CNewMenu::m_pSharedMenuIcons = NULL;
// Gloabal logfont for all menutitles
LOGFONT CNewMenu::m_MenuTitleFont = {16, 0, 0, 0, FW_BOLD,
0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH,_T("Arial")};
void CNewMenu::SetMenuTitleFont(CFont* pFont)
{
ASSERT(pFont);
pFont->GetLogFont(&m_MenuTitleFont);
}
void CNewMenu::SetMenuTitleFont(LOGFONT* pLogFont)
{
ASSERT(pLogFont);
m_MenuTitleFont = *pLogFont;
}
LOGFONT CNewMenu::GetMenuTitleFont()
{
return m_MenuTitleFont;
}
DWORD CNewMenu::m_dwLastActiveItem = NULL;
// how the menu's are drawn in winXP
BOOL CNewMenu::m_bEnableXpBlendig=TRUE;
BOOL CNewMenu::m_bSelectDisable=TRUE;
const Win32Type g_Shell = IsShellType();
BOOL bRemoteSession = FALSE;
// one instance of the hook for menu-subclassing
static CNewMenuHook MyNewMenuHookInstance;
CNewMenu::CNewMenu(HMENU hParent)
: m_hParentMenu(hParent),
m_bIsPopupMenu(TRUE),
m_dwOpenMenu(NULL),
m_LastActiveMenuRect(0,0,0,0),
m_pData(NULL)
{
// O.S. - no dynamic icons by default
m_bDynIcons = FALSE;
// Icon sizes default to 16 x 16
m_iconX = 16;
m_iconY = 15;
m_selectcheck = -1;
m_unselectcheck = -1;
m_checkmaps=NULL;
m_checkmapsshare=FALSE;
// set the color used for the transparent background in all bitmaps
m_bitmapBackground = CLR_DEFAULT;
}
CNewMenu::~CNewMenu()
{
DestroyMenu();
}
COLORREF CNewMenu::GetMenuBarColor()
{
if(IsShellType()==WinXP)
{
BOOL bFlatMenu = FALSE;
if(SystemParametersInfo(SPI_GETFLATMENU,0,&bFlatMenu,0) && bFlatMenu==TRUE)
{
return GetSysColor(COLOR_MENUBAR);
}
}
return GetSysColor(COLOR_MENU);
}
void CNewMenu::SetLastMenuRect(HDC hDC, LPRECT pRect)
{
if(!m_bIsPopupMenu)
{
HWND hWnd = WindowFromDC(hDC);
if(hWnd && pRect)
{
CRect Temp;
GetWindowRect(hWnd,Temp);
m_LastActiveMenuRect = *pRect;
m_LastActiveMenuRect.OffsetRect(Temp.TopLeft());
#ifdef _TRACE_MENU_
TRACE(_T("ActiveRect: (%ld,%ld,%ld,%ld)\n"),m_LastActiveMenuRect.left,m_LastActiveMenuRect.top,m_LastActiveMenuRect.right,m_LastActiveMenuRect.bottom);
#endif
}
}
}
BOOL CNewMenu::IsNewShell ()
{
return (g_Shell>=Win95);
}
BOOL CNewMenu::OnMeasureItem(const MSG* pMsg)
{
if(pMsg->message==WM_MEASUREITEM)
{
LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)pMsg->lParam;
if(lpMIS->CtlType==ODT_MENU)
{
CMenu* pMenu=NULL;
if(::IsMenu(UIntToHMenu(lpMIS->itemID)) )
{
pMenu = CMenu::FromHandlePermanent(UIntToHMenu(lpMIS->itemID) );
}
else
{
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState ();
if (pThreadState->m_hTrackingWindow == pMsg->hwnd)
{
// start from popup
pMenu = FindPopupMenuFromIDData(pThreadState->m_hTrackingMenu,lpMIS->itemID,lpMIS->itemData);
}
if(pMenu==NULL)
{
// start from menubar
pMenu = FindPopupMenuFromIDData(::GetMenu(pMsg->hwnd),lpMIS->itemID,lpMIS->itemData);
if(pMenu==NULL)
{
// finaly start from system menu.
pMenu = FindPopupMenuFromIDData(::GetSystemMenu(pMsg->hwnd,FALSE),lpMIS->itemID,lpMIS->itemData);
}
}
}
if(pMenu!=NULL)
{
pMenu->MeasureItem(lpMIS);
return TRUE;
}
}
}
return FALSE;
}
CMenu* CNewMenu::FindPopupMenuFromID(HMENU hMenu, UINT nID)
{
// check for a valid menu-handle
if ( ::IsMenu(hMenu))
{
CMenu *pMenu = CMenu::FromHandlePermanent(hMenu);
if(pMenu)
{
return FindPopupMenuFromID(pMenu,nID);
}
}
return NULL;
}
CMenu* CNewMenu::FindPopupMenuFromIDData(HMENU hMenu, UINT nID, ULONG_PTR pData)
{
// check for a valid menu-handle
if ( ::IsMenu(hMenu))
{
CMenu *pMenu = CMenu::FromHandlePermanent(hMenu);
if(pMenu)
{
return FindPopupMenuFromIDData(pMenu,nID,pData);
}
}
return NULL;
}
CMenu* CNewMenu::FindPopupMenuFromIDData(CMenu* pMenu, UINT nID, ULONG_PTR pData)
{
if(!pMenu || !IsMenu(pMenu->m_hMenu))
{
return NULL;
}
ASSERT_VALID(pMenu);
// walk through all items, looking for ID match
UINT nItems = pMenu->GetMenuItemCount();
for (int iItem = 0; iItem < (int)nItems; iItem++)
{
CMenu* pPopup = pMenu->GetSubMenu(iItem);
if (pPopup!=NULL)
{
// recurse to child popup
pPopup = FindPopupMenuFromIDData(pPopup, nID, pData);
// check popups on this popup
if (pPopup != NULL)
return pPopup;
}
else if (pMenu->GetMenuItemID(iItem) == nID)
{
MENUITEMINFO MenuItemInfo;
::ZeroMemory(&MenuItemInfo,sizeof(MenuItemInfo));
MenuItemInfo.cbSize = sizeof(MenuItemInfo);
MenuItemInfo.fMask = MIIM_DATA;
if(pMenu->GetMenuItemInfo(iItem,&MenuItemInfo,TRUE))
{
if(MenuItemInfo.dwItemData==pData)
{
// it is a normal item inside our popup
return pMenu;
}
}
}
}
// not found
return NULL;
}
CMenu* CNewMenu::FindPopupMenuFromID(CMenu* pMenu, UINT nID)
{
if(!pMenu || !IsMenu(pMenu->m_hMenu))
{
return NULL;
}
ASSERT_VALID(pMenu);
// walk through all items, looking for ID match
UINT nItems = pMenu->GetMenuItemCount();
for (int iItem = 0; iItem < (int)nItems; iItem++)
{
CMenu* pPopup = pMenu->GetSubMenu(iItem);
if (pPopup != NULL)
{
// recurse to child popup
pPopup = FindPopupMenuFromID(pPopup, nID);
// check popups on this popup
if (pPopup != NULL)
return pPopup;
}
else if (pMenu->GetMenuItemID(iItem) == nID)
{
// it is a normal item inside our popup
return pMenu;
}
}
// not found
return NULL;
}
BOOL CNewMenu::DestroyMenu()
{
// Destroy Sub menus:
int m;
int numSubMenus = (int)m_SubMenus.GetUpperBound();
for(m = numSubMenus; m >= 0; m--)
{
// Destroy only if we createt it!!!!!
CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_SubMenus[m]));
if(pMenu)
{
delete pMenu;
}
}
m_SubMenus.RemoveAll();
// Destroy menu data
int numItems = (int)m_MenuItemList.GetUpperBound();
for(m = 0; m <= numItems; m++)
{
delete(m_MenuItemList[m]);
}
m_MenuItemList.RemoveAll();
if(m_checkmaps&&!m_checkmapsshare)
{
delete m_checkmaps;
m_checkmaps=NULL;
}
// Call base-class implementation last:
return(CMenu::DestroyMenu());
};
int CNewMenu::GetMenuDrawMode()
{
ASSERT(m_pActMenuDrawing);
return m_pActMenuDrawing->m_dwThemeId;
}
void CNewMenu::SetMenuDrawMode(UINT mode)
{
CMenuTheme* pTheme = CNewMenuHook::FindTheme(mode);
if(pTheme)
{
m_pActMenuDrawing = pTheme;
}
}
HMENU CNewMenu::GetParent()
{
return m_hParentMenu;
}
BOOL CNewMenu::IsPopup()
{
return m_bIsPopupMenu;
}
BOOL CNewMenu::SetPopup(BOOL bIsPopup)
{
BOOL bOldFlag = m_bIsPopupMenu;
m_bIsPopupMenu = bIsPopup;
return bOldFlag;
}
BOOL CNewMenu::SetSelectDisableMode(BOOL mode)
{
BOOL bOldMode = m_bSelectDisable;
m_bSelectDisable=mode;
return bOldMode;
}
BOOL CNewMenu::GetSelectDisableMode()
{
return m_bSelectDisable;
}
BOOL CNewMenu::SetXpBlendig(BOOL bEnable)
{
BOOL bOldMode = m_bEnableXpBlendig;
m_bEnableXpBlendig = bEnable;
return bOldMode;
}
BOOL CNewMenu::GetXpBlendig()
{
return m_bEnableXpBlendig;
}
void CNewMenu::OnSysColorChange()
{
static DWORD dwLastTicks = 0;
DWORD dwAktTicks = GetTickCount();
// Last Update 2 sec
if((dwAktTicks-dwLastTicks)>2000)
{
dwLastTicks = dwAktTicks;
if(m_pSharedMenuIcons)
{
POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
while(pos)
{
CNewMenuIcons* pMenuIcons = m_pSharedMenuIcons->GetNext(pos);
pMenuIcons->OnSysColorChange();
}
}
}
}
void CNewMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
ASSERT(m_pActMenuDrawing);
BOOL bIsMenuBar = IsMenuBar(UIntToHMenu(lpMIS->itemID));
if(!bIsMenuBar && m_hParentMenu &&::IsMenu(UIntToHMenu(lpMIS->itemID)) )
{
CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_hParentMenu));
if(pMenu)
{
((*pMenu).*m_pActMenuDrawing->m_pMeasureItem)(lpMIS,bIsMenuBar);
return;
}
}
((*this).*m_pActMenuDrawing->m_pMeasureItem)(lpMIS,bIsMenuBar);
}
void CNewMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
{
ASSERT(m_pActMenuDrawing);
BOOL bIsMenuBar = m_hParentMenu ? FALSE: ((m_bIsPopupMenu)?FALSE:TRUE);
if(bIsMenuBar && m_dwLastActiveItem==lpDIS->itemData)
{
if(! (lpDIS->itemState&ODS_HOTLIGHT) )
{
// Mark for redraw helper for win 98
m_dwLastActiveItem = NULL;
}
}
(this->*m_pActMenuDrawing->m_pDrawItem)(lpDIS,bIsMenuBar);
}
// Erase the Background of the menu
BOOL CNewMenu::EraseBkgnd(HWND hWnd, HDC hDC)
{
CDC* pDC = CDC::FromHandle (hDC);
CRect Rect;
// Get the size of the menu...
GetClientRect(hWnd, Rect );
pDC->FillSolidRect (Rect,GetMenuBarColor());
return TRUE;
}
void CNewMenu::DrawTitle(LPDRAWITEMSTRUCT lpDIS,BOOL bIsMenuBar)
{
ASSERT(m_pActMenuDrawing);
(this->*m_pActMenuDrawing->m_pDrawTitle)(lpDIS,bIsMenuBar);
}
void CNewMenu::DrawMenuTitle(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
UNREFERENCED_PARAMETER(bIsMenuBar);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
ASSERT(pMenuData);
COLORREF ColA = GetSysColor(COLOR_WINDOW);
COLORREF ColB = GetMenuBarColor();
//Timur[8/27/2002]
COLORREF colorMenu = MixedColor(ColA,ColB);
CRect rcClipBox;
pDC->GetClipBox(rcClipBox);
// draw the title bar
CRect rect = lpDIS->rcItem;
CPoint TextPoint;
CFont Font;
LOGFONT MyFont = m_MenuTitleFont;
if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
rect.top = rcClipBox.top;
rect.bottom = rcClipBox.bottom;
rect.right += GetSystemMetrics(SM_CXMENUCHECK);
MyFont.lfOrientation = 900;
MyFont.lfEscapement = 900;
TextPoint = CPoint(rect.left+2, rect.bottom-4);
}
else
{
MyFont.lfOrientation = 0;
MyFont.lfEscapement = 0;
TextPoint = CPoint(rect.left+2, rect.top);
}
Font.CreateFontIndirect(&MyFont);
CFont *pOldFont = pDC->SelectObject(&Font);
SIZE size;
VERIFY(::GetTextExtentPoint32(pDC->m_hDC,pMenuData->m_szMenuText,pMenuData->m_szMenuText.GetLength(),&size));
COLORREF oldColor = pDC->SetTextColor(::GetSysColor(COLOR_CAPTIONTEXT));
int OldMode = pDC->SetBkMode(TRANSPARENT);
if(pMenuData->m_nTitleFlags&MFT_GRADIENT)
{
if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
DrawGradient(pDC,rect,colorMenu,::GetSysColor(COLOR_ACTIVECAPTION),false);
}
else
{
DrawGradient(pDC,rect,::GetSysColor(COLOR_ACTIVECAPTION),colorMenu,true);
}
}
else
{
if(pMenuData->m_nTitleFlags&MFT_ROUND)
{
if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
TextPoint.y-=2;
rect.right = rect.left+size.cy;
}
else
{
int maxSpace = ((rect.Width()-size.cx)/2);
TextPoint.x+=min(maxSpace,10);
}
CBrush brush(GetSysColor(COLOR_ACTIVECAPTION));
CPen* pOldPen = (CPen*)pDC->SelectStockObject(WHITE_PEN);
CBrush* pOldBrush = pDC->SelectObject(&brush);
pDC->RoundRect(rect,CPoint(10,10));
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
else
{
pDC->FillSolidRect(rect,GetSysColor(COLOR_ACTIVECAPTION));
}
}
if (pMenuData->m_nTitleFlags&MFT_SUNKEN)
{
pDC->Draw3dRect(rect,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
}
if (pMenuData->m_nTitleFlags&MFT_CENTER)
{
if (pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
TextPoint.y = rect.bottom - ((rect.Height()-size.cx)>>1);
}
else
{
TextPoint.x = rect.left + ((rect.Width()-size.cx)>>1);
}
}
pDC->TextOut(TextPoint.x,TextPoint.y, pMenuData->GetString());
if(pMenuData->m_nTitleFlags&MFT_LINE)
{
if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
CRect rect2(rect.left+20,rect.top+5,rect.left+22,rect.bottom-5);
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
rect2.OffsetRect(3,0);
rect2.InflateRect(0,-10);
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
}
else
{
CRect rect2(rect.left+2,rect.bottom-7,rect.right-2,rect.bottom-5);
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
rect2.OffsetRect(0,3);
rect2.InflateRect(-10,0);
pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
}
}
pDC->SetBkMode(OldMode);
pDC->SetTextColor(oldColor);
pDC->SelectObject(pOldFont);
}
void CNewMenu::DrawItem_WinXP(LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
ASSERT(lpDIS != NULL);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rect;
CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
ASSERT(pMenuData);
UINT state = pMenuData->m_nFlags;
COLORREF ColA = GetSysColor(COLOR_WINDOW);
COLORREF ColB = GetMenuBarColor();
COLORREF colorMenu = MixedColor(ColA,ColB);
COLORREF colorBitmap = MixedColor(ColB,ColA);
COLORREF colorText = MixedColor(GetSysColor(COLOR_WINDOWTEXT),GetSysColor(COLOR_MENUTEXT));
COLORREF colorSel = MidColor(ColA,GetSysColor(COLOR_HIGHLIGHT));
// Better contrast when you have less than 256 colors
if(pDC->GetNearestColor(colorMenu)==pDC->GetNearestColor(colorBitmap))
{
colorMenu = ColA;
colorBitmap = ColB;
}
CPen Pen(PS_SOLID,0,GetSysColor(COLOR_HIGHLIGHT));
#ifdef _TRACE_MENU_
TRACE(_T("DrawItem: 0x%lX Menus %ld\n"),lpDIS->itemState,lpDIS->itemData);
#endif
if(bIsMenuBar)
{
#ifdef _TRACE_MENU_
TRACE(_T("BarState: 0x%lX Menus %ld\n"),lpDIS->itemState,m_dwOpenMenu);
#endif
if(!m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
{
lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
}
if(!(lpDIS->itemState&ODS_HOTLIGHT))
{
colorSel = colorBitmap;
}
colorMenu = ColB;
}
CBrush m_brBackground(colorMenu);
CBrush m_brSel(colorSel);
CBrush m_brBitmap(colorBitmap);
CRect RectL(lpDIS->rcItem);
CRect RectR(lpDIS->rcItem);
CRect RectSel(lpDIS->rcItem);
if(bIsMenuBar)
{
RectR.InflateRect (0,0,0,0);
RectSel.InflateRect (0,0,-2 -2,0);
}
else
{
RectL.right = RectL.left + m_iconX + 8;
RectR.left = RectL.right;
// Draw for Bitmapbackground
pDC->FillSolidRect (RectL,colorBitmap);
}
// Draw for Textbackground
pDC->FillSolidRect (RectR,colorMenu);
// Spacing for submenu only in popups
if(!bIsMenuBar)
{
RectR.left += 4;
RectR.right-= 15;
}
// Flag for highlighted item
if(lpDIS->itemState & (ODS_HOTLIGHT|ODS_INACTIVE) )
{
lpDIS->itemState |= ODS_SELECTED;
}
if(bIsMenuBar && (lpDIS->itemState&ODS_SELECTED) )
{
if(!(lpDIS->itemState&ODS_INACTIVE) )
{
SetLastMenuRect(lpDIS->hDC,RectSel);
if(!(lpDIS->itemState&ODS_HOTLIGHT) )
{
// Create a new pen for the special color
Pen.DeleteObject();
COLORREF clrPen = DarkenColor(128,GetMenuBarColor());
Pen.CreatePen(PS_SOLID,0,clrPen);
int X,Y;
CRect rect = RectR;
int winH = rect.Height();
// Simulate a shadow on right edge...
for (X=1; X<=4 ;X++)
{
for (Y=0; Y<4 ;Y++)
{
pDC->SetPixel(rect.right-X,Y+rect.top, ColB );
}
for (Y=4; Y<8 ;Y++)
{
pDC->SetPixel(rect.right-X,Y+rect.top,DarkenColor(2* 3 * X * (Y - 3), ColB)) ;
}
for (Y=8; Y<=(winH-1) ;Y++)
{
pDC->SetPixel(rect.right - X, Y+rect.top, DarkenColor(2*15 * X, ColB) );
}
}
}
}
}
// For keyboard navigation only
BOOL bDrawSmalSelection = FALSE;
// remove the selected bit if it's grayed out
if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable)
{
if( lpDIS->itemState & ODS_SELECTED )
{
lpDIS->itemState = lpDIS->itemState & (~ODS_SELECTED);
DWORD MsgPos = ::GetMessagePos();
if( MsgPos==CNewMenuHook::m_dwMsgPos )
{
bDrawSmalSelection = TRUE;
}
else
{
CNewMenuHook::m_dwMsgPos = MsgPos;
}
}
}
// Draw the seperator
if( state & MF_SEPARATOR )
{
if( pMenuData->m_nTitleFlags&MFT_TITLE )
{
DrawTitle(lpDIS,bIsMenuBar);
}
else
{
// Draw only the seperator
CRect rect;
rect.top = RectR.CenterPoint().y;
rect.bottom = rect.top+1;
rect.right = lpDIS->rcItem.right;
rect.left = RectR.left;
pDC->FillSolidRect(rect,GetSysColor(COLOR_GRAYTEXT));
}
}
else
{
if( (lpDIS->itemState & ODS_SELECTED) && !(lpDIS->itemState&ODS_INACTIVE) )
{
pDC->FillSolidRect(RectSel,colorSel);
// Draw the selection
CPen* pOldPen = pDC->SelectObject(&Pen);
//CBrush* pOldBrush = pDC->SelectObject(&m_brSel);
CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
pDC->Rectangle(RectSel);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
else if (bDrawSmalSelection)
{
pDC->FillSolidRect(RectSel,colorMenu);
// Draw the selection for keyboardnavigation
CPen* pOldPen = pDC->SelectObject(&Pen);
CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
//CBrush* pOldBrush = pDC->SelectObject(&m_brBackground);
pDC->Rectangle(RectSel);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
UINT state = lpDIS->itemState;
BOOL standardflag=FALSE;
BOOL selectedflag=FALSE;
BOOL disableflag=FALSE;
BOOL checkflag=FALSE;
CBrush m_brSelect;
CPen m_penBack;
CString strText = pMenuData->GetString();
if( (state&ODS_CHECKED) && (pMenuData->m_nMenuIconOffset<0) )
{
if(state&ODS_SELECTED && m_selectcheck>0)
{
checkflag=TRUE;
}
else if(m_unselectcheck>0)
{
checkflag=TRUE;
}
}
else if(pMenuData->m_nMenuIconOffset != -1)
{
standardflag=TRUE;
if(state&ODS_SELECTED)
{
selectedflag=TRUE;
}
else if(state&ODS_GRAYED)
{
disableflag=TRUE;
}
}
// draw the menutext
if(!strText.IsEmpty())
{
LOGFONT LogFontMenu;
CFont FontMenu;
NONCLIENTMETRICS nm;
::ZeroMemory(&nm,sizeof(nm));
nm.cbSize = sizeof (nm);
VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0));
LogFontMenu = nm.lfMenuFont;
// Default selection?
if(state&ODS_DEFAULT)
{
// Make the font bold
LogFontMenu.lfWeight = FW_BOLD;
}
FontMenu.CreateFontIndirect(&LogFontMenu);
CString leftStr;
CString rightStr;
leftStr.Empty();
rightStr.Empty();
int tablocr=strText.ReverseFind(_T('\t'));
if(tablocr!=-1)
{
rightStr=strText.Mid(tablocr+1);
leftStr=strText.Left(strText.Find(_T('\t')));
}
else
leftStr=strText;
// Draw the text in the correct colour:
UINT nFormat = DT_LEFT| DT_SINGLELINE|DT_VCENTER;
UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
int iOldMode = pDC->SetBkMode( TRANSPARENT);
CFont* pOldFont = pDC->SelectObject (&FontMenu);
COLORREF OldTextColor;
if( (lpDIS->itemState&ODS_GRAYED) ||
(bIsMenuBar && lpDIS->itemState&ODS_INACTIVE) )
{
// Draw the text disabled?
OldTextColor = pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
}
else
{
//Timur[8/27/2002]
// Draw the text normal
OldTextColor = pDC->SetTextColor( colorText );
}
if(bIsMenuBar)
{
pDC->DrawText(leftStr,RectSel, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
}
else
{
pDC->DrawText(leftStr,RectR, nFormat);
if(tablocr!=-1)
pDC->DrawText (rightStr,RectR,nFormatr);
}
pDC->SetTextColor(OldTextColor);
pDC->SelectObject(pOldFont);
pDC->SetBkMode(iOldMode);
}
// Draw the bitmap or checkmarks
if(!bIsMenuBar)
{
CRect rect2 = RectR;
if(checkflag||standardflag||selectedflag||disableflag)
{
if(checkflag && m_checkmaps)
{
CPoint ptImage(RectL.left+3,RectL.top+4);
if(state&ODS_SELECTED)
m_checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
else
m_checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
}
else
{
CSize size = pMenuData->m_pMenuIcon->GetIconSize();
HICON hDrawIcon = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
//CPoint ptImage(RectL.left+3,RectL.top+ 4);
CPoint ptImage( RectL.left+3, RectL.top + ((RectL.Height()-size.cy)>>1) );
// Need to draw the checked state
if (state&ODS_CHECKED)
{
CRect rect = RectL;
rect.InflateRect (-1,-1);
if(selectedflag)
{
pDC->FillSolidRect(rect,MixedColor(colorSel,GetSysColor(COLOR_HIGHLIGHT)));
}
else
{
pDC->FillSolidRect(rect,MixedColor(colorBitmap,GetSysColor(COLOR_HIGHLIGHT)));
}
CPen* pOldPen = pDC->SelectObject(&Pen);
CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
pDC->Rectangle(rect);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
// Correcting of a smaler icon
if(size.cx<m_iconX)
{
ptImage.x += (m_iconX-size.cx)>>1;
}
//if(size.cy<m_iconY)
//{
// ptImage.y += (m_iconY-size.cy)>>1;
//}
if(state & ODS_DISABLED)
{
if(m_bEnableXpBlendig)
{
// draws the icon blended
HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+2);
pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
DestroyIcon(hDrawIcon2);
}
else
{
CBrush Brush;
Brush.CreateSolidBrush(pDC->GetNearestColor(DarkenColor(70,colorBitmap)));
pDC->DrawState(ptImage, size, hDrawIcon, DSS_MONO, &Brush);
}
}
else
{
if(selectedflag)
{
CBrush Brush;
// Color of the shade
Brush.CreateSolidBrush(pDC->GetNearestColor(DarkenColorXP(colorSel)));
if(!(state & ODS_CHECKED))
{
ptImage.x++; ptImage.y++;
pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL | DSS_MONO, &Brush);
ptImage.x-=2; ptImage.y-=2;
}
pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
}
else
{
if(m_bEnableXpBlendig)
{
// draws the icon blended
HICON hDrawIcon2 = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset+1);
pDC->DrawState(ptImage, size, hDrawIcon2, DSS_NORMAL,(HBRUSH)NULL);
DestroyIcon(hDrawIcon2);
}
else
{
// draws the icon with normal color
pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL,(HBRUSH)NULL);
}
}
}
DestroyIcon(hDrawIcon);
}
}
if(pMenuData->m_nMenuIconOffset<0 && state&ODS_CHECKED && !checkflag)
{
MENUITEMINFO info;
ZeroMemory(&info,sizeof(info));
info.cbSize = sizeof(info);
info.fMask = MIIM_CHECKMARKS;
::GetMenuItemInfo(HWndToHMenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);
if(state&ODS_CHECKED || info.hbmpUnchecked)
{
CRect rect = RectL;
rect.InflateRect(-1,-1);
// draw the color behind checkmarks
if(state&ODS_SELECTED)
{
pDC->FillSolidRect(rect,MixedColor(colorSel,GetSysColor(COLOR_HIGHLIGHT)));
}
else
{
pDC->FillSolidRect(rect,MixedColor(colorBitmap,GetSysColor(COLOR_HIGHLIGHT)));
}
CPen* pOldPen = pDC->SelectObject(&Pen);
CBrush* pOldBrush = (CBrush*)pDC->SelectStockObject(HOLLOW_BRUSH);
pDC->Rectangle(rect);
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
if (state&ODS_CHECKED)
{
CRect rect(RectL);
rect.InflateRect(2,((m_iconY-RectL.Height())>>1)+2);
if (!info.hbmpChecked)
{ // Checkmark
DrawSpecialCharStyle(pDC,rect,98,state);
}
else
{ // Bullet
DrawSpecialCharStyle(pDC,rect,105,state);
}
}
else
{
CSize size = rect.Size();
CPoint ptImage = rect.TopLeft();
if(state & ODS_DISABLED)
pDC->DrawState(ptImage, size, info.hbmpUnchecked, DSS_DISABLED, (HBRUSH)NULL);
else
pDC->DrawState(ptImage, size, info.hbmpUnchecked, DSS_NORMAL,(HBRUSH)NULL);
}
}
}
else if ((lpDIS->itemID&0xffff)>=SC_SIZE && (lpDIS->itemID&0xffff)<=SC_HOTKEY )
{
DrawSpecial_WinXP(pDC,RectL,lpDIS->itemID,state);
}
}
}
}
void CNewMenu::DrawItem_SpecialStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
if(!bIsMenuBar)
{
DrawItem_OldStyle(lpDIS,bIsMenuBar);
return;
}
ASSERT(lpDIS != NULL);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
ASSERT(lpDIS->itemData);
CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
CRect rect(lpDIS->rcItem);
//rect.InflateRect(0,-1);
COLORREF ColorBack;
if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
{
ColorBack = GetSysColor(COLOR_HIGHLIGHT);
SetLastMenuRect(lpDIS->hDC,rect);
}
else
{
ColorBack = GetMenuBarColor();
}
pDC->FillSolidRect(rect,ColorBack);
int iOldMode = pDC->SetBkMode( TRANSPARENT);
CString strText = pMenuData->GetString();
COLORREF crTextColor;
if(!(lpDIS->itemState & ODS_GRAYED))
{
if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
crTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
else
crTextColor = GetSysColor(COLOR_MENUTEXT);
}
else
{
crTextColor = GetSysColor(COLOR_GRAYTEXT);
}
COLORREF oldColor = pDC->SetTextColor(crTextColor);
pDC->DrawText(strText,rect,DT_CENTER|DT_SINGLELINE|DT_VCENTER);
pDC->SetTextColor(oldColor);
pDC->SetBkMode( iOldMode);
}
void CNewMenu::DrawItem_OldStyle (LPDRAWITEMSTRUCT lpDIS, BOOL bIsMenuBar)
{
ASSERT(lpDIS != NULL);
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
CRect rect;
ASSERT(lpDIS->itemData);
CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpDIS->itemData);
UINT state = pMenuData->m_nFlags;
CBrush m_brBackground;
COLORREF ColorBack = bIsMenuBar?GetMenuBarColor():GetSysColor(COLOR_MENU);
m_brBackground.CreateSolidBrush(ColorBack);
CRect RectL(lpDIS->rcItem);
CRect RectR(lpDIS->rcItem);
CRect RectSel(lpDIS->rcItem);
RectL.InflateRect (-1,0,0,0);
RectR.InflateRect (-1,0,0,0);
RectSel.InflateRect (0,0,0,0);
if(!bIsMenuBar)
{
RectL.right = RectL.left + m_iconX + 6 + GAP;
RectR.left = RectL.right;
// Draw for Bitmapbackground
// pDC->FillSolidRect (RectL,ColorBack);
}
else
{
#ifdef _TRACE_MENU_
TRACE(_T("BarState: 0x%lX Menus %ld\n"),lpDIS->itemState,m_dwOpenMenu);
#endif
if(!m_dwOpenMenu && lpDIS->itemState&ODS_SELECTED)
{
lpDIS->itemState = (lpDIS->itemState&~ODS_SELECTED)|ODS_HOTLIGHT;
}
RectR.InflateRect (1,0,0,0);
RectSel.InflateRect (0,0,-5,0);
RectSel.OffsetRect(1,-1);
if(lpDIS->itemState&(ODS_SELECTED|ODS_HOTLIGHT))
SetLastMenuRect(lpDIS->hDC,RectSel);
}
// For keyboard navigation only
BOOL bDrawSmalSelection = FALSE;
// remove the selected bit if it's grayed out
if( (lpDIS->itemState&ODS_GRAYED) && !m_bSelectDisable )
{
if(lpDIS->itemState & ODS_SELECTED)
{
lpDIS->itemState &= ~ODS_SELECTED;
DWORD MsgPos = ::GetMessagePos();
if(MsgPos==CNewMenuHook::m_dwMsgPos)
{
bDrawSmalSelection = TRUE;
}
else
{
CNewMenuHook::m_dwMsgPos = MsgPos;
}
}
}
if(state & MF_SEPARATOR)
{
if(pMenuData->m_nTitleFlags&MFT_TITLE)
{
DrawTitle(lpDIS,bIsMenuBar);
}
else
{
rect = lpDIS->rcItem;
rect.left += 1;
pDC->FillSolidRect(rect,ColorBack);
pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
}
}
else
{
CRect rect2;
BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
BOOL checkflag=FALSE;
CBrush m_brSelect;
int nIconNormal=-1;
//CImageList *bitmap=NULL;
// set some colors and the font
m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
// draw the colored rectangle portion
rect.CopyRect(&lpDIS->rcItem);
rect.OffsetRect (1,1);
rect2=rect=RectSel;
// draw the up/down/focused/disabled state
UINT state = lpDIS->itemState;
CString strText;
nIconNormal = pMenuData->m_nMenuIconOffset;
strText = pMenuData->GetString();
if( (state&ODS_CHECKED) && nIconNormal<0)
{
if(state&ODS_SELECTED && m_selectcheck>0)
checkflag=TRUE;
else if(m_unselectcheck>0)
checkflag=TRUE;
}
else if(nIconNormal != -1)
{
standardflag=TRUE;
if(state&ODS_SELECTED && !(state&ODS_GRAYED))
selectedflag=TRUE;
else if(state&ODS_GRAYED)
disableflag=TRUE;
}
if(bIsMenuBar)
{
//rect.InflateRect (1,0,0,0);
rect.OffsetRect(-1,1);
rect2=rect;
pDC->FillSolidRect (rect,ColorBack);
}
else
{
// Draw the background
pDC->FillSolidRect (rect,ColorBack);
}
// Draw the selection
if(state&ODS_SELECTED)
{
// You need only Text highlight and that's what you get
if(!bIsMenuBar)
{
if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
{
rect2.SetRect(rect.left+m_iconX+4+GAP,rect.top,rect.right,rect.bottom);
}
pDC->FillRect(rect2,&m_brSelect);
}
else
{
pDC->Draw3dRect(rect ,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
}
}
else if(bIsMenuBar && (state&ODS_HOTLIGHT) && !(state&ODS_INACTIVE))
{
pDC->Draw3dRect(rect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
}
else if (bDrawSmalSelection)
{
pDC->DrawFocusRect(rect);
}
// Draw the Bitmap or checkmarks
if(!bIsMenuBar)
{
CRect IconRect(rect.TopLeft(),CSize(m_iconX,m_iconY));
IconRect.OffsetRect(GAP+1,((rect.Height()-m_iconY)>>1));
CPoint ptImage = IconRect.TopLeft();
IconRect.InflateRect(2,2);
if(checkflag||standardflag||selectedflag||disableflag)
{
if(checkflag && m_checkmaps)
{
if(state&ODS_SELECTED)
m_checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
else
m_checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
}
else
{
// Need to draw the checked state
if (IsNewShell())
{
if(state&ODS_CHECKED)
{
pDC->Draw3dRect(IconRect,GetSysColor(COLOR_3DSHADOW),GetSysColor(COLOR_3DHILIGHT));
}
else if (selectedflag)
{
pDC->Draw3dRect(IconRect,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DSHADOW));
}
}
CSize size = pMenuData->m_pMenuIcon->GetIconSize();
// Correcting of a smaler icon
if(size.cx<m_iconX)
{
ptImage.x += (m_iconX-size.cx)>>1;
}
if(size.cy<m_iconY)
{
ptImage.y += (m_iconY-size.cy)>>1;
}
HICON hDrawIcon = pMenuData->m_pMenuIcon->m_IconsList.ExtractIcon(pMenuData->m_nMenuIconOffset);
if(state & ODS_DISABLED)
{
//HICON hDrawIcon = bitmap->ExtractIcon(0);
//int cx,cy;
//::ImageList_GetIconSize(*bitmap, &cx, &cy);
//CSize size(cx,cy);
pDC->DrawState(ptImage, size, hDrawIcon, DSS_DISABLED, (HBRUSH)NULL);
}
else
{
pDC->DrawState(ptImage, size, hDrawIcon, DSS_NORMAL, (HBRUSH)NULL);
//bitmap->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
}
DestroyIcon(hDrawIcon);
}
}
if(nIconNormal<0 && state&ODS_CHECKED && !checkflag)
{
MENUITEMINFO info;
ZeroMemory(&info, sizeof(info));
info.cbSize = sizeof(info);
info.fMask = MIIM_CHECKMARKS;
::GetMenuItemInfo(HWndToHMenu(lpDIS->hwndItem),lpDIS->itemID,MF_BYCOMMAND, &info);
if(state&ODS_CHECKED || info.hbmpUnchecked)
{
// Rectangle for checkmarks
CRect rect = IconRect;
if (state&ODS_CHECKED)
Draw3DCheckmark(pDC, IconRect,info.hbmpChecked,state);
else
Draw3DCheckmark(pDC, IconRect,info.hbmpUnchecked,state);
}
}
else if ((lpDIS->itemID&0xffff)>=SC_SIZE && (lpDIS->itemID&0xffff)<=SC_HOTKEY )
{
DrawSpecial_OldStyle(pDC,IconRect,lpDIS->itemID,state);
}
}
if(!strText.IsEmpty())
{
COLORREF crText = GetSysColor(COLOR_MENUTEXT);
if(bIsMenuBar)
{
rect.left += 6;
if(lpDIS->itemState&ODS_INACTIVE)
crText = GetSysColor(COLOR_GRAYTEXT);
}
else
{
if(lpDIS->itemState&ODS_SELECTED)
crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
rect.left += m_iconX + 12;
}
CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
// Find tabs
CString leftStr,rightStr;
leftStr.Empty();rightStr.Empty();
int tablocr=strText.ReverseFind(_T('\t'));
if(tablocr!=-1)
{
rightStr=strText.Mid(tablocr+1);
leftStr=strText.Left(strText.Find(_T('\t')));
rectt.right-=m_iconX;
}
else
leftStr=strText;
int iOldMode = pDC->SetBkMode( TRANSPARENT);
// Draw the text in the correct colour:
UINT nFormat = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
if(bIsMenuBar)
{
rectt = RectSel;
if(state & ODS_SELECTED)
{
rectt.OffsetRect(1,1);
}
nFormat = DT_CENTER|DT_SINGLELINE|DT_VCENTER;
}
if(!(lpDIS->itemState & ODS_GRAYED))
{
pDC->SetTextColor(crText);
pDC->DrawText (leftStr,rectt,nFormat);
if(tablocr!=-1)
pDC->DrawText (rightStr,rectt,nFormatr);
}
else
{
// Draw the disabled text
if(!(state & ODS_SELECTED))
{
CRect offset = rectt;
offset.OffsetRect (1,1);
pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
pDC->DrawText(leftStr,&offset, nFormat);
if(tablocr!=-1)
pDC->DrawText (rightStr,&offset,nFormatr);
pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
pDC->DrawText(leftStr,rectt, nFormat);
if(tablocr!=-1)
pDC->DrawText(rightStr,rectt,nFormatr);
}
else
{
// And the standard Grey text:
pDC->SetTextColor(ColorBack);
pDC->DrawText(leftStr,rectt, nFormat);
if(tablocr!=-1)
pDC->DrawText (rightStr,rectt,nFormatr);
}
}
pDC->SetBkMode( iOldMode );
}
m_brSelect.DeleteObject();
}
m_brBackground.DeleteObject();
}
BOOL CNewMenu::IsMenuBar(HMENU hMenu)
{
BOOL bIsMenuBar = ::IsMenu(hMenu);
if(bIsMenuBar)
{
if(m_hParentMenu==NULL)
{
return m_bIsPopupMenu?FALSE:TRUE;
}
CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(m_hParentMenu));
if (pMenu!=NULL)
{
return pMenu->m_bIsPopupMenu?FALSE:TRUE;
}
}
return bIsMenuBar;
}
/*
==========================================================================
void CNewMenu::MeasureItem(LPMEASUREITEMSTRUCT)
---------------------------------------------
Called by the framework when it wants to know what the width and height
of our item will be. To accomplish this we provide the width of the
icon plus the width of the menu text, and then the height of the icon.
==========================================================================
*/
void CNewMenu::MeasureItem_OldStyle( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
{
ASSERT(lpMIS->itemData);
CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);
UINT state = pMenuData->m_nFlags;
if(state & MF_SEPARATOR)
{
if(pMenuData->m_nTitleFlags&MFT_TITLE)
{
// DC of the desktop
CClientDC myDC(NULL);
CFont font;
LOGFONT MyFont = m_MenuTitleFont;
MyFont.lfOrientation = 0;
MyFont.lfEscapement = 0;
font.CreateFontIndirect(&MyFont);
CFont* pOldFont = myDC.SelectObject (&font);
LPCTSTR lpstrText = pMenuData->GetString();
SIZE size;
VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
// Select old font in
myDC.SelectObject(pOldFont);
if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
lpMIS->itemWidth = size.cy -GetSystemMetrics(SM_CXMENUCHECK);
// Don't make the menu higher than menuitems in it
lpMIS->itemHeight = 0;
if(pMenuData->m_nTitleFlags&MFT_LINE)
{
lpMIS->itemWidth += 8;
}
}
else
{
lpMIS->itemWidth = size.cx;
lpMIS->itemHeight = size.cy;
if(pMenuData->m_nTitleFlags&MFT_LINE)
{
lpMIS->itemHeight += 8;
}
}
}
else
{
lpMIS->itemHeight = 3;
}
}
else
{
CFont m_fontMenu;
LOGFONT m_lf;
ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
NONCLIENTMETRICS nm;
nm.cbSize = sizeof (NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm,0));
m_lf = nm.lfMenuFont;
// Default selection?
if(state&ODS_DEFAULT)
{
// Make the font bold
m_lf.lfWeight = FW_BOLD;
}
m_fontMenu.CreateFontIndirect (&m_lf);
// DC of the desktop
CClientDC myDC(NULL);
// Select menu font in...
CFont* pOldFont = myDC.SelectObject (&m_fontMenu);
//Get pointer to text SK
const LPCTSTR lpstrText = pMenuData->GetString();
SIZE size;
VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
// Select old font in
myDC.SelectObject(pOldFont);
// Set width and height:
if(bIsMenuBar)
{
lpMIS->itemWidth = size.cx; // - GetSystemMetrics(SM_CXMENUCHECK)/2;
}
else
{
lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
}
// Check the Key-Shortcut
if(_tcsstr(lpstrText, _T("\t")) != NULL)
lpMIS->itemWidth += 15;
int temp = GetSystemMetrics(SM_CYMENU);
lpMIS->itemHeight = (temp>(m_iconY+4)) ? temp : (m_iconY+4);
// set status bar as appropriate
UINT nItemID = (lpMIS->itemID & 0xFFF0);
// Special case for system menu
if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY)
{
BOOL bGetNext = FALSE;
// search the actual menu item
for (int j=0;j<m_MenuItemList.GetUpperBound();++j)
{
CNewMenuItemData* pTemp = m_MenuItemList[j];
if(pTemp==pMenuData || bGetNext==TRUE)
{
bGetNext = TRUE;
pTemp = m_MenuItemList[j+1];
if(pTemp->m_nID)
{
lpMIS->itemData = (ULONG_PTR)pTemp;
lpMIS->itemID = pTemp->m_nID;
UINT nOrgWidth = lpMIS->itemWidth;
MeasureItem_OldStyle(lpMIS,bIsMenuBar);
// Restore old values
lpMIS->itemData = (ULONG_PTR)pMenuData;
lpMIS->itemID = pMenuData->m_nID;
lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
break;
}
}
}
lpMIS->itemHeight = temp;
}
}
}
void CNewMenu::MeasureItem_WinXP( LPMEASUREITEMSTRUCT lpMIS, BOOL bIsMenuBar )
{
ASSERT(lpMIS->itemData);
CNewMenuItemData* pMenuData = (CNewMenuItemData*)(lpMIS->itemData);
UINT state = pMenuData->m_nFlags;
if(state & MF_SEPARATOR)
{
if(pMenuData->m_nTitleFlags&MFT_TITLE)
{
// DC of the desktop
CClientDC myDC(NULL);
CFont font;
LOGFONT MyFont = m_MenuTitleFont;
MyFont.lfOrientation = 0;
MyFont.lfEscapement = 0;
font.CreateFontIndirect(&MyFont);
CFont* pOldFont = myDC.SelectObject (&font);
LPCTSTR lpstrText = pMenuData->GetString();
SIZE size;
VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
// Select old font in
myDC.SelectObject(pOldFont);
if(pMenuData->m_nTitleFlags&MFT_SIDE_TITLE)
{
lpMIS->itemWidth = size.cy - GetSystemMetrics(SM_CXMENUCHECK);
// Don't make the menu higher than menuitems in it
lpMIS->itemHeight = 0;
if(pMenuData->m_nTitleFlags&MFT_LINE)
{
lpMIS->itemWidth += 8;
}
}
else
{
lpMIS->itemWidth = size.cx;//*3/4;
lpMIS->itemHeight = size.cy;//*3/4;
if(pMenuData->m_nTitleFlags&MFT_LINE)
{
lpMIS->itemHeight += 8;
}
}
}
else
{
lpMIS->itemHeight = 3;
}
}
else
{
CFont m_fontMenu;
LOGFONT m_lf;
ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
NONCLIENTMETRICS nm;
nm.cbSize = sizeof (NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, nm.cbSize,&nm,0));
m_lf = nm.lfMenuFont;
// Default selection?
if(state&ODS_DEFAULT)
{
// Make the font bold
m_lf.lfWeight = FW_BOLD;
}
m_fontMenu.CreateFontIndirect (&m_lf);
// DC of the desktop
CClientDC myDC(NULL);
// Select menu font in...
CFont* pOldFont = myDC.SelectObject (&m_fontMenu);
//Get pointer to text SK
const LPCTSTR lpstrText = pMenuData->GetString();
SIZE size;
VERIFY(::GetTextExtentPoint32(myDC.m_hDC,lpstrText,(int)_tcslen(lpstrText),&size));
// Select old font in
myDC.SelectObject(pOldFont);
// Set width and height:
if(bIsMenuBar)
{
lpMIS->itemWidth = size.cx; // - GetSystemMetrics(SM_CXMENUCHECK)/2;
}
else
{
lpMIS->itemWidth = m_iconX + size.cx + m_iconX + GAP;
}
// Check the Key-Shortcut
if(_tcsstr(lpstrText, _T("\t")) != NULL)
lpMIS->itemWidth += 15;
int temp = GetSystemMetrics(SM_CYMENU);
lpMIS->itemHeight = temp>m_iconY+8 ? temp : m_iconY+8;
// set status bar as appropriate
UINT nItemID = (lpMIS->itemID & 0xFFF0);
// Special case for system menu
if (nItemID>=SC_SIZE && nItemID<=SC_HOTKEY)
{
BOOL bGetNext = FALSE;
// search the actual menu item
for (int j=0;j<m_MenuItemList.GetUpperBound();++j)
{
CNewMenuItemData* pTemp = m_MenuItemList[j];
if(pTemp==pMenuData || bGetNext==TRUE)
{
bGetNext = TRUE;
pTemp = m_MenuItemList[j+1];
if(pTemp->m_nID)
{
lpMIS->itemData = (ULONG_PTR)pTemp;
lpMIS->itemID = pTemp->m_nID;
UINT nOrgWidth = lpMIS->itemWidth;
MeasureItem_WinXP(lpMIS,bIsMenuBar);
// Restore old values
lpMIS->itemData = (ULONG_PTR)pMenuData;
lpMIS->itemID = pMenuData->m_nID;
lpMIS->itemWidth = max(lpMIS->itemWidth,nOrgWidth);
break;
}
}
}
lpMIS->itemHeight = temp;
}
}
}
void CNewMenu::SetIconSize (int width, int height)
{
m_iconX = width;
m_iconY = height;
}
BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID, int nIconNormal)
{
return CNewMenu::AppendODMenu(lpstrText,nFlags,nID,(CImageList*)NULL,nIconNormal);
}
BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID,
CBitmap* pBmp)
{
int nIndex = -1;
CNewMenuIconLock iconLock(GetMenuIcon(nIndex,pBmp));
return AppendODMenu(lpstrText,nFlags,nID,iconLock,nIndex);
}
BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID,
CImageList* pil, int xoffset)
{
int nIndex = 0;
// Helper for addref and release
CNewMenuIconLock iconLock(GetMenuIcon(nIndex,nID,pil,xoffset));
return AppendODMenu(lpstrText,nFlags,nID,iconLock,nIndex);
}
BOOL CNewMenu::AppendODMenu(LPCTSTR lpstrText, UINT nFlags, UINT nID,
CNewMenuIcons* pIcons, int nIndex)
{
// Add the MF_OWNERDRAW flag if not specified:
if(!nID)
{
if(nFlags&MF_BYPOSITION)
nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
else
nFlags=MF_SEPARATOR|MF_OWNERDRAW;
}
else if(!(nFlags & MF_OWNERDRAW))
{
nFlags |= MF_OWNERDRAW;
}
if(nFlags & MF_POPUP)
{
CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nID)));
if(pSubMenu)
{
pSubMenu->m_hParentMenu = m_hMenu;
}
}
CNewMenuItemData* pItemData = new CNewMenuItemData;
m_MenuItemList.Add(pItemData);
pItemData->SetString(lpstrText);
pIcons->AddRef();
pItemData->m_pMenuIcon->Release();
pItemData->m_pMenuIcon = pIcons;
pItemData->m_nFlags = nFlags;
pItemData->m_nID = nID;
if(pIcons && nIndex>=0)
{
pItemData->m_nMenuIconOffset = nIndex;
CSize size = pIcons->GetIconSize();
m_iconX = max(m_iconX,size.cx);
m_iconY = max(m_iconY,size.cy);
}
else
{
pItemData->m_nMenuIconOffset = -1;
}
return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)pItemData));
}
BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID,
int nIconNormal)
{
int nIndex = -1;
CNewMenuIcons* pIcons=NULL;
if(nIconNormal>=0)
{
if(LoadFromToolBar(nID,nIconNormal,nIndex))
{
// the nIconNormal is a toolbar
pIcons = GetToolbarIcons(nIconNormal);
if(pIcons)
{
nIndex = pIcons->FindIndex(nID);
}
}
else
{
// the nIconNormal is a bitmap
pIcons = GetMenuIcon(nIndex,nIconNormal);
}
}
CNewMenuIconLock iconLock(pIcons);
return InsertODMenu(nPosition,lpstrText,nFlags,nID,iconLock,nIndex);
}
BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID,
CBitmap* pBmp)
{
int nIndex = -1;
CNewMenuIconLock iconLock(GetMenuIcon(nIndex,pBmp));
return InsertODMenu(nPosition,lpstrText,nFlags,nID,iconLock,nIndex);
}
BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID,
CImageList *pil, int xoffset)
{
int nIndex = -1;
CNewMenuIconLock iconLock(GetMenuIcon(nIndex,nID,pil,xoffset));
return InsertODMenu(nPosition,lpstrText,nFlags,nID,iconLock,nIndex);
}
BOOL CNewMenu::InsertODMenu(UINT nPosition, LPCTSTR lpstrText, UINT nFlags, UINT nID,
CNewMenuIcons* pIcons, int nIndex)
{
if(!(nFlags & MF_BYPOSITION))
{
int iPosition =0;
CNewMenu* pMenu = FindMenuOption(nPosition,iPosition);
if(pMenu)
{
return(pMenu->InsertODMenu(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,pIcons,nIndex));
}
else
return(FALSE);
}
if(!nID)
{
nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
}
else if(!(nFlags & MF_OWNERDRAW))
{
nFlags |= MF_OWNERDRAW;
}
if(nFlags & MF_POPUP)
{
CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nID)));
if(pSubMenu)
{
pSubMenu->m_hParentMenu = m_hMenu;
}
}
//Stephane Clog suggested adding this, believe it or not it's in the help
if(nPosition==(UINT)-1)
nPosition=GetMenuItemCount();
CNewMenuItemData *pItemData = new CNewMenuItemData;
m_MenuItemList.InsertAt(nPosition,pItemData);
pItemData->SetString(lpstrText);
pIcons->AddRef();
pItemData->m_pMenuIcon->Release();
pItemData->m_pMenuIcon = pIcons;
pItemData->m_nFlags = nFlags;
pItemData->m_nID = nID;
if(pIcons && nIndex>=0)
{
pItemData->m_nMenuIconOffset = nIndex;
CSize size = pIcons->GetIconSize();
m_iconX = max(m_iconX,size.cx);
m_iconY = max(m_iconY,size.cy);
}
else
{
pItemData->m_nMenuIconOffset = -1;
}
return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)pItemData));
}
BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, int nIconNormal)
{
int nLoc;
CNewMenuItemData* pItemData;
CArray<CNewMenu*,CNewMenu*>newSubs;
CArray<int,int&>newLocs;
// Find the old CNewMenuItemData structure:
CNewMenu *pSubMenu = FindMenuOption(nID,nLoc);
do {
if(pSubMenu && nLoc>=0)
{
pItemData = pSubMenu->m_MenuItemList[nLoc];
}
else
{
// Create a new CNewMenuItemData structure:
pItemData = new CNewMenuItemData;
m_MenuItemList.Add(pItemData);
}
ASSERT(pItemData);
if(lpstrText)
{
pItemData->SetString(lpstrText);
}
pItemData->m_nMenuIconOffset=-1;
if(nIconNormal>=0)
{
int nxOffset = -1;
CNewMenuIcons* pIcons=NULL;
if(LoadFromToolBar(nID,nIconNormal,nxOffset))
{
// the nIconNormal is a toolbar
pIcons = GetToolbarIcons(nIconNormal);
if(pIcons)
{
pItemData->m_nMenuIconOffset = pIcons->FindIndex(nID);
}
}
else
{
// the nIconNormal is a bitmap
pIcons = GetMenuIcon(pItemData->m_nMenuIconOffset,nIconNormal);
}
pIcons->AddRef();
pItemData->m_pMenuIcon->Release();
pItemData->m_pMenuIcon = pIcons;
if(pIcons)
{
CSize size = pIcons->GetIconSize();
pSubMenu->m_iconX = max(pSubMenu->m_iconX,size.cx);
pSubMenu->m_iconY = max(pSubMenu->m_iconY,size.cy);
}
}
pItemData->m_nFlags &= ~(MF_BYPOSITION);
pItemData->m_nFlags |= MF_OWNERDRAW;
pItemData->m_nID = nID;
newSubs.Add(pSubMenu);
newLocs.Add(nLoc);
if(pSubMenu && nLoc>=0)
pSubMenu = FindAnotherMenuOption(nID,nLoc,newSubs,newLocs);
else
pSubMenu=NULL;
}while(pSubMenu);
return (CMenu::ModifyMenu(nID,pItemData->m_nFlags,nID,(LPCTSTR)pItemData));
}
BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, CImageList *pil, int xoffset)
{
int nIndex = 0;
CNewMenuIcons* pIcons = GetMenuIcon(nIndex,nID,pil,xoffset);
pIcons->AddRef();
BOOL bResult = ModifyODMenu(lpstrText,nID,pIcons,nIndex);
pIcons->Release();
return bResult;
}
BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, CNewMenuIcons* pIcons, int xoffset)
{
ASSERT(pIcons);
int nLoc;
CNewMenuItemData *pItemData;
CArray<CNewMenu*,CNewMenu*>newSubs;
CArray<int,int&>newLocs;
// Find the old CNewMenuItemData structure:
CNewMenu *pSubMenu = FindMenuOption(nID,nLoc);
do {
if(pSubMenu && nLoc>=0)
{
pItemData = pSubMenu->m_MenuItemList[nLoc];
}
else
{
// Create a new CNewMenuItemData structure:
pItemData = new CNewMenuItemData;
m_MenuItemList.Add(pItemData);
}
ASSERT(pItemData);
if(lpstrText)
{
pItemData->SetString(lpstrText);
}
if(pIcons)
{
pIcons->AddRef();
pItemData->m_pMenuIcon->Release();
pItemData->m_pMenuIcon = pIcons;
pItemData->m_nMenuIconOffset = xoffset;
int x=0;
int y=0;
if(pSubMenu && pIcons->GetIconSize(&x,&y))
{
// Correct the size of the menuitem
pSubMenu->m_iconX = max(pSubMenu->m_iconX,x);
pSubMenu->m_iconY = max(pSubMenu->m_iconY,y);
}
}
else
{
pItemData->m_nMenuIconOffset = -1;
}
pItemData->m_nFlags &= ~(MF_BYPOSITION);
pItemData->m_nFlags |= MF_OWNERDRAW;
pItemData->m_nID = nID;
newSubs.Add(pSubMenu);
newLocs.Add(nLoc);
if(pSubMenu && nLoc>=0)
pSubMenu = FindAnotherMenuOption(nID,nLoc,newSubs,newLocs);
else
pSubMenu=NULL;
} while(pSubMenu);
return (CMenu::ModifyMenu(nID,pItemData->m_nFlags,nID,(LPCTSTR)pItemData));
}
BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, CBitmap* bmp)
{
if (bmp)
{
CImageList temp;
temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
temp.Add(bmp,GetBitmapBackground());
return ModifyODMenu(lpstrText,nID,&temp,0);
}
return ModifyODMenu(lpstrText,nID,(CImageList*)NULL,0);
}
BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, UINT nID, COLORREF fill, COLORREF border, int hatchstyle)
{
// Get device context
CClientDC DC(0);
CSize bitmap_size(m_iconX,m_iconY);
CBitmap bmp;
ColorBitmap(&DC,bmp,bitmap_size,fill,border,hatchstyle);
return ModifyODMenu(lpstrText,nID,&bmp);
}
BOOL CNewMenu::ModifyODMenu(LPCTSTR lpstrText, LPCTSTR OptionText, int nIconNormal)
{
int nIndex = 0;
CNewMenu* pOptionMenu = FindMenuOption(OptionText,nIndex);
if(pOptionMenu!=NULL && nIndex>=0)
{
CNewMenuItemData* pItemData = pOptionMenu->m_MenuItemList[nIndex];
if(lpstrText)
{
pItemData->SetString(lpstrText);
}
pItemData->m_nMenuIconOffset = nIconNormal;
if(nIconNormal>=0)
{
CNewMenuIcons* pIcons = GetMenuIcon(pItemData->m_nMenuIconOffset,nIconNormal);
pIcons->AddRef();
pItemData->m_pMenuIcon->Release();
pItemData->m_pMenuIcon = pIcons;
CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,pItemData->m_pMenuIcon);
if(pMenuIcon)
{
CSize size = pMenuIcon->GetIconSize();
pOptionMenu->m_iconX = max(pOptionMenu->m_iconX,size.cx);
pOptionMenu->m_iconY = max(pOptionMenu->m_iconY,size.cy);
}
}
return TRUE;
}
return FALSE;
}
CNewMenuItemData* CNewMenu::NewODMenu(UINT pos, UINT nFlags, UINT nID, LPCTSTR string)
{
CNewMenuItemData* pItemData;
pItemData = new CNewMenuItemData;
pItemData->m_nFlags = nFlags;
pItemData->m_nID = nID;
pItemData->SetString (string);
if(nFlags & MF_POPUP)
{
CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(UIntToHMenu(nID)));
if(pSubMenu)
{
pSubMenu->m_hParentMenu = m_hMenu;
}
}
if (nFlags&MF_OWNERDRAW)
{
ASSERT(!(nFlags&MF_STRING));
ModifyMenu(pos,nFlags,nID,(LPCTSTR)pItemData);
}
else if (nFlags&MF_BITMAP)
{
ModifyMenu(pos,nFlags,nID,(CBitmap*)string);
}
else if (nFlags&MF_SEPARATOR)
{
ASSERT(nFlags&MF_SEPARATOR);
ModifyMenu(pos,nFlags,nID);
}
else // (nFlags&MF_STRING)
{
ASSERT(!(nFlags&MF_OWNERDRAW));
ModifyMenu(pos,nFlags,nID,pItemData->GetString());
}
return(pItemData);
};
BOOL CNewMenu::LoadToolBars(const UINT* arID, int n, HMODULE hInst)
{
ASSERT(arID);
BOOL returnflag=TRUE;
for(int i=0;i<n;++i)
{
if(!LoadToolBar(arID[i],hInst))
returnflag=FALSE;
}
return(returnflag);
}
DWORD CNewMenu::SetMenuIcons(CNewMenuIcons* pMenuIcons)
{
int nCount = (int)pMenuIcons->m_IDs.GetSize();
while(nCount--)
{
ModifyODMenu(NULL,pMenuIcons->m_IDs[nCount],pMenuIcons,nCount*MENU_ICONS);
}
return pMenuIcons->m_dwRefCount;
}
CNewMenuIcons* CNewMenu::GetMenuIcon(int &nIndex, UINT nID, CImageList *pil, int xoffset)
{
if(pil==NULL || xoffset<0)
{
nIndex=-1;
return NULL;
}
HICON hIcon = pil->ExtractIcon(xoffset);
if(m_pSharedMenuIcons!=NULL)
{
POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
while(pos)
{
CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,m_pSharedMenuIcons->GetNext(pos));
if(pMenuIcon)
{
nIndex = pMenuIcon->Add(hIcon,nID);
if(nIndex!=-1)
{
DestroyIcon(hIcon);
return pMenuIcon;
}
}
}
}
else
{
m_pSharedMenuIcons = new CTypedPtrList<CPtrList, CNewMenuIcons*>;
}
CNewMenuBitmaps* pMenuIcon = new CNewMenuBitmaps();
pMenuIcon->m_crTransparent = m_bitmapBackground;
nIndex = pMenuIcon->Add(hIcon,nID);
DestroyIcon(hIcon);
if(nIndex!=-1)
{
m_pSharedMenuIcons->AddTail(pMenuIcon);
return pMenuIcon;
}
delete pMenuIcon;
return NULL;
}
CNewMenuIcons* CNewMenu::GetMenuIcon(int &nIndex, int nID)
{
if(m_pSharedMenuIcons!=NULL)
{
POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
while(pos)
{
CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,m_pSharedMenuIcons->GetNext(pos));
if(pMenuIcon)
{
if(m_bDynIcons)
{
nIndex = pMenuIcon->Add((HICON)(INT_PTR)nID);
}
else
{
nIndex = pMenuIcon->Add(nID,m_bitmapBackground);
}
if(nIndex!=-1)
return pMenuIcon;
}
}
}
else
{
m_pSharedMenuIcons = new CTypedPtrList<CPtrList, CNewMenuIcons*>;
}
CNewMenuBitmaps* pMenuIcon = new CNewMenuBitmaps();
pMenuIcon->m_crTransparent = m_bitmapBackground;
nIndex = pMenuIcon->Add(nID,m_bitmapBackground);
if(nIndex!=-1)
{
m_pSharedMenuIcons->AddTail(pMenuIcon);
return pMenuIcon;
}
delete pMenuIcon;
return NULL;
}
CNewMenuIcons* CNewMenu::GetMenuIcon(int &nIndex, CBitmap* pBmp)
{
if(pBmp==NULL)
{
nIndex=-1;
return NULL;
}
if(m_pSharedMenuIcons!=NULL)
{
POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
while(pos)
{
CNewMenuBitmaps* pMenuIcon = DYNAMIC_DOWNCAST(CNewMenuBitmaps,m_pSharedMenuIcons->GetNext(pos));
if(pMenuIcon)
{
nIndex = pMenuIcon->Add(pBmp,m_bitmapBackground);
if(nIndex!=-1)
return pMenuIcon;
}
}
}
else
{
m_pSharedMenuIcons = new CTypedPtrList<CPtrList, CNewMenuIcons*>;
}
CNewMenuBitmaps* pMenuIcon = new CNewMenuBitmaps();
pMenuIcon->m_crTransparent = m_bitmapBackground;
nIndex = pMenuIcon->Add(pBmp,m_bitmapBackground);
if(nIndex!=-1)
{
m_pSharedMenuIcons->AddTail(pMenuIcon);
return pMenuIcon;
}
delete pMenuIcon;
return NULL;
}
CNewMenuIcons* CNewMenu::GetToolbarIcons(UINT nToolBar, HMODULE hInst)
{
ASSERT_VALID(this);
ASSERT(nToolBar != NULL);
if(m_pSharedMenuIcons!=NULL)
{
POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
while(pos)
{
CNewMenuIcons* pMenuIcon = m_pSharedMenuIcons->GetNext(pos);
if(pMenuIcon->DoMatch(MAKEINTRESOURCE(nToolBar),hInst))
{
return pMenuIcon;
}
}
}
else
{
m_pSharedMenuIcons = new CTypedPtrList<CPtrList, CNewMenuIcons*>;
}
CNewMenuIcons* pMenuIcon = new CNewMenuIcons();
pMenuIcon->m_crTransparent = m_bitmapBackground;
if(pMenuIcon->LoadToolBar(MAKEINTRESOURCE(nToolBar),hInst))
{
m_pSharedMenuIcons->AddTail(pMenuIcon);
return pMenuIcon;
}
delete pMenuIcon;
return NULL;
}
BOOL CNewMenu::LoadToolBar(LPCTSTR lpszResourceName, HMODULE hInst)
{
CNewMenuIcons* pMenuIcon = GetToolbarIcons((UINT)(UINT_PTR)lpszResourceName,hInst);
if(pMenuIcon)
{
SetMenuIcons(pMenuIcon);
return TRUE;
}
return FALSE;
}
BOOL CNewMenu::LoadToolBar(WORD* pToolInfo, COLORREF crTransparent)
{
ASSERT_VALID(this);
ASSERT(pToolInfo);
if(crTransparent==CLR_NONE)
crTransparent = m_bitmapBackground;
if(m_pSharedMenuIcons!=NULL)
{
POSITION pos = m_pSharedMenuIcons->GetHeadPosition();
while(pos)
{
CNewMenuIcons* pMenuIcon = m_pSharedMenuIcons->GetNext(pos);
if(pMenuIcon->DoMatch(pToolInfo,crTransparent))
{
SetMenuIcons(pMenuIcon);
return TRUE;
}
}
}
else
{
m_pSharedMenuIcons = new CTypedPtrList<CPtrList, CNewMenuIcons*>;
}
CNewMenuIcons* pMenuIcon = new CNewMenuIcons();
if(pMenuIcon->LoadToolBar(pToolInfo,crTransparent))
{
m_pSharedMenuIcons->AddTail(pMenuIcon);
SetMenuIcons(pMenuIcon);
return TRUE;
}
delete pMenuIcon;
return FALSE;
}
BOOL CNewMenu::LoadToolBar(UINT nToolBar, HMODULE hInst)
{
return LoadToolBar((LPCTSTR)(UINT_PTR)nToolBar,hInst);
}
BOOL CNewMenu::LoadFromToolBar(UINT nID, UINT nToolBar, int& xoffset)
{
int xset,offset;
UINT nStyle;
BOOL returnflag=FALSE;
CToolBar bar;
CWnd* pWnd = AfxGetMainWnd();
if (pWnd == NULL)
{
pWnd = CWnd::GetDesktopWindow();
}
bar.Create(pWnd);
if(bar.LoadToolBar(nToolBar))
{
offset=bar.CommandToIndex(nID);
if(offset>=0)
{
bar.GetButtonInfo(offset,nID,nStyle,xset);
if(xset>0)
xoffset=xset;
returnflag=TRUE;
}
}
return returnflag;
}
// O.S.
CNewMenuItemData* CNewMenu::FindMenuItem(UINT nID)
{
CNewMenuItemData *pData = NULL;
int i;
for(i = 0; i <= m_MenuItemList.GetUpperBound(); i++)
{
if (m_MenuItemList[i]->m_nID == nID)
{
pData = m_MenuItemList[i];
break;
}
}
if (!pData)
{
int loc;
CNewMenu *pMenu = FindMenuOption(nID, loc);
ASSERT(pMenu != this);
if (loc >= 0)
{
return pMenu->FindMenuItem(nID);
}
}
return pData;
}
CNewMenu* CNewMenu::FindAnotherMenuOption(int nId, int& nLoc,
CArray<CNewMenu*,CNewMenu*>&newSubs,
CArray<int,int&>&newLocs)
{
int i,numsubs,j;
CNewMenu *pSubMenu,*pgoodmenu;
BOOL foundflag;
for(i=0;i<(int)(GetMenuItemCount());++i)
{
pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
if(pSubMenu)
{
pgoodmenu=pSubMenu->FindAnotherMenuOption(nId,nLoc,newSubs,newLocs);
if(pgoodmenu)
return(pgoodmenu);
}
else if(nId==(int)GetMenuItemID(i))
{
numsubs = (int)newSubs.GetSize();
foundflag=TRUE;
for(j=0;j<numsubs;++j)
{
if(newSubs[j]==this&&newLocs[j]==i)
{
foundflag=FALSE;
break;
}
}
if(foundflag)
{
nLoc=i;
return(this);
}
}
}
nLoc = -1;
return(NULL);
}
CNewMenu* CNewMenu::FindMenuOption(int nId, int& nLoc)
{
int i;
CNewMenu *pSubMenu,*pgoodmenu;
for(i=0;i<(int)(GetMenuItemCount());++i)
{
pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
if(pSubMenu)
{
pgoodmenu=pSubMenu->FindMenuOption(nId,nLoc);
if(pgoodmenu)
return(pgoodmenu);
}
else if(nId==(int)GetMenuItemID(i))
{
nLoc=i;
return(this);
}
}
nLoc = -1;
return NULL;
}
CNewMenu* CNewMenu::FindMenuOption(LPCTSTR lpstrText, int& nLoc)
{
int i;
// First look for all item text.
for(i=0;i<=(int)m_MenuItemList.GetUpperBound();++i)
{
if(m_MenuItemList[i]->m_szMenuText.Compare(lpstrText)==NULL)
{
nLoc = i;
return this;
}
}
CNewMenu* pSubMenu;
// next, look in all submenus
for(i=0; i<(int)(GetMenuItemCount());++i)
{
pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,GetSubMenu(i));
if(pSubMenu)
{
pSubMenu = pSubMenu->FindMenuOption(lpstrText,nLoc);
if(pSubMenu)
{
return pSubMenu;
}
}
}
nLoc = -1;
return NULL;
}
BOOL CNewMenu::LoadMenu(HMENU hMenu)
{
if(!::IsMenu(hMenu) || !Attach(hMenu))
{
return FALSE;
}
m_bIsPopupMenu = FALSE;
for(int i=0;i<(int)(GetMenuItemCount());++i)
{
HMENU hSubMenu = ::GetSubMenu(m_hMenu,i);
if(hSubMenu)
{
CNewMenu* pMenu = new CNewMenu(m_hMenu);
m_SubMenus.Add(hSubMenu);
pMenu->LoadMenu(hSubMenu);
pMenu->m_bIsPopupMenu = TRUE;
}
}
SynchronizeMenu();
return TRUE;
}
BOOL CNewMenu::LoadMenu(int nResource)
{
return(CNewMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
}
BOOL CNewMenu::LoadMenu(LPCTSTR lpszResourceName)
{
HMENU hMenu = ::LoadMenu(AfxFindResourceHandle(lpszResourceName,RT_MENU), lpszResourceName);
return LoadMenu(hMenu);
}
BOOL CNewMenu::SetItemData(UINT uiId, DWORD_PTR dwItemData, BOOL fByPos)
{
MENUITEMINFO MenuItemInfo;
ZeroMemory(&MenuItemInfo,sizeof(MenuItemInfo));
MenuItemInfo.cbSize = sizeof(MenuItemInfo);
MenuItemInfo.fMask = MIIM_DATA;
if(::GetMenuItemInfo(m_hMenu,uiId,fByPos,&MenuItemInfo))
{
CNewMenuItemData* pItem = CheckMenuItemData(MenuItemInfo.dwItemData);
if(pItem)
{
pItem->m_pData = (void*)dwItemData;
return TRUE;
}
}
return FALSE;
}
BOOL CNewMenu::SetItemDataPtr(UINT uiId, void* pItemData, BOOL fByPos )
{
return SetItemData(uiId, (DWORD_PTR) pItemData, fByPos);
}
DWORD_PTR CNewMenu::GetItemData(UINT uiId, BOOL fByPos) const
{
MENUITEMINFO MenuItemInfo;
ZeroMemory(&MenuItemInfo,sizeof(MenuItemInfo));
MenuItemInfo.cbSize = sizeof(MenuItemInfo);
MenuItemInfo.fMask = MIIM_DATA;
if(::GetMenuItemInfo(m_hMenu,uiId,fByPos,&MenuItemInfo))
{
CNewMenuItemData* pItem = CheckMenuItemData(MenuItemInfo.dwItemData);
if(pItem)
{
return (DWORD_PTR)pItem->m_pData;
}
}
return DWORD_PTR(-1);
}
void* CNewMenu::GetItemDataPtr(UINT uiId, BOOL fByPos) const
{
return (void*)GetItemData(uiId,fByPos);
}
BOOL CNewMenu::SetMenuData(DWORD_PTR dwMenuData)
{
m_pData = (void*)dwMenuData;
return TRUE;
}
BOOL CNewMenu::SetMenuDataPtr(void* pMenuData)
{
m_pData = (void*)pMenuData;
return TRUE;
}
DWORD_PTR CNewMenu::GetMenuData() const
{
return (DWORD_PTR)m_pData;
}
void* CNewMenu::GetMenuDataPtr() const
{
return m_pData;
}
void CNewMenu::LoadCheckmarkBitmap(int unselect, int select)
{
if(unselect>0 && select>0)
{
m_selectcheck=select;
m_unselectcheck=unselect;
if(m_checkmaps)
m_checkmaps->DeleteImageList();
else
m_checkmaps=new(CImageList);
m_checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
BOOL flag1=AddBitmapToImageList(m_checkmaps,unselect);
BOOL flag2=AddBitmapToImageList(m_checkmaps,select);
if(!flag1||!flag2)
{
m_checkmaps->DeleteImageList();
delete m_checkmaps;
m_checkmaps=NULL;
}
}
}
BOOL CNewMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
{
BOOL returnflag=FALSE;
if(MF_BYPOSITION&nFlags)
{
UINT numMenuItems = (int)m_MenuItemList.GetUpperBound();
if(id<=numMenuItems)
{
string=m_MenuItemList[id]->GetString();
returnflag=TRUE;
}
}
else
{
int uiLoc;
CNewMenu* pMenu = FindMenuOption(id,uiLoc);
if(NULL!=pMenu)
{
returnflag = pMenu->GetMenuText(uiLoc,string);
}
}
return returnflag;
}
CNewMenuItemData* CNewMenu::CheckMenuItemData(ULONG_PTR nItemData) const
{
for(int i=0;i<=m_MenuItemList.GetUpperBound();++i)
{
CNewMenuItemData* pItem = m_MenuItemList[i];
if ( ((ULONG_PTR)pItem)==nItemData )
{
return pItem;
}
}
return NULL;
}
CNewMenuItemData* CNewMenu::FindMenuList(UINT nID)
{
for(int i=0;i<=m_MenuItemList.GetUpperBound();++i)
{
CNewMenuItemData* pMenuItem = m_MenuItemList[i];
if(pMenuItem->m_nID==nID && !pMenuItem->m_nSyncFlag)
{
pMenuItem->m_nSyncFlag=1;
return(pMenuItem);
}
}
return(NULL);
}
void CNewMenu::InitializeMenuList(int value)
{
for(int i=0;i<=m_MenuItemList.GetUpperBound();++i)
{
m_MenuItemList[i]->m_nSyncFlag=value;
}
}
void CNewMenu::DeleteMenuList()
{
for(int i=0;i<=m_MenuItemList.GetUpperBound();++i)
{
if(!m_MenuItemList[i]->m_nSyncFlag)
{
delete m_MenuItemList[i];
}
}
}
void CNewMenu::SynchronizeMenu()
{
CTypedPtrArray<CPtrArray, CNewMenuItemData*> temp;
CNewMenuItemData *pItemData;
CString string;
UINT submenu,state,j;
InitializeMenuList(0);
for(j=0;j<GetMenuItemCount();++j)
{
pItemData=NULL;
state=GetMenuState(j,MF_BYPOSITION);
// item doesn't exist
if(state==0xFFFFFFFF)
{
break;
}
if(state&MF_POPUP)
{
HMENU hSubMenu = GetSubMenu(j)->m_hMenu;
submenu=HMenuToUInt(hSubMenu);
pItemData=FindMenuList(submenu);
GetMenuString(j,string,MF_BYPOSITION);
if(!pItemData)
{
state &= ~(MF_USECHECKBITMAPS|MF_SEPARATOR);
pItemData=NewODMenu(j,state|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
}
else if(!string.IsEmpty ())
{
pItemData->SetString(string);
}
CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hSubMenu));
if(pSubMenu && pSubMenu->m_hParentMenu!=m_hMenu)
{ // Sets again the parent to this one
pSubMenu->m_hParentMenu = m_hMenu;
}
}
else if(state&MF_SEPARATOR)
{
pItemData=FindMenuList(0);
if(!pItemData)
pItemData=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,0,_T(""));
else
{
pItemData->m_nFlags = state|MF_BYPOSITION|MF_OWNERDRAW;
ModifyMenu(j,pItemData->m_nFlags,0,(LPCTSTR)pItemData);
}
}
else
{
UINT nID=GetMenuItemID(j);
pItemData=FindMenuList(nID);
GetMenuString(j,string,MF_BYPOSITION);
if(!pItemData)
{
pItemData=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,nID,string);
}
else
{
pItemData->m_nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
if(string.GetLength()>0)
{
pItemData->SetString(string);
}
ModifyMenu(j,pItemData->m_nFlags,nID,(LPCTSTR)pItemData);
}
}
if(pItemData)
temp.Add(pItemData);
}
DeleteMenuList();
m_MenuItemList.RemoveAll();
m_MenuItemList.Append(temp);
temp.RemoveAll();
}
void CNewMenu::OnInitMenuPopup(HWND hWnd, CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
UNREFERENCED_PARAMETER(nIndex);
UNREFERENCED_PARAMETER(bSysMenu);
#ifdef _TRACE_MENU_
TRACE(_T("InitMenuPopup: 0x%lx from Wnd 0x%lx\n"),HMenuToUInt(pPopupMenu->m_hMenu),HWndToUInt(hWnd));
#endif
CNewMenuHook::m_hLastMenu = pPopupMenu->m_hMenu;
if(pPopupMenu->m_hMenu)
{
CNewMenu* pSubMenu = DYNAMIC_DOWNCAST(CNewMenu,pPopupMenu);
if(pSubMenu)
{
pSubMenu->OnInitMenuPopup();
HMENU hMenu = pSubMenu->GetParent();
CNewMenu* pParent = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
if(pParent)
{
pParent->m_dwOpenMenu += 1;
if(pParent->m_dwOpenMenu==1 && !pParent->m_bIsPopupMenu)
{
// Redraw the menubar for the shade
CRect rect = pParent->GetLastActiveMenuRect();
if(!rect.IsRectEmpty())
{
rect.InflateRect(0,0,10,10);
CPoint Point(0,0);
ClientToScreen(hWnd,&Point);
rect.OffsetRect(-Point);
RedrawWindow(hWnd,rect,0,RDW_FRAME|RDW_INVALIDATE);
}
}
}
}
}
}
BOOL CNewMenu::Replace(UINT nID, UINT nNewID)
{
int nLoc=0;
CNewMenu* pTempMenu = FindMenuOption(nID,nLoc);
if(pTempMenu && nLoc >= 0)
{
CNewMenuItemData* pData = pTempMenu->m_MenuItemList[nLoc];
UINT nFlags = pData->m_nFlags|MF_OWNERDRAW|MF_BYPOSITION;
pData->m_nID = nNewID;
pTempMenu->ModifyMenu(nLoc,nFlags,nNewID,(LPCTSTR)pData);
return TRUE;
}
return FALSE;
}
void CNewMenu::OnInitMenuPopup()
{
m_bIsPopupMenu = true;
SynchronizeMenu();
// Special purpose for windows XP with themes!!!
if(g_Shell==WinXP)
{
Replace(SC_RESTORE,SC_RESTORE+1);
Replace(SC_CLOSE,SC_CLOSE+1);
Replace(SC_MINIMIZE,SC_MINIMIZE+1);
}
}
BOOL CNewMenu::OnUnInitPopupMenu(HWND hWnd)
{
#ifdef _TRACE_MENU_
TRACE(_T("UnInitMenuPopup: 0x%lx\n"),HMenuToUInt(m_hMenu));
#endif
if(g_Shell==WinXP)
{
// Special purpose for windows XP with themes!!!
// Restore old values otherwise you have disabled windowbuttons
Replace(SC_RESTORE+1,SC_RESTORE);
Replace(SC_CLOSE+1,SC_CLOSE);
Replace(SC_MINIMIZE+1,SC_MINIMIZE);
}
HMENU hMenu = GetParent();
CNewMenu* pParent = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
if(pParent)
{
pParent->m_dwOpenMenu -= 1;
if(pParent->m_dwOpenMenu>=NULL && !pParent->m_bIsPopupMenu)
{
pParent->m_dwOpenMenu = 0;
// Redraw the menubar for the shade
CRect rect = pParent->GetLastActiveMenuRect();
if(!rect.IsRectEmpty())
{
rect.InflateRect(0,0,10,10);
CPoint Point(0,0);
ClientToScreen(hWnd,&Point);
rect.OffsetRect(-Point);
RedrawWindow(hWnd,rect,0,RDW_FRAME|RDW_INVALIDATE);
}
return TRUE;
}
}
return FALSE;
}
LRESULT CNewMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags, CMenu* pMenu)
{
UNREFERENCED_PARAMETER(nFlags);
CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,pMenu);
if(pNewMenu)
{
//SK: modified for Unicode correctness
CString key(_T('&'),2);
key.SetAt(1,(TCHAR)nChar);
key.MakeLower();
CString menutext;
int menusize = (int)pNewMenu->GetMenuItemCount();
if(menusize!=(pNewMenu->m_MenuItemList.GetUpperBound()+1))
{
pNewMenu->SynchronizeMenu();
}
for(int i=0;i<menusize;++i)
{
if(pNewMenu->GetMenuText(i,menutext))
{
menutext.MakeLower();
if(menutext.Find(key)>=0)
{
return(MAKELRESULT(i,2));
}
}
}
}
return NULL;
}
BOOL CNewMenu::AddBitmapToImageList(CImageList* bmplist,UINT nResourceID)
{
// O.S.
if (m_bDynIcons)
{
bmplist->Add((HICON)(UINT_PTR)nResourceID);
return TRUE;
}
CBitmap mybmp;
HBITMAP hbmp = LoadSysColorBitmap(nResourceID);
if(hbmp)
{
// Object will be destroyd by destructor of CBitmap
mybmp.Attach(hbmp);
}
else
{
mybmp.LoadBitmap(nResourceID);
}
if (mybmp.m_hObject && bmplist->Add(&mybmp,GetBitmapBackground())>=0 )
{
return TRUE;
}
return FALSE;
}
COLORREF CNewMenu::SetBitmapBackground(COLORREF newColor)
{
COLORREF oldColor = m_bitmapBackground;
m_bitmapBackground = newColor;
return oldColor;
}
COLORREF CNewMenu::GetBitmapBackground()
{
if(m_bitmapBackground==CLR_DEFAULT)
return GetSysColor(COLOR_3DFACE);
return m_bitmapBackground;
}
BOOL CNewMenu::Draw3DCheckmark(CDC *pDC, const CRect& rc, HBITMAP hbmCheck, DWORD dwStyle)
{
CRect rect(rc);
rect.InflateRect (-1,-1);
if (IsNewShell()) //SK: looks better on the old shell
pDC->DrawEdge(rect, BDR_SUNKENOUTER, BF_RECT);
rect.InflateRect (2,2);
if (!hbmCheck)
{
// Checkmark
rect.OffsetRect(1,2);
DrawSpecialCharStyle(pDC,rect,98,dwStyle);
}
else
{
// Bullet
DrawSpecialCharStyle(pDC,rect,105,dwStyle);
}
return TRUE;
}
HBITMAP CNewMenu::LoadSysColorBitmap(int nResourceId)
{
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
if (hRsrc == NULL)
return NULL;
// determine how many colors in the bitmap
HGLOBAL hglb;
if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
return NULL;
LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
if (lpBitmap == NULL)
return NULL;
WORD numcol = NumBitmapColors(lpBitmap);
::FreeResource(hglb);
if(numcol!=16)
{
return(NULL);
}
return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
}
// sPos means Seperator's position, since we have no way to find the
// seperator's position in the menu we have to specify them when we call the
// RemoveMenu to make sure the unused seperators are removed;
// sPos = None no seperator removal;
// = Head seperator in front of this menu item;
// = Tail seperator right after this menu item;
// = Both seperators at both ends;
// remove the menu item based on their text, return -1 if not found, otherwise
// return the menu position;
int CNewMenu::RemoveMenu(LPCTSTR pText, ESeperator sPos)
{
int nPos = GetMenuPosition(pText);
if(nPos != -1)
{
switch (sPos)
{
case CNewMenu::NONE:
RemoveMenu(nPos, MF_BYPOSITION);
break;
case CNewMenu::HEAD:
ASSERT(nPos - 1 >= 0);
RemoveMenu(nPos-1, MF_BYPOSITION);
break;
case CNewMenu::TAIL:
RemoveMenu(nPos+1, MF_BYPOSITION);
break;
case CNewMenu::BOTH:
// remove the end first;
RemoveMenu(nPos+1, MF_BYPOSITION);
// remove the head;
ASSERT(nPos - 1 >= 0);
RemoveMenu(nPos-1, MF_BYPOSITION);
break;
}
}
return nPos;
}
BOOL CNewMenu::RemoveMenu(UINT uiId, UINT nFlags)
{
if(MF_BYPOSITION&nFlags)
{
UINT nItemState = GetMenuState(uiId,MF_BYPOSITION);
if((nItemState&MF_SEPARATOR) && !(nItemState&MF_POPUP))
{
CNewMenuItemData* pData = m_MenuItemList.GetAt(uiId);
m_MenuItemList.RemoveAt(uiId);
delete pData;
}
else
{
CMenu* pSubMenu = GetSubMenu(uiId);
if(NULL==pSubMenu)
{
UINT uiCommandId = GetMenuItemID(uiId);
for(int i=0;i<m_MenuItemList.GetSize(); i++)
{
if(m_MenuItemList[i]->m_nID==uiCommandId)
{
CNewMenuItemData* pData = m_MenuItemList.GetAt(i);
m_MenuItemList.RemoveAt(i);
delete pData;
break;
}
}
}
else
{
// Only remove the menu.
int numSubMenus = (int)m_SubMenus.GetUpperBound();
for(int m = numSubMenus; m >= 0; m--)
{
if(m_SubMenus[m]==pSubMenu->m_hMenu)
{
m_SubMenus.RemoveAt(m);
}
}
// int num = pSubMenu->GetMenuItemCount();
// for(int i=num-1;i>=0;--i)
// {
// pSubMenu->RemoveMenu(i,MF_BYPOSITION);
// }
for(int i=(int)m_MenuItemList.GetUpperBound();i>=0;i--)
{
if(m_MenuItemList[i]->m_nID==HMenuToUInt(pSubMenu->m_hMenu) )
{
CNewMenuItemData* pData = m_MenuItemList.GetAt(i);
m_MenuItemList.RemoveAt(i);
delete pData;
break;
}
}
// Don't delete it's only remove
//delete pSubMenu;
}
}
}
else
{
int iPosition =0;
CNewMenu* pMenu = FindMenuOption(uiId,iPosition);
if(pMenu)
{
return pMenu->RemoveMenu(iPosition,MF_BYPOSITION);
}
}
return CMenu::RemoveMenu(uiId,nFlags);
}
BOOL CNewMenu::DeleteMenu(UINT uiId, UINT nFlags)
{
if(MF_BYPOSITION&nFlags)
{
UINT nItemState = GetMenuState(uiId,MF_BYPOSITION);
if( (nItemState&MF_SEPARATOR) && !(nItemState&MF_POPUP))
{
CNewMenuItemData* pData = m_MenuItemList.GetAt(uiId);
m_MenuItemList.RemoveAt(uiId);
delete pData;
}
else
{
CMenu* pSubMenu = GetSubMenu(uiId);
if(NULL==pSubMenu)
{
UINT uiCommandId = GetMenuItemID(uiId);
for(int i=0;i<m_MenuItemList.GetSize(); i++)
{
if(m_MenuItemList[i]->m_nID==uiCommandId)
{
CNewMenuItemData* pData = m_MenuItemList.GetAt(i);
m_MenuItemList.RemoveAt(i);
delete pData;
}
}
}
else
{
BOOL bCanDelete = FALSE;
int numSubMenus = (int)m_SubMenus.GetUpperBound();
for(int m = numSubMenus; m >= 0; m--)
{
if(m_SubMenus[m]==pSubMenu->m_hMenu)
{
m_SubMenus.RemoveAt(m);
bCanDelete = TRUE;
}
}
// int num = pSubMenu->GetMenuItemCount();
// for(int i=num-1;i>=0;--i)
// {
// pSubMenu->DeleteMenu(i,MF_BYPOSITION);
// }
for(int i=(int)m_MenuItemList.GetUpperBound();i>=0;i--)
{
if(m_MenuItemList[i]->m_nID==HMenuToUInt(pSubMenu->m_hMenu) )
{
CNewMenuItemData* pData = m_MenuItemList.GetAt(i);
m_MenuItemList.RemoveAt(i);
delete pData;
break;
}
}
// Did we created the menu
if(bCanDelete)
{ // Oh yes so we can destroy it
delete pSubMenu;
}
}
}
}
else
{
int iPosition =0;
CNewMenu* pMenu = FindMenuOption(uiId,iPosition);
if(pMenu)
{
return pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
}
}
return CMenu::DeleteMenu(uiId,nFlags);
}
BOOL CNewMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, int nIconNormal)
{
return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
}
BOOL CNewMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CImageList* il, int xoffset)
{
return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
}
BOOL CNewMenu::AppendMenu(UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CBitmap* bmp)
{
return AppendODMenu(lpszNewItem,nFlags,nIDNewItem,bmp);
}
BOOL CNewMenu::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, int nIconNormal)
{
return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
}
BOOL CNewMenu::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CImageList* il, int xoffset)
{
return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
}
BOOL CNewMenu::InsertMenu(UINT nPosition, UINT nFlags, UINT nIDNewItem, LPCTSTR lpszNewItem, CBitmap* bmp)
{
return InsertODMenu(nPosition,lpszNewItem,nFlags,nIDNewItem,bmp);
}
CNewMenu* CNewMenu::AppendODPopupMenu(LPCTSTR lpstrText)
{
CNewMenu* pSubMenu = new CNewMenu(m_hMenu);
pSubMenu->m_unselectcheck=m_unselectcheck;
pSubMenu->m_selectcheck=m_selectcheck;
pSubMenu->m_checkmaps=m_checkmaps;
pSubMenu->m_checkmapsshare=TRUE;
pSubMenu->CreatePopupMenu();
if(AppendODMenu(lpstrText,MF_POPUP,HMenuToUInt(pSubMenu->m_hMenu), -1))
{
m_SubMenus.Add(pSubMenu->m_hMenu);
return pSubMenu;
}
delete pSubMenu;
return NULL;
}
//BOOL CNewMenu::ImageListDuplicate(CImageList* il, int xoffset, CImageList* newlist)
//{
// if (il == NULL||newlist==NULL||xoffset<0)
// return FALSE;
//
// HICON hIcon = il->ExtractIcon(xoffset);
// int cx, cy;
// ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
// newlist->Create(cx,cy,ILC_COLORDDB|ILC_MASK,1,1);
// newlist->Add(hIcon);
// ::DestroyIcon(hIcon);
// return TRUE;
//}
CMenu* CNewMenu::GetSubMenu(int nPos) const
{
return CMenu::GetSubMenu (nPos);
}
CMenu* CNewMenu::GetSubMenu(LPCTSTR lpszSubMenuName) const
{
int num = GetMenuItemCount ();
CString name;
for (int i=0; i<num; i++)
{
GetMenuString (i, name, MF_BYPOSITION);
if (name.Compare (lpszSubMenuName) == 0)
{
return CMenu::GetSubMenu (i);
}
}
return NULL;
}
// Tongzhe Cui, Functions to remove a popup menu based on its name. Seperators
// before and after the popup menu can also be removed if they exist.
int CNewMenu::GetMenuPosition(LPCTSTR pText)
{
for(int i=0;i<(int)(GetMenuItemCount());++i)
{
if(!GetSubMenu(i))
{
for(int j=0;j<=m_MenuItemList.GetUpperBound();++j)
{
if(m_MenuItemList[j]->m_szMenuText.Compare(pText)==NULL)
return j;
}
}
}
// means no found;
return -1;
}
BOOL CNewMenu::RemoveMenuTitle()
{
int numMenuItems = (int)m_MenuItemList.GetSize();
// We need a seperator at the beginning of the menu
if(!numMenuItems || !((m_MenuItemList[0]->m_nFlags)&MF_SEPARATOR) )
{
return FALSE;
}
CNewMenuItemData* pMenuData = m_MenuItemList[0];
// Check for title
if(pMenuData->m_nTitleFlags&MFT_TITLE)
{
if(numMenuItems>0)
{
CNewMenuItemData* pMenuNextData = m_MenuItemList[1];
if((pMenuNextData->m_nFlags&MF_MENUBREAK))
{
pMenuNextData->m_nFlags &= ~MF_MENUBREAK;
CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuNextData->m_nFlags,pMenuNextData->m_nID,(LPCTSTR)pMenuNextData);
}
}
// Now remove the title
RemoveMenu(0,MF_BYPOSITION);
return TRUE;
}
return FALSE;
}
BOOL CNewMenu::SetMenuTitle(LPCTSTR pTitle, UINT nTitleFlags)
{
// Check if menu is valid
if(!::IsMenu(m_hMenu))
return FALSE;
// Check the menu integrity
if((int)GetMenuItemCount()!=(int)m_MenuItemList.GetSize())
{
SynchronizeMenu();
}
int numMenuItems = (int)m_MenuItemList.GetSize();
// We need a seperator at the beginning of the menu
if(!numMenuItems || !((m_MenuItemList[0]->m_nFlags)&MF_SEPARATOR) )
{
InsertMenu(0,MF_SEPARATOR|MF_BYPOSITION);
}
numMenuItems = (int)m_MenuItemList.GetSize();
if(numMenuItems)
{
CNewMenuItemData* pMenuData = m_MenuItemList[0];
if(pMenuData->m_nFlags&MF_SEPARATOR)
{
pMenuData->SetString(pTitle);
pMenuData->m_nTitleFlags = nTitleFlags|MFT_TITLE;
if(numMenuItems>1)
{
CNewMenuItemData* pMenuData = m_MenuItemList[1];
if(nTitleFlags&MFT_SIDE_TITLE)
{
if(!(pMenuData->m_nFlags&MF_MENUBREAK))
{
pMenuData->m_nFlags |= MF_MENUBREAK;
CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuData->m_nFlags,pMenuData->m_nID,(LPCTSTR)pMenuData);
}
}
else
{
if((pMenuData->m_nFlags&MF_MENUBREAK))
{
pMenuData->m_nFlags &= ~MF_MENUBREAK;
CMenu::ModifyMenu(1,MF_BYPOSITION|pMenuData->m_nFlags,pMenuData->m_nID,(LPCTSTR)pMenuData);
}
}
return TRUE;
}
}
}
return FALSE;
}
BOOL CNewMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
{
BOOL returnflag=FALSE;
if(MF_BYPOSITION&nFlags)
{
int numMenuItems = (int)m_MenuItemList.GetSize();
if(id<UINT(numMenuItems))
{
m_MenuItemList[id]->SetString(string);
returnflag=TRUE;
}
}
else
{
int uiLoc;
CNewMenu* pMenu = FindMenuOption(id,uiLoc);
if(NULL!=pMenu)
{
returnflag = pMenu->SetMenuText(uiLoc,string);
}
}
return returnflag;
}
// courtesy of Warren Stevens
void CNewMenu::ColorBitmap(CDC* pDC, CBitmap& bmp, CSize size, COLORREF fill, COLORREF border, int hatchstyle)
{
// Create a memory DC
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
bmp.CreateCompatibleBitmap(pDC, size.cx, size.cy);
CPen border_pen(PS_SOLID, 1, border);
CBrush fill_brush;
if(hatchstyle!=-1)
{
fill_brush.CreateHatchBrush(hatchstyle, fill);
}
else
{
fill_brush.CreateSolidBrush(fill);
}
CBitmap* pOldBitmap = MemDC.SelectObject(&bmp);
CPen* pOldPen = MemDC.SelectObject(&border_pen);
CBrush* pOldBrush = MemDC.SelectObject(&fill_brush);
MemDC.Rectangle(0,0, size.cx, size.cy);
if(NULL!=pOldBrush) { MemDC.SelectObject(pOldBrush); }
if(NULL!=pOldPen) { MemDC.SelectObject(pOldPen); }
if(NULL!=pOldBitmap) { MemDC.SelectObject(pOldBitmap); }
}
void CNewMenu::DrawSpecial_OldStyle(CDC* pDC, LPCRECT pRect, UINT nID, DWORD dwStyle)
{
COLORREF oldColor;
if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
}
else if (dwStyle&ODS_SELECTED)
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
}
BOOL bBold = (dwStyle&ODS_DEFAULT) ? TRUE : FALSE;
switch(nID&0xfff0)
{
case SC_MINIMIZE:
DrawSpecialChar(pDC,pRect,48,bBold); // Min
break;
case SC_MAXIMIZE:
DrawSpecialChar(pDC,pRect,49,bBold); // Max
break;
case SC_CLOSE:
DrawSpecialChar(pDC,pRect,114,bBold); // Close
break;
case SC_RESTORE:
DrawSpecialChar(pDC,pRect,50,bBold); // restore
break;
}
pDC->SetTextColor(oldColor);
}
void CNewMenu::DrawSpecial_WinXP(CDC* pDC, LPCRECT pRect, UINT nID, DWORD dwStyle)
{
TCHAR cSign = 0;
switch(nID&0xfff0)
{
case SC_MINIMIZE:
cSign = 48; // Min
break;
case SC_MAXIMIZE:
cSign = 49;// Max
break;
case SC_CLOSE:
cSign = 114;// Close
break;
case SC_RESTORE:
cSign = 50;// Restore
break;
}
if(cSign)
{
COLORREF oldColor;
BOOL bBold = (dwStyle&ODS_DEFAULT) ? TRUE : FALSE;
CRect rect(pRect);
rect.InflateRect(0,(m_iconY-rect.Height())>>1);
if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
}
else if(dwStyle&ODS_SELECTED)
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
rect.OffsetRect(1,1);
DrawSpecialChar(pDC,rect,cSign,bBold);
pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
rect.OffsetRect(-2,-2);
}
else
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
}
DrawSpecialChar(pDC,rect,cSign,bBold);
pDC->SetTextColor(oldColor);
}
}
CRect CNewMenu::GetLastActiveMenuRect()
{
return m_LastActiveMenuRect;
}
void CNewMenu::DrawSpecialCharStyle(CDC* pDC, LPCRECT pRect, TCHAR Sign, DWORD dwStyle)
{
COLORREF oldColor;
if( (dwStyle&ODS_GRAYED) || (dwStyle&ODS_INACTIVE))
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
}
else
{
oldColor = pDC->SetTextColor(::GetSysColor(COLOR_MENUTEXT));
}
DrawSpecialChar(pDC,pRect,Sign,(dwStyle&ODS_DEFAULT) ? TRUE : FALSE);
pDC->SetTextColor(oldColor);
}
void CNewMenu::DrawSpecialChar(CDC* pDC, LPCRECT pRect, TCHAR Sign, BOOL bBold)
{
// 48 Min
// 49 Max
// 50 Restore
// 98 Checkmark
// 105 Bullet
// 114 Close
CFont MyFont;
LOGFONT logfont;
CRect rect(pRect) ;
rect.DeflateRect(2,2);
logfont.lfHeight = -rect.Height();
logfont.lfWidth = 0;
logfont.lfEscapement = 0;
logfont.lfOrientation = 0;
logfont.lfWeight = (bBold) ? FW_BOLD:FW_NORMAL;
logfont.lfItalic = FALSE;
logfont.lfUnderline = FALSE;
logfont.lfStrikeOut = FALSE;
logfont.lfCharSet = DEFAULT_CHARSET;
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logfont.lfQuality = DEFAULT_QUALITY;
logfont.lfPitchAndFamily = DEFAULT_PITCH;
_tcscpy(logfont.lfFaceName,_T("Marlett"));
VERIFY(MyFont.CreateFontIndirect (&logfont));
CFont* pOldFont = pDC->SelectObject (&MyFont);
int OldMode = pDC->SetBkMode(TRANSPARENT);
pDC->DrawText (&Sign,1,rect,DT_CENTER|DT_SINGLELINE);
pDC->SetBkMode(OldMode);
pDC->SelectObject(pOldFont);
MyFont.DeleteObject();
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMenuTheme::CMenuTheme()
{
ZeroMemory(this,sizeof(CMenuTheme));
}
CMenuTheme::CMenuTheme( DWORD dwThemeId,
pItemMeasureFkt pMeasureItem,
pItemDrawFkt pDrawItem,
pItemDrawFkt pDrawTitle,
DWORD dwFlags)
:m_dwThemeId(dwThemeId),
m_dwFlags(dwFlags),
m_pMeasureItem(pMeasureItem),
m_pDrawItem(pDrawItem),
m_pDrawTitle(pDrawTitle)
{
m_BorderTopLeft = CSize(2,2);
if(!IsShadowEnabled())
{
m_BorderBottomRight = CSize(5,6);
}
else
{
m_BorderBottomRight = CSize(2,2);
}
}
CMenuTheme::~CMenuTheme()
{
}
void CMenuTheme::DrawFrame(CDC* pDC, CRect rectOuter, CRect rectInner, COLORREF crBorder)
{
CRect Temp;
rectInner.right -= 1;
// Border top
Temp.SetRect(rectOuter.TopLeft(),CPoint(rectOuter.right,rectInner.top));
pDC->FillSolidRect(Temp,crBorder);
// Border bottom
Temp.SetRect(CPoint(rectOuter.left,rectInner.bottom),rectOuter.BottomRight());
pDC->FillSolidRect(Temp,crBorder);
// Border left
Temp.SetRect(rectOuter.TopLeft(),CPoint(rectInner.left,rectOuter.bottom));
pDC->FillSolidRect(Temp,crBorder);
// Border right
Temp.SetRect(CPoint(rectInner.right,rectOuter.top),rectOuter.BottomRight());
pDC->FillSolidRect(Temp,crBorder);
}
BOOL CMenuTheme::DoDrawBorder()
{
return (m_dwFlags&1)?TRUE:FALSE;
}
void CMenuTheme::DrawSmalBorder( HWND hWnd, HDC hDC)
{
CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
if(pData!=NULL)
{
if(pData->m_hMenu)
{
CNewMenu* pMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pData->m_hMenu));
if(pMenu && pMenu->GetParent())
{
CNewMenu* pParentMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(pMenu->GetParent()));
if(pParentMenu && !pParentMenu->IsPopup())
{
CRect Rect;
// Get the size of the menu...
GetWindowRect(hWnd, Rect );
Rect.OffsetRect(pData->m_Point - Rect.TopLeft());
Rect &= pParentMenu->GetLastActiveMenuRect();
if(!Rect.IsRectEmpty())
{
if(Rect.Width()>Rect.Height())
{
Rect.InflateRect(-1,0);
}
else
{
Rect.InflateRect(0,-1);
}
Rect.OffsetRect(-pData->m_Point);
CDC* pDC = CDC::FromHandle(hDC);
pDC->FillSolidRect(Rect,CNewMenu::GetMenuBarColor());
}
}
}
}
}
}
void CMenuTheme::DrawShade( HWND hWnd, HDC hDC, CPoint screen)
{
if(IsShadowEnabled())
return;
// Get the size of the menu...
CRect Rect;
GetWindowRect(hWnd, Rect );
long winW = Rect.Width();
long winH = Rect.Height();
long xOrg = screen.x;
long yOrg = screen.y;
// Get the desktop hDC...
HDC hDcDsk = GetWindowDC(0) ;
int X,Y;
// Simulate a shadow on right edge...
for (X=1; X<=4 ;X++)
{
for (Y=0; Y<4 ;Y++)
{
SetPixel(hDC,winW-X,Y, GetPixel(hDcDsk,xOrg+winW-X,yOrg+Y) );
}
for (Y=4; Y<8 ;Y++)
{
COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y) ;
SetPixel(hDC,winW-X,Y,DarkenColor(2* 3 * X * (Y - 3), c)) ;
}
for (Y=8; Y<=(winH-5) ;Y++)
{
COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y) ;
SetPixel( hDC, winW - X, Y, DarkenColor(2* 15 * X, c) );
}
for (Y=(winH-4); Y<=(winH-1) ;Y++)
{
COLORREF c = GetPixel(hDcDsk, xOrg + winW - X, yOrg + Y) ;
SetPixel( hDC, winW - X, Y, DarkenColor(2* 3 * X * -(Y - winH), c)) ;
}
}
// Simulate a shadow on the bottom edge...
for(Y=1; Y<=4 ;Y++)
{
for(X=0; X<=3 ;X++)
{
SetPixel(hDC,X,winH-Y, GetPixel(hDcDsk,xOrg+X,yOrg+winH-Y)) ;
}
for(X=4; X<=7 ;X++)
{
COLORREF c = GetPixel(hDcDsk, xOrg + X, yOrg + winH - Y) ;
SetPixel( hDC, X, winH - Y, DarkenColor(2*3 * (X - 3) * Y, c)) ;
}
for(X=8; X<=(winW-5) ;X++)
{
COLORREF c = GetPixel(hDcDsk, xOrg + X, yOrg + winH - Y);
SetPixel( hDC, X, winH - Y, DarkenColor(2* 15 * Y, c)) ;
}
}
// Release the desktop hDC...
ReleaseDC(0,hDcDsk);
}
BOOL CMenuTheme::OnInitWnd(HWND hWnd)
{
if(DoDrawBorder())
{
CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
ASSERT(pData);
// Flag for changing styles
pData->m_dwData |= 2;
SetWindowLong (hWnd, GWL_STYLE, pData->m_dwStyle & (~WS_BORDER) );
SetWindowLong (hWnd, GWL_EXSTYLE,pData->m_dwExStyle & ~(WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME));
return TRUE;
}
return FALSE;
}
BOOL CMenuTheme::OnUnInitWnd(HWND hWnd)
{
CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
if(pData)
{
HMENU hMenu = pData->m_hMenu;
CNewMenu* pNewMenu = DYNAMIC_DOWNCAST(CNewMenu,CMenu::FromHandlePermanent(hMenu));
if(pNewMenu)
{
// Redraw menubar on place.
pNewMenu->OnUnInitPopupMenu(GetParent(hWnd));
}
// were windows-style changed?
if(pData->m_dwData&2)
{
SetLastError(0);
if(!(pData->m_dwData&1))
{
SetWindowLong (hWnd, GWL_STYLE,pData->m_dwStyle);
}
else
{
// Restore old Styles for special menu!!
// (Menu 0x10012!!!) special VISIBLE flag must be set
SetWindowLong (hWnd, GWL_STYLE,pData->m_dwStyle|WS_VISIBLE);
}
ShowLastError();
SetWindowLong (hWnd, GWL_EXSTYLE, pData->m_dwExStyle);
ShowLastError();
// Normaly when you change the style you shold call next function
// but in this case you would lose the focus for the menu!!
//SetWindowPos(hWnd,0,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED|SWP_HIDEWINDOW);
}
}
return TRUE;
}
BOOL CMenuTheme::OnEraseBkgnd(HWND hWnd, HDC hDC)
{
// CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
// Get the size of the menu...
CDC* pDC = CDC::FromHandle (hDC);
CRect Rect;
GetClientRect(hWnd, Rect );
Rect.InflateRect(+2,0,-1,0);
pDC->FillSolidRect (Rect,GetSysColor(COLOR_MENU));
return TRUE;
}
BOOL CMenuTheme::OnWindowPosChanging(HWND hWnd, LPWINDOWPOS pPos)
{
UNREFERENCED_PARAMETER(hWnd);
if(DoDrawBorder())
{
if(!IsShadowEnabled())
{
pPos->cx +=2;
pPos->cy +=2;
}
else
{
pPos->cx -=2;
pPos->cy -=2;
}
pPos->y -=1;
return TRUE;
}
return FALSE;
}
BOOL CMenuTheme::OnNcCalcSize(HWND hWnd, NCCALCSIZE_PARAMS* pCalc)
{
UNREFERENCED_PARAMETER(hWnd);
if(DoDrawBorder())
{
pCalc->rgrc->top += m_BorderTopLeft.cy;
pCalc->rgrc->left += m_BorderTopLeft.cx;
pCalc->rgrc->bottom -= m_BorderBottomRight.cy;
pCalc->rgrc->right -= m_BorderBottomRight.cx;
}
return FALSE;
}
BOOL CMenuTheme::OnCalcFrameRect(HWND hWnd,LPRECT pRect)
{
if(GetWindowRect(hWnd,pRect))
{
if(DoDrawBorder())
{
pRect->top += 2;
pRect->left += 2;
if(!IsShadowEnabled())
{
pRect->bottom -= 7;
pRect->right -= 7;
}
else
{
pRect->bottom -= 3;
pRect->right -= 3;
}
}
return TRUE;
}
return FALSE;
}
BOOL CMenuTheme::OnDrawBorder(HWND hWnd, HDC hDC)
{
CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
if(DoDrawBorder() && pData)
{
CRect rect;
CRect client;
CDC* pDC = CDC::FromHandle (hDC);
// Get the size of the menu...
GetWindowRect(hWnd, rect );
GetClientRect(hWnd, client);
CPoint offset(0,0);
ClientToScreen(hWnd,&offset);
client.OffsetRect(offset-rect.TopLeft());
long winW = rect.Width();
long winH = rect.Height();
if(!IsShadowEnabled())
{
//pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),CNewMenu::GetMenuBarColor(),CNewMenu::GetMenuBarColor());
//pDC->FillSolidRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),CNewMenu::GetMenuBarColor());
DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-6,winH-6)),client,CNewMenu::GetMenuBarColor());
pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),GetSysColor(COLOR_HIGHLIGHT),GetSysColor(COLOR_HIGHLIGHT));
DrawShade(hWnd,hDC,pData->m_Point);
}
else
{
//pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),CNewMenu::GetMenuBarColor(),CNewMenu::GetMenuBarColor());
//pDC->FillSolidRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),CNewMenu::GetMenuBarColor());
DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-2,winH-2)),client,CNewMenu::GetMenuBarColor());
pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),GetSysColor(COLOR_HIGHLIGHT),GetSysColor(COLOR_HIGHLIGHT));
}
//DrawSmalBorder(hWnd,hDC);
return TRUE;
}
return FALSE;
}
CMenuThemeXP::CMenuThemeXP(DWORD dwThemeId,
pItemMeasureFkt pMeasureItem,
pItemDrawFkt pDrawItem,
pItemDrawFkt pDrawTitle,
DWORD dwFlags)
:CMenuTheme(dwThemeId,pMeasureItem,pDrawItem,pDrawTitle,dwFlags)
{
}
BOOL CMenuThemeXP::OnDrawBorder(HWND hWnd, HDC hDC)
{
CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
if(DoDrawBorder() && pData)
{
CRect rect;
CRect client;
CDC* pDC = CDC::FromHandle (hDC);
// Get the size of the menu...
GetWindowRect(hWnd, rect );
GetClientRect(hWnd,client);
CPoint offset(0,0);
ClientToScreen(hWnd,&offset);
client.OffsetRect(offset-rect.TopLeft());
long winW = rect.Width();
long winH = rect.Height();
// Same Color as in DrawItem_WinXP
COLORREF crMenuBar = CNewMenu::GetMenuBarColor();
COLORREF crWindow = GetSysColor(COLOR_WINDOW);
COLORREF crThinBorder = MixedColor(crWindow,crMenuBar);
COLORREF clrBorder = DarkenColor(128,crMenuBar);
COLORREF colorBitmap = MixedColor(crMenuBar,crWindow);
if(!IsShadowEnabled())
{
//pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_WINDOW));
//pDC->FillSolidRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),crMenuBar);
DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-6,winH-6)),client,colorBitmap);
pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-6,winH-6)),crThinBorder,crThinBorder);
pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-4,winH-4)),clrBorder,clrBorder);
DrawShade(hWnd,pDC->m_hDC,pData->m_Point);
}
else
{
//pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),GetSysColor(COLOR_WINDOW),GetSysColor(COLOR_WINDOW));
//pDC->FillSolidRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),crMenuBar);
DrawFrame(pDC,CRect(CPoint(1,1),CSize(winW-2,winH-2)),client,colorBitmap);
pDC->Draw3dRect(CRect(CPoint(1,1),CSize(winW-2,winH-2)),crThinBorder,crThinBorder);
pDC->Draw3dRect(CRect(CPoint(0,0),CSize(winW-0,winH-0)),clrBorder,clrBorder);
}
DrawSmalBorder(hWnd,pDC->m_hDC);
return TRUE;
}
return FALSE;
}
BOOL CMenuThemeXP::OnEraseBkgnd(HWND hWnd, HDC hDC)
{
CNewMenuHook::CMenuHookData* pData = CNewMenuHook::GetMenuHookData(hWnd);
if(pData->m_hMenu==NULL)
{
return CMenuTheme::OnEraseBkgnd(hWnd,hDC);
}
// Get the size of the menu...
CDC* pDC = CDC::FromHandle (hDC);
CRect Rect;
GetClientRect(hWnd, Rect );
Rect.InflateRect(+2,0,-1,0);
//BPO!!!!!!!!!! fehler Zeichnet auch in den rand hinein 2
pDC->FillSolidRect (Rect,CNewMenu::GetMenuBarColor());
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
const TCHAR _OldMenuProc[] = _T("OldMenuProc");
HMODULE CNewMenuHook::m_hLibrary = NULL;
HHOOK CNewMenuHook::HookOldMenuCbtFilter = NULL;
HMENU CNewMenuHook::m_hLastMenu = NULL;
DWORD CNewMenuHook::m_dwMsgPos = 0;
CTypedPtrList<CPtrList, CMenuTheme*>* CNewMenuHook::m_pRegisteredThemesList = NULL;
CTypedPtrMap<CMapPtrToPtr,HWND,CNewMenuHook::CMenuHookData*> CNewMenuHook::m_MenuHookData;
#ifndef SM_REMOTESESSION
#define SM_REMOTESESSION 0x1000
#endif
CNewMenuHook::CNewMenuHook()
{
if(g_Shell>=Win2000 && GetSystemMetrics(SM_REMOTESESSION))
{
bRemoteSession=TRUE;
}
// Try to load the library for gradient drawing
m_hLibrary = LoadLibrary(_T("Msimg32.dll"));
pGradientFill = (FktGradientFill)GetProcAddress(m_hLibrary,"GradientFill");
AddTheme(new CMenuTheme(CNewMenu::STYLE_ORIGINAL,
CNewMenu::MeasureItem_OldStyle,
CNewMenu::DrawItem_OldStyle,
CNewMenu::DrawMenuTitle,TRUE));
AddTheme(new CMenuTheme(CNewMenu::STYLE_ORIGINAL_NOBORDER,
CNewMenu::MeasureItem_OldStyle,
CNewMenu::DrawItem_OldStyle,
CNewMenu::DrawMenuTitle));
AddTheme(new CMenuThemeXP(CNewMenu::STYLE_XP,
CNewMenu::MeasureItem_WinXP,
CNewMenu::DrawItem_WinXP,
CNewMenu::DrawMenuTitle,TRUE));
AddTheme(new CMenuThemeXP(CNewMenu::STYLE_XP_NOBORDER,
CNewMenu::MeasureItem_WinXP,
CNewMenu::DrawItem_WinXP,
CNewMenu::DrawMenuTitle));
AddTheme(new CMenuTheme(CNewMenu::STYLE_SPECIAL,
CNewMenu::MeasureItem_OldStyle,
CNewMenu::DrawItem_SpecialStyle,
CNewMenu::DrawMenuTitle,TRUE));
AddTheme(new CMenuTheme(CNewMenu::STYLE_SPECIAL_NOBORDER,
CNewMenu::MeasureItem_OldStyle,
CNewMenu::DrawItem_SpecialStyle,
CNewMenu::DrawMenuTitle));
// CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_ORIGINAL);
// CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_ORIGINAL_NOBORDER);
CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_XP);
// CNewMenu::m_pActMenuDrawing = FindTheme(CNewMenu::STYLE_XP_NOBORDER);
if (HookOldMenuCbtFilter == NULL)
{
HookOldMenuCbtFilter = ::SetWindowsHookEx(WH_CALLWNDPROC, NewMenuHook, NULL, ::GetCurrentThreadId());
if (HookOldMenuCbtFilter == NULL)
{
ShowLastError();
AfxThrowMemoryException();
}
}
}
CNewMenuHook::~CNewMenuHook()
{
if (HookOldMenuCbtFilter != NULL)
{
if(!::UnhookWindowsHookEx(HookOldMenuCbtFilter))
{
ShowLastError();
}
HookOldMenuCbtFilter = NULL;
}
// Destroy all registered themes.
if( m_pRegisteredThemesList!= NULL)
{
while(m_pRegisteredThemesList->GetCount())
{
CMenuTheme* pTheme = m_pRegisteredThemesList->RemoveTail();
delete pTheme;
}
delete m_pRegisteredThemesList;
m_pRegisteredThemesList = NULL;
}
pGradientFill = NULL;
FreeLibrary(m_hLibrary);
// Cleanup for shared menu icons
if(CNewMenu::m_pSharedMenuIcons)
{
//while(CNewMenu::m_pSharedMenuIcons->GetSize())
//{
// delete CNewMenu::m_pSharedMenuIcons->RemoveTail();
//}
delete CNewMenu::m_pSharedMenuIcons;
CNewMenu::m_pSharedMenuIcons = NULL;
}
}
BOOL CNewMenuHook::AddTheme(CMenuTheme* pTheme)
{
if( m_pRegisteredThemesList== NULL)
{
m_pRegisteredThemesList = new CTypedPtrList<CPtrList, CMenuTheme*>;
}
if(m_pRegisteredThemesList->Find(pTheme))
{
return FALSE;
}
m_pRegisteredThemesList->AddTail(pTheme);
return TRUE;
}
CMenuTheme* CNewMenuHook::RemoveTheme(DWORD dwThemeId)
{
CMenuTheme* pTheme = FindTheme(dwThemeId);
if(pTheme==NULL)
{
return NULL;
}
POSITION pos = m_pRegisteredThemesList->Find(pTheme);
ASSERT(pos);
if(pos)
{
m_pRegisteredThemesList->RemoveAt(pos);
if(m_pRegisteredThemesList->GetCount()==NULL)
{
// Destroy the empty list.
delete m_pRegisteredThemesList;
m_pRegisteredThemesList = NULL;
}
}
return pTheme;
}
CMenuTheme* CNewMenuHook::FindTheme(DWORD dwThemeId)
{
if(m_pRegisteredThemesList==NULL)
{
return NULL;
}
POSITION pos = m_pRegisteredThemesList->GetHeadPosition();
while(pos)
{
CMenuTheme* pTheme = m_pRegisteredThemesList->GetNext(pos);
if(pTheme->m_dwThemeId==dwThemeId)
{
return pTheme;
}
}
return NULL;
}
CNewMenuHook::CMenuHookData* CNewMenuHook::GetMenuHookData(HWND hWnd)
{
CMenuHookData* pData=NULL;
if(m_MenuHookData.Lookup(hWnd,pData))
{
return pData;
}
return NULL;
}
void CNewMenuHook::UnsubClassMenu(HWND hWnd)
{
AFX_MANAGE_STATE(AfxGetModuleState());
WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
ASSERT(oldWndProc != NULL);
SetLastError(0);
if(!SetWindowLong(hWnd, GWL_WNDPROC, (DWORD)(DWORD_PTR)oldWndProc))
{
ShowLastError();
}
RemoveProp(hWnd, _OldMenuProc);
GlobalDeleteAtom(GlobalFindAtom(_OldMenuProc));
// now Clean up
HMENU hMenu = NULL;
// Restore old Styles for special menu!! (Menu 0x10012!!!)
CMenuHookData* pData = GetMenuHookData(hWnd);
if(pData)
{
hMenu = pData->m_hMenu;
CNewMenu::m_pActMenuDrawing->OnUnInitWnd(hWnd);
m_MenuHookData.RemoveKey(hWnd);
delete pData;
}
#ifdef _TRACE_MENU_
TRACE(_T("Unsubclass Menu=0x%lX, hwnd=0x%lX\n"),hMenu,hWnd);
#endif
}
LRESULT CALLBACK CNewMenuHook::SubClassMenu(HWND hWnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{
AFX_MANAGE_STATE(AfxGetModuleState());
WNDPROC oldWndProc = (WNDPROC)::GetProp(hWnd, _OldMenuProc);
LRESULT result = NULL;
static long NestedLevel = 0;
BOOL bCallDefault = TRUE;
NestedLevel++;
#ifdef _TRACE_MENU_
MSG msg = {hWnd,uMsg,wParam,lParam,0,0,0};
TCHAR Buffer[30];
wsprintf(Buffer,_T("Level %02ld"),NestedLevel);
MyTraceMsg(Buffer,&msg);
#endif
switch(uMsg)
{
case WM_NCPAINT:
{
CMenuHookData* pData = GetMenuHookData(hWnd);
if(pData && pData->m_bDrawBorder && CNewMenu::m_pActMenuDrawing->DoDrawBorder())
{
//HDC hDC = GetWindowDC(hWnd);
HDC hDC;
if(wParam!=1)
hDC = GetDCEx(hWnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
else
hDC = GetWindowDC (hWnd);
if(hDC)
{
//if(wParam!=1)
//{
// CRect rect;
// CNewMenu::m_pActMenuDrawing->OnCalcFrameRect(hWnd,rect);
// CRgn rgn;
// //rect.InflateRect(-1,-1);
// rgn.CreateRectRgnIndirect(rect);
// rgn.CombineRgn(&rgn,CRgn::FromHandle((HRGN)wParam),RGN_AND);
//
// SelectClipRgn(hDC,NULL);
// SelectClipRgn(hDC,rgn);
// rgn.GetRgnBox(rect);
//}
if(CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,hDC))
{
bCallDefault=FALSE;
CRect rect;
if(CNewMenu::m_pActMenuDrawing->OnCalcFrameRect(hWnd,rect))
{
CRgn rgn;
rect.InflateRect(-1,-1);
rgn.CreateRectRgnIndirect(rect);
// do we need a combination of the regions?
if(wParam!=1)
{
rgn.CombineRgn(&rgn,CRgn::FromHandle((HRGN)wParam),RGN_AND);
}
ASSERT(oldWndProc);
result = CallWindowProc(oldWndProc, hWnd, uMsg, (WPARAM)(rgn.m_hObject), lParam);
}
}
//if(wParam!=1)
//{
// SelectClipRgn(hDC,NULL);
//}
ReleaseDC(hWnd,hDC);
}
}
pData->m_bDrawBorder = TRUE;
}
break;
case WM_PRINT:
{
CMenuHookData* pData = GetMenuHookData(hWnd);
if(pData && CNewMenu::m_pActMenuDrawing->DoDrawBorder())
{
pData->m_bDrawBorder = FALSE;
// We need to create a bitmap for drawing
// We can't clipp or make a offset to the DC because NT2000 (blue-screen!!)
CRect rect;
GetWindowRect(hWnd, rect);
CDC dc;
CBitmap bitmap;
CDC* pDC = CDC::FromHandle((HDC)wParam);
dc.CreateCompatibleDC(pDC);
bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap* pOldBitmap = dc.SelectObject(&bitmap);
CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,dc.m_hDC);
CRect rectClient;
if(CNewMenu::m_pActMenuDrawing->OnCalcFrameRect(hWnd,rectClient))
{
// might as well clip to the same rectangle
CRect clipRect = rectClient;
clipRect.OffsetRect(rectClient.TopLeft()-rect.TopLeft());
clipRect.InflateRect(-1,-1);
dc.IntersectClipRect(clipRect);
result = CallWindowProc(oldWndProc, hWnd, uMsg, (WPARAM)dc.m_hDC, lParam&~PRF_CLIENT);
pDC->BitBlt(0,0, rect.Width(), rect.Height(), &dc,0,0, SRCCOPY);
GetClientRect(hWnd,clipRect);
SelectClipRgn(dc.m_hDC,NULL);
dc.IntersectClipRect(clipRect);
SendMessage(hWnd,WM_ERASEBKGND,(WPARAM)dc.m_hDC,0);
SendMessage(hWnd,WM_PRINTCLIENT,(WPARAM)dc.m_hDC,lParam);
CPoint wndOffset(0,0);
ClientToScreen(hWnd,&wndOffset);
wndOffset -= rect.TopLeft();
pDC->BitBlt(wndOffset.x,wndOffset.y, clipRect.Width()-1, clipRect.Height(), &dc, 0, 0, SRCCOPY);
dc.SelectObject(pOldBitmap);
}
bCallDefault=FALSE;
}
//if(pData && CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,(HDC)wParam) )
//{
// pData->m_bDrawBorder = FALSE;
//if(pData && CNewMenu::m_pActMenuDrawing->DoDrawBorder() )
//{
// CRect rectClient;
// if(CNewMenu::m_pActMenuDrawing->OnCalcFrameRect(hWnd,rectClient))
// {
// IntersectClipRect((
// }
//
// result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam&~PRF_CLIENT);
// //CNewMenu::m_pActMenuDrawing->OnDrawBorder(hWnd,(HDC)wParam);
// pData->m_bDrawBorder = FALSE;
//
// if(0)
// {
// // We need to create a bitmap for drawing
// // We can't clipp or make a offset to the DC because NT2000 (blue-screen!!)
// CRect rect;
// GetClientRect(hWnd, rect);
// CDC dc;
// CBitmap bitmap;
// CDC* pDC = CDC::FromHandle((HDC)wParam);
// dc.CreateCompatibleDC(pDC);
// bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
// CBitmap* pOldBitmap = dc.SelectObject(&bitmap);
// // might as well clip to the same rectangle
// dc.IntersectClipRect(rect);
// SendMessage(hWnd,WM_ERASEBKGND,(WPARAM)dc.m_hDC,0);
// SendMessage(hWnd,WM_PRINTCLIENT,(WPARAM)dc.m_hDC,lParam);
// CRect rectWnd;
// CPoint wndOffset(0,0);
// GetWindowRect(hWnd,rectWnd);
// ClientToScreen(hWnd,&wndOffset);
// wndOffset -= rectWnd.TopLeft();
// pDC->BitBlt(wndOffset.x,wndOffset.y, rect.Width()-1, rect.Height(), &dc, 0, 0, SRCCOPY);
// dc.SelectObject(pOldBitmap);
// }
// bCallDefault=FALSE;
//}
}
break;
case WM_ERASEBKGND:
{
if(CNewMenu::m_pActMenuDrawing->OnEraseBkgnd(hWnd,(HDC)wParam))
{
bCallDefault=FALSE;
result = TRUE;
}
}
break;
case WM_WINDOWPOSCHANGED:
case WM_WINDOWPOSCHANGING:
{
CMenuHookData* pData=GetMenuHookData(hWnd);
ASSERT(pData);
LPWINDOWPOS pPos = (LPWINDOWPOS)lParam;
if(uMsg==WM_WINDOWPOSCHANGING)
{
CNewMenu::m_pActMenuDrawing->OnWindowPosChanging(hWnd,pPos);
}
if(!(pPos->flags&SWP_NOMOVE) )
{
if(pData->m_Point==CPoint(0,0))
{
pData->m_Point = CPoint(pPos->x,pPos->y);
}
else if(pData->m_Point!=CPoint(pPos->x,pPos->y))
{
/* CRect rect(0,0,0,0);
if(!GetWindowRect(hWnd,rect))
{
TRACE(_T("Error get rect\n"));
}
#ifdef _TRACE_MENU_
DWORD dwPos =GetMessagePos();
TRACE(_T("Rect pos (%ld/%ld), dimensions [%ld,%ld], Delta(%ld/%ld),MPos %lx\n"),
pData->m_Point.x,pData->m_Point.y,rect.Width(),rect.Height(),
pData->m_Point.x-pPos->x,pData->m_Point.y-pPos->y,dwPos);
#endif
*/
if(!(pPos->flags&SWP_NOSIZE))
UnsubClassMenu(hWnd);
else
pData->m_Point=CPoint(pPos->x,pPos->y);
}
}
}
break;
case WM_KEYDOWN:
if(wParam==VK_ESCAPE)
{
CMenuHookData* pData = GetMenuHookData(hWnd);
if(pData)
{
pData->m_dwData |= 4;
}
}
m_dwMsgPos = GetMessagePos();
break;
case WM_NCCALCSIZE:
{
NCCALCSIZE_PARAMS* pCalc = (NCCALCSIZE_PARAMS*)lParam;
if(CNewMenu::m_pActMenuDrawing->OnNcCalcSize(hWnd,pCalc))
{
bCallDefault=FALSE;
}
}
break;
case WM_SHOWWINDOW:
// Hide the window ? Test for 98 and 2000
if(wParam==NULL)
{
// Special handling for NT 2000 and WND 0x10012.
UnsubClassMenu(hWnd);
}
break;
case WM_NCDESTROY:
UnsubClassMenu (hWnd);
break;
}
if( bCallDefault )
{
ASSERT(oldWndProc != NULL);
// call original wndproc for default handling
result = CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam);
}
NestedLevel--;
return result;
}
BOOL CNewMenuHook::CheckSubclassing(HWND hWnd, BOOL bSpecialWnd)
{
TCHAR Name[20];
int Count = GetClassName (hWnd,Name,ARRAY_SIZE(Name));
// Check for the menu-class
if(Count!=6 || _tcscmp(Name,_T("#32768"))!=0)
{
// does not match to menuclass
return false;
}
BOOL bDoNewSubclass = FALSE;
CMenuHookData* pData=GetMenuHookData(hWnd);
// check if we have allready some data
if(pData==NULL)
{
WNDPROC oldWndProc;
// subclass the window with the proc which does gray backgrounds
oldWndProc = (WNDPROC)(LONG_PTR)GetWindowLong(hWnd, GWL_WNDPROC);
if (oldWndProc != NULL && GetProp(hWnd, _OldMenuProc) == NULL)
{
ASSERT(oldWndProc!=SubClassMenu);
if(!SetProp(hWnd, _OldMenuProc, oldWndProc))
{
ShowLastError();
}
if ((WNDPROC)GetProp(hWnd, _OldMenuProc) == oldWndProc)
{
GlobalAddAtom(_OldMenuProc);
CMenuHookData* pData=GetMenuHookData(hWnd);
ASSERT(pData==NULL);
if(pData==NULL)
{
pData = new CMenuHookData(hWnd,bSpecialWnd);
m_MenuHookData.SetAt (hWnd,pData);
SetLastError(0);
if(!SetWindowLong(hWnd, GWL_WNDPROC,(DWORD)(DWORD_PTR)SubClassMenu))
{
ShowLastError();
}
bDoNewSubclass = TRUE;
#ifdef _TRACE_MENU_
TRACE(_T("Subclass Menu=0x%lX, hwnd=0x%lX\n"),pData->m_hMenu,hWnd);
#endif
CNewMenu::m_pActMenuDrawing->OnInitWnd(hWnd);
}
}
else
{
ASSERT(0);
}
}
}
// Menu was set also assign it to this menu.
if(m_hLastMenu)
{
CMenuHookData* pData = GetMenuHookData(hWnd);
if(pData)
{
// Safe actual menu
pData->m_hMenu = m_hLastMenu;
// Reset for the next menu
m_hLastMenu = NULL;
}
}
return bDoNewSubclass;
}
LRESULT CALLBACK CNewMenuHook::NewMenuHook(int code, WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CWPSTRUCT* pTemp = (CWPSTRUCT*)lParam;
if(code == HC_ACTION )
{
HWND hWnd = pTemp->hwnd;
// Normal and special handling for menu 0x10012
if(pTemp->message==WM_CREATE || pTemp->message==0x01E2)
{
CheckSubclassing(hWnd,pTemp->message==0x01E2);
}
}
return CallNextHookEx(HookOldMenuCbtFilter, code,wParam, lParam);
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewDialog,CDialog)
BEGIN_MESSAGE_MAP(CNewDialog, CNewFrame<CDialog>)
//{{AFX_MSG_MAP(CNewDialog)
ON_WM_INITMENUPOPUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CNewDialog::CNewDialog()
{
}
CNewDialog::CNewDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd)
{
ASSERT(IS_INTRESOURCE(lpszTemplateName) || AfxIsValidString(lpszTemplateName));
m_pParentWnd = pParentWnd;
m_lpszTemplateName = lpszTemplateName;
if (IS_INTRESOURCE(m_lpszTemplateName))
m_nIDHelp = LOWORD((DWORD_PTR)m_lpszTemplateName);
}
CNewDialog::CNewDialog(UINT nIDTemplate, CWnd* pParentWnd)
{
m_pParentWnd = pParentWnd;
m_lpszTemplateName = MAKEINTRESOURCE(nIDTemplate);
m_nIDHelp = nIDTemplate;
}
BOOL CNewDialog::OnInitDialog()
{
BOOL bRetval = CDialog::OnInitDialog();
HMENU hMenu = m_SystemNewMenu.Detach();
HMENU hSysMenu = ::GetSystemMenu(m_hWnd,FALSE);
if(hMenu!=hSysMenu)
{
if(IsMenu(hMenu))
{
if(!::DestroyMenu(hMenu))
{
ShowLastError();
}
}
}
m_SystemNewMenu.Attach(hSysMenu);
m_DefaultNewMenu.LoadMenu(::GetMenu(m_hWnd));
return bRetval;
}
extern void AFXAPI AfxCancelModes(HWND hWndRcvr);
// Most of the code is copied from the MFC code from CFrameWnd::OnInitMenuPopup
void CNewDialog::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
AfxCancelModes(m_hWnd);
// don't support system menu
if (!bSysMenu)
{
ASSERT(pMenu != NULL);
// check the enabled state of various menu items
CCmdUI state;
state.m_pMenu = pMenu;
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pParentMenu == NULL);
// determine if menu is popup in top-level menu and set m_pOther to
// it if so (m_pParentMenu == NULL indicates that it is secondary popup)
HMENU hParentMenu;
if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
{
state.m_pParentMenu = pMenu; // parent == child for tracking popup
}
else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
{
CWnd* pParent = GetTopLevelParent();
// child windows don't have menus -- need to go to the top!
if (pParent != NULL &&
(hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
{
int nIndexMax = ::GetMenuItemCount(hParentMenu);
for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
{
if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu)
{
// when popup is found, m_pParentMenu is containing menu
state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
break;
}
}
}
}
state.m_nIndexMax = pMenu->GetMenuItemCount();
for (state.m_nIndex = 0; state.m_nIndex<state.m_nIndexMax; state.m_nIndex++)
{
state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
if (state.m_nID == 0)
continue; // menu separator or invalid cmd - ignore it
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pMenu != NULL);
if (state.m_nID == (UINT)-1)
{
// possibly a popup menu, route to first item of that popup
state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
if (state.m_pSubMenu == NULL ||
(state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
state.m_nID == (UINT)-1)
{
continue; // first item of popup can't be routed to
}
state.DoUpdate(this, FALSE); // popups are never auto disabled
}
else
{
// normal menu item
// Auto enable/disable if frame window has 'm_bAutoMenuEnable'
// set and command is _not_ a system command.
state.m_pSubMenu = NULL;
state.DoUpdate(this, state.m_nID < 0xF000);
}
// adjust for menu deletions and additions
UINT nCount = pMenu->GetMenuItemCount();
if (nCount < state.m_nIndexMax)
{
state.m_nIndex -= (state.m_nIndexMax - nCount);
while (state.m_nIndex < nCount &&
pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
{
state.m_nIndex++;
}
}
state.m_nIndexMax = nCount;
}
}
// Do the work for update
CNewFrame<CDialog>::OnInitMenuPopup(pMenu,nIndex,bSysMenu);
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CNewMiniFrameWnd,CMiniFrameWnd)
IMPLEMENT_DYNCREATE(CNewMDIChildWnd,CMDIChildWnd)
IMPLEMENT_DYNCREATE(CNewMiniDockFrameWnd,CMiniDockFrameWnd);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CNewFrameWnd,CFrameWnd)
#if _MFC_VER < 0x0700
#include <../src/afximpl.h>
BOOL CNewFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
{
// only do this once
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
CString strFullString;
if (strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
// attempt to create the window
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
LPCTSTR lpszTitle = m_strTitle;
if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
{
return FALSE; // will self destruct on failure normally
}
// save the default menu handle
ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd);
// load accelerator resource
LoadAccelTable(MAKEINTRESOURCE(nIDResource));
if (pContext == NULL) // send initial update
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
return TRUE;
}
#endif
BOOL CNewFrameWnd::Create(LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
LPCTSTR lpszMenuName,
DWORD dwExStyle,
CCreateContext* pContext)
{
if (lpszMenuName != NULL)
{
m_DefaultNewMenu.LoadMenu(lpszMenuName);
// load in a menu that will get destroyed when window gets destroyed
if (m_DefaultNewMenu.m_hMenu == NULL)
{
#if _MFC_VER < 0x0700
TRACE0("Warning: failed to load menu for CNewFrameWnd.\n");
#else
TRACE(traceAppMsg, 0, "Warning: failed to load menu for CNewFrameWnd.\n");
#endif
PostNcDestroy(); // perhaps delete the C++ object
return FALSE;
}
}
m_strTitle = lpszWindowName; // save title for later
if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), m_DefaultNewMenu.m_hMenu, (LPVOID)pContext))
{
#if _MFC_VER < 0x0700
TRACE0("Warning: failed to create CNewFrameWnd.\n");
#else
TRACE(traceAppMsg, 0, "Warning: failed to create CNewFrameWnd.\n");
#endif
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewMDIFrameWnd,CMDIFrameWnd)
#if _MFC_VER < 0x0700
BOOL CNewMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
{
// only do this once
ASSERT_VALID_IDR(nIDResource);
ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
CString strFullString;
if (strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
// attempt to create the window
LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);
LPCTSTR lpszTitle = m_strTitle;
if (!Create(lpszClass, lpszTitle, dwDefaultStyle, rectDefault,
pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))
{
return FALSE; // will self destruct on failure normally
}
// save the default menu handle
ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd);
// load accelerator resource
LoadAccelTable(MAKEINTRESOURCE(nIDResource));
if (pContext == NULL) // send initial update
SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);
// save menu to use when no active MDI child window is present
ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd);
if (m_hMenuDefault == NULL)
TRACE0("Warning: CMDIFrameWnd without a default menu.\n");
return TRUE;
}
#endif
BOOL CNewMDIFrameWnd::Create( LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
LPCTSTR lpszMenuName,
DWORD dwExStyle,
CCreateContext* pContext)
{
if (lpszMenuName != NULL)
{
m_DefaultNewMenu.LoadMenu(lpszMenuName);
// load in a menu that will get destroyed when window gets destroyed
if (m_DefaultNewMenu.m_hMenu == NULL)
{
#if _MFC_VER < 0x0700
TRACE0("Warning: failed to load menu for CNewMDIFrameWnd.\n");
#else
TRACE(traceAppMsg, 0, "Warning: failed to load menu for CNewMDIFrameWnd.\n");
#endif
PostNcDestroy(); // perhaps delete the C++ object
return FALSE;
}
}
m_strTitle = lpszWindowName; // save title for later
if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,
rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
pParentWnd->GetSafeHwnd(), m_DefaultNewMenu.m_hMenu, (LPVOID)pContext))
{
#if _MFC_VER < 0x0700
TRACE0("Warning: failed to create CNewMDIFrameWnd.\n");
#else
TRACE(traceAppMsg, 0, "Warning: failed to create CNewMDIFrameWnd.\n");
#endif
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CNewMultiDocTemplate,CMultiDocTemplate)
CNewMultiDocTemplate::CNewMultiDocTemplate(UINT nIDResource,
CRuntimeClass* pDocClass,
CRuntimeClass* pFrameClass,
CRuntimeClass* pViewClass)
: CMultiDocTemplate(nIDResource,pDocClass,pFrameClass,pViewClass)
{
if (m_nIDResource != 0 && m_hMenuShared)
{
// Attach the menu.
m_NewMenuShared.LoadMenu(m_hMenuShared);
// Try to load icons to the toolbar.
m_NewMenuShared.LoadToolBar(m_nIDResource);
}
}
CNewMultiDocTemplate::~CNewMultiDocTemplate()
{
// Let only the CNewMenu to destroy the menu.
if(m_hMenuShared==m_NewMenuShared.m_hMenu)
{
m_hMenuShared = NULL;
}
}