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

📄 toolbarex.cpp

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

		CClientDC cdc(this);
		CDC dcOld, dcNew;
		dcOld.CreateCompatibleDC(&cdc);
		dcNew.CreateCompatibleDC(&cdc);

		HGDIOBJ hOldBmp = ::SelectObject(dcOld.GetSafeHdc(), m_hbmImageWell);

		// create the new bitmap and make it big enough to
		// hold all images (old+new)
		CBitmap bmpNew;
		bmpNew.CreateCompatibleBitmap(
			&cdc,
			bitmap.bmWidth + nButtons * m_sizeImage.cx,
			m_sizeImage.cy);
		CBitmap * pbmpNew = dcNew.SelectObject(&bmpNew);

		dcNew.BitBlt(0,0,bitmap.bmWidth,bitmap.bmHeight,&dcOld,0,0,SRCCOPY);

		::SelectObject(dcOld.GetSafeHdc(), hBitmap);
		dcNew.BitBlt(bitmap.bmWidth,0,m_sizeImage.cx*nButtons,bitmap.bmHeight,&dcOld,0,0,SRCCOPY);

		::SelectObject(dcOld.GetSafeHdc(), hOldBmp);
		dcNew.SelectObject(pbmpNew);
		dcOld.DeleteDC();
		dcNew.DeleteDC();

		VERIFY(bmpNew.GetObject(sizeof(BITMAP), &bitmap));

		HRESULT hRes = DefWindowProc(TB_ADDBITMAP, wParam, lParam);

		// syncronize toolbarcontrol's bitmap with our's
		AddReplaceBitmap(HBITMAP(bmpNew.Detach()));

		return HRESULT(nImageCount);
	}

	return DefWindowProc(TB_ADDBITMAP, wParam, lParam);
}


// intercept TB_DELETEBUTTON, so we can delete controls too.
LRESULT CToolBarEx::OnDeleteButton(WPARAM wParam, LPARAM lParam) {
	CWnd * pControl = GetControl(int(wParam));
	if( pControl ) {
		// this is the control associated with the button to delete
		BOOL bMustDelete = FALSE;
		if( m_pControls ) {
			// It is really a good idea to add a control via the
			// CToolBarEx own members. This will guarantee that
			// all resources are freed.
			POSITION pos = m_pControls->Find(pControl);
			if( pos ) {
				m_pControls->RemoveAt(pos);
				bMustDelete = TRUE;
			}
		}
		pControl->DestroyWindow();
		if( bMustDelete )
			delete pControl;
	}

	return DefWindowProc(TB_DELETEBUTTON, wParam, lParam);
}


#ifdef _MEMDC_H_
BOOL CToolBarEx::OnEraseBkgnd(CDC* pDC) 
{
	return IsFlatLook() ? FALSE : CToolBar::OnEraseBkgnd(pDC);
}
#endif

/////////////////////////////////////////////////////////////////////////////
// ALT-drag

// To keep the users of CToolBarEx from inserting cursor-resources, we
// create the cursors on the fly. This makes usage of CToolBarEx as easy as
// possible:

static const BYTE ANDmaskDrop[] = { 
    0xFF, 0xFF, 0xFF, 0xFF,   // line 1
    0xFF, 0xFF, 0xFF, 0xFF,   // line 2
    0xF3, 0xFF, 0xFF, 0xFF,   // line 3
    0xF1, 0xFF, 0xFF, 0xFF,   // line 4
 
    0xF0, 0xFF, 0xFF, 0xFF,   // line 5
    0xF0, 0x7F, 0xFF, 0xFF,   // line 6
    0xF0, 0x3F, 0xFF, 0xFF,   // line 7
    0xF0, 0x1F, 0xFF, 0xFF,   // line 8
 
    0xF0, 0x0F, 0xFF, 0xFF,   // line 9
    0xF0, 0x07, 0xFF, 0xFF,   // line 10
    0xF0, 0x03, 0xFF, 0xFF,   // line 11
    0xF0, 0x01, 0xFF, 0xFF,   // line 12
 
    0xF0, 0x00, 0xFF, 0xFF,   // line 13
    0xF0, 0x0F, 0xFF, 0xFF,   // line 14
    0xF0, 0x0F, 0xFF, 0xFF,   // line 15
    0xF1, 0x07, 0xFF, 0xFF,   // line 16
 
    0xF3, 0x07, 0xFF, 0xFF,   // line 17
    0xF6, 0x00, 0x00, 0x3F,   // line 18
    0xFE, 0x00, 0x00, 0x3F,   // line 19
    0xFE, 0x00, 0x00, 0x3F,   // line 20
 
    0xFE, 0x00, 0x00, 0x3F,   // line 21
    0xFE, 0x00, 0x00, 0x3F,   // line 22
    0xFE, 0x00, 0x00, 0x3F,   // line 23
    0xFE, 0x00, 0x00, 0x3F,   // line 24
 
    0xFE, 0x00, 0x00, 0x3F,   // line 25
    0xFE, 0x00, 0x00, 0x3F,   // line 26
    0xFF, 0xFF, 0xFF, 0xFF,   // line 27
    0xFF, 0xFF, 0xFF, 0xFF,   // line 28
 
    0xFF, 0xFF, 0xFF, 0xFF,   // line 29
    0xFF, 0xFF, 0xFF, 0xFF,   // line 30
    0xFF, 0xFF, 0xFF, 0xFF,   // line 31
    0xFF, 0xFF, 0xFF, 0xFF    // line 32
};
 
static const BYTE XORmaskDrop[] = { 
    0x00, 0x00, 0x00, 0x00,   // line 1
    0x00, 0x00, 0x00, 0x00,   // line 2
    0x00, 0x00, 0x00, 0x00,   // line 3
    0x04, 0x00, 0x00, 0x00,   // line 4
 
    0x06, 0x00, 0x00, 0x00,   // line 5
    0x07, 0x00, 0x00, 0x00,   // line 6
    0x07, 0x80, 0x00, 0x00,   // line 7
    0x07, 0xC0, 0x00, 0x00,   // line 8
 
    0x07, 0xE0, 0x00, 0x00,   // line 9
    0x07, 0xF0, 0x00, 0x00,   // line 10
    0x07, 0xF8, 0x00, 0x00,   // line 11
    0x07, 0xFC, 0x00, 0x00,   // line 12
 
    0x07, 0xE0, 0x00, 0x00,   // line 13
    0x07, 0x60, 0x00, 0x00,   // line 14
    0x06, 0x60, 0x00, 0x00,   // line 15
    0x04, 0x30, 0x00, 0x00,   // line 16
 
    0x00, 0x30, 0x00, 0x00,   // line 17
    0x00, 0x18, 0x00, 0x00,   // line 18
    0x00, 0xDD, 0xFF, 0x00,   // line 19
    0x00, 0xAC, 0xAA, 0x00,   // line 20
 
    0x00, 0xCD, 0x55, 0x00,   // line 21
    0x00, 0xA0, 0xAA, 0x00,   // line 22
    0x00, 0xD5, 0x55, 0x00,   // line 23
    0x00, 0xAA, 0xAA, 0x00,   // line 24
 
    0x00, 0x00, 0x00, 0x00,   // line 25
    0x00, 0x00, 0x00, 0x00,   // line 26
    0x00, 0x00, 0x00, 0x00,   // line 27
    0x00, 0x00, 0x00, 0x00,   // line 28
 
    0x00, 0x00, 0x00, 0x00,   // line 29
    0x00, 0x00, 0x00, 0x00,   // line 30
    0x00, 0x00, 0x00, 0x00,   // line 31
    0x00, 0x00, 0x00, 0x00    // line 32
};

static const BYTE ANDmaskNoDrop[] = { 
    0xFF, 0xFF, 0xFF, 0xFF,   // line 1
    0xFF, 0xFF, 0xFF, 0xFF,   // line 2
    0xF3, 0xFF, 0xFF, 0xFF,   // line 3
    0xF1, 0xFF, 0xFF, 0xFF,   // line 4
 
    0xF0, 0xFF, 0xFF, 0xFF,   // line 5
    0xF0, 0x7F, 0xFF, 0xFF,   // line 6
    0xF0, 0x3F, 0xFF, 0xFF,   // line 7
    0xF0, 0x1F, 0xFF, 0xFF,   // line 8
 
    0xF0, 0x0F, 0xFF, 0xFF,   // line 9
    0xF0, 0x07, 0xFF, 0xFF,   // line 10
    0xF0, 0x03, 0xFF, 0xFF,   // line 11
    0xF0, 0x01, 0xFF, 0xFF,   // line 12
 
    0xF0, 0x00, 0xFF, 0xFF,   // line 13
    0xF0, 0x0F, 0xFF, 0xFF,   // line 14
    0xF0, 0x0F, 0xFF, 0xFF,   // line 15
    0xF1, 0x07, 0xFF, 0xFF,   // line 16
 
    0xF3, 0x07, 0xFF, 0xFF,   // line 17
    0xF6, 0x00, 0x00, 0x3F,   // line 18
    0xFE, 0x00, 0x00, 0x3F,   // line 19
    0xFE, 0x00, 0x00, 0x3F,   // line 20
 
    0xFE, 0x00, 0x00, 0x3F,   // line 21
    0xFE, 0x00, 0x00, 0x0F,   // line 22
    0xFE, 0x00, 0x00, 0x0F,   // line 23
    0xFE, 0x00, 0x00, 0x0F,   // line 24
 
    0xFE, 0x00, 0x00, 0x0F,   // line 25
    0xFE, 0x00, 0x00, 0x0F,   // line 26
    0xFF, 0xFF, 0x80, 0x0F,   // line 27
    0xFF, 0xFF, 0x80, 0x0F,   // line 28
 
    0xFF, 0xFF, 0x80, 0x0F,   // line 29
    0xFF, 0xFF, 0x80, 0x0F,   // line 30
    0xFF, 0xFF, 0x80, 0x0F,   // line 31
    0xFF, 0xFF, 0x80, 0x0F    // line 32
};
 
static const BYTE XORmaskNoDrop[] = {
    0x00, 0x00, 0x00, 0x00,   // line 1
    0x00, 0x00, 0x00, 0x00,   // line 2
    0x00, 0x00, 0x00, 0x00,   // line 3
    0x04, 0x00, 0x00, 0x00,   // line 4
 
    0x06, 0x00, 0x00, 0x00,   // line 5
    0x07, 0x00, 0x00, 0x00,   // line 6
    0x07, 0x80, 0x00, 0x00,   // line 7
    0x07, 0xC0, 0x00, 0x00,   // line 8
 
    0x07, 0xE0, 0x00, 0x00,   // line 9
    0x07, 0xF0, 0x00, 0x00,   // line 10
    0x07, 0xF8, 0x00, 0x00,   // line 11
    0x07, 0xFC, 0x00, 0x00,   // line 12
 
    0x07, 0xE0, 0x00, 0x00,   // line 13
    0x07, 0x60, 0x00, 0x00,   // line 14
    0x06, 0x60, 0x00, 0x00,   // line 15
    0x04, 0x30, 0x00, 0x00,   // line 16
 
    0x00, 0x30, 0x00, 0x00,   // line 17
    0x00, 0x18, 0x00, 0x00,   // line 18
    0x00, 0xDD, 0xFF, 0x00,   // line 19
    0x00, 0xAC, 0xAA, 0x00,   // line 20
 
    0x00, 0xCD, 0x55, 0x00,   // line 21
    0x00, 0xA0, 0x80, 0x00,   // line 22
    0x00, 0xD5, 0x3F, 0xE0,   // line 23
    0x00, 0xAA, 0xA7, 0x20,   // line 24
 
    0x00, 0x00, 0x22, 0x20,   // line 25
    0x00, 0x00, 0x30, 0x60,   // line 26
    0x00, 0x00, 0x38, 0xE0,   // line 27
    0x00, 0x00, 0x30, 0x60,   // line 28
 
    0x00, 0x00, 0x22, 0x20,   // line 29
    0x00, 0x00, 0x27, 0x20,   // line 30
    0x00, 0x00, 0x3F, 0xE0,   // line 31
    0x00, 0x00, 0x00, 0x00    // line 32
};

void CToolBarEx::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if( ::GetAsyncKeyState(VK_MENU) & (1<<15) )
		// one of the ALT keys is pressed too - begin drag operation
		if( BeginDrag() )
			return;
	
	if( ::GetAsyncKeyState(VK_SHIFT) & (1<<15) )
		// disable the old-style drag
		return;
	
	CToolBar::OnLButtonDown(nFlags, point);
}

void CToolBarEx::OnLButtonUp(UINT nFlags, CPoint point) 
{
	if( m_bDragging )
		EndDrag();
	else
		CToolBar::OnLButtonUp(nFlags, point);
}

BOOL CToolBarEx :: BeginDrag() {
	TRACE0("beginning drag operation\n");

	VERIFY(!m_hDragCursor);
	VERIFY(!m_hNoDragCursor);

	if( !(::GetWindowLong(GetToolBarCtrl().GetSafeHwnd(),GWL_STYLE) & CCS_ADJUSTABLE) )
		return FALSE;	// Bar is not adjustable

	register const int nBtn = GetToolBarCtrl().GetButtonCount();
	const int nLastBtn = m_nLastBtn;
	m_nLastBtn = -1;
	CPoint pt;
	::GetCursorPos(&pt);
	ScreenToClient(&pt);

	m_nDragButton = -1;

	// have a look for whether the button is valid and
	// - if so - draw a dragging border around it.
	for( register int i = 0 ; i < nBtn ; ++i ) {
		if( IsSeparator(i) )
			continue;	// real separators are not draggable

		CRect rc;
		GetItemRect(i, rc);

		const BOOL bHasCursor = rc.PtInRect(pt);

		if( bHasCursor ) {
			// OK we've found the button. Now ask for deletion:
			if( ! DoQueryDelete(i) )
				// the app does not allow the removal ...
				return FALSE;

			m_nDragButton = i;
			CClientDC cdc(this);
			cdc.DrawDragRect(rc, CSize(2,2),0,CSize(0,0));
			break;
		}
	}

	if( m_nDragButton < 0 )
		return FALSE;		// nothing to drag ...

	VERIFY(m_hDragCursor = ::CreateCursor(0, 4, 2, 32, 32, ANDmaskDrop, XORmaskDrop));
	VERIFY(m_hNoDragCursor = ::CreateCursor(0, 4, 2, 32, 32, ANDmaskNoDrop, XORmaskNoDrop));

	// capture the mouse during the drag operation
	SetCapture();

	// make sure we receive keyboard-input
	SetFocus();

	m_hOrigCursor = ::SetCursor(m_hDragCursor);
	m_bDragCursor = TRUE;

	m_bDragging = TRUE;

	::GetCursorPos(&pt);
	SetMarker(m_pDropBar=this, m_ptDrop=pt);

	return m_bDragging;
}



BOOL CToolBarEx :: IsValidDropTarget(const CWnd * pWnd) const {
	return	(pWnd &&
			pWnd->IsKindOf(RUNTIME_CLASS(CToolBarEx)) &&
			(::GetWindowLong(((CToolBarEx*)pWnd)->GetToolBarCtrl()
						.GetSafeHwnd(),GWL_STYLE) & CCS_ADJUSTABLE) &&
			((const CToolBarEx*)pWnd)->GetParentFrame() == GetParentFrame())
			? TRUE : FALSE;
}


void CToolBarEx :: DragMove() {
	//TRACE0("dragmove in progress\n");

	CPoint pt;
	::GetCursorPos(&pt);
	const CWnd * pWnd = WindowFromPoint(pt);

	// is the cursor moving over an adjustable toolbar ?
	BOOL bToolBar =	IsValidDropTarget(pWnd);
	
	// If the window under the cursor is not a toolbar, then
	// check whether this window is a child of a toolbar.
	while( ! bToolBar && (pWnd = pWnd->GetParent()) != 0 )
		bToolBar =	IsValidDropTarget(pWnd);

	// check whether we have to switch the cursor
	if( bToolBar && ! m_bDragCursor ) {
		::SetCursor(m_hDragCursor);
		m_bDragCursor = TRUE;
	} else if( ! bToolBar && m_bDragCursor ) {
		::SetCursor(m_hNoDragCursor);
		m_bDragCursor = FALSE;
	}

	SetMarker(m_pDropBar = (bToolBar ? (CToolBarEx*)pWnd : 0), m_ptDrop = pt);
}

void CToolBarEx :: EndDrag(BOOL bDoMove) {
	TRACE0("ending drag operation\n");

	// remove the marker
	SetMarker(0, CPoint(0,0));

	VERIFY(::SetCursor(m_hOrigCursor));
	::DestroyCursor(m_hDragCursor);
	::DestroyCursor(m_hNoDragCursor);
	m_hDragCursor = 0;
	m_hNoDragCursor = 0;

	if( m_nDragButton >= 0 ) {
		CToolBarCtrl & wndTBCtrl = GetToolBarCtrl();
		register const int nBtn = wndTBCtrl.GetButtonCount();

		if( m_bDragCursor && bDoMove ) {
			// move the button to a different location

			// make sure the last "DragMove()" has done its work correctly:
			ASSERT(m_pDropBar != 0);
			ASSERT_KINDOF(CToolBarEx, m_pDropBar);
			ASSERT(::GetWindowLong(m_pDropBar->GetToolBarCtrl()
									.GetSafeHwnd(),GWL_STYLE) & CCS_ADJUSTABLE);

			// have a look for where to drop the button
			int nDropBtn = m_pDropBar->FindDropButton(m_ptDrop);
			TBBUTTON tbButton;
			memset(&tbButton, 0, sizeof(TBBUTTON)); // not the safest, but the easiest way
													// to zero out all members ;-)

			if( m_pDropBar == this ) {
				// move the button around, but stay on *this* toolbar
				if( nDropBtn == m_nDragButton+1 || (nDropBtn < 0 && m_nDragButton == nBtn-1) ) {
					// simply insert a separator before the dragged button,
					// if there is still none
					if( m_nDragButton > 0 && !IsSeparator(m_nDragButton-1) ) {
						tbButton.iBitmap = 8;
						tbButton.fsState = TBSTATE_ENABLED;
						tbButton.fsStyle = TBSTYLE_SEP;
						if( DoQueryInsert(tbButton, m_nDragButton) )
							wndTBCtrl.InsertButton(m_nDragButton, &tbButton);
					}
				} else if( nDropBtn == m_nDragButton && m_nDragButton > 0 ) {
					// Remove the separator immediately before the dragged button.
					// if there is no such separator, then do nothing
					if( IsSeparator(nDropBtn-1) )
						if( DoQueryDelete(nDropBtn-1) )
							wndTBCtrl.DeleteButton(nDropBtn-1);
				} else {
					wndTBCtrl.GetButton(m_nDragButton, &tbButton);
					if( DoQueryInsert(tbButton, (nDropBtn>=0) ? nDropBtn : nBtn) ) {
						CWnd * pControl = 0;
						if( IsControl(m_nDragButton) ) {
							// Beware: The TB_DELETEBUTTON message causes the toolbar
							// to destroy the associated control.
							// To avoid this we temporary set the parent of the
							// control to NULL.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -