📄 menubar.cpp
字号:
/*********************************************************
* Simple IE-like Menu And Toolbar
* Version: 1.3
* Date: Semptember 1, 2003
* Autor: Michal Mecinski
* E-mail: mimec@mimec.w.pl
* WWW: http://www.mimec.w.pl
*
* Copyright (C) 2002-03 by Michal Mecinski
*********************************************************/
#include "stdafx.h"
#include "MenuBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// size of menu icons
#define MB_CX_ICON 16
#define MB_CY_ICON 16
#define GRAY_AREA_LENGTH 23
CMenuBar::CMenuBar()
{
m_bCues = false;
m_bFlatMenu = true;
m_bKeepPrefix = false;
m_bKeyboard = FALSE;
m_bNextMenu = false;
m_bPopMenu = FALSE;
m_bPrefix = TRUE;
m_hSelMenu = NULL;
m_bSelPopup = false;
m_bWndActive = TRUE;
m_hSelMenu = NULL;
m_nItemCount = 0;
m_nPressed = -1;
m_pMenu = NULL;
m_pPopupMenu = NULL;
m_pPrevFocus = NULL;
}
CMenuBar::~CMenuBar()
{
delete m_pMenu;
delete m_pPopupMenu;
}
BEGIN_MESSAGE_MAP(CMenuBar, CToolBarCtrl)
ON_WM_LBUTTONDOWN()
ON_WM_KILLFOCUS()
ON_WM_INITMENUPOPUP()
ON_WM_MEASUREITEM()
ON_WM_DRAWITEM()
ON_WM_ENTERIDLE()
ON_WM_MENUSELECT()
ON_MESSAGE(MBM_POPUPMENU, OnPopupMenu)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMenuBar public functions
BOOL CMenuBar::Create(CWnd* pParentWnd, UINT nID)
{
return CToolBarCtrl::Create(WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NODIVIDER | CCS_NORESIZE,
CRect(0, 0, 0, 0), pParentWnd, nID);
}
BOOL CMenuBar::LoadMenuBar(UINT nID, int nStyle)
{
if (m_pMenu)
m_pMenu->DestroyMenu();
else
m_pMenu = new CMenu;
// load menu resource
if (!m_pMenu->LoadMenu(nID))
return FALSE;
// create image list
if (!m_ImgList.Create(MB_CX_ICON, MB_CY_ICON, nStyle))
return FALSE;
m_CmdArray.RemoveAll();
// delete previous buttons if any
while (m_nItemCount--)
DeleteButton(0);
m_nItemCount = m_pMenu->GetMenuItemCount();
SetBitmapSize(CSize(1, 1));
TBBUTTON tbb;
ZeroMemory(&tbb, sizeof(tbb));
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE;
// add button for each menu
for(int i=0; i<m_nItemCount; i++)
{
CString strText;
m_pMenu->GetMenuString(i, strText, MF_BYPOSITION);
tbb.iString = AddStrings(strText);
tbb.idCommand = i;
if (!AddButtons(1, &tbb))
return FALSE;
}
// get system settings and resize toolbar
UpdateSettings();
return TRUE;
}
BOOL CMenuBar::AttachMenu(HMENU hMenu)
{
if (m_pMenu)
m_pMenu->Detach();
else
m_pMenu = new CMenu;
m_pMenu->Attach(hMenu);
while (m_nItemCount--)
DeleteButton(0);
m_nItemCount = m_pMenu->GetMenuItemCount();
SetBitmapSize(CSize(1, 1));
TBBUTTON tbb;
ZeroMemory(&tbb, sizeof(tbb));
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE;
// add button for each menu
for(int i=0; i<m_nItemCount; i++)
{
CString strText;
m_pMenu->GetMenuString(i, strText, MF_BYPOSITION);
tbb.iString = AddStrings(strText);
tbb.idCommand = i;
if (!AddButtons(1, &tbb))
return FALSE;
}
UpdateSettings();
return TRUE;
}
BOOL CMenuBar::LoadToolBar(UINT nID)
{
HINSTANCE hInst = AfxFindResourceHandle(MAKEINTRESOURCE(nID), RT_TOOLBAR);
HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nID), RT_TOOLBAR);
if (hRsrc == NULL)
return FALSE;
HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
if (hGlobal == NULL)
return FALSE;
struct TBDATA
{
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
WORD aItems[1];
};
// get the toolbar data
TBDATA* pData = (TBDATA*)LockResource(hGlobal);
if (pData == NULL)
return FALSE;
ASSERT(pData->wVersion == 1);
// add command IDs to the array
for (int i=0; i < pData->wItemCount; i++)
{
int nCmd = pData->aItems[i];
if (nCmd != 0) // ignore separators
m_CmdArray.Add(nCmd);
}
// load bitmap image
BOOL bResult = m_ImgList.AddBitmap(nID);
UnlockResource(hGlobal);
FreeResource(hGlobal);
return bResult;
}
HMENU CMenuBar::GetMenuHandle()
{
return m_pMenu ? m_pMenu->m_hMenu : NULL;
}
BOOL CMenuBar::LoadPopupMenu(UINT nID)
{
if (m_pPopupMenu)
m_pPopupMenu->DestroyMenu();
else
m_pPopupMenu = new CMenu;
return m_pPopupMenu->LoadMenu(nID);
}
void CMenuBar::TrackPopup(int nIndex, CPoint ptPos)
{
// use window menu if popup menu is not loaded
CMenu* pSubMenu = m_pPopupMenu ? m_pPopupMenu->GetSubMenu(nIndex) : m_pMenu->GetSubMenu(nIndex);
m_bPopMenu = m_pPopupMenu!=NULL;
if (pSubMenu)
pSubMenu->TrackPopupMenu(0, ptPos.x, ptPos.y, this);
}
void CMenuBar::TrackPopup(LPCSTR lpszName, CPoint ptPos)
{
CMenu* pMenu = m_pPopupMenu ? m_pPopupMenu : m_pMenu;
for (UINT i=0; i<pMenu->GetMenuItemCount(); i++)
{
CString str;
pMenu->GetMenuString(i, str, MF_BYPOSITION);
if (str.Compare(lpszName) == 0)
{
TrackPopup(i, ptPos);
return;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar input filter
//CMenuBar* CMenuBar::g_pMenuBar = NULL;
//HHOOK CMenuBar::g_hMsgHook = NULL;
static CMenuBar* g_pMenuBar = NULL;
static HHOOK g_hMsgHook = NULL;
LRESULT CMenuBar::MenuInputFilter(int nCode, WPARAM wParam, LPARAM lParam)
{
MSG* pMsg = (MSG*)lParam;
if (g_pMenuBar && nCode == MSGF_MENU)
{
// process menu message
if (g_pMenuBar->OnMenuInput(pMsg))
return TRUE;
}
if(!g_hMsgHook) return 0;
return CallNextHookEx(g_hMsgHook, nCode, wParam, lParam);
}
BOOL CMenuBar::OnMenuInput(MSG* pMsg)
{
BOOL bResult = FALSE;
switch(pMsg->message)
{
case WM_MOUSEMOVE:
{
CPoint pt;
pt.x = LOWORD(pMsg->lParam);
pt.y = HIWORD(pMsg->lParam);
ScreenToClient(&pt);
if (pt == m_ptLast) // ignore if mouse not moved
return TRUE;
m_ptLast = pt;
int nTest = HitTest(&pt);
// check if another menu was highlighted
if (nTest>=0 && nTest<m_nItemCount && nTest != m_nPressed)
{
PressButton(m_nPressed, FALSE);
m_bKeepPrefix = TRUE;
m_bNextMenu = TRUE;
SendMessage(WM_CANCELMODE); // close current menu
m_nPressed = nTest;
PostMessage(MBM_POPUPMENU); // open highlighted menu
return TRUE;
}
}
break;
case WM_LBUTTONDOWN:
{
POINT pt;
pt.x = LOWORD(pMsg->lParam);
pt.y = HIWORD(pMsg->lParam);
ScreenToClient(&pt);
int nTest = HitTest(&pt);
if (nTest == m_nPressed) // close menu if clicked again
{
m_bKeepPrefix = TRUE;
m_bNextMenu = TRUE;
SendMessage(WM_CANCELMODE,0,0);
return TRUE;
}
}
break;
case WM_KEYDOWN:
{
switch (pMsg->wParam)
{
case VK_LEFT:
if (InSubMenu()) // default action - close submenu
return FALSE;
PressButton(m_nPressed, FALSE);
m_bKeepPrefix = TRUE;
m_bNextMenu = TRUE;
SendMessage(WM_CANCELMODE);
m_nPressed--; // open previous menu
m_bKeyboard = TRUE;
PostMessage(MBM_POPUPMENU);
return TRUE;
case VK_RIGHT:
if (m_bSelPopup) // default action - open submenu
return FALSE;
PressButton(m_nPressed,FALSE);
m_bKeepPrefix = TRUE;
m_bNextMenu = TRUE;
SendMessage(WM_CANCELMODE);
m_nPressed++; // open next menu
m_bKeyboard = TRUE;
PostMessage(MBM_POPUPMENU);
return TRUE;
case VK_ESCAPE:
if (InSubMenu()) // default action - close submenu
return FALSE;
m_ptLast = CPoint(-1,-1);
m_bKeepPrefix = TRUE;
SendMessage(WM_CANCELMODE);
Highlight(m_nPressed); // activate the menu bar
return TRUE;
}
}
break;
case WM_MENUSELECT:
{
// store info about selected item
m_hSelMenu = (HMENU)pMsg->lParam;
m_bSelPopup = (HIWORD(pMsg->wParam) & MF_POPUP) != 0;
// notify main frame
if (HIWORD(pMsg->wParam) != 0xFFFF)
GetParentFrame()->SendMessage(WM_MENUSELECT, pMsg->wParam, pMsg->lParam);
return TRUE;
}
break;
}
return FALSE;
}
BOOL CMenuBar::InSubMenu()
{
for (int i=0; i<m_nItemCount; i++)
{
// check if current menu is one of top level menus
if (m_hSelMenu == m_pMenu->GetSubMenu(i)->m_hMenu)
return FALSE;
}
// otherwise it's a submenu
return TRUE;
}
void CMenuBar::Highlight(int nItem)
{
SetHotItem(nItem); // hihglight item
if (nItem < 0)
{
// restore focus
if (m_pPrevFocus && IsWindow(m_pPrevFocus->m_hWnd))
m_pPrevFocus->SetFocus();
m_pPrevFocus = NULL;
}
else
{
// steal focus
m_pPrevFocus = SetFocus();
}
}
void CMenuBar::UpdateSettings()
{
m_bCues = TRUE;
m_bFlatMenu = FALSE;
SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &m_bCues, 0);
SystemParametersInfo(SPI_GETFLATMENU, 0, &m_bFlatMenu, 0);
//指定为平面模式
m_bFlatMenu = TRUE;
SetPrefix(m_bCues);
// create menu font
NONCLIENTMETRICS ncmet;
ncmet.cbSize = sizeof(ncmet);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncmet), &ncmet, 0);
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&ncmet.lfMenuFont);
SetFont(&m_Font); // use it to draw toolbar buttons too
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -