📄 menubar.cpp
字号:
int dx = pItem->m_sizeHorz.cx;
if (dx + CXGAP > nWidth) { // bigger than nWidth
if (pItem->CanWrap()) {
pItem->m_bWrapped = TRUE;
// if (i != nCount - 1)
++nResult;
}
}
else if (dx + x + CXGAP > nWidth) {
if (i > 0 && m_arrItem[i-1]->CanWrap()) {
// LTRACE("index %d is wrap\n", i-1);
m_arrItem[i-1]->m_bWrapped = TRUE;
pItem->m_bWrapped = FALSE;
x = xStart;
// if (i != nCount - 1)///////////////////////////
++nResult;
}
}
else {
pItem->m_bWrapped = FALSE;
}
x += dx;
}
}
*/
return nResult + 1;
}
// calc only size, by using m_bWrapped
CSize CMenuBar::CalcSize(int nCount)
{
ASSERT(nCount > 0);
CPoint cur(CXGAP, CYGAP);
CSize sizeResult(0, 0);
int nWrap = 0;
for (int i = 0; i < nCount; ++i) {
CMenuItem* pItem = m_arrItem[i];
if (pItem->IsValid()) {
sizeResult.cx = max(cur.x + pItem->m_sizeHorz.cx, sizeResult.cx);
sizeResult.cy = max(cur.y + pItem->m_sizeHorz.cy, sizeResult.cy);
cur.x += pItem->m_sizeHorz.cx;
if (pItem->m_bWrapped == TRUE) {
LTRACE(" nIndex:%d is wrapped\n", i);
cur.x = CXGAP; // reset x pos
cur.y += pItem->m_sizeHorz.cy;
++nWrap;
}
}
}
sizeResult.cy += CYGAP;
sizeResult.cx += CXGAP;
return sizeResult;
}
void CMenuBar::SizeMenuBar(int nCount, int nLength, BOOL bVert)
{
//LTRACE("CMenuBar::SizeMenuBar\n");
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 know 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");
}
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;
}
void CMenuBar::OnDestroy()
{
CControlBar::OnDestroy();
// TODO: 偙偺埵抲偵儊僢僙乕僕 僴儞僪儔梡偺僐乕僪傪捛壛偟偰偔偩偝偄
_KillTimer();
DeleteItems();
}
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]->CanTrack() || !m_arrItem[nIndex]->IsValid()) {
return GetNextOrPrevButton(nIndex, bPrev);
}
return nIndex;
}
void CMenuBar::AddIcon(HICON hIcon)
{
// ASSERT(m_bIcon == FALSE);
// m_bIcon = TRUE;
}
CMenuControl::CMenuControl(CControlBar* pBar)
{
m_bValid = FALSE;
m_pBar = pBar;
m_bDown = FALSE;
m_nTracking = -1;
int cxCaption = cyMenuButton - CYGAP + 1;
m_sizeHorz = CSize(cxCaption*3 + CXGAP/2, cyMenuButton);
}
CMenuControl::~CMenuControl()
{
}
void CMenuControl::Update(CDC* pDC)
{
// do nothing
}
void CMenuControl::Layout(CPoint point, BOOL bHorz)
{
LTRACE("CMenuControl::Layout bHorz:%d\n", bHorz);
m_bHorz = bHorz;
// just layout easily
if (bHorz) {
m_rcItem = CRect(point, m_sizeHorz);
}
else {
m_rcItem = CRect(point, CSize(m_sizeHorz.cy, m_sizeHorz.cx));
}
}
void CMenuControl::DelayLayoutAndDraw(CDC* pDC, CSize sizeBar)
{
// if (!IsValid())
// return;
// layout
if (m_bHorz) {
int cxCaption = cyMenuButton - CYGAP + 1;
int cyCaption = cxCaption - 1;
CRect rcCaption;
rcCaption.right = sizeBar.cx;
rcCaption.bottom = sizeBar.cy - CYGAP;
rcCaption.left = rcCaption.right - cxCaption;
rcCaption.top = rcCaption.bottom - cyCaption;
m_arrCaption[0] = rcCaption;
rcCaption -= CPoint(cxCaption+CXGAP/2, 0);
m_arrCaption[1] = rcCaption;
rcCaption -= CPoint(cxCaption, 0);
m_arrCaption[2] = rcCaption;
m_rcItem = CRect(m_arrCaption[2].left, m_arrCaption[2].top,
m_arrCaption[0].right, m_arrCaption[0].bottom);
}
else {
int cxCaption = cyMenuButton - CYGAPVERT - 1;
int cyCaption = cxCaption - 1;
CRect rcCaption;
rcCaption.left = CYGAPVERT;
rcCaption.bottom = sizeBar.cy;
rcCaption.right = rcCaption.left + cxCaption;
rcCaption.top = rcCaption.bottom - cyCaption;
m_arrCaption[0] = rcCaption;
rcCaption -= CPoint(0, cyCaption+CXGAP/2);
m_arrCaption[1] = rcCaption;
rcCaption -= CPoint(0, cyCaption);
m_arrCaption[2] = rcCaption;
m_rcItem = CRect(m_arrCaption[2].left, m_arrCaption[2].top,
m_arrCaption[0].right, m_arrCaption[0].bottom);
}
if (!IsValid())
return;
// draw frame controls
for (int i = 0; i < 3; ++i) {
DrawControl(pDC, i, FALSE);
}
// pDC->DrawFrameControl(m_arrCaption[0], DFC_CAPTION, DFCS_CAPTIONCLOSE);
// pDC->DrawFrameControl(m_arrCaption[1], DFC_CAPTION, DFCS_CAPTIONRESTORE);
// pDC->DrawFrameControl(m_arrCaption[2], DFC_CAPTION, DFCS_CAPTIONMIN);
}
// pasted from CDockContext
void CMenuBarDockContext::StartDrag(CPoint pt)
{
ASSERT_VALID(m_pBar);
m_bDragging = TRUE;
InitLoop();
if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC)
{
// get TRUE bar size (including borders)
CRect rect;
m_pBar->GetWindowRect(rect);
m_ptLast = pt;
CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK);
CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK);
CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
// calculate frame dragging rectangle
m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat);
#ifdef _MAC
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz,
WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert,
WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX);
#else
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
#endif
m_rectFrameDragHorz.InflateRect(-cxBorder2, -cyBorder2);
m_rectFrameDragVert.InflateRect(-cxBorder2, -cyBorder2);
}
else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED)
{
// get TRUE bar size (including borders)
CRect rect;
m_pBar->GetWindowRect(rect);
m_ptLast = pt;
CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK);
CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK);
// calculate frame dragging rectangle
m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
m_rectFrameDragHorz.InflateRect(-cxBorder2, -cyBorder2);
m_rectFrameDragVert.InflateRect(-cxBorder2, -cyBorder2);
}
else
{
// get TRUE bar size (including borders)
CRect rect;
m_pBar->GetWindowRect(rect);
m_ptLast = pt;
BOOL bHorz = HORZF(m_dwStyle);
DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK;
CSize size = m_pBar->CalcDynamicLayout(-1, dwMode);
// calculate inverted dragging rect
if (bHorz)
{
m_rectDragHorz = rect;
m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size);
}
else // vertical orientation
{
m_rectDragVert = rect;
m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size);
}
// calculate frame dragging rectangle
m_rectFrameDragHorz = m_rectDragHorz;
m_rectFrameDragVert = m_rectDragVert;
CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz);
CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert);
m_rectFrameDragHorz.InflateRect(-cxBorder2, -cyBorder2);
m_rectFrameDragVert.InflateRect(-cxBorder2, -cyBorder2);
}
// adjust rectangles so that point is inside
AdjustRectangle(m_rectDragHorz, pt);
AdjustRectangle(m_rectDragVert, pt);
AdjustRectangle(m_rectFrameDragHorz, pt);
AdjustRectangle(m_rectFrameDragVert, pt);
// initialize tracking state and enter tracking loop
m_dwOverDockStyle = CanDock();
Move(pt); // call it here to handle special keys
_Track();
}
BOOL CMenuBarDockContext::_Track()
{
// don't handle if capture already set
if (::GetCapture() != NULL)
return FALSE;
// set capture to the window which received this message
m_pBar->SetCapture();
ASSERT(m_pBar == CWnd::GetCapture());
#ifndef _MAC
// get messages until capture lost or cancelled/accepted
while (CWnd::GetCapture() == m_pBar)
{
MSG msg;
if (!::GetMessage(&msg, NULL, 0, 0))
{
AfxPostQuitMessage(msg.wParam);
break;
}
switch (msg.message)
{
case WM_LBUTTONUP:
if (m_bDragging)
_EndDrag();
else
EndResize();
return TRUE;
case WM_MOUSEMOVE:
if (m_bDragging)
Move(msg.pt);
else
Stretch(msg.pt);
break;
case WM_KEYUP:
if (m_bDragging)
OnKey((int)msg.wParam, FALSE);
break;
case WM_KEYDOWN:
if (m_bDragging)
OnKey((int)msg.wParam, TRUE);
if (msg.wParam == VK_ESCAPE)
{
CancelLoop();
return FALSE;
}
break;
case WM_RBUTTONDOWN:
CancelLoop();
return FALSE;
// just dispatch rest of the messages
default:
DispatchMessage(&msg);
break;
}
}
#else
Point ptCur = {0};
// get messages until capture lost or cancelled/accepted
while (CWnd::GetCapture() == m_pBar)
{
EventRecord er;
if (OSEventAvail(everyEvent, &er))
{
GetNextEvent(everyEvent, &er);
switch (er.what)
{
case mouseUp:
if (m_bDragging)
EndDrag();
else
EndResize();
return TRUE;
case keyDown:
case keyUp:
case autoKey:
case app2Evt:
{
MSG msg;
if (WrapEvent(&er, &msg, PM_REMOVE))
{
if (m_bDragging)
OnKey((int)msg.wParam, msg.message == WM_KEYDOWN);
if (msg.message == WM_KEYUP && msg.wParam == VK_ESCAPE)
{
CancelLoop();
return FALSE;
}
}
break;
}
default:
break;
}
}
else
{
if (!EqualPt(er.where, ptCur))
{
POINT pt = {er.where.h, er.where.v};
if (m_bDragging)
Move(pt);
else
Stretch(pt);
}
}
}
#endif
CancelLoop();
return FALSE;
}
void CMenuBarDockContext::_EndDrag()
{
CancelLoop();
if (m_dwOverDockStyle != 0)
{
CDockBar* pDockBar = GetDockBar(m_dwOverDockStyle);
ASSERT(pDockBar != NULL);
CRect rect = (m_dwOverDockStyle & CBRS_ORIENT_VERT) ?
m_rectDragVert : m_rectDragHorz;
UINT uID = _AfxGetDlgCtrlID(pDockBar->m_hWnd);
if (uID >= AFX_IDW_DOCKBAR_TOP &&
uID <= AFX_IDW_DOCKBAR_BOTTOM)
{
m_uMRUDockID = uID;
m_rectMRUDockPos = rect;
pDockBar->ScreenToClient(&m_rectMRUDockPos);
}
// dock it at the specified position, RecalcLayout will snap
// insisting own line trick!
CRect rcDockBar;
pDockBar->GetWindowRect(rcDockBar);
if (m_dwOverDockStyle & CBRS_ORIENT_VERT) {
rect.top = rcDockBar.top - 1;
}
else {
rect.left = rcDockBar.left - 10;
}
m_pDockSite->DockControlBar(m_pBar, pDockBar, &rect);
m_pDockSite->RecalcLayout();
}
else if ((m_dwStyle & CBRS_SIZE_DYNAMIC) || (HORZF(m_dwStyle) && !m_bFlip) ||
(VERTF(m_dwStyle) && m_bFlip))
{
m_dwMRUFloatStyle = CBRS_ALIGN_TOP | (m_dwDockStyle & CBRS_FLOAT_MULTI);
m_ptMRUFloatPos = m_rectFrameDragHorz.TopLeft();
m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
}
else // vertical float
{
m_dwMRUFloatStyle = CBRS_ALIGN_LEFT | (m_dwDockStyle & CBRS_FLOAT_MULTI);
m_ptMRUFloatPos = m_rectFrameDragVert.TopLeft();
m_pDockSite->FloatControlBar(m_pBar, m_ptMRUFloatPos, m_dwMRUFloatStyle);
}
}
void CMenuBar::OnPaintMDIClient()
{
LTRACE("CMenuBar::OnPaintMDIClient\n");
if (m_hWndMDIClient) {
BOOL bMax = FALSE;
// get active MDI child window
HWND hWndChild = (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0,
(LPARAM)&bMax);
//ASSERT(::IsWindow(hWndChild)); crash! tell me why!
if (bMax != m_bMDIMaximized) {
LTRACE(" max state changed\n");
m_bMDIMaximized = bMax;
if (bMax) {
LTRACE(" maximized\n");
m_pMenuControl->Validate(TRUE);
m_pMenuIcon->Validate(TRUE);
}
else {
LTRACE(" not maximized\n");
m_pMenuControl->Validate(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -