NGenericMenu.cpp
资源名称:VCMenu.zip [点击查看]
上传用户:whjcdz88
上传日期:2007-01-02
资源大小:350k
文件大小:14k
源码类别:
工具条
开发平台:
Visual C++
- // NGenericMenu.cpp: implementation of the CNGenericMenu class.
- //
- /*
- Copyright (C) 1998 Tony Hoyle (tmh@netfusion.co.uk)
- This program is free software; you can redistribute it and/or modify it under the terms
- of the GNU General Public License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along with this program;
- if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- //////////////////////////////////////////////////////////////////////
- // Revised by Zhenxin Li.
- // Fix the no-sub-menu bug.
- #include "stdafx.h"
- #include "afxpriv.h"
- #include "NGenericMenu.h"
- #include "NGenericPopup.h"
- #include "NMDIClient.h"
- #include "resource.h"
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[]=__FILE__;
- #define new DEBUG_NEW
- #endif
- IMPLEMENT_DYNAMIC(CNGenericMenu,CNGenericToolBar)
- BEGIN_MESSAGE_MAP(CNGenericMenu,CNGenericToolBar)
- //{{AFX_MSG_MAP(CNGenericMenu)
- ON_WM_NCPAINT()
- ON_WM_SYSCOMMAND()
- ON_WM_LBUTTONDOWN()
- ON_WM_MOUSEMOVE()
- ON_WM_LBUTTONUP()
- ON_WM_PAINT()
- ON_WM_NCCALCSIZE()
- //}}AFX_MSG_MAP
- ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
- ON_NOTIFY_REFLECT(TBN_DROPDOWN,OnDropDown)
- ON_NOTIFY_REFLECT(TBN_HOTITEMCHANGE,OnHotChange)
- ON_UPDATE_COMMAND_UI_RANGE(65000,65100,OnMenuUpdate)
- ON_REGISTERED_MESSAGE(WM_MENU_DISMISS, OnDismiss)
- END_MESSAGE_MAP()
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CNGenericMenu::CNGenericMenu()
- {
- m_bHasBitmaps=FALSE;
- m_bItemDropped=FALSE;
- m_bForceText=TRUE;
- m_pParent=NULL;
- m_hMenu=NULL;
- m_bSysMenuIcon=FALSE;
- m_pIconMap=NULL;
- m_nIconMapSize=0;
- }
- CNGenericMenu::~CNGenericMenu()
- {
- }
- BOOL CNGenericMenu::Create(CFrameWnd* pParent)
- {
- m_pParent=pParent;
- m_hMenu=NULL;
- if(!CNGenericToolBar::CreateEx(pParent,TBSTYLE_FLAT|TBSTYLE_LIST|TBSTYLE_AUTOSIZE|TBSTYLE_TRANSPARENT|TBSTYLE_TOOLTIPS,WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_SIZE_DYNAMIC,AFX_IDW_MENU_BAR)) return FALSE;
- // Menu font fix by lg@ndirect.co.uk
- NONCLIENTMETRICS info;
- info.cbSize = sizeof(info);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
- VERIFY(menuFont.CreateFontIndirect(&info.lfMenuFont));
- SetFont(&menuFont,TRUE);
- CString csMenu;
- csMenu.LoadString(IDS_MENU);
- SetWindowText(csMenu);
- SendMessage(TB_BUTTONSTRUCTSIZE,sizeof(TBBUTTON));
- SendMessage(TB_SETBITMAPSIZE,0,MAKELPARAM(0,0));
- return TRUE;
- }
- BOOL CNGenericMenu::DrawMenuBar()
- {
- return SetMenu(m_hMenu);
- }
- BOOL CNGenericMenu::SetMenu(HMENU hMenu)
- {
- m_hMenu=hMenu;
- if(!hMenu) return FALSE;
- CToolBarCtrl* pCtrl=&GetToolBarCtrl();
- CMenu* pMenu=CMenu::FromHandle(hMenu);
- int nCount=pMenu->GetMenuItemCount();
- int* idString=new int[nCount];
- TBBUTTON* pTB=new TBBUTTON[nCount];
- int n;
- char tmp[65];
- LPCTSTR q;
- m_accelList.SetSize(0);
- CFrameWnd* pChildFrame=m_pParent->GetActiveFrame();
- if(pChildFrame && pChildFrame!=m_pParent)
- {
- m_hSysMenuIcon=(HICON)GetClassLong(*pChildFrame,GCL_HICONSM);
- }
- for(n=0; n<nCount; n++)
- {
- pMenu->GetMenuString(n,tmp,64,MF_BYPOSITION);
- tmp[strlen(tmp)+1]=' ';
- idString[n]=pCtrl->AddStrings(tmp);
- for(q=tmp; *q; q++)
- {
- if(*q=='&')
- {
- int s=m_accelList.GetSize();
- m_accelList.SetSize(s+1);
- m_accelList[s].nKey=toupper(*(q+1));
- m_accelList[s].nId=65000+n;
- break;
- }
- }
- memset(&pTB[n],0,sizeof(TBBUTTON));
- pTB[n].iBitmap=1;
- pTB[n].idCommand=65000+n;
- pTB[n].fsState=TBSTATE_ENABLED;
- pTB[n].fsStyle=TBSTYLE_BUTTON|TBSTYLE_DROPDOWN|TBSTYLE_AUTOSIZE;
- pTB[n].iString=idString[n];
- }
- while(pCtrl->DeleteButton(0))
- ;
- pCtrl->AddButtons(nCount,pTB);
- delete []idString;
- delete []pTB;
- RecalcSize();
- return TRUE;
- }
- void CNGenericMenu::OnDropDown(NMHDR * pNotifyStruct, LRESULT* result)
- {
- LPNMTOOLBAR lpnmtb = (LPNMTOOLBAR)pNotifyStruct;
- ShowDropDown(FALSE,lpnmtb->iItem);
- *result=TBDDRET_DEFAULT;
- }
- void CNGenericMenu::ShowDropDown(BOOL bFromKey, int iItem)
- {
- HMENU hPopup;
- CRect rect;
- CWnd* pParent;
- hPopup=*m_pParent->GetActiveFrame()->GetSystemMenu(FALSE);
- if(!m_bItemDropped)
- {
- if(iItem==-1)
- m_pParent->GetActiveFrame()->SendMessage(WM_INITMENU,(WPARAM)hPopup);
- else
- m_pParent->SendMessage(WM_INITMENU,(WPARAM)m_hMenu);
- }
- else
- {
- if(m_iItem==-1 && iItem!=-1)
- m_pParent->SendMessage(WM_INITMENU,(WPARAM)m_hMenu);
- else if(m_iItem!=-1 && iItem==-1)
- m_pParent->GetActiveFrame()->SendMessage(WM_INITMENU,(WPARAM)hPopup);
- if(m_iItem!=-1) SendMessage(TB_SETSTATE,m_iItem,TBSTATE_ENABLED);
- }
- m_iItem=iItem;
- m_bItemDropped=TRUE;
- if(iItem!=-1) SendMessage(TB_SETSTATE,iItem,TBSTATE_ENABLED|TBSTATE_PRESSED);
- if(iItem!=-1)
- {
- hPopup=::GetSubMenu(m_hMenu,iItem-65000);
- GetItemRect(iItem-65000,rect);
- ClientToScreen(rect);
- }
- else
- {
- CRect wr;
- GetWindowRect(wr);
- rect=m_rectSysMenu;
- rect.OffsetRect(wr.left,wr.top);
- }
- // revised by Zhenxin Li.
- // no sub menu, so return.
- if (!hPopup)
- return;
- if(iItem!=-1)
- {
- pParent=m_pParent;
- pParent->SendMessage(WM_INITMENUPOPUP,(WPARAM)hPopup,iItem-65000);
- }
- else
- {
- pParent=m_pParent->GetActiveFrame();
- pParent->SendMessage(WM_INITMENUPOPUP,(WPARAM)hPopup,0);
- }
- if (m_dwStyle & CBRS_ALIGN_LEFT)
- m_popup.ShowMenu(POP_MENU_LEFT,bFromKey,this,rect.right+1,rect.top,m_pParent,hPopup);
- else if(m_dwStyle & CBRS_ALIGN_RIGHT)
- m_popup.ShowMenu(POP_MENU_RIGHT,bFromKey,this,rect.left,rect.top,m_pParent,hPopup);
- else if(m_dwStyle & CBRS_ALIGN_TOP)
- m_popup.ShowMenu(POP_MENU_TOP,bFromKey,this,rect.left,rect.bottom+1,m_pParent,hPopup);
- else if(m_dwStyle & CBRS_ALIGN_BOTTOM)
- m_popup.ShowMenu(POP_MENU_BOTTOM,bFromKey,this,rect.left,rect.top,m_pParent,hPopup);
- }
- void CNGenericMenu::OnHotChange(NMHDR * pNotifyStruct, LRESULT* result)
- {
- LPNMTBHOTITEM lpnmtb = (LPNMTBHOTITEM)pNotifyStruct;
- if(m_bItemDropped && lpnmtb->idNew!=m_iItem)
- {
- if(lpnmtb->idNew)
- ShowDropDown(FALSE,lpnmtb->idNew);
- else
- {
- CPoint pt;
- CRect r;
- GetCursorPos(&pt);
- GetWindowRect(r);
- pt.x-=r.left;
- pt.y-=r.top;
- if(m_bSysMenuIcon && m_rectSysMenu.PtInRect(pt))
- ShowDropDown(FALSE,-1);
- }
- }
- *result=0;
- }
- void CNGenericMenu::OnOverSysMenu()
- {
- if(m_bItemDropped && m_iItem!=-1)
- ShowDropDown(FALSE,-1);
- }
- void CNGenericMenu::OnMenuUpdate(CCmdUI* pCmd)
- {
- if(!m_hMenu) return;
- CMenu* pMenu=CMenu::FromHandle(m_hMenu);
- if(!pMenu) return;
- pCmd->Enable(pMenu->GetMenuState(pCmd->m_nID-65000,MF_DISABLED));
- }
- LRESULT CNGenericMenu::OnDismiss(WPARAM wParam, LPARAM lParam)
- {
- if(m_bItemDropped)
- {
- if(m_iItem!=-1) SendMessage(TB_SETSTATE,m_iItem,TBSTATE_ENABLED);
- }
- m_bItemDropped=FALSE;
- return 0;
- }
- BOOL CNGenericMenu::TranslateMenuChar(UINT nChar)
- {
- for(int n=0; n<m_accelList.GetSize(); n++)
- {
- if(m_accelList[n].nKey==(UINT)toupper(nChar))
- {
- ShowDropDown(TRUE,m_accelList[n].nId);
- return TRUE;
- }
- }
- return FALSE;
- }
- BOOL CNGenericMenu::KeyboardFilter(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- if(m_bItemDropped)
- {
- if(nChar==VK_LEFT)
- {
- if(m_iItem>65000)
- ShowDropDown(TRUE,m_iItem-1);
- else if(m_iItem==-1)
- ShowDropDown(TRUE,65000+GetToolBarCtrl().GetButtonCount()-1);
- else
- ShowDropDown(TRUE,m_bSysMenuIcon?-1:65000+GetToolBarCtrl().GetButtonCount()-1);
- }
- if(nChar==VK_RIGHT)
- {
- if(m_iItem==-1)
- ShowDropDown(TRUE,65000);
- else if(m_iItem<65000+GetToolBarCtrl().GetButtonCount()-1)
- ShowDropDown(TRUE,m_iItem+1);
- else
- ShowDropDown(TRUE,m_bSysMenuIcon?-1:65000);
- }
- }
- return FALSE;
- }
- void CNGenericMenu::OnNcPaint()
- {
- EraseNonClient(TRUE);
- }
- void CNGenericMenu::OnSysCommand(UINT nID, LPARAM lParam)
- {
- if(m_bSysMenuIcon)
- {
- switch(nID&0xfff0)
- {
- case SC_KEYMENU:
- ShowDropDown(TRUE,-1);
- break;
- case SC_MOUSEMENU:
- ShowDropDown(FALSE,-1);
- break;
- }
- m_pParent->GetActiveFrame()->PostMessage(WM_SYSCOMMAND,nID,lParam);
- }
- }
- void CNGenericMenu::OnIdleUpdateCmdUI()
- {
- BOOL bSysMenuIcon=(m_pParent->GetActiveFrame()!=m_pParent && m_pParent->GetActiveFrame()->IsZoomed())?TRUE:FALSE;
- if(bSysMenuIcon!=m_bSysMenuIcon)
- {
- m_bSysMenuIcon=bSysMenuIcon;
- SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
- PostMessage(WM_LBUTTONDOWN, 0, MAKELONG(-1, -1));
- PostMessage(WM_LBUTTONUP, 0, MAKELONG(-1, -1));
- }
- CNGenericToolBar::OnIdleUpdateCmdUI(0,0);
- }
- BOOL CNGenericMenu::SetIconMap(int nIconMapSize, IconMap* pIconMap)
- {
- m_nIconMapSize=nIconMapSize;
- m_pIconMap=pIconMap;
- return m_popup.SetIconMap(nIconMapSize,pIconMap);
- }
- CSize CNGenericMenu::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
- {
- // Revised by Zhenxin Li.
- // Fix the WIN98(95) Showing bug. If the width value is too high, the menu bar won't be displayed.
- CRect r;
- m_pDockBar->GetParent()->GetClientRect(r);
- CSize s = CNGenericToolBar::CalcFixedLayout(bStretch, bHorz);
- if (m_dwStyle&CBRS_ORIENT_HORZ)
- s.cx = r.right;
- else
- s.cy = r.bottom;
- return s;
- }
- CSize CNGenericMenu::CalcDynamicLayout(int nLength, DWORD dwMode)
- {
- CSize s = CNGenericToolBar::CalcDynamicLayout(nLength, dwMode);
- // Revised by Zhenxin Li.
- // Make room for system icon.
- //#th Fixed to allow for buttons as well
- if (m_bSysMenuIcon)
- {
- int nSize=16; // Icon size
- CRect r1,r2,r3;
- GetSysButtonRects(r1,r2,r3);
- nSize=r3.right-r1.left;
- nSize+=12; // Gap
- if (m_dwStyle&CBRS_ORIENT_HORZ)
- s.cx += nSize;
- else
- s.cy += nSize;
- }
- return s;
- }
- void CNGenericMenu::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
- {
- CNGenericToolBar::OnNcCalcSize(bCalcValidRects, lpncsp);
- // Adjust for system menu icon
- if(m_bSysMenuIcon)
- {
- if(m_dwStyle&CBRS_ORIENT_HORZ)
- {
- // move 16 pixels right to make room
- lpncsp->rgrc[0].left += 16;
- lpncsp->rgrc[0].right += 16;
- }
- else
- {
- // move 16 pixels downto make room
- lpncsp->rgrc[0].top += 16;
- lpncsp->rgrc[0].bottom += 16;
- }
- }
- }
- void CNGenericMenu::GetSysButtonRects(CRect& r1, CRect& r2, CRect& r3)
- {
- CRect r;
- CPoint p;
- int rows = SendMessage(TB_GETROWS);
- int cxIcon = 16;
- int cyIcon = 16;
- #define gap1 1
- #define gap2 2
- #define bcx (3*cxIcon+gap1+gap2+1)
- #define bcy (3*cyIcon+gap1+gap2+1)
- if (m_dwStyle&CBRS_FLOATING)
- {
- GetClientRect(r);
- p.x = r.right - 12 - bcx;
- p.y = r.bottom*(rows-1)/rows+(r.bottom/rows-cyIcon)/2;
- }
- else
- if (m_dwStyle&CBRS_ORIENT_HORZ)
- {
- m_pDockBar->GetClientRect(r);
- p.x = r.right;
- m_pDockBar->MapWindowPoints(this, &p, 1);
- GetClientRect(r);
- p.y = r.bottom*(rows-1)/rows+(r.bottom/rows-cyIcon)/2;
- p.x -= bcx;
- }
- else
- {
- m_pDockBar->GetClientRect(r);
- p.y = r.bottom - 1;
- m_pDockBar->MapWindowPoints(this, &p, 1);
- GetClientRect(r);
- p.x = (r.right-cxIcon)/2;
- p.y -= bcy;
- }
- r1 = CRect(p, CSize(cxIcon, cyIcon));
- if (m_dwStyle&CBRS_ORIENT_HORZ)
- {
- r2 = r1;
- r2.OffsetRect(cxIcon+gap1, 0);
- r3 = r2;
- r3.OffsetRect(cxIcon+gap2, 0);
- }
- else
- {
- r2 = r1;
- r2.OffsetRect(0, cyIcon+gap1);
- r3 = r2;
- r3.OffsetRect(0, cyIcon+gap2);
- }
- }
- void CNGenericMenu::DrawButton(CDC* pDC, CRect rect, LPCTSTR szText, BOOL bPressed)
- {
- DWORD c1 = GetSysColor(COLOR_3DHILIGHT);
- DWORD c2 = GetSysColor(COLOR_3DDKSHADOW);
- DWORD c3 = GetSysColor(COLOR_3DSHADOW);
- if (bPressed)
- {
- pDC->FillRect(rect,&CBrush(GetSysColor(COLOR_BTNFACE)));
- pDC->TextOut(rect.left+4,rect.top+4,szText);
- pDC->Draw3dRect(rect, c2, c1);
- rect.top++;
- rect.left++;
- pDC->Draw3dRect(rect, c3, c1);
- }
- else
- {
- pDC->FillRect(rect,&CBrush(GetSysColor(COLOR_BTNFACE)));
- pDC->TextOut(rect.left+3,rect.top+3,szText);
- pDC->Draw3dRect(rect, c1, c2);
- rect.bottom--;
- rect.right--;
- pDC->Draw3dRect(rect, c1, c3);
- }
- }
- ENButtonState CNGenericMenu::UpdateSysButtons(UINT nFlags, CPoint point)
- {
- if (m_bSysMenuIcon)
- {
- CRect r1, r2, r3;
- GetSysButtonRects(r1, r2, r3);
- CDC* pDC = GetDC();
- CFont f;
- f.CreatePointFont(80,"Marlett",pDC);
- pDC->SelectObject(f);
- pDC->SetBkMode(TRANSPARENT);
- DrawButton(pDC, r1, "0", r1.PtInRect(point)?nFlags&MK_LBUTTON:0);
- DrawButton(pDC, r2, "2", r2.PtInRect(point)?nFlags&MK_LBUTTON:0);
- DrawButton(pDC, r3, "r", r3.PtInRect(point)?nFlags&MK_LBUTTON:0);
- ReleaseDC(pDC);
- if(r1.PtInRect(point)) return Button_Minimize;
- if(r2.PtInRect(point)) return Button_Restore;
- if(r3.PtInRect(point)) return Button_Close;
- return Button_None;
- }
- return Button_None;
- }
- void CNGenericMenu::OnLButtonDown(UINT nFlags, CPoint point)
- {
- if (UpdateSysButtons(nFlags, point))
- SetCapture();
- else
- CNGenericToolBar::OnLButtonDown(nFlags, point);
- }
- void CNGenericMenu::OnMouseMove(UINT nFlags, CPoint point)
- {
- BOOL bCapture = (::GetCapture()==m_hWnd);
- if (!((bCapture)&&(UpdateSysButtons(nFlags, point))))
- CNGenericToolBar::OnMouseMove(nFlags, point);
- }
- void CNGenericMenu::OnLButtonUp(UINT nFlags, CPoint point)
- {
- ENButtonState state;
- BOOL bCapture = (::GetCapture()==m_hWnd);
- ReleaseCapture();
- if (bCapture&&(state=UpdateSysButtons(nFlags, point))!=Button_None)
- {
- switch(state)
- {
- case Button_Minimize:
- PostMessage(WM_SYSCOMMAND,SC_MINIMIZE);
- break;
- case Button_Restore:
- PostMessage(WM_SYSCOMMAND,SC_RESTORE);
- break;
- case Button_Close:
- PostMessage(WM_SYSCOMMAND,SC_CLOSE);
- break;
- }
- }
- else
- CNGenericToolBar::OnLButtonUp(nFlags, point);
- }
- void CNGenericMenu::OnPaint()
- {
- CNGenericToolBar::OnPaint();
- POINT point;
- GetCursorPos(&point);
- UpdateSysButtons(0, point);
- }