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; }