www.pudn.com > ToolBar.rar > ToolbarDialog.cpp


//   Author:      Lucian Barbulescu      lucian@xts.ro 
// 
//   Disclaimer 
//   ---------- 
//   THIS SOFTWARE AND THE ACCOMPANYING FILES ARE DISTRIBUTED "AS IS" AND WITHOUT 
//   ANY WARRANTIES WHETHER EXPRESSED OR IMPLIED. NO REPONSIBILITIES FOR POSSIBLE 
//   DAMAGES OR EVEN FUNCTIONALITY CAN BE TAKEN. THE USER MUST ASSUME THE ENTIRE 
//   RISK OF USING THIS SOFTWARE. 
// 
//   Terms of use 
//   ------------ 
//   THIS SOFTWARE IS FREE FOR PERSONAL USE OR FREEWARE APPLICATIONS. 
//   IF YOU USE THIS SOFTWARE IN COMMERCIAL OR SHAREWARE APPLICATIONS YOU 
//   MUST HAVE THE PERMISION OF THE AUTHOR. 
// 
// 
//	 History 
//   ------- 
// 
//   v1.0.0 - 7 April 2004		- First release 
//	 
//   v1.0.1 - 8 April 2004		- FIXED BUG: when toolbar is attached to the right or  
//                              the left no dragging possible by clicking on the handle 
//                              (thanks to ReorX for informing me about this bug) 
// 
//                              - FIXED BUG: when the floating toolbar is docked the  
//                              parent dialog does not receives the focus 
// 
//   v1.0.2 - 9 April 2004      - ADDED: VC6 compatibility 
//                              - ADDED: Tooltips support  
//                              (thanks to Randy More for his article about adding  
//                              tooltips to toolbars in dialogs) 
//                              - FIXED BUG: UPDATE_COMMAND_UI does not work  
//                              (thanks to =[ Abin ]= for informing me about this bug) 
 
#include "stdafx.h" 
#include  
#include "ToolbarDialog.h" 
 
// CSmartToolbar 
 
IMPLEMENT_DYNAMIC(CSmartToolbar, CToolBar) 
CSmartToolbar::CSmartToolbar() 
{ 
	m_bState = TS_HIDDEN; 
	m_bNoMove = false; 
} 
 
CSmartToolbar::~CSmartToolbar() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CSmartToolbar, CToolBar) 
	ON_WM_LBUTTONDOWN() 
	ON_WM_LBUTTONUP() 
	ON_WM_MOUSEMOVE() 
	ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI) 
END_MESSAGE_MAP() 
 
// CSmartToolbar message handlers 
 
LRESULT CSmartToolbar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM) 
{ 
	if (IsWindowVisible()) 
	{ 
		//CFrameWnd *pParent = (CFrameWnd *)GetParent(); 
		CFrameWnd *pParent = (CFrameWnd *)m_pMessageReceiver; 
		if (pParent) 
			OnUpdateCmdUI(pParent, (BOOL)wParam); 
	} 
	return 0L; 
} 
 
 
void CSmartToolbar::OnLButtonDown(UINT nFlags, CPoint point) 
{ 
	if(m_bState & TS_FIXED) 
	{ 
		int ht = GetToolBarCtrl().HitTest(&point); 
		if((ht < 0)||(ht >= GetToolBarCtrl().GetButtonCount())) 
		{ 
			SetCapture(); 
			CPoint newPoint = point; 
			this->MapWindowPoints(m_pMessageReceiver,&newPoint,1); 
			m_pMessageReceiver->SendMessage(TDM_BUTTONDOWN,WPARAM(0),LPARAM(&newPoint)); 
		} 
		else 
			m_bNoMove = true; 
	} 
 
	CToolBar::OnLButtonDown(nFlags, point); 
} 
 
void CSmartToolbar::OnLButtonUp(UINT nFlags, CPoint point) 
{ 
	if(m_bState & TS_FIXED) 
	{ 
		if(!m_bNoMove) 
		{ 
			ReleaseCapture(); 
			CPoint newPoint = point; 
			this->MapWindowPoints(m_pMessageReceiver,&newPoint,1); 
			m_pMessageReceiver->SendMessage(TDM_BUTTONUP,WPARAM(0),LPARAM(&newPoint)); 
		} 
		else 
			m_bNoMove = false; 
	} 
 
	CToolBar::OnLButtonUp(nFlags, point); 
} 
 
void CSmartToolbar::OnMouseMove(UINT nFlags, CPoint point) 
{ 
	if((m_bState & TS_FIXED) && !m_bNoMove && (nFlags & MK_LBUTTON)) 
	{ 
		CPoint newPoint = point; 
		this->MapWindowPoints(m_pMessageReceiver,&newPoint,1); 
		m_pMessageReceiver->SendMessage(TDM_MOUSEMOVE,WPARAM(0),LPARAM(&newPoint)); 
	} 
 
	CToolBar::OnMouseMove(nFlags, point); 
} 
 
void CSmartToolbar::Initialize(CWnd* pParent, UINT uTemplateID) 
{ 
	DWORD style = WS_CHILD|WS_VISIBLE|CBRS_FLYBY|CBRS_GRIPPER|CBRS_SIZE_DYNAMIC|CBRS_TOOLTIPS; 
 
	if(m_bState & TS_FIXED) 
		style|=(m_bState&TS_FIXED); 
	else 
		style|= TS_TOP; 
	CreateEx(pParent,TBSTYLE_FLAT,style); 
 
	LoadToolBar(IDR_TOOLBAR1); 
} 
 
void CSmartToolbar::UpdateToolbarStyle(DWORD dwStyle) 
{ 
	m_bState = dwStyle; 
 
	if(dwStyle == TS_HIDDEN) 
	{ 
		//hide the toolbar and return 
		ModifyStyle(WS_VISIBLE,0); 
		return; 
	} 
	else 
	{ 
		//ensure the toolbar is visible 
		ModifyStyle(0,WS_VISIBLE); 
	} 
 
	DWORD dwCurrentStyle = GetBarStyle(); 
 
	dwCurrentStyle &= ~(CBRS_ALIGN_ANY); 
	dwCurrentStyle &= ~(CBRS_BORDER_ANY); 
 
	//now decide where to place the toolbar 
	if(dwStyle == TS_FLOATING){ 
		SetBarStyle((dwCurrentStyle & ~CBRS_GRIPPER) | TS_TOP); 
	} 
	else{ 
		SetBarStyle(dwCurrentStyle | dwStyle | CBRS_GRIPPER); 
	} 
} 
 
 
// CFloatToolbarDlg 
 
IMPLEMENT_DYNAMIC(CFloatToolbarDlg, CWnd) 
CFloatToolbarDlg::CFloatToolbarDlg(CSmartToolbar* pToolbar) 
{ 
	m_pToolbar = pToolbar; 
	m_bMoving = false; 
 
} 
 
CFloatToolbarDlg::~CFloatToolbarDlg() 
{ 
} 
 
 
BEGIN_MESSAGE_MAP(CFloatToolbarDlg, CWnd) 
	ON_WM_CLOSE() 
	ON_WM_LBUTTONUP() 
	ON_WM_SETCURSOR() 
	ON_WM_MOUSEMOVE() 
	ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI) 
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText) 
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText) 
END_MESSAGE_MAP() 
 
 
 
// CFloatToolbarDlg message handlers 
 
 
BOOL CFloatToolbarDlg::ShowWindow(int nCmdShow) 
{ 
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0); 
	return CWnd::ShowWindow(nCmdShow); 
} 
 
void CFloatToolbarDlg::CreateToolDlg(CWnd* pParent) 
{ 
	BOOL bSuccess; 
 
	// Register window class 
	CString csClassName = AfxRegisterWndClass(CS_OWNDC|CS_HREDRAW|CS_VREDRAW, 
		::LoadCursor(NULL, IDC_APPSTARTING), 
		CBrush(::GetSysColor(COLOR_BTNFACE))); 
 
	SIZE sz; 
	m_pToolbar->GetToolBarCtrl().GetMaxSize(&sz); 
 
	// Create popup window 
	bSuccess = CreateEx(WS_EX_TOOLWINDOW,						// Extended style 
		csClassName,								// Classname 
		_T("Toolbar"),								// Title 
		WS_POPUP | WS_CAPTION | WS_SYSMENU ,   // style 
		0,0, 
		sz.cx+6,100, 
		pParent->GetSafeHwnd(),						// handle to parent 
		0,											// No menu 
		NULL);     
 
 
 
	CRect rWnd, rClient; 
	GetWindowRect(rWnd); 
	GetClientRect(rClient); 
 
	rWnd.bottom = rWnd.top + rWnd.Height() - rClient.Height() + sz.cy; 
 
	MoveWindow(rWnd); 
 
	CenterWindow(); 
 
} 
 
 
 
void CFloatToolbarDlg::OnClose() 
{ 
	GetParent()->SendMessage(TDM_FLOATCLOSE,WPARAM(0),LPARAM(0)); 
} 
 
LRESULT CFloatToolbarDlg::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM lParam) 
{ 
	SendMessageToDescendants(WM_IDLEUPDATECMDUI, 
		wParam, lParam, TRUE, TRUE); 
	return 0; 
} 
 
BOOL CFloatToolbarDlg::OnToolTipText(UINT nID, NMHDR* pNMHDR, LRESULT* pResult) 
{ 
	return (BOOL)(GetParent()->SendMessage(WM_NOTIFY,(WPARAM)nID,(LPARAM)pNMHDR)); 
} 
 
 
void CFloatToolbarDlg::OnLButtonUp(UINT nFlags, CPoint point) 
{ 
	// TODO: Add your message handler code here and/or call default 
 
	if(m_bMoving) 
	{ 
		m_bMoving = false; 
		ReleaseCapture(); 
		CPoint newPoint = point; 
		this->MapWindowPoints(GetParent(),&newPoint,1); 
		GetParent()->SendMessage(TDM_BUTTONUP,WPARAM(0),LPARAM(&newPoint)); 
	} 
 
	CWnd::OnLButtonUp(nFlags, point); 
} 
 
BOOL CFloatToolbarDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{ 
	if(message == WM_LBUTTONDOWN) 
	{ 
		if(nHitTest == HTCAPTION) 
		{ 
			m_bMoving = true; 
			SetCapture(); 
 
			ShowWindow(SW_HIDE); 
 
			CPoint pt; 
			GetCursorPos(&pt); 
			GetParent()->ScreenToClient(&pt); 
 
			GetParent()->SendMessage(TDM_BUTTONDOWN,WPARAM(0),LPARAM(&pt)); 
		} 
	} 
 
	return CWnd::OnSetCursor(pWnd, nHitTest, message); 
} 
 
void CFloatToolbarDlg::OnMouseMove(UINT nFlags, CPoint point) 
{ 
	if(nFlags & MK_LBUTTON) 
	{ 
		if(m_bMoving) 
		{ 
			CPoint newPoint = point; 
			this->MapWindowPoints(GetParent(),&newPoint,1); 
			GetParent()->SendMessage(TDM_MOUSEMOVE,WPARAM(0),LPARAM(&newPoint)); 
		} 
	} 
 
	CWnd::OnMouseMove(nFlags, point); 
} 
 
BOOL CFloatToolbarDlg::OnCommand(WPARAM wParam, LPARAM lParam) 
{ 
	HWND hWnd = m_pToolbar->m_hWnd; 
 
	if((LPARAM)hWnd == lParam) 
	{ 
		GetParent()->SendMessage(TDM_TOOLBTNPRESS,wParam,LPARAM(0)); 
	} 
 
 
	return CWnd::OnCommand(wParam, lParam); 
} 
 
 
 
 
// CToolbarDialog dialog 
 
IMPLEMENT_DYNAMIC(CToolbarDialog, CDialog) 
CToolbarDialog::CToolbarDialog(UINT uID, CWnd* pParent, UINT uToolbarID, DWORD dwToolbarState) 
	: CDialog(uID, pParent),m_ptOffset(0,0),m_ptDialogOffset(0,0), 
	m_rcOldToolRect(0,0,0,0) 
{ 
	m_pToolbar = new CSmartToolbar(); 
	m_pFloatToolbar = new CFloatToolbarDlg(m_pToolbar); 
	m_pToolbar->SetTolbarState(dwToolbarState); 
	m_uToolbarID = uToolbarID; 
	m_dwToolbarState = dwToolbarState; 
 
   WORD HatchBits[8] = { 0x11, 0x22, 0x44, 0x88, 0x11, 
      0x22, 0x44, 0x88 }; 
 
   // Use the bit pattern to create a bitmap. 
   CBitmap bm; 
   bm.CreateBitmap(8,8,1,1, HatchBits); 
 
   m_brBrush.CreatePatternBrush(&bm); 
} 
 
CToolbarDialog::~CToolbarDialog() 
{ 
	delete m_pFloatToolbar; 
	delete m_pToolbar; 
} 
 
void CToolbarDialog::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
} 
 
 
BEGIN_MESSAGE_MAP(CToolbarDialog, CDialog) 
	ON_WM_SIZE() 
	ON_MESSAGE(TDM_BUTTONDOWN,OnToolbarLButtonDown) 
	ON_MESSAGE(TDM_BUTTONUP,OnToolbarLButtonUp) 
	ON_MESSAGE(TDM_MOUSEMOVE,OnToolbarMouseMove) 
	ON_MESSAGE(TDM_FLOATCLOSE,OnFloatToolbarClose) 
	ON_MESSAGE(TDM_TOOLBTNPRESS,OnToolbarButtonPressed) 
	ON_MESSAGE(WM_KICKIDLE, OnKickIdle) 
END_MESSAGE_MAP() 
 
 
// CToolbarDialog message handlers 
 
 
 
BOOL CToolbarDialog::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
	m_pToolbar->Initialize(this, m_uToolbarID); 
	m_pToolbar->SetMessageReceiver(this); 
 
	m_pFloatToolbar->CreateToolDlg(this); 
 
	//initialy there is no toolbar 
	//so I have to "lie" the PositionToolbar function 
	//I set the "current state" to TS_HIDDEN 
	DWORD dwState = m_dwToolbarState; 
	m_dwToolbarState = TS_HIDDEN; 
	PositionToolbar(dwState); 
 
 
	return TRUE;  // return TRUE unless you set the focus to a control 
	// EXCEPTION: OCX Property Pages should return FALSE 
} 
 
void CToolbarDialog::OnSize(UINT nType, int cx, int cy) 
{ 
	CDialog::OnSize(nType, cx, cy); 
 
} 
 
LRESULT CToolbarDialog::OnKickIdle(WPARAM, LPARAM) 
{  
	if(m_pToolbar->GetParent() != this) 
		AfxCallWndProc(m_pFloatToolbar,m_pFloatToolbar->GetSafeHwnd(),WM_IDLEUPDATECMDUI,(WPARAM)FALSE, 0); 
	else 
        SendMessageToDescendants(WM_IDLEUPDATECMDUI,(WPARAM)FALSE, 0, TRUE, TRUE); 
	 
	return 0; 
} 
 
void CToolbarDialog::PositionToolbar(DWORD dwPosition) 
{	 
	//ensure the floating toolbar is hidden if this is required 
	if((dwPosition != TS_FLOATING) && (m_pToolbar->GetParent() == m_pFloatToolbar)) 
	{ 
		m_pFloatToolbar->ShowWindow(SW_HIDE); 
		m_pToolbar->SetParent(this); 
	} 
	m_pToolbar->UpdateToolbarStyle(dwPosition); 
	//based on the new style of the toolbar several actions have  
	//to be performed 
	 
	CPoint ptOffset(0,0); 
	CPoint ptDialogOffset(0,0); 
	if(dwPosition & TS_FIXED) 
	{ 
		//the offset of the controls and the new size of the dialog 
		//have to be computed 
		CRect rcClientStart; 
		CRect rcClientNow; 
		GetClientRect(rcClientStart); 
		RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 
					0, reposQuery, rcClientNow); 
 
		//ptOffset.SetPoint(rcClientNow.left - rcClientStart.left, 
		//				rcClientNow.top - rcClientStart.top); 
 
		ptOffset.x = rcClientNow.left - rcClientStart.left; 
		ptOffset.y = rcClientNow.top - rcClientStart.top; 
 
		//ptDialogOffset.SetPoint(rcClientStart.Width() - rcClientNow.Width(), 
		//					rcClientStart.Height() - rcClientNow.Height()); 
 
		ptDialogOffset.x = rcClientStart.Width() - rcClientNow.Width(); 
		ptDialogOffset.y = rcClientStart.Height() - rcClientNow.Height(); 
	} 
 
	// We need to resize the dialog to make room for control bars. 
	// First, figure out how big the control bars are. 
 
	//now we have to move the controls, but only if this is realy neaded 
 
	if((ptOffset - m_ptOffset) != CSize(0,0)) 
	{ 
		CRect  rcChild; 
		CWnd* pwndChild = GetWindow(GW_CHILD); 
		while (pwndChild) 
		{ 
			pwndChild->GetWindowRect(rcChild); 
			ScreenToClient(rcChild); 
			rcChild.OffsetRect(ptOffset - m_ptOffset); 
			pwndChild->MoveWindow(rcChild, TRUE); 
			pwndChild = pwndChild->GetNextWindow(); 
		} 
	} 
	 
	// Adjust the dialog window dimensions if this is realy neaded 
	if((ptDialogOffset - m_ptDialogOffset) != CSize(0,0)) 
	{ 
		CRect rcWindow; 
		GetWindowRect(rcWindow); 
		rcWindow.right += ptDialogOffset.x - m_ptDialogOffset.x; 
		rcWindow.bottom += ptDialogOffset.y - m_ptDialogOffset.y; 
 
		MoveWindow(rcWindow, TRUE); 
 
		RedrawWindow(); 
	} 
 
	//if the new style is TS_FLOATING, set the new parent of the toolbar 
	if(dwPosition == TS_FLOATING) 
	{ 
		m_pToolbar->SetParent(m_pFloatToolbar); 
 
		m_pFloatToolbar->ShowWindow(SW_SHOW); 
	} 
 
 
	m_ptDialogOffset = ptDialogOffset; 
	m_ptOffset = ptOffset; 
	 
	 
	// And position the control bars 
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); 
} 
 
LONG CToolbarDialog::OnToolbarLButtonDown(WPARAM wParam, LPARAM lParam) 
{ 
	CPoint* pPoint = (CPoint*)lParam; 
	CRect rcToolRect; 
 
	ComputeToolbarRect(*pPoint,&rcToolRect); 
 
	DrawToolRect(rcToolRect); 
 
	return 0; 
} 
 
LONG CToolbarDialog::OnToolbarMouseMove(WPARAM wParam, LPARAM lParam) 
{ 
	CPoint* pPoint = (CPoint*)lParam; 
	CRect rcToolRect; 
 
	//TRACE2("x=%d, y=%d \n",pPoint->x, pPoint->y); 
	ComputeToolbarRect(*pPoint,&rcToolRect); 
 
	DrawToolRect(rcToolRect); 
 
	return 0; 
} 
 
LONG CToolbarDialog::OnFloatToolbarClose(WPARAM wParam, LPARAM lParam) 
{ 
 
	m_dwToolbarState = TS_HIDDEN; 
 
	PositionToolbar(m_dwToolbarState); 
	return 0; 
} 
 
LONG CToolbarDialog::OnToolbarButtonPressed(WPARAM wParam, LPARAM lParam) 
{ 
	ToolbarButtonCommand(UINT(wParam)); 
	return 0; 
} 
 
 
LONG CToolbarDialog::OnToolbarLButtonUp(WPARAM wParam, LPARAM lParam) 
{ 
 
	PositionToolbar(m_dwToolbarState); 
	 
	if(m_dwToolbarState == TS_FLOATING) 
	{ 
		CRect rcWnd = m_rcOldToolRect; 
		ClientToScreen(rcWnd); 
		m_pFloatToolbar->MoveWindow(rcWnd); 
	} 
	else 
		SetFocus(); 
 
	DrawToolRect(CRect(0,0,0,0)); 
	 
	return 0; 
} 
 
void CToolbarDialog::ComputeToolbarRect(CPoint ptPoint, CRect* pToolRect) 
{ 
   SIZE sz; 
   m_pToolbar->GetToolBarCtrl().GetMaxSize(&sz); 
   long min, max; 
   min = sz.cx > sz.cy ? sz.cy : sz.cx;  
   max = sz.cx > sz.cy ? sz.cx : sz.cy; 
 
   pToolRect->SetRect(0,0,0,0); 
 
   CRect chRect; 
   GetClientRect(chRect); 
 
   if(ptPoint.y <= (chRect.top + 30)) 
   { 
      //the rectangle is a horisontal one 
      pToolRect->right = max; 
      pToolRect->bottom = min; 
	  m_dwToolbarState = TS_TOP; 
   } 
   else if(ptPoint.y >= (chRect.bottom - 30)) 
   { 
      //the rectangle is a horisontal one 
      pToolRect->right = max; 
      pToolRect->bottom = min; 
	  m_dwToolbarState = TS_BOTTOM; 
   } 
   else if(ptPoint.x <= (chRect.left + 30)) 
   { 
      //the rectangle is a vertical one 
      pToolRect->right = min; 
      pToolRect->bottom = max; 
	  m_dwToolbarState = TS_LEFT; 
   } 
   else if(ptPoint.x >= (chRect.right - 30)) 
   { 
      //the rectangle is a vertical one 
      pToolRect->right = min; 
      pToolRect->bottom = max; 
	  m_dwToolbarState = TS_RIGHT; 
   } 
   else 
   { 
      CRect rcFloatRect; 
	  m_pFloatToolbar->GetWindowRect(rcFloatRect); 
 
      pToolRect->right = rcFloatRect.Width(); 
      pToolRect->bottom = rcFloatRect.Height(); 
 
	  m_dwToolbarState = TS_FLOATING; 
   } 
 
   pToolRect->OffsetRect(ptPoint); 
} 
 
void CToolbarDialog::DrawToolRect(CRect rcToolRect) 
{ 
	//erase the old rectangle 
	RedrawWindow(m_rcOldToolRect); 
 
	//if the new Tool Rect is 0,0,0,0, do not draw it 
	if(rcToolRect != CRect(0,0,0,0)) 
	{ 
		CDC* pDC = GetDC(); 
 
		pDC->FrameRect(rcToolRect,&m_brBrush); 
 
		ReleaseDC(pDC); 
	} 
 
	m_rcOldToolRect = rcToolRect; 
 
} 
 
BOOL CToolbarDialog::OnCommand(WPARAM wParam, LPARAM lParam) 
{ 
	HWND hWnd = m_pToolbar->m_hWnd; 
 
	if((LPARAM)hWnd == lParam) 
	{ 
		OnToolbarButtonPressed(wParam,LPARAM(0)); 
	} 
 
	return CDialog::OnCommand(wParam, lParam); 
} 
 
 
//this function must be implemented in your class 
LONG CToolbarDialog::ToolbarButtonCommand(UINT uButtonID) 
{ 
	MessageBox("I am a ToolBar!"); 
	return 0; 
}