📄 menubar.cpp
字号:
DrawPressed(pDC);
}
else {
DrawNone(pDC);
}
}
void CMenuButton::TrackPopup(CWnd* pBar, CWnd* pWndSentCmd)
{
LTRACE(_T("CMenuButton::TrackPopup\n"));
ASSERT_VALID(pBar);
ASSERT(!(m_fsState & MISTATE_HIDDEN));
CMenuBar* pMenuBar = STATIC_DOWNCAST(CMenuBar, pBar);
ASSERT_VALID(pMenuBar);
// "! menu" (no sub menu)
if (!m_hSubMenu) {
ASSERT(m_nID != -1);
pWndSentCmd->SendMessage(WM_COMMAND, (WPARAM)m_nID, (LPARAM)pBar->GetSafeHwnd());
return;
}
CRect rcItem(m_rcItem); pMenuBar->ClientToScreen(rcItem);
UINT fuFlags; TPMPARAMS tpm;
CPoint pt = _ComputeMenuTrackPoint(rcItem, pMenuBar->GetBarStyle(), fuFlags, tpm);
if (m_hSubMenu == pMenuBar->m_hWindowMenu)
_bWindowMenuSendCmd = TRUE;
else
_bWindowMenuSendCmd = FALSE;
::TrackPopupMenuEx(m_hSubMenu, fuFlags,
pt.x, pt.y, pWndSentCmd->GetSafeHwnd(), &tpm);
}
void CMenuButton::DrawHorzText(CDC* pDC, CPoint ptOffset)
{
COLORREF clr = (m_fsState & MISTATE_INACTIVE) ?
::GetSysColor(COLOR_GRAYTEXT) : ::GetSysColor(COLOR_MENUTEXT);
pDC->SetTextColor(clr);
CRect rcBtn = m_rcItem;
pDC->SetBkMode(TRANSPARENT);
CFont* pOldFont = pDC->SelectObject(&_fontHorzMenu);
// I know precise text size, but better to leave this job to Windows
// *****fixed by andi, thanks!*****
pDC->DrawText(m_strBtn, rcBtn + ptOffset,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
pDC->SelectObject(pOldFont);
}
void CMenuButton::DrawVertText(CDC* pDC, CPoint ptOffset)
{
COLORREF clr = (m_fsState & MISTATE_INACTIVE) ?
::GetSysColor(COLOR_GRAYTEXT) : ::GetSysColor(COLOR_MENUTEXT);
pDC->SetTextColor(clr);
CRect rcBtn = m_rcItem;
int nLength = m_strBtn.GetLength();
int nIndex = m_strBtn.Find('&');
CString strBtn = m_strBtn.Left(nIndex) + m_strBtn.Right(nLength - (nIndex+1));
// fixed for WinNT. *****fixed by Simon, thanks!*****
int iGraphicsMode = ::GetGraphicsMode(pDC->m_hDC);
::SetGraphicsMode(pDC->m_hDC, GM_ADVANCED);
pDC->SetBkMode(TRANSPARENT);
CFont* pOldFont = pDC->SelectObject(&_fontVertMenu);
// I know precise text size
CRect rcString = CRect(
CPoint(rcBtn.right - _cyTextMargin, rcBtn.top + CXTEXTMARGIN), m_sizeHorz);
pDC->DrawText(strBtn, rcString + ptOffset,
DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX);// don't forget DT_NOCLIP
pDC->SelectObject(pOldFont);
// CDC::DrawText is poor, so we have to draw vertical line by ourselves
CPen pen(PS_SOLID, 0, clr);
CPen* pOldPen = pDC->SelectObject(&pen);
pDC->MoveTo(rcBtn.TopLeft() + m_ptLineFrom + ptOffset);
pDC->LineTo(rcBtn.TopLeft() + m_ptLineTo + ptOffset);
pDC->SelectObject(pOldPen);
::SetGraphicsMode( pDC->m_hDC, iGraphicsMode );
}
void CMenuButton::DrawHot(CDC* pDC)
{
if (m_fsState & MISTATE_HORZ) {
// draw pressed button
pDC->DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
DrawHorzText(pDC);
}
else {
pDC->DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
DrawVertText(pDC);
}
}
void CMenuButton::DrawPressed(CDC* pDC)
{
if (m_fsState & MISTATE_HORZ) {
pDC->DrawEdge(m_rcItem, BDR_SUNKENOUTER, BF_RECT);// draw pressed button
DrawHorzText(pDC, CPoint(1, 1));
}
else {
pDC->DrawEdge(m_rcItem, BDR_SUNKENOUTER, BF_RECT);
DrawVertText(pDC, CPoint(1, 1));
}
}
void CMenuButton::DrawNone(CDC* pDC)
{
if (m_fsState & MISTATE_HORZ) {
DrawHorzText(pDC);
}
else {
DrawVertText(pDC);
}
}
//////////////////////////////////////////////////////////////////////
// CMenuIcon class
CMenuIcon::CMenuIcon(CWnd* pMenuBar)
{
ASSERT_VALID(pMenuBar);
m_pMenuBar = pMenuBar;
m_hIconWinLogo = AfxGetApp()->LoadStandardIcon(IDI_WINLOGO);
ASSERT(m_hIconWinLogo);
m_fsStyle |= MISTYLE_TRACKABLE;
m_fsState |= MISTATE_HIDDEN;
m_sizeHorz = CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
}
CMenuIcon::~CMenuIcon()
{
if (m_hIconWinLogo != NULL)
::FreeResource(m_hIconWinLogo);
}
void CMenuIcon::OnActivateChildWnd()
{
//LTRACE(_T("CMenuIcon::OnActivateChildWnd\n"));
ASSERT_VALID(m_pMenuBar);
CWnd* pFrame = m_pMenuBar->GetTopLevelFrame();
ASSERT_VALID(pFrame);
CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame);
HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient;
ASSERT(::IsWindow(hWndMDIClient));
BOOL bMaximized = FALSE;
HWND hWndChild = (HWND)::SendMessage(hWndMDIClient,
WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
if (bMaximized == FALSE) {
//LTRACE(_T(" not maximized\n"));
m_fsState |= MISTATE_HIDDEN;
}
else {
//LTRACE(_T(" maximized\n"));
m_fsState &= ~MISTATE_HIDDEN;
}
m_hDocIcon = (HICON)::GetClassLong(hWndChild, GCL_HICONSM);
if (m_hDocIcon == NULL) // if hWndChild doesn't have own icon
m_hDocIcon = m_hIconWinLogo;
}
void CMenuIcon::Update(CDC* pDC)
{
if (m_fsState & MISTATE_HIDDEN)
return;
ASSERT(m_hDocIcon);
ASSERT(m_rcItem.IsRectEmpty() == FALSE);
::DrawIconEx(pDC->m_hDC, m_rcItem.left, m_rcItem.top, m_hDocIcon,
m_rcItem.Width(), m_rcItem.Height(), 0, NULL, DI_NORMAL);
}
void CMenuIcon::TrackPopup(CWnd* /*pBar*/, CWnd* pWndSentCmd)
{
ASSERT(!(m_fsState & MISTATE_HIDDEN));
ASSERT_VALID(m_pMenuBar);
CWnd* pFrame = m_pMenuBar->GetTopLevelFrame();
ASSERT_VALID(pFrame);
CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame);
HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient;
ASSERT(::IsWindow(hWndMDIClient));
BOOL bMaximized = FALSE;
HWND hWndChild = (HWND)::SendMessage(hWndMDIClient,
WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
ASSERT(bMaximized);
HMENU hSysMenu = ::GetSystemMenu(hWndChild, FALSE);
ASSERT(::IsMenu(hSysMenu));
CControlBar* pControlBar = STATIC_DOWNCAST(CControlBar, m_pMenuBar);
ASSERT_VALID(pControlBar);
CRect rcItem(m_rcItem); m_pMenuBar->ClientToScreen(rcItem);
UINT fuFlags; TPMPARAMS tpm;
CPoint pt = _ComputeMenuTrackPoint(rcItem, pControlBar->GetBarStyle(), fuFlags, tpm);
::TrackPopupMenuEx(hSysMenu, fuFlags, pt.x, pt.y, pWndSentCmd->GetSafeHwnd(), &tpm);
}
void CMenuIcon::Layout(CPoint point, BOOL bHorz)
{
if (bHorz)
m_fsState |= MISTATE_HORZ;
else
m_fsState &= ~MISTATE_HORZ;
if (m_fsState & MISTATE_HIDDEN) {
m_rcItem.SetRectEmpty();
return;
}
m_rcItem = CRect(point, CSize(::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON)));
}
//////////////////////////////////////////////////////////////////////
// CMenuControl class
#define CX_GAP_CAPTION 2
CMenuControl::CMenuControl(CWnd* pMenuBar)
{
ASSERT_VALID(pMenuBar);
m_pMenuBar = pMenuBar;
m_bDown = FALSE;
m_nTracking = -1;
m_fsState |= MISTATE_HIDDEN;
CSize sizeCaption = GetCaptionSize();
m_sizeHorz = CSize(sizeCaption.cx*3 + CX_GAP_CAPTION + 1, sizeCaption.cy + 2);
}
void CMenuControl::Update(CDC* pDC)
{
// do nothing
}
void CMenuControl::Layout(CPoint point, BOOL bHorz)
{
//LTRACE(_T("CMenuControl::Layout bHorz:%d\n"), bHorz);
if (bHorz)
m_fsState |= MISTATE_HORZ;
else
m_fsState &= ~MISTATE_HORZ;
if (m_fsState & MISTATE_HIDDEN) {
m_rcItem.SetRectEmpty();
return;
}
// 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)
{
//LTRACE(_T("CMenuControl::DelayLayoutAndDraw\n"));
//LTRACE(_T(" %d, %d\n"), sizeBar.cx, sizeBar.cy);
// layout
CSize sizeCaption = GetCaptionSize();
int cxCaption = sizeCaption.cx;
int cyCaption = sizeCaption.cy;
if (m_fsState & MISTATE_HORZ) {
CRect rcCaption;
rcCaption.right = sizeBar.cx;
rcCaption.bottom = sizeBar.cy;
rcCaption.left = rcCaption.right - cxCaption;
rcCaption.top = rcCaption.bottom - cyCaption;
m_arrCaption[0] = rcCaption;
rcCaption -= CPoint(cxCaption+CX_GAP_CAPTION, 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 {
CRect rcCaption;
rcCaption.left = 0;
rcCaption.bottom = sizeBar.cy;
rcCaption.right = rcCaption.left + cxCaption;
rcCaption.top = rcCaption.bottom - cyCaption;
m_arrCaption[0] = rcCaption;
rcCaption -= CPoint(0, cyCaption+CX_GAP_CAPTION);
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 (m_fsState & MISTATE_HIDDEN) {
//LTRACE(_T(" hidden\n"));
return;
}
// draw frame controls
for (int i = 0; i < 3; ++i) {
DrawControl(pDC, i, FALSE);
}
}
BOOL CMenuControl::OnMouseMsg(UINT msg, UINT nFlags, CPoint pt)
{
if (m_fsState & MISTATE_HIDDEN)
return FALSE;
if (msg == WM_LBUTTONDOWN) {
//LTRACE(_T(" WM_LBUTTONDOWN\n"));
m_nTracking = HitTest(pt);
if (m_nTracking >= 0) {
CClientDC dc(m_pMenuBar);
DrawControl(&dc, m_nTracking, TRUE);
m_bDown = TRUE;
m_pMenuBar->SetCapture(); // grab mouse input
return TRUE;
}
}
else if ((msg == WM_MOUSEMOVE) && m_nTracking >= 0) {
// mouse moved, and I am tracking: possibly draw button up/down
BOOL bOldDown = m_bDown;
m_bDown = m_arrCaption[m_nTracking].PtInRect(pt);
if (bOldDown != m_bDown) {
// up/down state changed: need to redraw button
CClientDC dc(m_pMenuBar);
DrawControl(&dc, m_nTracking, m_bDown);
}
return TRUE; // handled
}
else if (msg == WM_LBUTTONUP && m_nTracking >= 0) {
// user released the mouse and I am tracking: do button command
ReleaseCapture(); // let go the mouse
if (m_bDown) {
// if button was down when released: draw button up, and do system cmd
CClientDC dc(m_pMenuBar);
DrawControl(&dc, m_nTracking, FALSE);
CFrameWnd* pFrame = m_pMenuBar->GetTopLevelFrame()->GetActiveFrame();
ASSERT_VALID(pFrame);
static int syscmd[3] =
{ /*SC_MOUSEMENU,*/ SC_CLOSE, SC_RESTORE, SC_MINIMIZE };
// SendMessage occur access violation!
// *****fixed by Koay Kah Hoe. Thanks!*****
pFrame->PostMessage(WM_SYSCOMMAND, syscmd[m_nTracking]);
}
m_nTracking = -1; // stop tracking
return TRUE; // handled (eat)
}
return FALSE;
}
int CMenuControl::HitTest(CPoint point)
{
for (int i = 0; i < 3; ++i) {
if (m_arrCaption[i].PtInRect(point))
return i;
}
return -1;
}
void CMenuControl::DrawControl(CDC* pDC, int nIndex, BOOL bPressed)
{
//LTRACE(_T("CMenuControl::DrawControl\n"));
// draw frame controls
CRect& rc = m_arrCaption[nIndex];
//LTRACE(_T(" %d, %d, %d, %d\n"), rc.left, rc.top, rc.right, rc.bottom);
static UINT dfcs[3] = { DFCS_CAPTIONCLOSE, DFCS_CAPTIONRESTORE, DFCS_CAPTIONMIN };
UINT uState = dfcs[nIndex];
if (bPressed)
uState |= DFCS_PUSHED;
pDC->DrawFrameControl(rc, DFC_CAPTION, uState);
}
void CMenuControl::ForceDrawControl(CDC * pDC)
{
if (m_fsState & MISTATE_HIDDEN)
return;
for (int i = 0; i < 3; ++i) {
DrawControl(pDC, i, FALSE);
}
}
void CMenuControl::OnActivateChildWnd()
{
//LTRACE(_T("CMenuControl::OnActivateChildWnd\n"));
ASSERT_VALID(m_pMenuBar);
CWnd* pFrame = m_pMenuBar->GetTopLevelFrame();
ASSERT_VALID(pFrame);
CMDIFrameWnd* pMDIFrame = STATIC_DOWNCAST(CMDIFrameWnd, pFrame);
HWND hWndMDIClient = pMDIFrame->m_hWndMDIClient;
ASSERT(::IsWindow(hWndMDIClient));
BOOL bMaximized = FALSE;
HWND hWndChild = (HWND)::SendMessage(hWndMDIClient,
WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
if (bMaximized == FALSE) {
m_fsState |= MISTATE_HIDDEN;
}
else {
m_fsState &= ~MISTATE_HIDDEN;
}
}
CSize CMenuControl::GetCaptionSize()
{
NONCLIENTMETRICS info; info.cbSize = sizeof(info);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
// due to my own feeling
return CSize(info.iMenuHeight - info.iBorderWidth*2, info.iMenuHeight - info.iBorderWidth*4);
}
#if _MFC_VER < 0x0600
void CMenuBar::SetBorders(int cxLeft, int cyTop, int cxRight, int cyBottom)
{
ASSERT(cxLeft >= 0);
ASSERT(cyTop >= 0);
ASSERT(cxRight >= 0);
ASSERT(cyBottom >= 0);
m_cxLeftBorder = cxLeft;
m_cyTopBorder = cyTop;
m_cxRightBorder = cxRight;
m_cyBottomBorder = cyBottom;
}
#endif
void CMenuBar::_DrawGripper(CDC* pDC, const CRect& rect)
{
COLORREF clrBtnHilite = ::GetSysColor(COLOR_BTNHILIGHT);
COLORREF clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);
BOOL bDrawGripper = !(m_dwStyle & CBRS_FLOATING) && (m_dwExStyle & CBRS_GRIPPER);
// only draw the gripper if not floating and gripper is specified
if (bDrawGripper)
{
// draw the gripper in the border
if (m_dwStyle & CBRS_ORIENT_HORZ)
{
if (bDrawGripper) {
pDC->Draw3dRect(rect.left+CX_BORDER_GRIPPER,
rect.top+m_cyTopBorder,
CX_GRIPPER, rect.Height()-m_cyTopBorder-m_cyBottomBorder,
clrBtnHilite, clrBtnShadow);
}
}
else
{
if (bDrawGripper) {
pDC->Draw3dRect(rect.left+m_cyTopBorder,
rect.top+CY_BORDER_GRIPPER,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -