📄 menubar.cpp.svn-base
字号:
//-----------------------------------------------------------------------//
// This is a part of the GuiLib MFC Extention. //
// Modified by : Francisco Campos //
// (C) 2002 Francisco Campos <www.beyondata.com> All rights reserved //
// This code is provided "as is", with absolutely no warranty expressed //
// or implied. Any use is at your own risk. //
// You must obtain the author's consent before you can include this code //
// in a software library. //
// If the source code in this file is used in any application //
// then acknowledgement must be made to the author of this program //
// fcampos@tutopia.com //
//-----------------------------------------------------------------------//
//
// Class : CMenuBar
//
// Version : 1.0
//
// Created : Jan 14, 2001
//
// Last Modified: Francisco Campos.
//
// CMenuBar class version 2.12
// simulates a Dev Studio style dockable menu bar.
// based on PixieLib written by Paul DiLascia<www.dilascia.com>
//
// version history
// 2.12 : support OLE menu carelessly.
// 2.11 : WindowMenu fixed by VORGA.
// 2.10 : CMenuDockBar's problem fixed again and again.
// 2.08 : give up precise ComputeMenuTrackPoint
// 2.07 : Sychronizing with frame activation problem fixed
// 2.06 : CMenuItem::ComputeMenuTrackPoint fixed a little
// 2.05 : CMenuDockBar fixed
// : Inactive state problem fixed
// 2.04 : bug with ::TrackPopupEx carelessly fixed
// : synchronizing TrackPopup animation with win98 effect
//
// written by MB <mb2@geocities.co.jp> 1999.11.27
//
//
//
// CMenuBar version 2.13
#include "stdafx.h"
#include "MenuBar.h"
#include "resource.h"
#include "GuiDockContext.h"
#include <afxole.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifdef _DEBUG
const BOOL bTraceOn = FALSE;
#define LTRACE if (bTraceOn) TRACE
const BOOL bTraceOn2 = TRUE;
#define LTRACE2 if (bTraceOn2) TRACE
#else
#define LTRACE
#define LTRACE2
#endif
//////////////////////////////////////////////////////////////////////
// I've found string resource of "More windows" in "user.exe".
// But I can't load it, so please replace a following with your language.
static const TCHAR _szMoreWindows[] = _T("&More windows...");
//////////////////////////////////////////////////////////////////////
// used for OLE menu (easy fix)
static BOOL _bWindowMenuSendCmd = FALSE;
static int _nPrevIndexForCmd = -1;
//////////////////////////////////////////////////////////////////////
// hook
static CMenuBar* g_pMenuBar = NULL;
static HHOOK g_hMsgHook = NULL;
// message
const UINT CMenuBar::WM_GETMENU = ::RegisterWindowMessage(_T("CMenuBar::WM_GETMENU"));
const UINT MB_SET_MENU_NULL = ::RegisterWindowMessage(_T("CMenuBar::MB_SET_MENU_NULL"));
const int cxBorder2 = ::GetSystemMetrics(SM_CXBORDER)*2;
const int cyBorder2 = ::GetSystemMetrics(SM_CYBORDER)*2;
// common resources
static CFont _fontHorzMenu, _fontVertMenu;
static int _cyHorzFont, _cyMenuOnBar, _cyTextMargin;
const int CXTEXTMARGIN = 5;
DWORD dSt;
int gbintHorz; //Horz=0, Vert=1
CRect rcMenu; //CRect of button
static BOOL _InitCommonResources(BOOL bForce = FALSE)
{
if (bForce == FALSE && _fontHorzMenu.m_hObject != NULL)
return TRUE;// no need to reinitialize
// clean up
_fontHorzMenu.DeleteObject();
_fontVertMenu.DeleteObject();
// create fonts
NONCLIENTMETRICS info; info.cbSize = sizeof(info);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
if (!_fontHorzMenu.CreateFontIndirect(&info.lfMenuFont))
return FALSE;
// create vertical font
info.lfMenuFont.lfEscapement = -900;
info.lfMenuFont.lfOrientation = -900;
if (!_fontVertMenu.CreateFontIndirect(&info.lfMenuFont))
return FALSE;
// get font height
_cyHorzFont = abs(info.lfMenuFont.lfHeight);
// calc Y text margin
_cyMenuOnBar = info.iMenuHeight;
_cyMenuOnBar = max(_cyMenuOnBar, ::GetSystemMetrics(SM_CYSMICON));
_cyTextMargin = (_cyMenuOnBar - _cyHorzFont) / 2;
return TRUE;
}
// I wanted to control popup point, but I've fount we can never get popupmenu rect before popup.
// even if not owner draw menu...
static CPoint _ComputeMenuTrackPoint(const CRect& rcItem, DWORD dwStyle, UINT& fuFlags, TPMPARAMS& tpm)
{
fuFlags = TPM_LEFTBUTTON | TPM_LEFTALIGN | TPM_HORIZONTAL;
tpm.cbSize = sizeof(tpm);
CPoint pt;
CRect& rcExclude = (CRect&)tpm.rcExclude;
CWnd::GetDesktopWindow()->GetWindowRect(&rcExclude);
CRect rcFrame;
AfxGetMainWnd()->GetWindowRect(&rcFrame);
switch (dwStyle & CBRS_ALIGN_ANY) {
case CBRS_ALIGN_RIGHT:
case CBRS_ALIGN_LEFT:
pt = CPoint(rcItem.right+1, rcItem.top-1);
// to avoid strange menu flip, won't do : [rcExclude.right = rcItem.right+1;]
// I want to use : fuFlags |= TPM_HORNEGANIMATION;
break;
default: // case CBRS_ALIGN_TOP:
pt = CPoint(rcItem.left-1, rcItem.bottom);
rcExclude.bottom = rcItem.bottom+1;// <- insead of [fuFlags |= TPM_VERPOSANIMATION;]
break;
}
return pt;
}
//******************************************************************
static int _CalcTextWidth(const CString& strText)
{
CWindowDC dc(NULL);
CRect rcText(0, 0, 0, 0);
CFont* pOldFont = dc.SelectObject(&_fontHorzMenu);
dc.DrawText(strText, &rcText, DT_SINGLELINE | DT_CALCRECT);
dc.SelectObject(pOldFont);
return rcText.Width();
}
//******************************************************************
// grippers pasted from MFC6
#define CX_GRIPPER 3
#define CY_GRIPPER 3
#define CX_BORDER_GRIPPER 2
#define CY_BORDER_GRIPPER 2
#define CX_GRIPPER_ALL CX_GRIPPER + CX_BORDER_GRIPPER*2
#define CY_GRIPPER_ALL CY_GRIPPER + CY_BORDER_GRIPPER*2
/////////////////////////////////////////////////////////////////////////////
// CMenuBar
BEGIN_MESSAGE_MAP(CMenuBar, CControlBar)
//{{AFX_MSG_MAP(CMenuBar)
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_CREATE()
ON_WM_LBUTTONUP()
ON_WM_TIMER()
ON_WM_DESTROY()
ON_WM_NCCALCSIZE()
ON_WM_NCPAINT()
ON_WM_NCHITTEST()
ON_WM_SIZE()
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(MB_SET_MENU_NULL, OnSetMenuNull)
END_MESSAGE_MAP()
IMPLEMENT_DYNAMIC(CMenuBar, CControlBar)
/////////////////////////////////////////////////////////////////////////////
// CMenuBar Construction
CMenuBar::CMenuBar()
{
m_nCurIndex = -1;
m_nTrackingState = none;
m_bProcessRightArrow = m_bProcessLeftArrow = TRUE;
m_bIgnoreAlt = FALSE;
m_hMenu = NULL;
m_nIDEvent = NULL;
szNameHistory.Empty();
bSaveHistory=FALSE;
m_bMDIMaximized = FALSE;
m_hWndMDIClient = NULL;
m_hWndActiveChild = NULL;
m_pMenuIcon = NULL;
m_pMenuControl = NULL;
m_bDelayedButtonLayout = TRUE;
m_dwExStyle = 0;
m_bFrameActive = FALSE;
m_bMDIApp = FALSE;
m_style = Office97; //by default
m_bXP=FALSE;
cmb=NULL;
m_bCombo=FALSE;//combobox by default
bIsTabbed=FALSE;
}
//******************************************************************
BOOL CMenuBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
{
return CreateEx(pParentWnd, dwStyle,
CRect(m_cxLeftBorder, m_cyTopBorder, m_cxRightBorder, m_cyBottomBorder), nID);
}
//******************************************************************
BOOL CMenuBar::CreateEx(CWnd* pParentWnd, DWORD dwStyle, CRect rcBorders, UINT nID)
{
ASSERT_VALID(pParentWnd);// must have a parent
ASSERT (!((dwStyle & CBRS_SIZE_FIXED) && (dwStyle & CBRS_SIZE_DYNAMIC)));
SetBorders(rcBorders);
// save the original style
m_dwExStyle = dwStyle;
// save the style
m_dwStyle = (dwStyle & CBRS_ALL);// ******fixed by Mark Gentry, thanx!******
dwStyle &= ~CBRS_ALL;
dwStyle|=WS_CLIPCHILDREN | CCS_NOPARENTALIGN | CCS_NOMOVEY | CCS_NORESIZE;
CString strClass = AfxRegisterWndClass(
CS_HREDRAW | CS_VREDRAW |
CS_DBLCLKS,// don't forget!
AfxGetApp()->LoadStandardCursor(IDC_ARROW),
(HBRUSH)(COLOR_BTNFACE+1));
return CWnd::Create(strClass, _T("MenuBar"), dwStyle, CRect(), pParentWnd, nID);
}
void CMenuBar::SetSaveHistory(CString sNameHistory,BOOL bsaveHistory)
{
szNameHistory=sNameHistory;
bSaveHistory=bsaveHistory;
}
//******************************************************************
int CMenuBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CControlBar::OnCreate(lpCreateStruct) == -1)
return -1;
CWnd* pFrame = GetOwner();
ASSERT_VALID(pFrame);
// hook frame window to trap WM_MENUSELECT
//m_hookFrame.Install(this, pFrame->GetSafeHwnd());
// If this is an MDI app, hook client window to trap WM_MDISETMENU
if (pFrame->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))) {
m_bMDIApp = TRUE;
m_hWndMDIClient = ((CMDIFrameWnd*)pFrame)->m_hWndMDIClient;
ASSERT(::IsWindow(m_hWndMDIClient));
m_hookMDIClient.Install(this, m_hWndMDIClient);
}
if (m_pDockContext==NULL)
m_pDockContext=new CGuiDockContext(this);
ASSERT(m_pDockContext);
if (!_InitCommonResources()) {
TRACE(_T("Failed to create menubar resource\n"));
return FALSE;
}
return 0;
}
//******************************************************************
BOOL CMenuBar::CreateCombo(CComboBox* pControl,UINT nID,int iSize,DWORD dwStyle)
{
CFont m_Font;
m_Font.CreateStockObject (DEFAULT_GUI_FONT);
if(!pControl->Create(dwStyle, CRect(1,1,iSize,200), this, nID))
{
TRACE(_T("Failed to create combo-box\n"));
m_bCombo=FALSE;
return FALSE;
}
m_bCombo=TRUE;
cmb=(CGuiComboBoxExt*)pControl;
cmb->ActiveHistory(TRUE);
cmb->LoadHistory(szNameHistory,bSaveHistory);
return TRUE;
}
//******************************************************************
void CMenuBar::OnSize(UINT nType, int cx, int cy)
{
RefreshBar();
if (m_bCombo==TRUE)
DrawCombo();
}
void CMenuBar::SetTabbed(BOOL bIstabed)
{
bIsTabbed=bIstabed;
}
//******************************************************************
BOOL CMenuBar::InitItems()
{
ASSERT(m_hMenu);
// clean up all items
DeleteItems();
// buttons
for (int i = 0; i < ::GetMenuItemCount(m_hMenu); ++i) {
m_arrItem.Add(new CMenuButton(m_hMenu, i));
}
if (m_bMDIApp) {
// icon
if (!bIsTabbed)
{
m_pMenuIcon = new CMenuIcon(this);
m_arrItem.InsertAt(0, m_pMenuIcon);
// frame control
m_pMenuControl = new CMenuControl(this);
m_arrItem.Add(m_pMenuControl);
// reinitializing
m_pMenuIcon->OnActivateChildWnd();
m_pMenuControl->OnActivateChildWnd();
}
}
return TRUE;
}
//******************************************************************
BOOL CMenuBar::LoadMenuBar(UINT nIDResource)
{
ASSERT(m_hMenu == NULL);
ASSERT_VALID(m_pDockSite);
if (m_pDockSite->GetMenu()) {
PostMessage(MB_SET_MENU_NULL, (WPARAM)m_pDockSite->GetSafeHwnd());
}
m_hMenu = ::LoadMenu(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIDResource));
if (m_hMenu == NULL) {
TRACE(_T("Failed to load menu\n"));
return FALSE;
}
return InitItems();
}
//******************************************************************
HMENU CMenuBar::LoadMenu(HMENU hMenu, HMENU hWindowMenu)
{
ASSERT(::IsMenu(hMenu));
ASSERT_VALID(this);
CFrameWnd* pFrame = GetParentFrame();
if (::GetMenu(pFrame->GetSafeHwnd()) != NULL) {
// not to make MFC ignore SetMenu(NULL), post it.
PostMessage(MB_SET_MENU_NULL, (WPARAM)pFrame->GetSafeHwnd());
}
HMENU hOldMenu = m_hMenu;
m_hMenu = hMenu;// menu is shared with MFC
// initialize Items
VERIFY(InitItems());
if (hMenu) {
m_hWindowMenu = hWindowMenu;
RefreshBar();// and menubar itself
}
return hOldMenu;
}
//******************************************************************
void CMenuBar::RefreshBar()
{
InvalidateRect(NULL);
#if _MFC_VER >= 0x600
if (GetParent()->IsKindOf(RUNTIME_CLASS(CReBar))) {
m_bDelayedButtonLayout = TRUE;// to avoid ASSERTION
Layout();
}
#endif
CFrameWnd* pFrame = (CFrameWnd*)GetTopLevelFrame();
ASSERT_VALID(pFrame); ASSERT(pFrame->IsFrameWnd());
pFrame->RecalcLayout();
// floating frame
CFrameWnd* pMiniFrame = GetParentFrame();
if (pMiniFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
pMiniFrame->RecalcLayout();
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar clean up
CMenuBar::~CMenuBar()
{
}
//******************************************************************
void CMenuBar::DeleteItems()
{
for(int i = 0; i < m_arrItem.GetSize(); ++i) {
CMenuItem* pItem = m_arrItem[i];
delete pItem;
}
m_arrItem.RemoveAll();
m_pMenuIcon = NULL;
m_pMenuControl = NULL;
}
//******************************************************************
/////////////////////////////////////////////////////////////////////////////
// CMenuBar draw
void CMenuBar::DoPaint(CDC* pDC)
{
CRect rect; GetClientRect(rect);
BOOL bFlota=m_dwStyle & CBRS_FLOATING;
// draw items
m_sizex=0;
for (int i = 0; i < m_arrItem.GetSize(); ++i) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -