📄 toolbarex.cpp
字号:
}
void CToolBarEx :: SetFlatLook( BOOL bFlat ) {
if( bFlat != m_bFlatLook ) {
m_bFlatLook = bFlat;
if( ::IsWindow(GetSafeHwnd()) ) {
//flat tool bars have gripper space at the left, cause non-client to resize
SetWindowPos(0, 0,0,0,0,SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);
// force a repaint of all buttons
Invalidate();
// erase/draw the gripper
OnNcPaint();
// if the "FrameEnableDocking()" function is used, we have to adjust
// the bars inside the parent.
VERIFY(::IsWindow(m_hwndParent));
((CFrameWnd*)(CWnd::FromHandle(m_hwndParent)))->RecalcLayout();
}
}
}
void CToolBarEx::OnPaint()
{
HIMAGELIST hImg = GetImageList();
#ifdef _DEBUG
if( hImg == 0 ) {
TRACE0("CToolBarEx::OnPaint(): could not get image list\n");
}
#endif
if( m_bFlatLook && hImg ) {
CRect rcUpdate;
if( ! GetUpdateRect(rcUpdate) )
return;
if( HasButtonText() )
CalculateOffset(); // strings may have been added
// attach image-list for even more MFC feeling :)
CImageList imglist;
imglist.Attach(hImg);
POINT cursor;
::GetCursorPos(&cursor);
ScreenToClient(&cursor);
#ifdef _MEMDC_H_
// if you have Keith Rule's CMemDC class inserted
// in "stdafx.h", then we use it here ...
CPaintDC dcp(this);
CMemDC dc(&dcp);
dc.FillSolidRect(rcUpdate, m_clrBtnFace);
#else // _MEMDC_H_
CPaintDC dc(this); // device context for painting
#endif // _MEMDC_H_
CFont * pOldFont = dc.SelectObject(&m_GuiFont);
// Now it's time for the first custom-draw-notification...
CCustomDrawInfo cdrw(dc, this);
cdrw.NotifyPrePaint();
register const int nBtn = GetToolBarCtrl().GetButtonCount();
for( register int i = 0; i < nBtn; ++i ) {
CRect rc;
GetItemRect(i, rc);
int nBitmap; UINT uID, uStyleState;
GetButtonInfo(i, uID, uStyleState, nBitmap);
WORD wStyle = LOWORD(uStyleState);
WORD wState = HIWORD(uStyleState);
if( wState & TBSTATE_HIDDEN )
continue;
if( wStyle == TBSTYLE_SEP ) {
if( !(wState & TBSTATE_WRAP) || ! IsFloating() )
DrawSeparator(dc, rc);
} else {
if( ! CRect().IntersectRect(rcUpdate, rc) )
continue; // this button needs no repaint
BOOL bBtnDown = (wState & TBSTATE_CHECKED) || (wState & TBSTATE_PRESSED);
BOOL bBtnEnabled = GetToolBarCtrl().IsButtonEnabled(int(uID));
BOOL bHasCursor = rc.PtInRect(cursor);
COLORREF clrRect = (bBtnDown && !bHasCursor) ? m_clrBtnLight : m_clrBtnFace;
// maybe the button has text
dc.SetTextColor(RGB(0,0,0));
dc.SetBkColor(clrRect);
if( HasButtonText() )
// There is a bug in CToolBar: If there are texts assigned
// to buttons, then the button-widths may change transparently
// (without notified by CToolBar), so we recalculate the
// horizontal offset here:
m_sizeOffset.cx = (rc.Width() - m_sizeImage.cx) / 2;
if( ! cdrw.NotifyItemPrePaint(i) )
continue; // parent has already drawn the button
dc.FillSolidRect(rc, clrRect);
// it seems, that CDC::Draw3dRect() changes the background color
COLORREF clrBk = dc.GetBkColor();
if( bBtnDown ) {
// draw a pressed button
dc.Draw3dRect(rc, m_clrBtnShadow, m_clrBtnHilight);
if( ! bHasCursor ) {
// if the button does not have the cursor on it,
// then the pressed button is somewhat lighter
// then the other buttons.
CRect rcCheck = rc;
rcCheck.DeflateRect(1,1);
// draw an invisible frame around the hilighted area
dc.Draw3dRect(rcCheck, m_clrBtnFace, m_clrBtnFace);
rcCheck.DeflateRect(1,1);
CBrush *pBrush = CDC::GetHalftoneBrush();
dc.SetTextColor(m_clrBtnHilight);
dc.SetBkColor(m_clrBtnFace);
dc.FillRect(rcCheck, pBrush);
dc.SetTextColor(RGB(0,0,0));
dc.SetBkColor(clrRect);
}
} else if( bHasCursor && ! bBtnDown && bBtnEnabled )
// draw a normal button
dc.Draw3dRect(rc, m_clrBtnHilight, m_clrBtnShadow);
else if( ! bBtnDown && bBtnEnabled )
// Draw an invisible rect around the button.
// This prevents us from erasing the background
// if the button was formed before
// (that would cause the button to flicker ...)
dc.Draw3dRect(rc, m_clrBtnFace, m_clrBtnFace);
dc.SetBkColor(clrBk);
// the point where to start with the image
CPoint pt(rc.left + m_sizeOffset.cx + bBtnDown,
rc.top + m_sizeOffset.cy + bBtnDown);
imglist.Draw(&dc, nBitmap, pt, ILD_TRANSPARENT);
CString strText = GetButtonText(i);
if( strText.GetLength() ) {
CRect rectText(
rc.left+3+bBtnDown,
rc.top+m_sizeOffset.cy+m_sizeImage.cy+1+bBtnDown,
rc.right-3+bBtnDown,
rc.bottom-3+bBtnDown
);
int nBkMode = dc.SetBkMode(TRANSPARENT) ;
dc.DrawText(strText, rectText, DT_CENTER|DT_VCENTER|DT_NOCLIP);
dc.SetBkMode(nBkMode) ;
}
if( ! bBtnEnabled ) {
// gray out that button
rc.DeflateRect(bBtnDown,bBtnDown);
DrawDisabledButton(dc, rc);
}
cdrw.NotifyItemPostPaint(i);
}
}
dc.SelectObject(pOldFont);
if( ! m_bDeleteImgList )
imglist.Detach();
// last but not least: inform the parent for end of painting
cdrw.NotifyPostPaint();
} else
// classic mode (or couldn't receive imagelist)
CToolBar::OnPaint();
}
void CToolBarEx :: DrawDisabledButton( CDC & dc, const CRect & rc ) const {
// create a monochrome memory DC
CDC ddc;
ddc.CreateCompatibleDC(0);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&ddc, rc.Width(), rc.Height());
CBitmap * pOldBmp = ddc.SelectObject(&bmp);
// build a mask
ddc.PatBlt(0, 0, rc.Width(), rc.Height(), WHITENESS);
dc.SetBkColor(m_clrBtnFace);
ddc.BitBlt(0, 0, rc.Width(), rc.Height(), &dc, rc.left, rc.top, SRCCOPY);
dc.SetBkColor(m_clrBtnHilight);
ddc.BitBlt(0, 0, rc.Width(), rc.Height(), &dc, rc.left, rc.top, SRCPAINT);
// Copy the image from the toolbar into the memory DC
// and draw it (grayed) back into the toolbar.
dc.FillSolidRect(rc.left, rc.top, rc.Width(), rc.Height(), m_clrBtnFace);
dc.SetBkColor(RGB(0, 0, 0));
dc.SetTextColor(RGB(255, 255, 255));
CBrush brShadow, brHilight;
brHilight.CreateSolidBrush(m_clrBtnHilight);
brShadow.CreateSolidBrush(m_clrBtnShadow);
CBrush * pOldBrush = dc.SelectObject(&brHilight);
dc.BitBlt(rc.left+1, rc.top+1, rc.Width(), rc.Height(), &ddc, 0, 0, 0x00E20746L);
dc.SelectObject(&brShadow);
dc.BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &ddc, 0, 0, 0x00E20746L);
// reset DCs
dc.SelectObject(pOldBrush);
ddc.SelectObject(pOldBmp);
ddc.DeleteDC();
bmp.DeleteObject();
}
void CToolBarEx :: DrawSeparator( CDC & dc, CRect & rc ) const {
BOOL bHorz = ((m_dwStyle & CBRS_ORIENT_HORZ) != 0) ? TRUE : FALSE;
// make sure, this separator is not a placeholder for
// another control.
if( rc.Width() <= 8 ) {
if( bHorz ) {
// draw the separator bar in the middle
int x = (rc.left + rc.right) / 2;
rc.left = x-1; rc.right = x+1;
dc.Draw3dRect(
rc,
m_clrBtnShadow,
m_clrBtnHilight
);
} else {
// draw the separator bar in the middle
rc.left = rc.left - m_sizeButton.cx;
rc.right = rc.left + m_sizeButton.cx;
rc.top = rc.bottom+1;
rc.bottom = rc.top+3;
int y = (rc.top+rc.bottom)/2;
rc.top = y-1; rc.bottom = y+1;
dc.Draw3dRect(
rc,
m_clrBtnShadow,
m_clrBtnHilight
);
}
}
}
void CToolBarEx :: DrawGripper( CDC & dc ) const {
// Do not draw a gripper if the bar is floating or not
// dockable.
if( (m_dwStyle & CBRS_FLOATING) || m_dwDockStyle == 0 )
return;
CRect gripper;
GetWindowRect(gripper);
ScreenToClient(gripper);
gripper.OffsetRect(-gripper.left, -gripper.top);
if( m_dwStyle & CBRS_ORIENT_HORZ ) {
// gripper at left
gripper.DeflateRect(4, 4);
gripper.right = gripper.left+3;
dc.Draw3dRect(
gripper,
m_clrBtnHilight,
m_clrBtnShadow
);
gripper.OffsetRect(3, 0);
dc.Draw3dRect(
gripper,
m_clrBtnHilight,
m_clrBtnShadow
);
} else {
// gripper at top
gripper.DeflateRect(4, 4);
gripper.bottom = gripper.top+3;
dc.Draw3dRect(
gripper,
m_clrBtnHilight,
m_clrBtnShadow
);
gripper.OffsetRect(0, 3);
dc.Draw3dRect(
gripper,
m_clrBtnHilight,
m_clrBtnShadow
);
}
}
void CToolBarEx :: OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHndler ) {
if( m_bFlatLook ) {
// save current styles
register const int nBtn = GetToolBarCtrl().GetButtonCount();
register int nIdx;
for( nIdx = 0; nIdx < nBtn; ++nIdx )
m_Styles.SetAtGrow(nIdx, GetButtonStyle(nIdx));
// do base class processing
CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
//check whether styles have been changed
for( nIdx = 0; nIdx < nBtn; ++nIdx ) {
if( m_Styles[nIdx] != GetButtonStyle(nIdx) )
// invalidate that button
InvalidateButton(nIdx);
}
} else
// simply delegate
CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);
}
void CToolBarEx::OnSysColorChange()
{
CToolBar::OnSysColorChange();
m_clrBtnFace = ::GetSysColor(COLOR_BTNFACE);
m_clrBtnHilight = ::GetSysColor(COLOR_BTNHILIGHT);
m_clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);
m_clrBtnLight = ::GetSysColor(COLOR_3DLIGHT);
}
void CToolBarEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
{
CToolBar::OnNcCalcSize(bCalcValidRects, lpncsp);
if( m_bFlatLook ) {
// adjust non-client area for gripper at left or top
if( m_dwStyle & CBRS_ORIENT_HORZ ) {
lpncsp->rgrc[0].left += 4;
lpncsp->rgrc[0].right += 4;
} else {
lpncsp->rgrc[0].top += 6;
lpncsp->rgrc[0].bottom += 6;
}
}
}
void CToolBarEx::OnMouseMove(UINT nFlags, CPoint point)
{
if( m_bDragging ) {
DragMove();
return;
}
if( m_bFlatLook && IsTopParentActive() && GetTopLevelParent()->IsWindowEnabled()) {
register const int nBtn = GetToolBarCtrl().GetButtonCount();
const int nLastBtn = m_nLastBtn;
m_nLastBtn = -1;
for( register int i = 0 ; i < nBtn ; ++i ) {
CRect rc;
GetItemRect(i, rc);
const BOOL bBtnEnabled = GetToolBarCtrl().IsButtonEnabled(int(GetItemID(i)));
const BOOL bSep = GetButtonStyle(i) & TBBS_SEPARATOR;
if( bSep || ! bBtnEnabled )
continue;
const BOOL bHasCursor = rc.PtInRect(point);
if( bHasCursor && bBtnEnabled ) {
if( nLastBtn != i ) {
// force a repaint of the button with the cursor on it
InvalidateRect(rc, FALSE);
}
m_nLastBtn = i;
} else if( !bHasCursor && i == nLastBtn ) {
// force a repaint of the last formed button
InvalidateRect(rc, FALSE);
}
}
// One problem occures with WM_MOUSEMOVE: we cannot detect
// that the mouse leaves the window. If the mouse moves quick
// enough, then the last formed button stays visible. To
// resolve this problem, we set a timer and check, whether
// the mouse is outside the window ...
KillTimer(m_uTimerEvent);
m_uTimerEvent = SetTimer(1, 250, 0);
}
CToolBar::OnMouseMove(nFlags, point);
}
void CToolBarEx::OnNcPaint()
{
if( m_bFlatLook ) {
// 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);
Draw3DBorders(&dc, rectWindow);
dc.IntersectClipRect(rectWindow);
#ifdef _MEMDC_H_
// You're using Keith Rule's CMemDC. In this case
// we have to make sure that WM_ERASEBKGND
// will not be sent.
dc.FillSolidRect(rectWindow, m_clrBtnFace);
#else
// erase parts not drawn
SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);
#endif
DrawGripper(dc);
} else
CToolBar::OnNcPaint();
}
void CToolBarEx :: Draw3DBorders(CDC * pDC, CRect & rect) {
ASSERT_VALID(this);
ASSERT_VALID(pDC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -