📄 newmenu.cpp
字号:
//------------------------------------------------------------------------------
// 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
// Modified by jingzhou Xu
//
// 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
/////////////////////////////////////////////////////////////////////////////
// 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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -