📄 cjmenu.cpp
字号:
}
/*
==========================================================================
void CCJMenu::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 CCJMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
{
UINT state = (((CCJMenuData*)(lpMIS->itemData))->nFlags);
if(state & MF_SEPARATOR){
lpMIS->itemWidth = 0;
lpMIS->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
}
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;
m_fontMenu.CreateFontIndirect (&m_lf);
// Obtain the width of the text:
CWnd *pWnd = AfxGetMainWnd(); // Get main window
CDC *pDC = pWnd->GetDC(); // Get device context
CFont* pFont=NULL; // Select menu font in...
if (IsNewShell())
pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
//Get pointer to text SK
const wchar_t *lpstrText = ((CCJMenuData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
SIZE size;
if (Win32s!=g_Shell)
VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
wcslen(lpstrText),&size)); //SK should also work on 95
#ifndef UNICODE //can't be UNICODE for Win32s
else{//it's Win32suckx
RECT rect;
rect.left=rect.top=0;
size.cy=DrawText(pDC->m_hDC,(LPCTSTR)lpstrText,
wcslen(lpstrText),&rect,
DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
//+3 makes at least three pixels space to the menu border
size.cx=rect.right-rect.left+3;
size.cx += 3*(size.cx/wcslen(lpstrText));
}
#endif
CSize t = CSize(size);
if(IsNewShell())
pDC->SelectObject (pFont); // Select old font in
AfxGetMainWnd()->ReleaseDC(pDC); // Release the DC
// Set width and height:
lpMIS->itemWidth = m_iconX + t.cx + m_iconX + GAP;
int temp = GetSystemMetrics(SM_CYMENU);
lpMIS->itemHeight = temp>m_iconY+4 ? temp : m_iconY+4;
m_fontMenu.DeleteObject();
}
}
void CCJMenu::SetIconSize (int width, int height)
{
m_iconX = width;
m_iconY = height;
}
BOOL CCJMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
int nIconNormal)
{
ASSERT(lpstrText);
USES_CONVERSION;
return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);//SK: See MFC Tech Note 059
}
BOOL CCJMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
int nIconNormal)
{
// Add the MF_OWNERDRAW flag if not specified:
ASSERT(lpstrText);
if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW;
else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
CCJMenuData *mdata = new CCJMenuData;
m_MenuList.Add(mdata);
mdata->SetWideString(lpstrText); //SK: modified for dynamic allocation
mdata->menuIconNormal = nIconNormal;
mdata->xoffset=-1;
if(nIconNormal>=0){
mdata->xoffset=0;
LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
AddBitmapToImageList(mdata->bitmap,nIconNormal);
}
mdata->nFlags = nFlags;
mdata->nID = nID;
return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
}
BOOL CCJMenu::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);//SK: see MFC Tech Note 059
}
BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
{
int nLoc;
CCJMenuData *mdata;
// Find the old CCJMenuData structure:
CCJMenu *psubmenu = FindMenuOption(nID,nLoc);
if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
else{
// Create a new CCJMenuData structure:
mdata = new CCJMenuData;
m_MenuList.Add(mdata);
}
ASSERT(mdata);
if(lpstrText)
mdata->SetWideString(lpstrText); //SK: modified for dynamic allocation
mdata->menuIconNormal = nIconNormal;
mdata->xoffset=-1;
if(nIconNormal>=0){
mdata->xoffset=0;
LoadFromToolBar(nID,nIconNormal,mdata->xoffset);
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
AddBitmapToImageList(mdata->bitmap,nIconNormal);
}
mdata->nFlags = MF_BYCOMMAND | MF_OWNERDRAW;
mdata->nID = nID;
return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
}
BOOL CCJMenu::ModifyODMenuA(const char *lpstrText,const char *OptionText,
int nIconNormal)
{
USES_CONVERSION;
return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC Tech Note 059
}
BOOL CCJMenu::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,
int nIconNormal)
{
CCJMenuData *mdata;
// Find the old CCJMenuData structure:
CString junk=OptionText;
mdata=FindMenuOption(OptionText);
if(mdata){
if(lpstrText)
mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
mdata->menuIconNormal = nIconNormal;
mdata->xoffset=-1;
if(nIconNormal>=0){
mdata->xoffset=0;
if(mdata->bitmap)mdata->bitmap->DeleteImageList();
else mdata->bitmap=new(CImageList);
mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
AddBitmapToImageList(mdata->bitmap,nIconNormal);
}
return(TRUE);
}
return(FALSE);
}
CCJMenuData *CCJMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
{
CCJMenuData *mdata;
mdata = new CCJMenuData;
mdata->menuIconNormal = -1;
mdata->xoffset=-1;
#ifdef UNICODE
mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
#else
mdata->SetAnsiString(string);
#endif
mdata->nFlags = nFlags;
mdata->nID = nID;
if (nFlags&MF_OWNERDRAW){
ASSERT(!(nFlags&MF_STRING));
ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
}
else if (nFlags&MF_STRING){
ASSERT(!(nFlags&MF_OWNERDRAW));
ModifyMenu(pos,nFlags,nID,mdata->GetString());
}
else{
ASSERT(nFlags&MF_SEPARATOR);
ModifyMenu(pos,nFlags,nID);
}
return(mdata);
};
BOOL CCJMenu::LoadToolbars(const UINT *arID,int n)
{
ASSERT(arID);
BOOL returnflag=TRUE;
for(int i=0;i<n;++i){
if(!LoadToolbar(arID[i]))returnflag=FALSE;
}
return(returnflag);
}
BOOL CCJMenu::LoadToolbar(UINT nToolBar)
{
UINT nID;
BOOL returnflag=FALSE;
CToolBar bar;
bar.Create(AfxGetMainWnd());
if(bar.LoadToolBar(nToolBar)){
for(int i=0;i<bar.GetCount();++i){
nID = bar.GetItemID(i);
if(nID && GetMenuState(nID, MF_BYCOMMAND)
!=0xFFFFFFFF)ModifyODMenu(NULL,nID,nToolBar);
}
returnflag=TRUE;
}
return(returnflag);
}
BOOL CCJMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
{
int xset,offset;
UINT nStyle;
BOOL returnflag=FALSE;
CToolBar bar;
bar.Create(AfxGetMainWnd());
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);
}
CCJMenu *CCJMenu::FindMenuOption(int nId,int& nLoc)
{
int i;
CCJMenu *psubmenu,*pgoodmenu;
for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI
psubmenu=dynamic_cast<CCJMenu *>(GetSubMenu(i));
#else
psubmenu=(CCJMenu *)GetSubMenu(i);
#endif
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);
}
CCJMenuData *CCJMenu::FindMenuOption(wchar_t *lpstrText)
{
int i,j;
CCJMenu *psubmenu;
CCJMenuData *pmenulist;
for(i=0;i<(int)(GetMenuItemCount());++i){
#ifdef _CPPRTTI
psubmenu=dynamic_cast<CCJMenu *>(GetSubMenu(i));
#else
psubmenu=(CCJMenu *)GetSubMenu(i);
#endif
if(psubmenu){
pmenulist=psubmenu->FindMenuOption(lpstrText);
if(pmenulist)return(pmenulist);
}
else{
const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
for(j=0;j<=m_MenuList.GetUpperBound();++j){
szWide = m_MenuList[j]->GetWideString ();
if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
return(m_MenuList[j]);
}
}
}
return(NULL);
}
BOOL CCJMenu::LoadMenu(int nResource)
{
return(CCJMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
};
BOOL CCJMenu::LoadMenu(LPCTSTR lpszResourceName)
{
TRACE(_T(
"IMPORTANT:Use CCJMenu::DestroyMenu to destroy Loaded Menu's\n"));
ASSERT_VALID(this);
ASSERT(lpszResourceName != NULL);
// Find the Menu Resource:
HINSTANCE m_hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
HRSRC hRsrc = ::FindResource(m_hInst,lpszResourceName,RT_MENU);
if(hRsrc == NULL)return FALSE;
// Load the Menu Resource:
HGLOBAL hGlobal = LoadResource(m_hInst, hRsrc);
if(hGlobal == NULL)return FALSE;
// Attempt to create us as a menu...
if(!CMenu::CreateMenu())return FALSE;
// Get Item template Header, and calculate offset of MENUITEMTEMPLATES
MENUITEMTEMPLATEHEADER *pTpHdr=
(MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
BYTE* pTp=(BYTE*)pTpHdr +
(sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
// Variables needed during processing of Menu Item Templates:
int j=0;
WORD dwFlags = 0; // Flags of the Menu Item
WORD dwID = 0; // ID of the Menu Item
UINT uFlags; // Actual Flags.
wchar_t *szCaption=NULL;
int nLen = 0; // Length of caption
CTypedPtrArray<CPtrArray, CCJMenu*> m_Stack; // Popup menu stack
CArray<BOOL,BOOL> m_StackEnd; // Popup menu stack
m_Stack.Add(this); // Add it to this...
m_StackEnd.Add(FALSE);
do{
// Obtain Flags and (if necessary), the ID...
memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
if(!(dwFlags & MF_POPUP)){
memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
pTp+=sizeof(WORD);
}
else dwID = 0;
uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
uFlags -= MF_END;
// Obtain Caption (and length)
nLen = 0;
szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
wcscpy(szCaption,(wchar_t *)pTp);
pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
// Handle popup menus first....
//WideCharToMultiByte
if(dwFlags & MF_POPUP){
if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
CCJMenu* pSubMenu = new CCJMenu;
pSubMenu->m_unselectcheck=m_unselectcheck;
pSubMenu->m_selectcheck=m_selectcheck;
pSubMenu->checkmaps=checkmaps;
pSubMenu->checkmapsshare=TRUE;
pSubMenu->CreatePopupMenu();
// Append it to the top of the stack:
m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
(UINT)pSubMenu->m_hMenu, -1);
m_Stack.Add(pSubMenu);
m_StackEnd.Add(FALSE);
m_SubMenus.Add(pSubMenu);
}
else {
m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
dwID, -1);
if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
j = m_Stack.GetUpperBound();
while(j>=0 && m_StackEnd.GetAt(j)){
m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
m_Stack.RemoveAt(j);
m_StackEnd.RemoveAt(j);
--j;
}
}
delete[] szCaption;
}while(m_Stack.GetUpperBound() != -1);
for(int i=0;i<(int)GetMenuItemCount();++i){
CString str=m_MenuList[i]->GetString();
if(GetSubMenu(i)){
m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
(UINT)GetSubMenu(i)->m_hMenu,str);
}
else{
m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
}
}
return(TRUE);
}
void CCJMenu::InsertSpaces(void)
{
int i,j,numitems,maxlength;
CString string,newstring;
CSize t;
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;
m_fontMenu.CreateFontIndirect (&m_lf);
CWnd *pWnd = AfxGetMainWnd();
CDC *pDC = pWnd->GetDC();
CFont* pFont = pDC->SelectObject (&m_fontMenu);
numitems=GetMenuItemCount();
maxlength = -1;
for(i=0;i<numitems;++i){
string=m_MenuList[i]->GetString();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -