📄 toolbarex.cpp
字号:
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 whether 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();
}
}
/////////////////////////////////////////////////////////////////////////////
// helpers for docking
/////////////////////////////////////////////////////////////////////////////
// We need our own version of a dock bar, because the original
// MFC implementation overlapps toolbars. CToolBarEx don't want
// such a overlapping, because this makes it impossible to draw
// a real 3d border ...
class CToolDockBar : public CDockBar {
DECLARE_DYNAMIC(CToolDockBar)
public:
// this is the one and only method of interest
virtual CSize CalcFixedLayout(BOOL bStretch, BOOL bHorz);
};
IMPLEMENT_DYNAMIC(CToolDockBar, CDockBar);
CSize CToolDockBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
ASSERT_VALID(this);
CSize sizeFixed = CControlBar::CalcFixedLayout(bStretch, bHorz);
// get max size
CSize sizeMax;
if (!m_rectLayout.IsRectEmpty())
sizeMax = m_rectLayout.Size();
else
{
CRect rectFrame;
CFrameWnd* pFrame = GetParentFrame();
pFrame->GetClientRect(&rectFrame);
sizeMax = rectFrame.Size();
}
// prepare for layout
AFX_SIZEPARENTPARAMS layout;
layout.hDWP = m_bLayoutQuery ?
NULL : ::BeginDeferWindowPos(m_arrBars.GetSize());
int cxBorder = 2, cyBorder = 2;
CPoint pt(-cxBorder, -cyBorder);
int nWidth = 0;
BOOL bWrapped = FALSE;
// layout all the control bars
for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
{
CControlBar* pBar = GetDockedControlBar(nPos);
void* pVoid = m_arrBars[nPos];
if (pBar != NULL)
{
if(pBar->IsKindOf(RUNTIME_CLASS(CToolBarEx)) && ((CToolBarEx*)pBar)->IsFlatLook())
((CToolBarEx*)pBar)->m_bReal3DBorder = TRUE,
cxBorder = cyBorder = 0;
else if(pBar->IsKindOf(RUNTIME_CLASS(CToolBarEx)) && !((CToolBarEx*)pBar)->IsFlatLook())
((CToolBarEx*)pBar)->m_bReal3DBorder = FALSE,
cxBorder = cyBorder = 2;
else
cxBorder = cyBorder = 2;
if (pBar->IsVisible())
{
// get ideal rect for bar
DWORD dwMode = 0;
if ((pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) &&
(pBar->m_dwStyle & CBRS_FLOATING))
dwMode |= LM_HORZ | LM_MRUWIDTH;
else if (pBar->m_dwStyle & CBRS_ORIENT_HORZ)
dwMode |= LM_HORZ | LM_HORZDOCK;
els
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -