MFC toolbar上添加控件
// CEditBar.h
// 可调用InsertControl向工具栏添加控件,调用HideButton来隐藏button或控件
Code
class CEditorBar : public CToolBar
{
public:
CEditorBar();
virtual ~CEditorBar();
BOOL m_bHideChildWndOnVertical; // Hide the windows when docked vertical
BOOL CreateEx(CWnd* pParentWnd,DWORD dwCtrlStyle = TBSTYLE_FLAT,DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP);
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
CWnd* InsertControl(CRuntimeClass* pClass,LPCTSTR lpszWindowName,CRect& rect,UINT nID,DWORD dwStyle );
CWnd* InsertControl(CWnd* pCtrl,CRect& rect,UINT nID);
BOOL HideButton( int nID, BOOL bHide = TRUE );
protected:
CObList* m_pControls; // CObject pointer list which contains controls added to the toolbar
map<int, CWnd*> m_mapID2Ctrl;
BOOL IsVertDocked();
DECLARE_MESSAGE_MAP()
DECLARE_EVENTSINK_MAP()
};
class CEditorBar : public CToolBar
{
public:
CEditorBar();
virtual ~CEditorBar();
BOOL m_bHideChildWndOnVertical; // Hide the windows when docked vertical
BOOL CreateEx(CWnd* pParentWnd,DWORD dwCtrlStyle = TBSTYLE_FLAT,DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP);
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
CWnd* InsertControl(CRuntimeClass* pClass,LPCTSTR lpszWindowName,CRect& rect,UINT nID,DWORD dwStyle );
CWnd* InsertControl(CWnd* pCtrl,CRect& rect,UINT nID);
BOOL HideButton( int nID, BOOL bHide = TRUE );
protected:
CObList* m_pControls; // CObject pointer list which contains controls added to the toolbar
map<int, CWnd*> m_mapID2Ctrl;
BOOL IsVertDocked();
DECLARE_MESSAGE_MAP()
DECLARE_EVENTSINK_MAP()
};
// CEditBar.cpp
Code
/////////////////////////////////////////////////////////////////////////
// CEditorBar
CEditorBar::CEditorBar()
{
m_pControls = NULL;
}
CEditorBar::~CEditorBar()
{
if( m_pControls )
{
for( POSITION pos = m_pControls->GetHeadPosition() ; pos ; )
{
delete m_pControls->GetNext(pos);
}
delete m_pControls;
}
m_mapID2Ctrl.clear();
}
BOOL CEditorBar::CreateEx(CWnd* pParentWnd,DWORD dwCtrlStyle,DWORD dwStyle)
{
if (!CToolBar::CreateEx(pParentWnd,dwCtrlStyle,dwStyle) || !LoadToolBar(IDR_MAINFRAME))
return FALSE;
return TRUE;
}
// Since we're inside an ActiveX control, we don't own the message
// loop. Thus, the CWnd::PreTranslateMessage function is not called.
// As a result, we must manually call the FilterToolTipMessage()
// function to get tooltips. If you don't care about tooltips then
// you can remove this function from your toolbar.
BEGIN_MESSAGE_MAP(CEditorBar, CToolBar)
//{{AFX_MSG_MAP(CEditorBar)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_EVENTSINK_MAP(CEditorBar, CToolBar)
//{{AFX_EVENTSINK_MAP(CEditorBar)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
LRESULT CEditorBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
//AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//#ifndef _DEBUG
MSG msg;
msg.hwnd = m_hWnd;
msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
GetCursorPos(&msg.pt);
FilterToolTipMessage(&msg);
//#endif //_DEBUG
return CToolBar::WindowProc(message,wParam,lParam);
}
//Inserts a control into the toolbar at the given button id.
CWnd* CEditorBar::InsertControl( CRuntimeClass* pClass, LPCTSTR lpszWindowName, CRect& rect, UINT nID, DWORD dwStyle )
{
CWnd *pCtrl = NULL;
if( pClass->IsDerivedFrom( RUNTIME_CLASS( CSymbolCombo ))) // CComboBox control.
{
pCtrl = new CSymbolCombo;
ASSERT_VALID( pCtrl );
if(((CSymbolCombo*)pCtrl)->Create( WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
}else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CEdit ))) // CEdit control.
{
pCtrl = new CEdit;
ASSERT_VALID( pCtrl );
if(((CEdit*)pCtrl)->Create( WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
}
else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CButton ))) // CButton control.
{
pCtrl = new CButton;
ASSERT_VALID( pCtrl );
if(((CButton*)pCtrl)->Create( lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
}
else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CWnd ))) // CWnd object.
{
pCtrl = new CWnd;
ASSERT_VALID( pCtrl );
#ifdef _UNICODE
TCHAR szClassName[ 256 ];
MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pClass->m_lpszClassName,
-1,
szClassName,
255 );
if(((CWnd*)pCtrl)->Create( szClassName, lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
#else
if(((CWnd*)pCtrl)->Create( pClass->m_lpszClassName, lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
#endif
}
else // An invalid object was passed in
{
ASSERT( FALSE );
return NULL;
}
return InsertControl( pCtrl, rect, nID );
}
CWnd* CEditorBar::InsertControl(CWnd* pCtrl, CRect & rect, UINT nID)
{
ASSERT_VALID( pCtrl );
ASSERT(IsWindow(pCtrl->m_hWnd));
// make sure the id is valid, and set the button
// style for a seperator.
int nIndex = CommandToIndex( nID ) ;
if (nIndex>-1)
{
ASSERT( nIndex >= 0 );
SetButtonInfo( nIndex, nID, TBBS_SEPARATOR, rect.Width());
// insert the control into the toolbar.
GetItemRect( nIndex, &rect );
CRect rt;
pCtrl->GetWindowRect(&rt);
rect.top+=max((rect.Height()-rt.Height())/2,0); //move to middle
pCtrl->SetWindowPos(0, rect.left, rect.top, 0, 0,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS );
pCtrl->SetFont( GetFont( ));
BOOL bVert = IsVertDocked(); //(m_dwStyle & CBRS_ORIENT_VERT) != 0;
if (bVert && m_bHideChildWndOnVertical)
{
int nState=GetToolBarCtrl().GetState(nIndex);
GetToolBarCtrl().SetState(nID,(nState | TBSTATE_HIDDEN));
pCtrl->ShowWindow( SW_HIDE );
}
else
{
int nState=GetToolBarCtrl().GetState(nIndex);
GetToolBarCtrl().SetState(nIndex,(nState & ~TBSTATE_HIDDEN));
pCtrl->ShowWindow( SW_SHOW );
}
}
else
{
pCtrl->ShowWindow( SW_HIDE);
}
ModifyStyle(0,WS_CLIPCHILDREN);
// if our object list has not been allocated, do it now
if( m_pControls == NULL )
{
m_pControls = new CObList();
ASSERT( m_pControls );
}
// we have to remember this control, so we can delete it later
m_pControls->AddTail( pCtrl );
m_mapID2Ctrl[nID] = pCtrl;
return pCtrl;
}
// 支持运行时隐藏button或控件
BOOL CEditorBar::HideButton( int nID, BOOL bHide)
{
int ix = -1;
CRect rect;
BOOL bSuccess = FALSE;
CToolBarCtrl &toolbar = this->GetToolBarCtrl();
if (bHide) // to hide
{
ix = CommandToIndex(nID);
GetItemRect(ix, &rect);
bSuccess = toolbar.HideButton(nID, bHide);
}
else // to show
{
bSuccess = toolbar.HideButton(nID, bHide);
ix = CommandToIndex(nID);
GetItemRect(ix, &rect);
}
map<int, CWnd*> ::iterator iter = m_mapID2Ctrl.begin();
for( ; iter != m_mapID2Ctrl.end(); ++iter)
{
int nCtrlID = (*iter).first;
CWnd *pCtrl = (*iter).second;
int ixCtrl = this->CommandToIndex(nCtrlID);
// skip controls which are before this nID
if (ixCtrl <= ix)
{
continue;
}
if (pCtrl && ::IsWindow(pCtrl->m_hWnd) )
{
CRect rcCtrl;
pCtrl->GetWindowRect(&rcCtrl);
this->ScreenToClient(&rcCtrl);
int nLeft = rcCtrl.left;
if (bHide) // to hide
{
nLeft = rcCtrl.left - rect.Width();
}
else // to show
{
nLeft = rcCtrl.left + rect.Width();
}
pCtrl->SetWindowPos(0, nLeft, rcCtrl.top, 0, 0,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS );
}
}
return bSuccess;
}
BOOL CEditorBar::IsVertDocked()
{
UINT nID =GetParent()->GetDlgCtrlID();
return ( (nID ==AFX_IDW_DOCKBAR_LEFT) || (nID== AFX_IDW_DOCKBAR_RIGHT));
}
/////////////////////////////////////////////////////////////////////////
// CEditorBar
CEditorBar::CEditorBar()
{
m_pControls = NULL;
}
CEditorBar::~CEditorBar()
{
if( m_pControls )
{
for( POSITION pos = m_pControls->GetHeadPosition() ; pos ; )
{
delete m_pControls->GetNext(pos);
}
delete m_pControls;
}
m_mapID2Ctrl.clear();
}
BOOL CEditorBar::CreateEx(CWnd* pParentWnd,DWORD dwCtrlStyle,DWORD dwStyle)
{
if (!CToolBar::CreateEx(pParentWnd,dwCtrlStyle,dwStyle) || !LoadToolBar(IDR_MAINFRAME))
return FALSE;
return TRUE;
}
// Since we're inside an ActiveX control, we don't own the message
// loop. Thus, the CWnd::PreTranslateMessage function is not called.
// As a result, we must manually call the FilterToolTipMessage()
// function to get tooltips. If you don't care about tooltips then
// you can remove this function from your toolbar.
BEGIN_MESSAGE_MAP(CEditorBar, CToolBar)
//{{AFX_MSG_MAP(CEditorBar)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_EVENTSINK_MAP(CEditorBar, CToolBar)
//{{AFX_EVENTSINK_MAP(CEditorBar)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
LRESULT CEditorBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
//AFX_MANAGE_STATE( AfxGetStaticModuleState() );
//#ifndef _DEBUG
MSG msg;
msg.hwnd = m_hWnd;
msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
GetCursorPos(&msg.pt);
FilterToolTipMessage(&msg);
//#endif //_DEBUG
return CToolBar::WindowProc(message,wParam,lParam);
}
//Inserts a control into the toolbar at the given button id.
CWnd* CEditorBar::InsertControl( CRuntimeClass* pClass, LPCTSTR lpszWindowName, CRect& rect, UINT nID, DWORD dwStyle )
{
CWnd *pCtrl = NULL;
if( pClass->IsDerivedFrom( RUNTIME_CLASS( CSymbolCombo ))) // CComboBox control.
{
pCtrl = new CSymbolCombo;
ASSERT_VALID( pCtrl );
if(((CSymbolCombo*)pCtrl)->Create( WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
}else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CEdit ))) // CEdit control.
{
pCtrl = new CEdit;
ASSERT_VALID( pCtrl );
if(((CEdit*)pCtrl)->Create( WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
}
else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CButton ))) // CButton control.
{
pCtrl = new CButton;
ASSERT_VALID( pCtrl );
if(((CButton*)pCtrl)->Create( lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
}
else if( pClass->IsDerivedFrom( RUNTIME_CLASS( CWnd ))) // CWnd object.
{
pCtrl = new CWnd;
ASSERT_VALID( pCtrl );
#ifdef _UNICODE
TCHAR szClassName[ 256 ];
MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pClass->m_lpszClassName,
-1,
szClassName,
255 );
if(((CWnd*)pCtrl)->Create( szClassName, lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
#else
if(((CWnd*)pCtrl)->Create( pClass->m_lpszClassName, lpszWindowName, WS_CHILD|WS_VISIBLE|dwStyle, rect, this, nID ) == FALSE )
{
delete pCtrl;
return NULL;
}
#endif
}
else // An invalid object was passed in
{
ASSERT( FALSE );
return NULL;
}
return InsertControl( pCtrl, rect, nID );
}
CWnd* CEditorBar::InsertControl(CWnd* pCtrl, CRect & rect, UINT nID)
{
ASSERT_VALID( pCtrl );
ASSERT(IsWindow(pCtrl->m_hWnd));
// make sure the id is valid, and set the button
// style for a seperator.
int nIndex = CommandToIndex( nID ) ;
if (nIndex>-1)
{
ASSERT( nIndex >= 0 );
SetButtonInfo( nIndex, nID, TBBS_SEPARATOR, rect.Width());
// insert the control into the toolbar.
GetItemRect( nIndex, &rect );
CRect rt;
pCtrl->GetWindowRect(&rt);
rect.top+=max((rect.Height()-rt.Height())/2,0); //move to middle
pCtrl->SetWindowPos(0, rect.left, rect.top, 0, 0,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS );
pCtrl->SetFont( GetFont( ));
BOOL bVert = IsVertDocked(); //(m_dwStyle & CBRS_ORIENT_VERT) != 0;
if (bVert && m_bHideChildWndOnVertical)
{
int nState=GetToolBarCtrl().GetState(nIndex);
GetToolBarCtrl().SetState(nID,(nState | TBSTATE_HIDDEN));
pCtrl->ShowWindow( SW_HIDE );
}
else
{
int nState=GetToolBarCtrl().GetState(nIndex);
GetToolBarCtrl().SetState(nIndex,(nState & ~TBSTATE_HIDDEN));
pCtrl->ShowWindow( SW_SHOW );
}
}
else
{
pCtrl->ShowWindow( SW_HIDE);
}
ModifyStyle(0,WS_CLIPCHILDREN);
// if our object list has not been allocated, do it now
if( m_pControls == NULL )
{
m_pControls = new CObList();
ASSERT( m_pControls );
}
// we have to remember this control, so we can delete it later
m_pControls->AddTail( pCtrl );
m_mapID2Ctrl[nID] = pCtrl;
return pCtrl;
}
// 支持运行时隐藏button或控件
BOOL CEditorBar::HideButton( int nID, BOOL bHide)
{
int ix = -1;
CRect rect;
BOOL bSuccess = FALSE;
CToolBarCtrl &toolbar = this->GetToolBarCtrl();
if (bHide) // to hide
{
ix = CommandToIndex(nID);
GetItemRect(ix, &rect);
bSuccess = toolbar.HideButton(nID, bHide);
}
else // to show
{
bSuccess = toolbar.HideButton(nID, bHide);
ix = CommandToIndex(nID);
GetItemRect(ix, &rect);
}
map<int, CWnd*> ::iterator iter = m_mapID2Ctrl.begin();
for( ; iter != m_mapID2Ctrl.end(); ++iter)
{
int nCtrlID = (*iter).first;
CWnd *pCtrl = (*iter).second;
int ixCtrl = this->CommandToIndex(nCtrlID);
// skip controls which are before this nID
if (ixCtrl <= ix)
{
continue;
}
if (pCtrl && ::IsWindow(pCtrl->m_hWnd) )
{
CRect rcCtrl;
pCtrl->GetWindowRect(&rcCtrl);
this->ScreenToClient(&rcCtrl);
int nLeft = rcCtrl.left;
if (bHide) // to hide
{
nLeft = rcCtrl.left - rect.Width();
}
else // to show
{
nLeft = rcCtrl.left + rect.Width();
}
pCtrl->SetWindowPos(0, nLeft, rcCtrl.top, 0, 0,
SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS );
}
}
return bSuccess;
}
BOOL CEditorBar::IsVertDocked()
{
UINT nID =GetParent()->GetDlgCtrlID();
return ( (nID ==AFX_IDW_DOCKBAR_LEFT) || (nID== AFX_IDW_DOCKBAR_RIGHT));
}