⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 toolbarex.cpp

📁 深入剖析Visual C++编程技术及应用实例
💻 CPP
📖 第 1 页 / 共 5 页
字号:

	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 + -