📄 toolbarex.cpp
字号:
if( m_bReal3DBorder ) {
DWORD dwStyle = m_dwStyle;
if (!(dwStyle & CBRS_BORDER_ANY))
return;
COLORREF clr = (m_dwStyle & CBRS_BORDER_3D) ? m_clrBtnHilight : m_clrBtnShadow;
if(m_dwStyle & CBRS_BORDER_LEFT)
pDC->FillSolidRect(0, 0, 1, rect.Height() - 1, clr);
if(m_dwStyle & CBRS_BORDER_TOP)
pDC->FillSolidRect(0, 0, rect.Width()-1 , 1, clr);
if(m_dwStyle & CBRS_BORDER_RIGHT)
pDC->FillSolidRect(rect.right, 1, -1, rect.Height() - 1, m_clrBtnShadow);
if(m_dwStyle & CBRS_BORDER_BOTTOM)
pDC->FillSolidRect(0, rect.bottom, rect.Width()-1, -1, m_clrBtnShadow);
// if undockable toolbar at top of frame, apply special formatting to mesh
// properly with frame menu
if(!m_pDockContext) {
pDC->FillSolidRect(0,0,rect.Width(),1,m_clrBtnShadow);
pDC->FillSolidRect(0,1,rect.Width(),1,m_clrBtnHilight);
}
if (dwStyle & CBRS_BORDER_LEFT)
++rect.left;
if (dwStyle & CBRS_BORDER_TOP)
++rect.top;
if (dwStyle & CBRS_BORDER_RIGHT)
--rect.right;
if (dwStyle & CBRS_BORDER_BOTTOM)
--rect.bottom;
} else
DrawBorders(pDC, rect);
}
void CToolBarEx::OnTimer(UINT nIDEvent)
{
if( nIDEvent == m_uTimerEvent ) {
if( m_nLastBtn >= 0 ) {
POINT pt;
::GetCursorPos(&pt);
CRect rc;
GetWindowRect(rc);
if( ! rc.PtInRect(pt) ) {
InvalidateButton(m_nLastBtn);
m_nLastBtn = -1;
}
}
if( m_nLastBtn < 0 )
KillTimer(nIDEvent);
} else
CToolBar::OnTimer(nIDEvent);
}
int CToolBarEx::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CToolBar::OnCreate(lpCreateStruct) == -1)
return -1;
// Save the parent at creation time. It may change, if
// the toolbar is floating; but we want to know of the
// "real" parent (for notification messages)!
m_hwndParent = lpCreateStruct->hwndParent;
return 0;
}
void CToolBarEx::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
CToolBar::OnWindowPosChanging(lpwndpos);
// If moved just force a redraw. This stops the partial redraw bug.
if( !(lpwndpos->flags & SWP_NOMOVE) )
Invalidate(FALSE);
}
#define PADWIDTH(x) (((x)*8+31)&~31)/8
HIMAGELIST CToolBarEx :: GetImageList() {
m_bDeleteImgList = FALSE;
HIMAGELIST hImg = 0;
#ifdef TB_GETIMAGELIST
// Some older versions of VC++ do not know of
// the TB_GETIMAGELIST macro (defined in commctrl.h).
hImg = HIMAGELIST(SendMessage(TB_GETIMAGELIST));
#ifdef _DEBUG
if( hImg == 0 ) {
TRACE0("CToolBarEx::GetImageList(): could not get image list\n");
}
#endif
#endif // TB_GETIMAGELIST
if( ! hImg ) {
// comctl32.dll version prior to 4.70 doesn't know
// anything of the TB_GETIMAGELIST message
if( m_hbmImageWell != 0 ) {
// Yep - we have a valid image.
// But beware: Do not use this bitmap directly.
// We make the copy by ourself. CopyImage() (for
// instace) produces inacceptable copies under
// some circumstances ...
CImageList imglist;
CBitmap bmp;
// retrieve the size of the bitmap
BITMAP bmHdr;
::GetObject(m_hbmImageWell, sizeof(BITMAP), &bmHdr);
DWORD dwWidth, dwHeight = bmHdr.bmHeight;
if (bmHdr.bmBitsPixel > 8)
dwWidth = PADWIDTH(bmHdr.bmWidth * 3);
else
dwWidth = PADWIDTH(bmHdr.bmWidth);
// copy the bitmap
CClientDC cdc(this);
CDC dc1, dc2;
dc1.CreateCompatibleDC(&cdc);
dc2.CreateCompatibleDC(&cdc);
bmp.CreateCompatibleBitmap(&cdc, dwWidth, dwHeight);
CBitmap * pOBmp = dc1.SelectObject(&bmp);
HGDIOBJ hOObj = ::SelectObject(dc2.GetSafeHdc(), m_hbmImageWell);
dc1.BitBlt(0,0,dwWidth,dwHeight,&dc2,0,0,SRCCOPY);
::SelectObject(dc2.GetSafeHdc(), hOObj);
dc1.SelectObject(pOBmp);
dc1.DeleteDC();
dc2.DeleteDC();
imglist.Create(m_sizeImage.cx, m_sizeImage.cy,TRUE,dwWidth/m_sizeImage.cx,1);
imglist.SetBkColor(m_clrBtnFace);
imglist.Add(&bmp,m_clrBtnFace);
hImg = imglist.Detach();
bmp.DeleteObject();
m_bDeleteImgList = TRUE;
}
}
return hImg;
}
void CToolBarEx::InvalidateButton(int nIndex) {
if( nIndex < 0 || nIndex >= GetToolBarCtrl().GetButtonCount() )
return;
CRect rc;
GetItemRect(nIndex, rc);
InvalidateRect(rc, FALSE);
}
BOOL CToolBarEx :: IsSeparator(int nIndex) const {
if( nIndex >= 0 && nIndex < GetToolBarCtrl().GetButtonCount() )
if( GetButtonStyle(nIndex) == TBBS_SEPARATOR ) {
// make sure this is a "real" separator
CRect rc;
GetItemRect(nIndex, rc);
if( rc.Width() <= 8 )
return TRUE;
}
return FALSE;
}
BOOL CToolBarEx :: IsControl(int nIndex) const {
if( nIndex >= 0 && nIndex < GetToolBarCtrl().GetButtonCount() )
if( GetButtonStyle(nIndex) == TBBS_SEPARATOR ) {
// make sure this is a placeholder for a control
CRect rc;
GetItemRect(nIndex, rc);
if( rc.Width() > 8 )
return TRUE;
}
return FALSE;
}
CWnd * CToolBarEx :: GetControl(int idx, BOOL bIdxIsID) const {
UINT uID = bIdxIsID ? UINT(idx) : GetItemID(idx);
for( CWnd * pWnd = GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow() )
if( UINT(::GetWindowLong(pWnd->GetSafeHwnd(), GWL_ID)) == uID )
return pWnd;
return 0;
}
CWnd * CToolBarEx :: CtrlReplace(
CRuntimeClass * pClass,
CRect & rc,
UINT ID,
DWORD dwStyle ) {
int nIndex = CommandToIndex(ID);
if(nIndex < 0) {
TRACE1("CToolBarEx::CtrlReplace(): 0x%x is not a valid ID for this toolbar.\n,", ID);
return 0;
}
int nWidth = rc.Width();
if( nWidth < 0 )
nWidth = -nWidth;
SetButtonInfo(nIndex, ID, TBBS_SEPARATOR, nWidth);
CWnd * pCtrl = CreateControl(pClass, rc, ID, dwStyle);
return pCtrl;
}
CWnd * CToolBarEx :: CtrlInsert(
CRuntimeClass * pClass,
CRect & rc,
UINT ID,
int nBefore,
DWORD dwStyle) {
BOOL bAppend = FALSE;
CToolBarCtrl & wndToolBarCtrl = GetToolBarCtrl();
if( nBefore < 0 || nBefore > wndToolBarCtrl.GetButtonCount() )
bAppend = TRUE;
int nWidth = rc.Width();
if( nWidth < 0 )
nWidth = -nWidth;
TBBUTTON tbButton;
tbButton.iBitmap = nWidth;
tbButton.idCommand = ID;
tbButton.fsState = TBSTATE_ENABLED;
tbButton.fsStyle = TBSTYLE_SEP;
tbButton.dwData = 0;
tbButton.iString = 0;
if( bAppend )
wndToolBarCtrl.AddButtons(1, &tbButton);
else
wndToolBarCtrl.InsertButton(nBefore, &tbButton);
CWnd * pCtrl = CreateControl(pClass, rc, ID, dwStyle);
return pCtrl;
}
CWnd * CToolBarEx :: CreateControl(
CRuntimeClass * pClass,
CRect & rc,
UINT ID,
DWORD dwStyle) {
if( ! pClass || ! pClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)) ) {
TRACE0("CToolBarEx::CreateControl(): given class is NULL or not derived from CWnd.\n");
return 0;
}
CWnd * pCtrl = 0;
BOOL bSelfDeleting = TRUE;
CString strClass = pClass->m_lpszClassName;
if( strClass == TEXT("CComboBox") ) {
pCtrl = new CComboBox();
bSelfDeleting = FALSE;
} else if( strClass == TEXT("CEdit") ) {
pCtrl = new CEdit();
bSelfDeleting = FALSE;
} else {
pCtrl = (CWnd *)pClass->CreateObject();
if( pCtrl == 0 ) {
TRACE1("CToolBarEx::CreateControl(): dynamic create of control %hs failed.\n",
pClass->m_lpszClassName);
return 0;
}
}
// create the control itself
CRect rect = rc;
BOOL bCreate = FALSE;
if( pCtrl->IsKindOf(RUNTIME_CLASS(CComboBox)) )
bCreate = ((CComboBox*)pCtrl)->Create(WS_CHILD|WS_VISIBLE|dwStyle, rect, this, ID);
else if( pCtrl->IsKindOf(RUNTIME_CLASS(CEdit)) )
bCreate = ((CEdit*)pCtrl)->Create(WS_CHILD|WS_VISIBLE|dwStyle, rect, this, ID);
else
bCreate = pCtrl->Create(0, 0, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, ID);
if( ! bCreate ) {
TRACE1("CToolBarEx::CreateControl(): could not Create() control.\n,", ID);
if( ! bSelfDeleting )
delete pCtrl;
return 0;
}
if( ! bSelfDeleting ) {
// we have to remember this control, so we can delete it later
if( ! m_pControls )
m_pControls = new CObList();
m_pControls->AddTail(pCtrl);
}
RepositionControls();
return pCtrl;
}
void CToolBarEx :: RepositionControls() {
// Walk all descendents.
for( CWnd * pWnd = GetWindow(GW_CHILD); pWnd; pWnd = pWnd->GetNextWindow() ) {
// If that window is a child of this
// toolbar, then reposition this control.
if( pWnd->GetParent() == this ) {
DWORD dwID = ::GetWindowLong(pWnd->GetSafeHwnd(), GWL_ID);
int idx = CommandToIndex(dwID);
ASSERT(idx >= 0);
CRect rc;
GetItemRect(idx, rc);
pWnd->SetWindowPos(0, rc.left, rc.top, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOCOPYBITS);
pWnd->ShowWindow(SW_SHOW);
}
}
}
void CToolBarEx :: RecalcLayout() {
// Recalculate the size of the bar.
BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT);
else if (bHorz)
CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK | LM_COMMIT);
else
CalcDynamicLayout(0, LM_VERTDOCK | LM_COMMIT);
RepositionControls();
// recalculate the parent frame
if( m_dwStyle & CBRS_FLOATING ) {
ASSERT(m_pDockBar != 0);
((CMiniDockFrameWnd *)m_pDockBar->GetParent())->RecalcLayout();
} else {
((CFrameWnd*)GetParentFrame())->RecalcLayout();
}
}
HBITMAP CToolBarEx :: GetBitmap(int nBtnID) {
int nBitmap = SendMessage(TB_GETBITMAP, WPARAM(nBtnID));
return GetBitmap(nBitmap, m_sizeImage);
}
HBITMAP CToolBarEx :: GetBitmap(int nIndex, const CSize & sizeBitmap) {
HIMAGELIST hImgList = GetImageList();
if( ! hImgList )
return 0;
CImageList imglist;
imglist.Attach(hImgList);
HICON hIcon = imglist.ExtractIcon(nIndex);
CBitmap bmp;
if( hIcon ) {
CClientDC cdc(this) ;
CDC dc;
dc.CreateCompatibleDC(&cdc);
VERIFY(bmp.CreateCompatibleBitmap(&cdc, sizeBitmap.cx, sizeBitmap.cy));
CBitmap* pOldBmp = dc.SelectObject(&bmp);
CBrush brush ;
VERIFY(brush.CreateSolidBrush(m_clrBtnFace));
::DrawIconEx(
dc.GetSafeHdc(),
0,
0,
hIcon,
sizeBitmap.cx,
sizeBitmap.cy,
0,
(HBRUSH)brush,
DI_NORMAL
);
dc.SelectObject( pOldBmp );
dc.DeleteDC();
// the icon is not longer needed
DestroyIcon(hIcon);
} else
TRACE1("CToolBarEx::GetBitmap(): unable to extract bitmap with index %d\n", nIndex);
if( ! m_bDeleteImgList )
imglist.Detach();
return hIcon ? HBITMAP(bmp.Detach()) : 0;
}
LRESULT CToolBarEx::OnAddBitmap(WPARAM wParam, LPARAM lParam) {
// work around a bug in CToolBar:
// if one calls CToolBar::GetToolBarCtrl().AddBitmap(...),
// then CToolBar does not realize this. This can lead to
// confusing button images ...
int nButtons = int(wParam);
LPTBADDBITMAP pAddBmp = LPTBADDBITMAP(lParam);
if( pAddBmp->hInst != HINST_COMMCTRL ) {
// This workaround does not work, if one
// specifies "HINST_COMMCTRL" to the "hInst"
// member of pAddBmp, because we cannot access
// the internals of commctl32.dll ...
TRACE0("Adding a bitmap\n");
HBITMAP hBitmap;
if( pAddBmp->hInst != 0 )
// Have to load the bitmap "pAddBmp->nID"
// contains the resource-ID of the bitmap.
hBitmap = ::LoadBitmap(pAddBmp->hInst, MAKEINTRESOURCE(pAddBmp->nID));
else
// "pAddBmp->nID" is the handle of the bitmap.
hBitmap = HBITMAP(pAddBmp->nID);
if(hBitmap == 0)
return HRESULT(-1);
// You really should use CToolBarEx as a replacement for
// CToolBar. So make sure you have set up a toolbar
// properly before you begin to customize it.
ASSERT(m_hbmImageWell);
// retrieve number of images currently stored in CToolBar
BITMAP bitmap;
VERIFY(::GetObject(m_hbmImageWell, sizeof(BITMAP), &bitmap));
int nImageCount = bitmap.bmWidth / m_sizeImage.cx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -