// XTPMenuTitleBar.cpp : implementation of the CXTPMenuTitleBar class. // // (c)1998-2023 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 "CommandBars/Resource.h" #include "Common/XTPTypeId.h" #include "Common/XTPCasting.h" #include "Common/XTPFramework.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPSynchro.h" #include "Common/XTPApplication.h" #include "Common/XTPSingleton.h" #include "Common/XTPGdiObjects.h" #include "Common/XTPResourceManager.h" #include "Common/XTPImageManager.h" #include "Common/XTPHookManager.h" #include "Common/XTPSystemHelpers.h" #include "Common/XTPColorManager.h" #include "Common/ScrollBar/XTPScrollInfo.h" #include "Common/XTPDrawHelpers.h" #include "Common/XTPSystemMetrics.h" #include "Common/Hook/XTPWinEventHook.h" #include "Common/FrameShadow/XTPFrameShadowManager.h" #include "CommandBars/XTPCommandBarsDefines.h" #include "CommandBars/XTPPaintManager.h" #include "CommandBars/XTPCommandBar.h" #include "CommandBars/XTPCommandBars.h" #include "CommandBars/XTPCommandBarsOptions.h" #include "CommandBars/XTPToolBar.h" #include "CommandBars/XTPMenuBar.h" #include "CommandBars/XTPMenuTitleBar.h" #include "CommandBars/XTPControls.h" #include "CommandBars/XTPControl.h" #include "CommandBars/XTPControlButton.h" #include "CommandBars/XTPControlPopup.h" #include "CommandBars/XTPControlExt.h" #include "CommandBars/XTPCommandBars.h" #include "CommandBars/XTPMouseManager.h" #include "CommandBars/XTPPopupBar.h" #include "CommandBars/Frame/XTPFrameHook.h" #include "CommandBars/Frame/XTPFramePaintManager.h" #include "CommandBars/XTPCommandBarsIIDs.h" #include "Common/Base/Diagnostic/XTPDisableNoisyWarnings.h" #ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define ICON_SZ 21 class CXTPMenuTitleBarIcon : public CXTPControlLabel { DECLARE_DYNAMIC(CXTPMenuTitleBarIcon); private: CXTPImageManagerIcon* m_pIcon; CXTPImageManagerIconHandle m_icon; public: CXTPMenuTitleBarIcon() : m_pIcon(NULL) { SetStyle(xtpButtonIcon); SetIconSize(XTP_DPI_SIZE(CSize(ICON_SZ, ICON_SZ))); } CXTPMenuTitleBarIcon(CXTPImageManagerIcon* pIcon) : m_pIcon(pIcon) { SetStyle(xtpButtonIcon); SetIconSize(XTP_DPI_SIZE(CSize(ICON_SZ, ICON_SZ))); } protected: void Draw(CDC* pDC) { if (m_pIcon) { if (m_pIcon->IsRasterIcon()) m_pIcon->GetIcon().Draw(pDC, GetRect().TopLeft(), GetIconSize()); if (m_pIcon->IsVectorIcon()) m_pIcon->GetVectorIcon().Draw(pDC, GetRect().TopLeft(), GetIconSize()); } else { if (m_icon.IsEmpty()) { if (!GetIconId()) return; HICON hIcon = AfxGetApp()->LoadIcon(XTPToUInt(GetIconId())); if (!hIcon) return; m_icon.Attach(hIcon, TRUE); } m_icon.Draw(pDC, GetRect().TopLeft(), GetIconSize()); } } }; IMPLEMENT_DYNAMIC(CXTPMenuTitleBarIcon, CXTPControlLabel); class CXTPMenuTitleBarCaption : public CXTPControlLabel { DECLARE_DYNAMIC(CXTPMenuTitleBarCaption); private: int m_nCaptionLength; public: CXTPMenuTitleBarCaption() { m_nCaptionLength = 0; SetStyle(xtpButtonCaption); } void SetCaptionLength(int len) { m_nCaptionLength = len; } int GetCaptionLength() { return m_nCaptionLength; } protected: void Draw(CDC* pDC) { CXTPMenuTitleBar* pMenuTitleBar = (CXTPMenuTitleBar*)GetParent(); if (pMenuTitleBar == NULL) return; CXTPPaintManager* pPaintManager = pMenuTitleBar->GetPaintManager(); if (pPaintManager == NULL) return; CXTPFramePaintManager* pFramePaintManager = pPaintManager->GetFramePaintManager(); if (pFramePaintManager == NULL) return; CXTPFontDC fntdc(pDC, &pFramePaintManager->m_fntFrameCaption); pDC->FillSolidRect(GetRect(), pPaintManager->GetControlBackColor(this)); SetVisible(m_nCaptionLength <= GetRect().Width() ? TRUE : FALSE); CXTPControlLabel::Draw(pDC); } }; IMPLEMENT_DYNAMIC(CXTPMenuTitleBarCaption, CXTPControlLabel); class CXTPMenuTitleBarControlCaptionButton : public CXTPControlButton { DECLARE_DYNAMIC(CXTPMenuTitleBarControlCaptionButton); public: CXTPMenuTitleBarControlCaptionButton() { m_bTemporary = TRUE; SetFlags(xtpFlagNoMovable | xtpFlagSkipFocus | xtpFlagManualUpdate); } protected: void Draw(CDC* pDC) { CXTPMenuTitleBar* pMenuTitleBar = (CXTPMenuTitleBar*)GetParent(); if (pMenuTitleBar == NULL) return; CXTPCommandBars* pCommandBars = pMenuTitleBar->GetCommandBars(); if (pCommandBars == NULL) return; CXTPCommandBarsFrameHook* pFrameHook = pCommandBars->GetFrameHook(); if (pFrameHook == NULL) return; CXTPPaintManager* pPaintManager = pMenuTitleBar->GetPaintManager(); if (pPaintManager == NULL) return; CXTPFramePaintManager* pFramePaintManager = pPaintManager->GetFramePaintManager(); if (pFramePaintManager == NULL) return; BOOL bActive = m_bEnabled && pFrameHook->IsFrameActive(); pFramePaintManager->DrawFrameCaptionButton(pDC, GetRect(), GetID(), GetSelected(), GetPressed(), bActive, /*pMenuTitleBar*/ 0); } //----------------------------------------------------------------------- // Summary: // This member is called to set the bounding rectangle of the control. // Parameters: // rcControl - Bounding rectangle of the control. //----------------------------------------------------------------------- void SetRect(CRect rcControl) { CXTPControlButton::SetRect(rcControl); } void OnExecute() { GetParent()->GetSite()->PostMessage(WM_SYSCOMMAND, XTPToWPARAM(GetID()), 0); } virtual BOOL IsCustomizeMovable() const { return FALSE; } }; IMPLEMENT_DYNAMIC(CXTPMenuTitleBarControlCaptionButton, CXTPControlButton); IMPLEMENT_XTP_COMMANDBAR(CXTPMenuTitleBar, CXTPMenuBar) #include "Common/Base/Diagnostic/XTPBeginAfxMap.h" BEGIN_MESSAGE_MAP(CXTPMenuTitleBar, CXTPMenuBar) ON_WM_LBUTTONDOWN() ON_WM_RBUTTONDOWN() ON_WM_LBUTTONDBLCLK() END_MESSAGE_MAP() #include "Common/Base/Diagnostic/XTPEndAfxMap.h" CXTPMenuTitleBar::CXTPMenuTitleBar() : m_nIconID(-1) { m_bCustomizable = FALSE; } CXTPMenuTitleBar::~CXTPMenuTitleBar() { } BOOL CXTPMenuTitleBar::LoadMenuBar(UINT nIDResource) { _ASSERTE(m_pControls->GetCount() == 0); m_pControls->RemoveAll(); CXTPControl* pControl = NULL; CString strCaptionText; GetSite()->GetWindowText(strCaptionText); CClientDC dc(this); int nCaptionLength = dc.GetTextExtent(strCaptionText).cx; CXTPImageManagerIcon* pIcon = GetCommandBars()->GetImageManager()->GetImage(XTPToUInt(m_nIconID), XTP_DPI_X(ICON_SZ)); if (nIDResource != 0) { CMenu menu; if (!XTPResourceManager()->LoadMenu(&menu, nIDResource)) return FALSE; m_nIDResourceCurrent = m_nIDResource = nIDResource; pControl = m_pControls->Add(new CXTPMenuTitleBarIcon(pIcon), XTP_ID_MENUTITLEBAR_ICON, NULL, -1, TRUE); if (pControl) pControl->SetIconId(XTPToInt(m_nIDResource)); if (!m_pControls->LoadMenu(&menu)) return FALSE; pControl = m_pControls->Add(new CXTPMenuTitleBarCaption(), XTP_ID_MENUTITLEBAR_CAPTION, NULL, -1, TRUE); if (pControl) { CXTPMenuTitleBarCaption* pMenuTitleBarCaption = DYNAMIC_DOWNCAST(CXTPMenuTitleBarCaption, pControl); if (pMenuTitleBarCaption) { pMenuTitleBarCaption->SetCaption(strCaptionText); pMenuTitleBarCaption->SetCaptionLength(nCaptionLength); } } } else { pControl = m_pControls->Add(new CXTPMenuTitleBarIcon(pIcon), XTP_ID_MENUTITLEBAR_ICON, NULL, -1, TRUE); pControl = m_pControls->Add(new CXTPMenuTitleBarCaption(), XTP_ID_MENUTITLEBAR_CAPTION, NULL, -1, TRUE); if (pControl) { CXTPMenuTitleBarCaption* pMenuTitleBarCaption = DYNAMIC_DOWNCAST(CXTPMenuTitleBarCaption, pControl); if (pMenuTitleBarCaption) { pMenuTitleBarCaption->SetCaption(strCaptionText); pMenuTitleBarCaption->SetCaptionLength(nCaptionLength); } } } SetupMenu(); return TRUE; } void CXTPMenuTitleBar::OnLButtonDown(UINT nFlags, CPoint point) { CXTPControl* pControl = m_pControls->HitTest(point); if (pControl && pControl->GetID() != XTP_ID_MENUTITLEBAR_ICON && pControl->GetID() != XTP_ID_MENUTITLEBAR_CAPTION) { CXTPMenuBar::OnLButtonDown(nFlags, point); return; } GetCommandBars()->ClosePopups(); UpdateWindow(); if (IsCustomizeMode()) { CXTPMenuBar::OnLButtonDown(nFlags, point); //::DefWindowProc(GetSite()->GetSafeHwnd(), WM_NCLBUTTONDOWN, HTNOWHERE, MAKELPARAM(point.x, // point.y)); return; } ::DefWindowProc(GetSite()->GetSafeHwnd(), WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y)); } void CXTPMenuTitleBar::OnRButtonDown(UINT nFlags, CPoint point) { CXTPControl* pControl = m_pControls->HitTest(point); if (pControl && pControl->GetID() != XTP_ID_MENUTITLEBAR_ICON && pControl->GetID() != XTP_ID_MENUTITLEBAR_CAPTION && pControl->GetID() != SC_MINIMIZE && pControl->GetID() != SC_MAXIMIZE && pControl->GetID() != SC_RESTORE && pControl->GetID() != SC_CLOSE) { CXTPMenuBar::OnRButtonDown(nFlags, point); return; } GetCommandBars()->ClosePopups(); UpdateWindow(); if (IsCustomizeMode()) { CXTPMenuBar::OnRButtonDown(nFlags, point); } else { CWnd* pSite = GetSite(); ClientToScreen(&point); pSite->SendMessage(WM_POPUPSYSTEMMENU, XTPToWPARAM(pSite->GetSafeHwnd()), MAKELPARAM(point.x, point.y)); } } void CXTPMenuTitleBar::OnLButtonDblClk(UINT nFlags, CPoint point) { CXTPControl* pControl = m_pControls->HitTest(point); if (pControl && pControl->GetID() != XTP_ID_MENUTITLEBAR_ICON && pControl->GetID() != XTP_ID_MENUTITLEBAR_CAPTION && pControl->GetID() != SC_MINIMIZE && pControl->GetID() != SC_MAXIMIZE && pControl->GetID() != SC_RESTORE && pControl->GetID() != SC_CLOSE) { CXTPMenuBar::OnLButtonDblClk(nFlags, point); return; } GetCommandBars()->ClosePopups(); UpdateWindow(); CWnd* pSite = GetSite(); ClientToScreen(&point); ::DefWindowProc(pSite->GetSafeHwnd(), WM_NCLBUTTONDBLCLK, XTPToWPARAM(HTCAPTION), MAKELPARAM(point.x, point.y)); } CSize CXTPMenuTitleBar::CalcDockingLayout(int nLength, DWORD dwMode, int nWidth) { CClientDC dc(this); // const int x = 102; // nLength -= x; CSize sz = m_pControls->CalcDynamicSize(&dc, nLength, dwMode, GetBorders(), nWidth); // nLength += x; // sz.cx += x; RepositionCaptionButtons(sz); RepositionCaptionText(sz); if ((m_nIdleFlags & xtpIdleLayout) && (dwMode & LM_COMMIT)) { m_nIdleFlags &= ~xtpIdleLayout; Redraw(); } return sz; } void CXTPMenuTitleBar::RepositionCaptionButtons(CSize sz) { CXTPCommandBarsFrameHook* pFrameHook = GetCommandBars()->GetFrameHook(); if (!pFrameHook) { return; } CWnd* pSite = GetSite(); DWORD dwStyle = pSite->GetStyle(); DWORD dwExStyle = pSite->GetExStyle(); BOOL bToolWindow = (dwExStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW; BOOL bEnableClose = TRUE; BOOL bMaximized = (dwStyle & WS_MAXIMIZE) == WS_MAXIMIZE; BOOL bSysMenu = (0 != (dwStyle & WS_SYSMENU)); BOOL bEnabledMaximize = ((dwStyle & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX); BOOL bEnabledMinimize = ((dwStyle & WS_MINIMIZEBOX) == WS_MINIMIZEBOX); BOOL bShowMinMaxButtons = !bToolWindow && bSysMenu && (bEnabledMaximize || bEnabledMinimize); BOOL bShowCloseButton = bSysMenu; if (bSysMenu && !bToolWindow) { CMenu* pMenu = GetSite()->GetSystemMenu(FALSE); if (pMenu && pMenu->GetMenuState(SC_CLOSE, MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED)) bEnableClose = FALSE; } if (bMaximized && (dwStyle & WS_CHILD)) { bShowMinMaxButtons = bShowCloseButton = FALSE; } // From outside to inside BOOL bAddClose = bShowCloseButton; BOOL bAddRestore = bShowMinMaxButtons && bMaximized; BOOL bAddMaximize = bShowMinMaxButtons && !bMaximized; BOOL bAddMinimize = bShowMinMaxButtons; m_rcHeader = CRect(0, 0, sz.cx, sz.cy); AddCaptionButton(SC_CLOSE, bAddClose, bEnableClose, m_rcHeader); AddCaptionButton(SC_RESTORE, bAddRestore, bEnabledMaximize, m_rcHeader); AddCaptionButton(SC_MAXIMIZE, bAddMaximize, bEnabledMaximize, m_rcHeader); AddCaptionButton(SC_MINIMIZE, bAddMinimize, bEnabledMinimize, m_rcHeader); // If there are native system buttons, make sure the title does not overlap them. UINT nNativeSysBtnCount = XTPToUIntChecked((!bAddClose && bEnableClose) + (!bAddRestore && !bAddMaximize && bEnabledMaximize) + (!bAddMinimize && bEnabledMinimize)); if (0 < nNativeSysBtnCount) { m_rcHeader.right -= ::GetSystemMetrics(SM_CXSIZE) * nNativeSysBtnCount; } } void CXTPMenuTitleBar::AddCaptionButton(int nId, BOOL bAdd, BOOL bEnabled, CRect& rcCaption) { CXTPCommandBarsFrameHook* pHook = GetCommandBars()->GetFrameHook(); CXTPFramePaintManager* pFramePaintManager = pHook->GetFramePaintManager(); if (NULL == pFramePaintManager) return; CXTPControl* pButton = m_pControls->FindControl(nId); if (!pButton && bAdd) { pButton = m_pControls->Add(new CXTPMenuTitleBarControlCaptionButton(), nId, NULL, -1, TRUE); CString strCaption; CMenu* pMenu = GetSite()->GetSystemMenu(FALSE); if (pMenu) { pMenu->GetMenuString(XTPToUInt(nId), strCaption, MF_BYCOMMAND); int nIndex = strCaption.Find(_T('\t')); if (nIndex > 0) { strCaption = strCaption.Left(nIndex); } } if (pButton->GetAction()) { pButton->GetAction()->SetCaption(_T("")); pButton->GetAction()->SetDescription(NULL); } pButton->SetDescription(NULL); pButton->SetCaption(_T("")); pButton->SetTooltip(strCaption); } else if (pButton && !bAdd) { m_pControls->Remove(pButton); } if (bAdd) { CSize szButton = pFramePaintManager->GetCaptionButtonSize(XTPToUInt(nId), GetSite()->GetSafeHwnd()); CRect rcButton(rcCaption.right - szButton.cx, // Left rcCaption.top, // Top rcCaption.right, // Right rcCaption.top + szButton.cy // Bottom ); rcCaption.right -= rcButton.Width(); rcButton.DeflateRect(pFramePaintManager->GetCaptionButtonMargin()); pButton->SetRect(rcButton); pButton->SetEnabled(bEnabled); } } void CXTPMenuTitleBar::RepositionCaptionText(CSize sz) { int left = 0, right = sz.cx; for (int i = 0; i < m_pControls->GetCount(); i++) { CXTPControl* pControl = m_pControls->GetAt(i); if (pControl && pControl->GetID() != XTP_ID_MENUTITLEBAR_CAPTION && pControl->GetID() != SC_MINIMIZE && pControl->GetID() != SC_MAXIMIZE && pControl->GetID() != SC_RESTORE && pControl->GetID() != SC_CLOSE) { left = max(left, pControl->GetRect().BottomRight().x); } if (pControl && pControl->GetID() == SC_MINIMIZE || pControl->GetID() == SC_MAXIMIZE || pControl->GetID() == SC_RESTORE || pControl->GetID() == SC_CLOSE) { right = min(right, pControl->GetRect().TopLeft().x); } } if (right <= left) return; CXTPControl* pControl = m_pControls->FindControl(XTP_ID_MENUTITLEBAR_CAPTION); if (pControl) { CXTPMenuTitleBarCaption* pCaption = DYNAMIC_DOWNCAST(CXTPMenuTitleBarCaption, pControl); CRect rcCaption = pCaption->GetRect(); { int len = pCaption->GetCaptionLength(); if (len == 0) return; CRect rc(0, 0, sz.cx, sz.cy); int center = rc.CenterPoint().x; int lcap = center - len / 2; int rcap = lcap + len; if (lcap < left + 1) { lcap = left + 1; rcap = lcap + len; } if (rcap > right - 1) rcap = right - 1; left = lcap; right = rcap; // ASSERT(left != right); // ASSERT(left < right); } rcCaption.left = left; rcCaption.right = right; pCaption->SetRect(rcCaption); // ASSERT(pCaption->GetCaptionLength() <= pCaption->GetRect().Width()); BOOL bVisible = pCaption->GetCaptionLength() <= pCaption->GetRect().Width() ? TRUE : FALSE; pCaption->SetVisible(bVisible); } } void CXTPMenuTitleBar::RefreshSysButtons() { CXTPMenuBar::RefreshSysButtons(); BOOL bMax = FALSE; GetActiveMdiChildWnd(&bMax); CXTPControl* pButton = NULL; pButton = m_pControls->FindControl(XTP_ID_MENUBAR_MINIMIZE); if (pButton && bMax) m_pControls->Remove(pButton); pButton = m_pControls->FindControl(XTP_ID_MENUBAR_RESTORE); if (pButton && bMax) m_pControls->Remove(pButton); pButton = m_pControls->FindControl(XTP_ID_MENUBAR_CLOSE); if (pButton && bMax) m_pControls->Remove(pButton); } #ifdef _XTP_COMMANDBARS_ACTIVEX BEGIN_DISPATCH_MAP(CXTPMenuTitleBar, CXTPMenuBar) END_DISPATCH_MAP() IMPLEMENT_OLETYPELIB_EX(CXTPMenuTitleBar, XTPDIID_IMenuTitleBar) BEGIN_INTERFACE_MAP(CXTPMenuTitleBar, CXTPMenuBar) INTERFACE_PART(CXTPMenuTitleBar, XTPDIID_IMenuTitleBar, Dispatch) END_INTERFACE_MAP() #endif