我们可以用CFrameWnd的EnableDocking让控制栏可停靠,但我们在CFrameWnd中却找不到DisableDocking之类的函数来移除控制栏的可停靠特性。那我们如何实现IE和Explore那样的锁定/解锁工具栏的功能呢?
MFC中并没有锁定/解锁控制栏的实现代码,那我们可不可以根据CFrameWnd::EnableDocking/CControlBar::EnableDocking的实现代码来实现DisableDocking的功能呢?我们发现CFrameWnd::EnableDocking和CControlBar::EnableDocking的实现代码相当难懂,想通过这种方式就要求我们对MFC的很多内部机制实现了解得很清楚才行(dwDockBarMap是?),非常困难。有没有更简单的方法呢?
我们可以想到的办法就是当工具栏被锁定后拦截会引用拖动的所有鼠标事件?我们需要拦截什么鼠标事件呢?在CControlBar的实现中我们可以找到答案;
void CControlBar::OnLButtonDown(UINT nFlags, CPoint pt)
{
// only start dragging if clicked in "void" space
if (m_pDockBar != NULL && OnToolHitTest(pt, NULL) == -1)
{
// start the drag

}
else
{
CWnd::OnLButtonDown(nFlags, pt);
}
}void CControlBar::OnLButtonDblClk(UINT nFlags, CPoint pt)
{
// only toggle docking if clicked in "void" space
if (m_pDockBar != NULL && OnToolHitTest(pt, NULL) == -1)
{
// start the drag

}
else
{
CWnd::OnLButtonDblClk(nFlags, pt);
}
}可以看到当在WM_LBUTTONDOWN和WM_LBUTTONDBCLK事件中并且OnToolHitTest(pt, NULL) == -1的时候将开始拖动,如果我过滤这两个事件,并判断OnToolHitTest的结果就可以阻止控制栏的拖动了。下面给出以ToolBar为例的实现代码
//------------------------------------------------------------------------------
// File:  LockToolBar.h
//
// Desc: A lockable/unlockable toolbar.
//
// Copyright (c) 2004 DentistryDoctor.  All rights reserved.
//------------------------------------------------------------------------------
// CLockToolBarclass CLockToolBar : public CToolBar
{
DECLARE_DYNAMIC(CLockToolBar)public:
CLockToolBar();
virtual ~CLockToolBar();
void SetLocked(BOOL bLocked=TRUE);
BOOL GetLocked() const
{
return m_bLocked;
}protected:
DECLARE_MESSAGE_MAP()
virtual BOOL PreTranslateMessage(MSG* pMsg);
BOOL m_bLocked;
};//------------------------------------------------------------------------------
// File:  LockToolBar.cpp
//
// Desc: A lockable/unlockable toolbar.
//
// Copyright (c) 2004 DentistryDoctor.  All rights reserved.
//------------------------------------------------------------------------------#include "stdafx.h"
#include "LockToolBar.h"// CLockToolBarIMPLEMENT_DYNAMIC(CLockToolBar, CToolBar)
CLockToolBar::CLockToolBar() : m_bLocked(FALSE)
{
}CLockToolBar::~CLockToolBar()
{
}BEGIN_MESSAGE_MAP(CLockToolBar, CToolBar)
END_MESSAGE_MAP()// CLockToolBar Message handle functions/////////////////////////////////////////////////void CLockToolBar::SetLocked(BOOL bLocked)
{
CFrameWnd* pFrame = GetParentFrame();
ASSERT(pFrame); m_bLocked = bLocked;
DWORD dwStyle = GetBarStyle();
if (bLocked) {
pFrame->DockControlBar(this);  // dock if not already
dwStyle &= ~CBRS_GRIPPER; // turn off gripper
} else {
dwStyle |= CBRS_GRIPPER;
}
SetBarStyle(dwStyle);
pFrame->RecalcLayout(); // make frame recalc toolbar sizes
}BOOL CLockToolBar::PreTranslateMessage(MSG* pMsg)
{
UINT msg = pMsg->message;
LPARAM lp = pMsg->lParam;
if ((pMsg->hwnd==GetSafeHwnd() || CWnd::FromHandle(pMsg->hwnd)->GetParent()==this) && (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONDBLCLK) && m_bLocked) 
{
CPoint pt(lp);
if (OnToolHitTest(pt, NULL) == -1)
return TRUE;
}
return CToolBar::PreTranslateMessage(pMsg);
}这样用CLockToolBar代替CToolBar就可以实现锁定/解锁的功能了。