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

📄 toolbarex.cpp

📁 很简单的小程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	// have a look for wether 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;
}

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 =	(pWnd &&
					pWnd->IsKindOf(RUNTIME_CLASS(CToolBarEx)) &&
					(::GetWindowLong(((CToolBarEx*)pWnd)->GetToolBarCtrl()
									.GetSafeHwnd(),GWL_STYLE) & CCS_ADJUSTABLE))
					? TRUE : FALSE;
	
	// If the window under the cursor is not a toolbar, then
	// check wether this window is a child of a toolbar.
	while( ! bToolBar && (pWnd = pWnd->GetParent()) != 0 )
		bToolBar =	(pWnd->IsKindOf(RUNTIME_CLASS(CToolBarEx)) &&
					(::GetWindowLong(((CToolBarEx*)pWnd)->GetToolBarCtrl()
									.GetSafeHwnd(),GWL_STYLE) & CCS_ADJUSTABLE))
					? TRUE : FALSE;

	// check wether 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.
							pControl = GetControl(m_nDragButton);
							VERIFY(pControl != 0);
							pControl->SetParent(0);
						}

						if( nDropBtn >= 0 )
							// have to insert
							wndTBCtrl.InsertButton(nDropBtn, &tbButton);
						else
							// append the button
							wndTBCtrl.AddButtons(1, &tbButton);

						// delete the button at its original location
						// we do not need to ask the owner, because this
						// was already done in "BeginDrag()"
						wndTBCtrl.DeleteButton(
							(m_nDragButton < nDropBtn || nDropBtn < 0)
								? m_nDragButton
								: m_nDragButton+1
						);

						// Reconnect the control (if any)
						if( pControl )
							pControl->SetParent(this);

						if( m_nDragButton == wndTBCtrl.GetButtonCount()-1 )
							// remove trailing separators too
							RemoveTrailingSeparators();
					}
				}
			} else {
				// move the button to a different toolbar

				wndTBCtrl.GetButton(m_nDragButton, &tbButton);
				CToolBarCtrl & wndDropTBCtrl = m_pDropBar->GetToolBarCtrl();

				if( m_pDropBar->DoQueryInsert(tbButton, (nDropBtn>=0) ? nDropBtn : wndDropTBCtrl.GetButtonCount()) ) {
					// Get the bitmap of the dragged button and resize it to
					// the image-size of the destination-bar.
					int nDestBitmap = 0;
					if( IsControl(m_nDragButton) ) {
						CRect rc;
						GetItemRect(m_nDragButton, rc);
						nDestBitmap = rc.Width();
					} else {
						HBITMAP hBmp = GetBitmap(tbButton.iBitmap, m_pDropBar->m_sizeImage);
						CBitmap bmp;
						if( hBmp ) {
							bmp.Attach(hBmp);
							nDestBitmap = wndDropTBCtrl.AddBitmap(1, &bmp);
						}
					}
					tbButton.iBitmap = nDestBitmap;
					//tbButton.iString = nDestString;
					tbButton.iString = -1;
					BOOL bInsertOK;
					if( nDropBtn >= 0 )
						bInsertOK = wndDropTBCtrl.InsertButton(nDropBtn, &tbButton);
					else
						bInsertOK = wndDropTBCtrl.AddButtons(1, &tbButton);

					if( bInsertOK ) {
						// transfer the string too, if any (check target first)
						if( m_pDropBar->HasButtonText() && HasButtonText() )
						{
							// let the CToolBar class do all the leg work
							m_pDropBar->SetButtonText(
								m_pDropBar->CommandToIndex(tbButton.idCommand),
								GetButtonText(m_nDragButton)
							);
						}
						// check wether the dragged button was a control in real life and
						// - if so - move that control to its new parent.
						CheckMoveControl(m_pDropBar, tbButton);

						wndTBCtrl.DeleteButton(m_nDragButton);

						if( m_nDragButton == wndTBCtrl.GetButtonCount()-1 )
							// remove trailing separators too
							RemoveTrailingSeparators();

						m_pDropBar->RecalcLayout();
					}
				}
			}
		} else {
			// remove the button from the toolbar
			if( bDoMove ) {
				wndTBCtrl.DeleteButton(m_nDragButton);

				if( m_nDragButton == wndTBCtrl.GetButtonCount() )
					// remove trailing separators too
					RemoveTrailingSeparators();
			} else
				// User has aborted the drag-operation.
				// Remove the drag-border from the button
				InvalidateButton(m_nDragButton);
		}

		// Recalculate the size of the bar.and the parent
		RecalcLayout();
	}

	m_bDragging = FALSE;

	// mouse capture is not longer needed
	ReleaseCapture();
}


void CToolBarEx :: CheckMoveControl( CToolBarEx * pToolBar, const TBBUTTON & tbButton ) {
	ASSERT_VALID(pToolBar);
	CWnd * pControl = GetControl(tbButton.idCommand, TRUE);
	if( pControl ) {
		// now change the parent of the control, so that it jumps to the
		// other toolbar
		pControl->SetParent(pToolBar);

		// remove the control from our list (if it's present there) and
		// add it to the target's list
		if( m_pControls ) {
			POSITION pos = m_pControls->Find(pControl);
			if(pos) {
				m_pControls->RemoveAt(pos);
				if( ! pToolBar->m_pControls )
					pToolBar->m_pControls = new CObList();
				pToolBar->m_pControls->AddTail(pControl);
			}
		}
	}
}


void CToolBarEx :: RemoveTrailingSeparators() {
	CToolBarCtrl & wndTBCtrl = GetToolBarCtrl();
	register const int nBtn = wndTBCtrl.GetButtonCount();
	register int i = nBtn;
	while( i && IsSeparator(--i) )
		if( DoQueryDelete(i) )
			wndTBCtrl.DeleteButton(i);
}

int CToolBarEx :: FindDropButton( const CPoint & point ) {
	CPoint pt = point;
	ScreenToClient(&pt);

	CRect rc;
	// find the button which is closest to the cursor
	register const int nBtn = GetToolBarCtrl().GetButtonCount();
	for( register int i = 0 ; i < nBtn ; ++i ) {
		GetItemRect(i, rc);
		if( rc.PtInRect(pt) )
			// insert the button to drop before this button:
			return (pt.x - rc.left < rc.right - pt.x)
					? i
					: ((i==nBtn-1)
						? -1
						: i+1);
	}
	
	// have to append the button
	return -1;
}

void CToolBarEx :: GetMarkerRect( int nButton, CRect & rc ) {
	register const int nBtn = GetToolBarCtrl().GetButtonCount();
	if( nButton < 0 || nButton > nBtn ) {
		// set the marker behind the last button
		GetItemRect(nBtn-1, rc);
		rc.right += 3;
		rc.left = rc.right-6;
	} else {
		// set the marker before the given button
		GetItemRect(nButton, rc);
		rc.left -= 3;
		rc.right = rc.left+6;
	}
	rc.DeflateRect(0,1);
}

void CToolBarEx :: ShowMarker( const CRect & rcMarker, CBitmap & bmpArea ) {
	ASSERT( bmpArea.GetSafeHandle() == 0 );

	CClientDC  WinDC(this);
	CDC MemDC; MemDC.CreateCompatibleDC(&WinDC);

	bmpArea.CreateCompatibleBitmap(&WinDC, rcMarker.Width(), rcMarker.Height());
	CBitmap * pOldBmp = MemDC.SelectObject(&bmpArea);

	CPen pen(PS_SOLID, 1, RGB(0,0,0));
	CPen * pOldPen = WinDC.SelectObject(&pen);

	// save original area:
	MemDC.BitBlt(0,0,rcMarker.Width(),rcMarker.Height(),
				&WinDC, rcMarker.left, rcMarker.top, SRCCOPY);

	WinDC.MoveTo(rcMarker.TopLeft());
	WinDC.LineTo(rcMarker.right, rcMarker.top);
	WinDC.MoveTo(rcMarker.left+1, rcMarker.top+1);
	WinDC.LineTo(rcMarker.right-1, rcMarker.top+1);

	WinDC.MoveTo(rcMarker.left+2, rcMarker.top+2);
	WinDC.LineTo(rcMarker.left+2, rcMarker.bottom-2);
	WinDC.MoveTo(rcMarker.left+3, rcMarker.top+2);
	WinDC.LineTo(rcMarker.left+3, rcMarker.bottom-2);

	WinDC.MoveTo(rcMarker.left, rcMarker.bottom-1);
	WinDC.LineTo(rcMarker.right, rcMarker.bottom-1);
	WinDC.MoveTo(rcMarker.left+1, rcMarker.bottom-2);
	WinDC.LineTo(rcMarker.right-1, rcMarker.bottom-2);

	MemDC.SelectObject(pOldBmp);
	MemDC.DeleteDC();
	WinDC.SelectObject(pOldPen);
}

void CToolBarEx :: RestoreMarker( const CRect & rcArea, CBitmap & bmpArea ) {
	if( bmpArea.GetSafeHandle() == 0 )
		return;

	CClientDC  WinDC(this);
	CDC MemDC; MemDC.CreateCompatibleDC(&WinDC);

	CBitmap * pOldBmp = MemDC.SelectObject(&bmpArea);
	WinDC.BitBlt(rcArea.left, rcArea.top, rcArea.Width(), rcArea.Height(),
				&MemDC, 0, 0, SRCCOPY);

	MemDC.SelectObject(pOldBmp);
	MemDC.DeleteDC();
}

void CToolBarEx :: SetMarker( CToolBarEx * pBar, const CPoint & point ) {
	static CToolBarEx * pLastToolBar = 0;
	static CRect lastRect(0,0,0,0);
	static CBitmap bmpLastSavedArea;

	CRect rcMarker;

	// retrieve proposed rectangle for the marker
	if( pBar != 0 ) {
		int nDropBtn = pBar->FindDropButton(point);
		pBar->GetMarkerRect(nDropBtn, rcMarker);

		if(rcMarker == lastRect)
			return;		// don't need to erase/draw
	}

	// restore the previously marked area:
	if( pLastToolBar ) {
		pLastToolBar->RestoreMarker(lastRect, bmpLastSavedArea);
		bmpLastSavedArea.DeleteObject();
	}

	// draw the marker
	if( pBar != 0 ) {
		pBar->ShowMarker(rcMarker, bmpLastSavedArea);
		lastRect = rcMarker;
	}
	pLastToolBar = pBar;
}

BOOL CToolBarEx :: DoQueryDelete(int nButton) {
	ASSERT(nButton >= 0);

	TBBUTTON tbButton;
	if( ! GetToolBarCtrl().GetButton(nButton, &tbButton) ) {
		TRACE1("CToolBarEx::DoQueryDelete(): could not retrieve button %d\n", nButton);
		return FALSE;
	}

	return QueryDeleteInsert(tbButton, TRUE, nButton);
}

BOOL CToolBarEx :: QueryDeleteInsert(TBBUTTON & tbButton, BOOL bDelete, int nIndex) {
	TBNOTIFY tbn;
	memset(&tbn, 0, sizeof(TBNOTIFY));
	tbn.hdr.hwndFrom = GetSafeHwnd();
	tbn.hdr.idFrom = UINT(::GetWindowLong(tbn.hdr.hwndFrom, GWL_ID));
	tbn.hdr.code = bDelete ? TBN_QUERYDELETE : TBN_QUERYINSERT;
	tbn.iItem = nIndex;
	memcpy((void *)(&tbn.tbButton), (const void *)(&tbButton), sizeof(TBBUTTON));

	CString strText;
	if( bDelete ) {
		strText = GetButtonText(nIndex);
		tbn.cchText = strText.GetLength();
		tbn.pszText = strText.GetBuffer(tbn.cchText);
	}

	ASSERT(GetParentFrame() != 0);
	ASSERT(::IsWindow(GetParentFrame()->GetSafeHwnd()));

	BOOL bRet = GetParentFrame()->SendMessage(
					WM_NOTIFY,
					WPARAM(tbn.hdr.idFrom),
					LPARAM(&tbn)
				);
	
	if( bDelete )
		strText.ReleaseBuffer();

	return bRet;
}

void CToolBarEx::OnCaptureChanged(CWnd *pWnd) 
{
	if( m_bDragging )
		// without the mouse-capture we cannot complete the drag-operation
		EndDrag(FALSE);

	CToolBar::OnCaptureChanged(pWnd);
}


BOOL CToolBarEx :: PreTranslateMessage( MSG * pMsg ) {
	if( m_bDragging &&
		(pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP) && 
		int(pMsg->wParam) == VK_ESCAPE ) {

		// user pressed ESC to abort drag operation
		EndDrag(FALSE);
		return TRUE;
	}
	return CToolBar::PreTranslateMessage(pMsg);
}

void CToolBarEx::OnParentNotify(UINT message, LPARAM lParam) 
{
	if( LOWORD(message) == WM_LBUTTONDOWN && (::GetAsyncKeyState(VK_MENU) & (1<<15)) ) {
		// I see no chance to abort the child's message processing.
		// That's why we set a flag here. If we lose the focus (a click
		// in a child's area will activate that child window), then
		// we start the real drag-operation (that would return the
		// focus to the toolbar).
		// This solution is somewhat obfuscated, so if you know of
		// a better way -- let me know.
		m_bDragChild = TRUE;
		SetFocus();
	}

	CToolBar::OnParentNotify(message, lParam);
}

void CToolBarEx::OnKillFocus(CWnd* pNewWnd) 
{
	CToolBar::OnKillFocus(pNewWnd);
	
	if( m_bDragChild ) {
		// See OnParentNotify() above ...
		m_bDragChild = FALSE;
		if( GetCapture() != this )
			BeginDrag();
	}
}

⌨️ 快捷键说明

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