📄 menubar.cpp
字号:
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
DrawBorders(&dc, rectWindow);
// erase parts not drawn
dc.IntersectClipRect(rectWindow);
SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
// draw gripper in non-client area
_DrawGripper(&dc, rectWindow);
}
#define CX_BORDER 1
#define CY_BORDER 1
void CMenuBar::DrawRaisedBorders(CDC* pDC, CRect& rect)
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
DWORD dwStyle = m_dwStyle;
if (!(dwStyle & CBRS_BORDER_ANY))
return;
// prepare for dark lines
ASSERT(rect.top == 0 && rect.left == 0);
CRect rect1, rect2;
rect1 = rect;
rect2 = rect;
COLORREF clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);//afxData.bWin4 ? afxData.clrBtnShadow : afxData.clrWindowFrame;
COLORREF clrBtnFace = ::GetSysColor(COLOR_BTNFACE);
COLORREF clrBtnHilight = ::GetSysColor(COLOR_BTNHILIGHT);
// draw dark line one pixel back/up
if (dwStyle & CBRS_BORDER_3D)
{
rect1.right -= CX_BORDER;
rect1.bottom -= CY_BORDER;
}
if (dwStyle & CBRS_BORDER_TOP)
rect2.top += cyBorder2;
if (dwStyle & CBRS_BORDER_BOTTOM)
rect2.bottom -= cyBorder2;
// draw left and top
if (dwStyle & CBRS_BORDER_LEFT)
pDC->FillSolidRect(0, rect2.top, CX_BORDER, rect2.Height(), clrBtnFace);
if (dwStyle & CBRS_BORDER_TOP)
pDC->FillSolidRect(0, 0, rect.right, CY_BORDER, clrBtnFace);
// draw right and bottom
if (dwStyle & CBRS_BORDER_RIGHT)
pDC->FillSolidRect(rect1.right, rect2.top, -CX_BORDER, rect2.Height(), clrBtnShadow);
if (dwStyle & CBRS_BORDER_BOTTOM)
pDC->FillSolidRect(0, rect1.bottom, rect.right, -CY_BORDER, clrBtnShadow);
if (dwStyle & CBRS_BORDER_3D)
{
// draw left and top
if (dwStyle & CBRS_BORDER_LEFT)
pDC->FillSolidRect(1, rect2.top, CX_BORDER, rect2.Height(), clrBtnHilight);
if (dwStyle & CBRS_BORDER_TOP)
pDC->FillSolidRect(0, 1, rect.right, CY_BORDER, clrBtnHilight);
// draw right and bottom
if (dwStyle & CBRS_BORDER_RIGHT)
pDC->FillSolidRect(rect.right, rect2.top, -CX_BORDER, rect2.Height(), clrBtnFace);
if (dwStyle & CBRS_BORDER_BOTTOM)
pDC->FillSolidRect(0, rect.bottom, rect.right, -CY_BORDER, clrBtnFace);
}
if (dwStyle & CBRS_BORDER_LEFT)
rect.left += cxBorder2;
if (dwStyle & CBRS_BORDER_TOP)
rect.top += cyBorder2;
if (dwStyle & CBRS_BORDER_RIGHT)
rect.right -= cxBorder2;
if (dwStyle & CBRS_BORDER_BOTTOM)
rect.bottom -= cyBorder2;
}
int CMenuBar::GetNextOrPrevButton(int nIndex, BOOL bPrev)
{
int nCount = GetItemCount();
if (bPrev) { // <-
--nIndex;
if (nIndex < 0)
nIndex = nCount - 1;
}
else { // ->
++nIndex;
if (nIndex >= nCount)
nIndex = 0;
}
if (!(m_arrItem[nIndex]->GetStyle() & MISTYLE_TRACKABLE) ||
(m_arrItem[nIndex]->GetState() & MISTATE_HIDDEN)) {
return GetNextOrPrevButton(nIndex, bPrev);
}
return nIndex;
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar insists own bar line
void CMenuBar::EnableDockingEx(DWORD dwDockStyle)
{
// pasted from CFrameWnd implementation
static const DWORD dwDockBarMap[4][2] =
{
{ AFX_IDW_DOCKBAR_TOP, CBRS_TOP },
{ AFX_IDW_DOCKBAR_BOTTOM, CBRS_BOTTOM },
{ AFX_IDW_DOCKBAR_LEFT, CBRS_LEFT },
{ AFX_IDW_DOCKBAR_RIGHT, CBRS_RIGHT },
};
EnableDocking(dwDockStyle);
// must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
CFrameWnd* pFrame = CControlBar::GetParentFrame(); ASSERT_VALID(pFrame);
//pFrame->m_pFloatingFrameClass = RUNTIME_CLASS(CMiniDockFrameWnd);
for (int i = 0; i < 4; i++)
{
if (dwDockBarMap[i][1] & dwDockStyle & CBRS_ALIGN_ANY)
{
CDockBar* pDock = (CDockBar*)pFrame->GetControlBar(dwDockBarMap[i][0]);
if (pDock == NULL)
{
pDock = new CMenuDockBar;// which wait for CMenuBar
if (!pDock->Create(pFrame,
WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE |
dwDockBarMap[i][1], dwDockBarMap[i][0]))
{
AfxThrowResourceException();
}
}
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CMenuBar OLE menu support
// MFC does'nt do command routing for other process server.
// ::TrackPopupMenuEx won't accept HWND of other process and
// we have to determine a message target(ole server window or not)
// as ::OleCreateMenuDescriptor do.
// This is a hard coding.
// First menu(ordinarily File menu) and WindowMenu regarded as container's own menu.
// Some components can't update toolbar button and statusbar pane.
HWND CMenuBar::OleMenuDescriptor(BOOL& bSend, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
CWnd* pOleWnd = GetCmdSentOleWnd();
if (pOleWnd == NULL)
return NULL;
HWND hWndSentCmd = NULL;
CMenuEx* pMenu = NULL;
HMENU hMenu = NULL;
if (nMsg == WM_INITMENUPOPUP || nMsg == WM_INITMENU)
hMenu = (HMENU)wParam;
else if (nMsg == WM_MENUSELECT)
hMenu = (HMENU)lParam;
switch (nMsg) {
case WM_INITMENUPOPUP:
if (!((BOOL)HIWORD(lParam)) &&
m_pMenu->IsMenu(CMenu::FromHandle((HMENU) wParam)))
CMenuEx::UpdateMenu(m_pMenu);
case WM_INITMENU:
case WM_MENUSELECT:
bSend = TRUE;
if (m_nTrackingState == popup) {
LTRACE2(_T(" now popup\n"));
if (m_bMDIApp) {
LTRACE2(_T(" this is MDI\n"));
if (m_nCurIndex == 0 || m_nCurIndex == 1 || hMenu == m_pWindowMenu->m_hMenu) {
LTRACE2(_T(" it's container menu, send to frame\n"));
return NULL;
}
}
else {
LTRACE2(_T(" it's container menu, send to frame\n"));
if (m_nCurIndex == 0) {
return NULL;
}
}
LTRACE2(_T(" it's server menu, send to server\n"));
return pOleWnd->GetSafeHwnd();
}
break;
case WM_COMMAND:
bSend = FALSE;
if (m_bMDIApp) {
LTRACE2(_T(" this is MDI\n"));
if (_nPrevIndexForCmd == 0 || _nPrevIndexForCmd == 1 || _bWindowMenuSendCmd) {
LTRACE2(_T(" it's container menu, send to frame\n"));
return NULL;
}
}
else {
if (_nPrevIndexForCmd == 0) {
LTRACE2(_T(" it's container menu, send to frame\n"));
return NULL;
}
}
LTRACE2(_T(" it's server menu, send to server\n"));
return pOleWnd->GetSafeHwnd();
}
return NULL;// send to frame
}
CWnd* CMenuBar::GetCmdSentOleWnd()
{
// *****fixed by VORGA, thanks!*****
CWnd* pWnd = AfxGetMainWnd();
if (pWnd == NULL || !pWnd->IsFrameWnd())
return NULL;
CFrameWnd* pFrame = NULL;
if (m_bMDIApp) {
CMDIFrameWnd *pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pWnd);
if (pMDIFrame == NULL)
return NULL;
pFrame = pMDIFrame->GetActiveFrame();
}
else {
pFrame = STATIC_DOWNCAST(CFrameWnd, pWnd);
}
if (pFrame == NULL)
return NULL;
CDocument* pDoc = pFrame->GetActiveDocument();
if (pDoc != NULL && pDoc->IsKindOf(RUNTIME_CLASS(COleDocument))) {
COleDocument* pOleDoc = STATIC_DOWNCAST(COleDocument, pDoc);
ASSERT_VALID(pOleDoc);
COleClientItem* pClientItem = pOleDoc->GetInPlaceActiveItem(pFrame);
CWnd* pWnd = (pClientItem == NULL) ? NULL : pClientItem->GetInPlaceWindow();
if (pWnd != NULL) {
// TCHAR str[256];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -