📄 menubar.cpp
字号:
BOOL CMenuBar::MapAccessKey(TCHAR cAccessKey, int& nIndex)
{
for (int i = 0; i < GetItemCount(); ++i) {
// fixing point
TCHAR cKey = m_arrItem[i]->GetAccessKey();
if (toupper(cKey)/*_totupper(cKey)*/ == cAccessKey) {// *****fixed by andi, thanx!*****
nIndex = i;
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar layout
int CMenuBar::GetClipBoxLength(BOOL bHorz)
{
CFrameWnd* pFrame = GetTopLevelFrame(); ASSERT_VALID(pFrame);
CRect rcFrame; pFrame->GetWindowRect(rcFrame);
CWnd* pParent = GetParent(); ASSERT_VALID(pParent);
CRect rcParent; pParent->GetWindowRect(rcParent);
const int cxFrameBorder = ::GetSystemMetrics(SM_CXFRAME);
int cxNonClient = cxFrameBorder*2 + m_cxLeftBorder + m_cxRightBorder;
if (m_dwExStyle & CBRS_GRIPPER)
cxNonClient += CX_GRIPPER_ALL;
if (m_dwStyle & CBRS_SIZE_DYNAMIC) {
if (bHorz) {
return rcFrame.Width() - cxNonClient;
}
else {
int nResult = rcParent.Height();
// I don't know the reason of the following code...
nResult -= m_cxRightBorder + m_cxLeftBorder + cyBorder2*2;
if (m_dwExStyle & CBRS_GRIPPER)
nResult -= CY_GRIPPER_ALL;
return nResult;
}
}
else {
CRect rect; GetClientRect(rect);
if (bHorz) {
return rect.Width();
}
else {
return rect.Height();
}
}
}
CSize CMenuBar::CalcLayout(DWORD dwMode, int nLength)
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
if (dwMode & LM_HORZDOCK)
ASSERT(dwMode & LM_HORZ);
// make SC_CLOSE button disable
if (m_dwStyle & CBRS_FLOATING) {
CFrameWnd* pMiniFrame = GetParentFrame(); ASSERT_KINDOF(CMiniFrameWnd, pMiniFrame);
// Don't do this, cause right click menu turns unavairable
// pMiniFrame->ModifyStyle(WS_SYSMENU, 0);
CMenu* pSysMenu = pMiniFrame->GetSystemMenu(FALSE); ASSERT_VALID(pSysMenu);
pSysMenu->EnableMenuItem(SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
}
int nCount = GetItemCount();
CSize sizeResult(0, 0);
if (nCount > 0)
{
if (!(m_dwStyle & CBRS_SIZE_FIXED))
{
BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
if (bDynamic && (dwMode & LM_MRUWIDTH))
{
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---LM_MRUWIDTH\n"));
SizeMenuBar(m_nMRUWidth);
CalcItemLayout(nCount);// added
sizeResult = CalcSize(nCount);
}
else if (bDynamic && (dwMode & LM_HORZDOCK))
{
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---LM_HORZDOCK\n"));
if (IsFloating() || (m_dwStyle & CBRS_ORIENT_VERT)) {
// I can't synchronize horz size on dragging with size on dock bar
// as VC++ developer can't.
SizeMenuBar(32767);
}
else {
// Menu Button wrapped by frame width
SizeMenuBar(GetClipBoxLength(TRUE));
}
CalcItemLayout(nCount);// added
sizeResult = CalcSize(nCount);
if (!IsFloating() && !(m_dwStyle & CBRS_ORIENT_VERT)) {
if (m_pDockContext->m_pDC) {// while dragging (m_pDockContext->m_bDragging is helpless)
sizeResult.cx = GetClipBoxLength(TRUE);
}
}
}
else if (bDynamic && (dwMode & LM_VERTDOCK))
{
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---LM_VERTDOCK\n"));
//SizeMenuBar(0);
CalcItemLayout(nCount, TRUE);// added
sizeResult = CalcVertDockSize(nCount);
if (!IsFloating() && !(m_dwStyle & CBRS_ORIENT_HORZ)) {
if (m_pDockContext->m_pDC) {// while dragging
sizeResult.cy = GetClipBoxLength(FALSE);//GetrcParent.Height() - m_cxRightBorder - m_cxLeftBorder;
}
}
}
else if (bDynamic && (nLength != -1))
{
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---nLength != -1\n"));
CRect rect; rect.SetRectEmpty();
_CalcInsideRect(rect, (dwMode & LM_HORZ));
BOOL bVert = (dwMode & LM_LENGTHY);
int nLen = nLength + (bVert ? rect.Height() : rect.Width());
SizeMenuBar(nLen, bVert);
CalcItemLayout(nCount, bVert);// added
sizeResult = CalcSize(nCount);
}
else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
{
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---CBRS_FLOATING\n"));
SizeMenuBar(m_nMRUWidth);
CalcItemLayout(nCount);// added
sizeResult = CalcSize(nCount);
}
else
{
if (!bDynamic) {
InvalidateRect(NULL);
goto Junk;
}
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_DYNAMIC)---other\n"));
BOOL bVert = !(dwMode & LM_HORZ);
SizeMenuBar(GetClipBoxLength(TRUE));
CalcItemLayout(nCount, bVert);// added
if (bVert) {
InvalidateRect(NULL);// draw forcefully for captions
sizeResult = CalcVertDockSize(nCount);
// DockBar not replaced yet, so I can't get precise size
sizeResult.cy = 10000;
}
else {
sizeResult = CalcSize(nCount);
sizeResult.cx = GetClipBoxLength(TRUE);
}
}
}
else {// CBRS_SIZE_FIXED
LTRACE(_T("CMenuBar::CalcLayout(CBRS_SIZE_FIXED)\n"));
Junk:
BOOL bVert = !(dwMode & LM_HORZ);
SizeMenuBar(32767);
CalcItemLayout(nCount, bVert);// added
if (bVert) {
sizeResult = CalcVertDockSize(nCount);
}
else {
sizeResult = CalcSize(nCount);
}
}
if (dwMode & LM_COMMIT)
{
LTRACE(_T("CMenuBar::CalcLayout---LM_COMMIT\n"));
int nControlCount = 0;
BOOL bIsDelayed = m_bDelayedButtonLayout;
m_bDelayedButtonLayout = FALSE;
if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
m_nMRUWidth = sizeResult.cx;
//CalcItemLayout(nCount, dwMode);
m_bDelayedButtonLayout = bIsDelayed;
}
}
//BLOCK: Adjust Margins
{
CRect rect; rect.SetRectEmpty();
_CalcInsideRect(rect, (dwMode & LM_HORZ));
sizeResult.cy -= rect.Height();
sizeResult.cx -= rect.Width();
CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
sizeResult.cx = max(sizeResult.cx, size.cx);
sizeResult.cy = max(sizeResult.cy, size.cy);
}
return sizeResult;
}
CSize CMenuBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
LTRACE(_T("CMenuBar::CalcFixedLayout\n"));
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
DWORD dwMode = bStretch ? LM_STRETCH : 0;
dwMode |= bHorz ? LM_HORZ : 0;
return CalcLayout(dwMode);
}
CSize CMenuBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
LTRACE(_T("CMenuBar::CalcDynamicLayout\n"));
if ((nLength == -1) && !(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
{
LTRACE(_T(" FixedLayout\n"));
return CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
}
return CalcLayout(dwMode, nLength);
}
// set m_bWrapped by nWidth
int CMenuBar::WrapMenuBar(int nCount, int nWidth)
{
// LTRACE(_T("CMenuBar::WrapMenuBar\n"));
int nResult = 0;
int x = 0;
for (int i = 0; i < nCount; ++i) {
CMenuItem* pItem = m_arrItem[i];
if (i+1 == nCount)
return ++nResult;
if (x + pItem->GetHorizontalSize().cx> nWidth) {// itself is over
if (pItem->GetStyle() & MISTYLE_WRAPPABLE) {
pItem->ModifyState(0, MISTATE_WRAP);
++nResult;
x = 0;
}
}
else if (x + pItem->GetHorizontalSize().cx +
m_arrItem[i+1]->GetHorizontalSize().cx> nWidth) {
if (pItem->GetStyle() & MISTYLE_WRAPPABLE) {
pItem->ModifyState(0, MISTATE_WRAP);
++nResult;
x = 0;
}
}
else {
pItem->ModifyState(MISTATE_WRAP, 0);
x += pItem->GetHorizontalSize().cx;
}
}
return nResult + 1;
}
// calc only size, by using m_bWrapped
CSize CMenuBar::CalcSize(int nCount)
{
ASSERT(nCount > 0);
CPoint cur(0,0);
CSize sizeResult(0,0);
int nWrap = 0;
for (int i = 0; i < nCount; ++i) {
CMenuItem* pItem = m_arrItem[i];
sizeResult.cx = max(cur.x + pItem->GetHorizontalSize().cx, sizeResult.cx);
sizeResult.cy = max(cur.y + pItem->GetHorizontalSize().cy, sizeResult.cy);
cur.x += pItem->GetHorizontalSize().cx;
if (pItem->GetState() & MISTATE_WRAP) {
//LTRACE(_T(" nIndex:%d is wrapped\n"), i);
cur.x = 0;// reset x pos
cur.y += pItem->GetHorizontalSize().cy;
++nWrap;
}
}
return sizeResult;
}
void CMenuBar::Layout()
{
ASSERT(m_bDelayedButtonLayout);
m_bDelayedButtonLayout = FALSE;
BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
((CMenuBar*)this)->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT);
else if (bHorz)
((CMenuBar*)this)->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK | LM_COMMIT);
else
((CMenuBar*)this)->CalcDynamicLayout(0, LM_VERTDOCK | LM_COMMIT);
}
void CMenuBar::SizeMenuBar(int nLength, BOOL bVert)
{
//LTRACE("CMenuBar::SizeMenuBar\n");
int nCount = GetItemCount(); ASSERT(nCount > 0);
if (!bVert) { // nLength is horizontal length
if (IsFloating()) { // half size wrapping
CSize sizeMax, sizeMin, sizeMid;
// Wrap MenuBar vertically
WrapMenuBar(nCount, 0);
sizeMin = CalcSize(nCount);
// Wrap MenuBar horizontally
WrapMenuBar(nCount, 32767);
sizeMax = CalcSize(nCount);
// we can never understand this algorithm :), see CToolBar implementation
while (sizeMin.cx < sizeMax.cx) {
// LTRACE("looping sizeMin.cx:%d < sizeMax.cx:%d\n", sizeMin.cx, sizeMax.cx);
sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
WrapMenuBar(nCount, sizeMid.cx);
sizeMid = CalcSize(nCount);
if (sizeMid.cx == sizeMax.cx) { // if you forget, it loops forever!
return;
}
// LTRACE(" sizeMid : %d %d\n", sizeMid.cx, sizeMid.cy);
if (nLength >= sizeMax.cx) {
// LTRACE(" nLength:%d >= sizeMax.cx:%d\n", nLength, sizeMax.cx);
if (sizeMin == sizeMid) {
WrapMenuBar(nCount, sizeMax.cx);
// LTRACE("out SizeMenuBar\n");
return;
}
sizeMin = sizeMid;
}
else if (nLength < sizeMax.cx) {
// LTRACE(" nLength:%d < sizeMax.cx:%d\n", nLength, sizeMax.cx);
sizeMax = sizeMid;
}
else {
// LTRACE("out SizeMenuBar\n");
return;
}
}
}
else { // each one wrapping
//LTRACE(" just each one wrapping\n");
WrapMenuBar(nCount, nLength);
}
}
else { // nLength is vertical length
CSize sizeMax, sizeMin, sizeMid;
// Wrap MenuBar vertically
WrapMenuBar(nCount, 0);
sizeMin = CalcSize(nCount);
// Wrap MenuBar horizontally
WrapMenuBar(nCount, 32767);
sizeMax = CalcSize(nCount);
while (sizeMin.cx < sizeMax.cx) {
sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
WrapMenuBar(nCount, sizeMid.cx);
sizeMid = CalcSize(nCount);
if (sizeMid.cx == sizeMax.cx) {
return;
}
if (nLength < sizeMid.cy) {
if (sizeMin == sizeMid) {
WrapMenuBar(nCount, sizeMax.cx);
//LTRACE("out SizeMenuBar\n");
return;
}
sizeMin = sizeMid;
}
else if (nLength > sizeMid.cy)
sizeMax = sizeMid;
else {
//LTRACE("out SizeMenuBar\n");
return;
}
}
}
//LTRACE("out SizeMenuBar\n");
}
CSize CMenuBar::CalcVertDockSize(int nCount)
{
ASSERT(nCount > 0);
CSize sizeResult(0, 0);
for (int i = 0; i < nCount; ++i) {
CMenuItem* pItem = m_arrItem[i];
sizeResult.cy += pItem->GetRect().Height();
}
sizeResult.cx = _cyMenuOnBar;
return sizeResult;
}
void CMenuBar::CalcItemLayout(int nCount, BOOL bVert)
{
ASSERT(nCount > 0);
int x = 0; int y = 0;
if (!bVert) {
for (int i = 0; i < nCount; ++i) {
CMenuItem* pItem = m_arrItem[i];
CPoint ptItem(x, y);
pItem->Layout(ptItem, TRUE);// layout by itself!
if (pItem->GetState() & MISTATE_WRAP) {
x = 0;// reset x to 0
y += pItem->GetRect().Height();
}
else
x += pItem->GetRect().Width();
}
}
else {
for (int i = 0; i < nCount; ++i) {
CMenuItem* pItem = m_arrItem[i];
CPoint ptItem(0, y);
pItem->Layout(ptItem, FALSE); // layout by itself
y += pItem->GetRect().Height();
}
}
}
//////////////////////////////////////////////////////////////////////
// Added by Koay Kah Hoe. Thanx!
void CMenuBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
// LTRACE(_T("CMenuBar::OnUpdateCmdUI\n"));
/*
// if mouse out of frame window, OnUpdateCmdUI never called...
if (m_nTrackingState == buttonmouse) {
CPoint pt; ::GetCursorPos(&pt);
CRect rect;
GetWindowRect(&rect);
if (!rect.PtInRect(pt))
UpdateBar();
}
*/
// but thanks to Koay Kah Hoe,
// I've found it's nice place for checking child window status.
if (m_bMDIApp)
CheckActiveChildWndMaximized();
}
//////////////////////////////////////////////////////////////////////
// CMenuBar decoration
void CMenuBar::EraseNonClientEx()
{
// get window DC that is clipped to the non-client area
CWindowDC dc(this);
CRect rectClient;
GetClientRect(rectClient);
CRect rectWindow;
GetWindowRect(rectWindow);
ScreenToClient(rectWindow);
rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);
dc.ExcludeClipRect(rectClient);
// draw borders in non-client area
rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);
if (m_dwExStyle & CBRS_RAISEDBORDER)
DrawRaisedBorders(&dc, rectWindow);
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -