// XTPMiniToolBar.cpp : implementation of the CXTPMiniToolBar class. // // This file is a part of the XTREME COMMANDBARS MFC class library. // (c)1998-2012 Codejock Software, All Rights Reserved. // // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN // CONSENT OF CODEJOCK SOFTWARE. // // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A // SINGLE COMPUTER. // // CONTACT INFORMATION: // support@codejock.com // http://www.codejock.com // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPHookManager.h" #include "Common/XTPColorManager.h" #include "XTPCommandBarsDefines.h" #include "XTPCommandBar.h" #include "XTPPopupBar.h" #include "XTPPaintManager.h" #include "XTPMouseManager.h" #include "XTPMiniToolBar.h" #include "XTPControls.h" #include "XTPControl.h" #include "XTPControlButton.h" #include "XTPControlCustom.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef LWA_ALPHA #define LWA_ALPHA 0x00000002 #endif #ifndef WS_EX_LAYERED #define WS_EX_LAYERED 0x00080000 #endif ///////////////////////////////////////////////////////////////////////////// // CXTPMiniToolBar IMPLEMENT_XTP_COMMANDBAR(CXTPMiniToolBar, CXTPPopupToolBar); CXTPMiniToolBar::CXTPMiniToolBar() { m_pfnSetLayeredWindowAttributes = NULL; m_pfnUpdateLayeredWindow = NULL; HMODULE hLib = GetModuleHandle(_T("USER32")); if (hLib) { m_pfnSetLayeredWindowAttributes = (PFNSETLAYEREDWINDOWATTRIBUTES) ::GetProcAddress(hLib, "SetLayeredWindowAttributes"); m_pfnUpdateLayeredWindow = (LPFNUPDATELAYEREDWINDOW) GetProcAddress(hLib, "UpdateLayeredWindow"); } m_bActivated = FALSE; m_bTracking = FALSE; m_nOpacity = 0; m_pContextMenu = FALSE; m_bTrackOnHover = FALSE; m_bCustomControlKeyboardInteraction = FALSE; m_rcBorders = CRect(2, 2, 2, 2); m_szButtonSpacing = CSize(0, 3); } CXTPMiniToolBar::~CXTPMiniToolBar() { } void CXTPMiniToolBar::UpdateOpacity() { CXTPWindowRect rc(this); CPoint pt; GetCursorPos(&pt); int x = pt.x < rc.left ? rc.left - pt.x : pt.x > rc.right ? pt.x - rc.right : 0; int y = pt.y < rc.top ? rc.top - pt.y : pt.y > rc.bottom ? pt.y - rc.bottom : 0; int nLen = max(x, y); int nOpacity = 0; if (m_nPopuped != -1 || m_pContextMenu || IsTrackingMode() || nLen == 0) { nLen = 0; nOpacity = 255; } else if (!m_bActivated) { if (nLen < 17) nOpacity = 17 + (16 - nLen) * 14; } else { if (nLen < 90) nOpacity = MulDiv(255, 90 - nLen, 90); } if ((m_nOpacity != nOpacity)) { m_nOpacity = nOpacity; if (m_pfnSetLayeredWindowAttributes) { m_pfnSetLayeredWindowAttributes(m_hWnd, 0x00, (BYTE)nOpacity, LWA_ALPHA); } else { SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | (nOpacity > 20 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); } CXTPShadowManager* pShadowManager = GetPaintManager()->GetShadowManager(); POSITION pos = pShadowManager->GetHeadPosition(this); while (pos) { CWnd* pShadow = pShadowManager->GetNext(pos); if (m_pfnUpdateLayeredWindow) { BLENDFUNCTION bf; bf.BlendOp = AC_SRC_OVER; bf.BlendFlags = 0; bf.SourceConstantAlpha = (BYTE)nOpacity; bf.AlphaFormat = 0x01; m_pfnUpdateLayeredWindow(pShadow->GetSafeHwnd(), (HDC)0, 0, 0, 0, 0, 0, &bf, 0x02); } else { pShadow->SetWindowPos(0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | (nOpacity > 20 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); } } } if (m_nOpacity == 255) { m_bActivated = TRUE; } if (nLen > (m_bActivated ? 180 : 110)) { m_bTracking = FALSE; } } void CXTPMiniToolBar::Animate() { GetPaintManager()->SetCommandBarRegion(this); if (m_pfnSetLayeredWindowAttributes != 0) { ModifyStyleEx(0, WS_EX_LAYERED); } } BOOL CXTPMiniToolBar::TrackMiniBar(UINT nFlags, int x, int y) { CXTPMouseManager* pMouseManager = XTPMouseManager(); m_bActivated = FALSE; m_bTracking = TRUE; m_popupFlags = xtpPopupUp; m_nOpacity = 0; CWnd* pWnd = GetSite(); if (pWnd && pWnd->GetExStyle() & (WS_EX_LAYOUTRTL | WS_EX_RIGHT)) nFlags |= TPM_RIGHTALIGN; m_bExecOnRButton = nFlags & TPM_RIGHTBUTTON; m_popupFlags = (nFlags & TPM_RIGHTALIGN) ? xtpPopupLeft | xtpPopupUp : xtpPopupUp; pMouseManager->SendTrackLost(); ReleaseCapture(); if (!Popup(x, y, CRect(0, 0, 0, 0))) { return FALSE; } InternalAddRef(); SetTrackingMode(FALSE); UpdateOpacity(); PumpMessage(); DestroyWindow(); InternalRelease(); return TRUE; } BOOL CXTPMiniToolBar::TrackPopupMenu(CXTPPopupBar* pPopup, UINT nFlags, int x, int y) { ASSERT(pPopup); if (!pPopup) { return FALSE; } m_bActivated = TRUE; m_bTracking = TRUE; m_nOpacity = 0; m_popupFlags = xtpPopupUp; const UINT uMenuAndToolbarIdent = 15; // px CWnd* pWnd = GetSite(); if (pWnd && pWnd->GetExStyle() & (WS_EX_LAYOUTRTL | WS_EX_RIGHT)) nFlags |= TPM_RIGHTALIGN; UINT nReturn = TRUE; pPopup->m_pReturnCmd = NULL; if (nFlags & TPM_RETURNCMD) { pPopup->m_pReturnCmd = &nReturn; nReturn = 0; } m_bExecOnRButton = nFlags & TPM_RIGHTBUTTON; pPopup->m_bIgnoreUpdateHandler = nFlags & TPM_NONOTIFY; pPopup->m_bExecOnRButton = nFlags & TPM_RIGHTBUTTON; if (nFlags & TPM_RIGHTALIGN) { SetPopupFlags(xtpPopupLeft | xtpPopupUp); pPopup->SetPopupFlags(xtpPopupLeft | xtpPopupDown); } else { SetPopupFlags(xtpPopupUp); pPopup->SetPopupFlags(xtpPopupDown); } CXTPMouseManager* pMouseManager = XTPMouseManager(); pMouseManager->SendTrackLost(); ReleaseCapture(); pMouseManager->IgnoreLButtonUp(); if (!Create()) return FALSE; if (!pPopup->Create()) return FALSE; int nPopupWidth = pPopup->GetWidth(); int nMiniBarWidth = GetWidth(); CSize szMiniBar = CalcDynamicLayout(0, 0); CSize szPopupBar = pPopup->CalcDynamicLayout(0, 0); CPoint ptPopup(x, y); CRect rc = pPopup->CalculatePopupRect(ptPopup, szPopupBar); int nWidth = max(szMiniBar.cx, szPopupBar.cx); int nTop = rc.top - uMenuAndToolbarIdent; // default minibar position pPopup->SetWidth(nWidth); SetWidth(nWidth); CRect rcWorkArea = XTPMultiMonitor()->GetWorkArea(ptPopup); if (nTop < rcWorkArea.top) // ? { nTop = rc.bottom + uMenuAndToolbarIdent; m_popupFlags &= ~xtpPopupUp; } else if ( (y+szPopupBar.cy) >= rcWorkArea.bottom) // the menu popup goes up, we're in the bottom of the screen { nTop = rc.bottom + uMenuAndToolbarIdent + szMiniBar.cy; // minibar will be below popup if (nTop >= rcWorkArea.bottom) // the minibar is too tall to fit below, we need to place it above { nTop = y - szPopupBar.cy - uMenuAndToolbarIdent; } } else if ( (nTop-szMiniBar.cy) <= rcWorkArea.top ) // the minibar is too tall to fit above, we need to place it below { nTop = rc.bottom + uMenuAndToolbarIdent + szMiniBar.cy; // minibar goes below popup } if (!Popup(x, nTop, CRect(0, 0, 0, 0))) { return FALSE; } m_pContextMenu = pPopup; UpdateOpacity(); UpdateWindow(); if (!pPopup->Popup(x, y, CRect(0, 0, 0, 0))) { m_pContextMenu = NULL; return FALSE; } InternalAddRef(); PumpMessage(); SetWidth(nMiniBarWidth); pPopup->SetWidth(nPopupWidth); m_pContextMenu = NULL; DestroyWindow(); InternalRelease(); return nReturn; } BOOL CXTPMiniToolBar::OnHookKeyDown(UINT nChar, LPARAM lParam) { if (m_pContextMenu) return FALSE; return CXTPPopupToolBar::OnHookKeyDown(nChar, lParam); } BOOL CXTPMiniToolBar::SetTrackingMode(int bMode, BOOL bSelectFirst, BOOL bKeyboard) { return CXTPCommandBar::SetTrackingMode(bMode, bSelectFirst, bKeyboard); } void CXTPMiniToolBar::SetCustomControlKeyboardInteraction(BOOL bInteract /*= TRUE*/) { m_bCustomControlKeyboardInteraction = bInteract; } BOOL CXTPMiniToolBar::IsCustomControlKeyboardInteraction() const { return m_bCustomControlKeyboardInteraction; } BOOL CXTPMiniToolBar::CursorInWindow() const { CPoint pt; GetCursorPos(&pt); if (CXTPWindowRect(this).PtInRect(pt)) return TRUE; CXTPCommandBar* pCommandBar = XTPMouseManager()->HitTest(pt); if (!pCommandBar) return FALSE; return pCommandBar->GetRootParent() == (CXTPCommandBar*)this; } int CXTPMiniToolBar::OnHookMessage(HWND hWnd, UINT nMessage, WPARAM& wParam, LPARAM& lParam, LRESULT& lResult) { if (m_bTracking) { if (nMessage == WM_ENABLE || nMessage == WM_ACTIVATEAPP) { ShowWindow(SW_HIDE); m_bTracking = FALSE; } } return CXTPPopupToolBar::OnHookMessage(hWnd, nMessage, wParam, lParam, lResult); } void CXTPMiniToolBar::PumpMessage() { HWND hwndSite = GetSite()->m_hWnd; CWinThread* pThread = XTPGetThread(); XTPHookManager()->SetHook(hwndSite, this); HWND hWndTopLevelParent = hwndSite; while (GetWindowLong(hWndTopLevelParent, GWL_STYLE) & WS_CHILD) hWndTopLevelParent = ::GetParent(hWndTopLevelParent); if (hwndSite != hWndTopLevelParent) XTPHookManager()->SetHook(hWndTopLevelParent, this); while (m_bTracking) { MSG msg; if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (!m_bTracking) break; if (!m_pContextMenu) { if (msg.message == WM_MOUSEMOVE) { UpdateOpacity(); } if ((msg.message == WM_KEYDOWN || msg.message == WM_CHAR || msg.message == WM_SYSKEYDOWN || msg.message == WM_MOUSEWHEEL) && !IsTrackingMode()) { BOOL bDisableTrackingMode = TRUE; if (IsCustomControlKeyboardInteraction()) { // custom controls does not have appropriate keyboard hooks, so // we need to disable setting tracking mode to FALSE on them // thus keyboard interaction with a custom control will not close it int i=0, c = GetControlCount(); for (i = 0; iGetControl()->GetSafeHwnd() == msg.hwnd) { bDisableTrackingMode = FALSE; break; } } } if (bDisableTrackingMode) m_bTracking = FALSE; } if (msg.message == WM_CLOSE || msg.message == WM_SYSCOMMAND) { m_bTracking = FALSE; } if ((msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN || msg.message == WM_NCLBUTTONDOWN || msg.message == WM_NCRBUTTONDOWN) && !CursorInWindow()) { m_bTracking = FALSE; } } else { if (msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONDOWN || msg.message == WM_MBUTTONDOWN || msg.message == WM_NCLBUTTONDOWN || msg.message == WM_NCRBUTTONDOWN) { if (!CursorInWindow()) { CPoint point; GetCursorPos(&point); if (XTPMouseManager()->HitTest(point) == 0) m_bTracking = FALSE; } else { m_pContextMenu->SetTrackingMode(FALSE); m_pContextMenu = NULL; SetTrackingMode(FALSE); } } } if (msg.message == WM_ACTIVATE || msg.message == WM_ACTIVATEAPP || msg.message == WM_CAPTURECHANGED) { m_bTracking = FALSE; } if (m_pContextMenu && !m_pContextMenu->IsTrackingMode()) { ShowWindow(SW_HIDE); m_bTracking = FALSE; } if (!m_bTracking) break; if (!::GetMessage(&msg, NULL, 0, 0)) break; if (m_pContextMenu && !m_pContextMenu->IsTrackingMode()) { m_bTracking = FALSE; } if (!m_bTracking) { ::PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam); break; } if (msg.message != WM_KICKIDLE && !pThread->PreTranslateMessage(&msg)) { // process this message ::TranslateMessage(&msg); ::DispatchMessage(&msg); } pThread->OnIdle(-1); OnIdleUpdateCmdUI(TRUE, 0L); } else { WaitMessage(); } } if (hwndSite != hWndTopLevelParent) XTPHookManager()->RemoveHook(hWndTopLevelParent, this); XTPHookManager()->RemoveHook(hwndSite, this); } CXTPMiniToolBar* CXTPMiniToolBar::CreateMiniToolBar(CXTPCommandBars* pCommandBars) { CXTPMiniToolBar* pMiniToolBar = new CXTPMiniToolBar(); pMiniToolBar->SetCommandBars(pCommandBars); return pMiniToolBar; } INT_PTR CXTPMiniToolBar::OnToolHitTest(CPoint /*point*/, TOOLINFO* /*pTI*/) const { return -1; // No Tips. } BEGIN_MESSAGE_MAP(CXTPMiniToolBar, CXTPPopupToolBar) //{{AFX_MSG_MAP(CXTPMiniToolBar) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CXTPMiniToolBar message handlers