📄 menubar.cpp
字号:
/****************************************************************************
* *
* GuiToolKit *
* (MFC extension) *
* Created by Francisco Campos G. www.beyondata.com fcampos@beyondata.com *
*--------------------------------------------------------------------------*
* *
* This program is free software;so you are free to use it any of your *
* applications (Freeware, Shareware, Commercial),but leave this header *
* intact. *
* *
* These files are provided "as is" without warranty of any kind. *
* *
* GuiToolKit is forever FREE CODE !!!!! *
* *
*--------------------------------------------------------------------------*
* *
* Bug Fixes and improvements : (Add your name) *
* -Francisco Campos *
* -igor1960 *
****************************************************************************/
//
// 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 "..\header\MenuBar.h"
#include "..\header\GuiDockContext.h"
#include <afxole.h>
#include "..\header\menubar.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
BOOL bActivSystemMenu;
//////////////////////////////////////////////////////////////////////
// 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;
COLORREF m_clrFace;
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;
strcpy(info.lfMenuFont.lfFaceName,"verdana");
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:
// changed by Manfred Drasch - start
CRect rcTmpItem;
rcTmpItem = rcItem;
if(rcTmpItem.left < 0)
{
rcTmpItem.right = rcTmpItem.Width();
rcTmpItem.left = 0;
}
if(rcTmpItem.left > rcExclude.right)
{
rcTmpItem.right = rcExclude.right;
rcTmpItem.left = rcTmpItem.right-rcTmpItem.Width();
}
pt = CPoint(rcTmpItem.left-1, rcTmpItem.bottom);
rcExclude.bottom = rcTmpItem.bottom+1;// <- insead of [fuFlags |= TPM_VERPOSANIMATION;]
// changed by Manfred Drasch - end
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_RBUTTONDOWN()
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()
ON_WM_SYSCOLORCHANGE()
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(MB_SET_MENU_NULL, OnSetMenuNull)
ON_WM_PAINT()
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_bChangeState=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;
m_MenuContext=NULL;
}
//******************************************************************
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));
m_clrFace=GuiDrawLayer::GetRGBColorFace();
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;
}
void CMenuBar::OnSysColorChange( )
{
CWnd::OnSysColorChange( );
CClientDC dc(this);
m_clrFace=GuiDrawLayer::GetRGBColorFace();
for (int i = 0; i < m_arrItem.GetSize(); ++i)
m_arrItem[i]->UpdateClr();
/*if(m_pMenuControl != NULL)
m_pMenuControl->SetColorButton(GuiDrawLayer::GetRGBColorFace());
if(m_pMenuIcon != NULL)
{
m_pMenuIcon->OnActivateChildWnd();
m_pMenuIcon->Update(&dc);
}*/
}
//******************************************************************
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,100), 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,this));
}
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -