You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

590 lines
13 KiB
C++

2 years ago
// XTPMessageBar.cpp : implementation of the CXTPMessageBar 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/XTPMarkupRender.h"
#include "Common/XTPToolTipContext.h"
#include "Common/XTPColorManager.h"
#include "Common/XTPDrawHelpers.h"
#include "XTPCommandBarsDefines.h"
#include "XTPCommandBars.h"
#include "XTPPaintManager.h"
#include "XTPMessageBar.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CXTPMessageBarButton::CXTPMessageBarButton()
{
m_rcButton.SetRectEmpty();
m_nID = 0;
m_bPressed = FALSE;
m_bHot = FALSE;
m_pUIElement = NULL;
}
CXTPMessageBarButton::~CXTPMessageBarButton()
{
XTPMarkupReleaseElement(m_pUIElement);
}
void CXTPMessageBarButton::PerformClick(CXTPMessageBar* pBar, CPoint pt)
{
if ((::GetCapture() != NULL))
return;
m_bPressed = TRUE;
pBar->InvalidateRect(m_rcButton, FALSE);
::SetCapture(pBar->GetSafeHwnd());
BOOL bClick = FALSE, bPressed;
while (::GetCapture() == pBar->GetSafeHwnd())
{
MSG msg;
if (!::GetMessage(&msg, NULL, 0, 0))
break;
switch (msg.message)
{
case WM_MOUSEMOVE:
pt = CPoint((short signed)LOWORD(msg.lParam), (short signed)HIWORD(msg.lParam));
bPressed = m_rcButton.PtInRect(pt);
if (bPressed != m_bPressed)
{
m_bPressed = bPressed;
pBar->InvalidateRect(m_rcButton, FALSE);
}
break;
case WM_LBUTTONUP:
bClick = m_bPressed;
goto ExitLoop;
case WM_KEYDOWN:
if (msg.wParam != VK_ESCAPE)
break;
case WM_CANCELMODE:
case WM_RBUTTONDOWN:
goto ExitLoop;
default:
DispatchMessage (&msg);
break;
}
}
ExitLoop:
ReleaseCapture();
m_bPressed = FALSE;
pBar->InvalidateRect(m_rcButton, FALSE);
if (bClick)
{
pBar->Click(this);
}
}
/////////////////////////////////////////////////////////////////////////////
// CXTPMessageBar
CXTPMessageBar::CXTPMessageBar()
: m_nHeight(40)
, m_bAutoSize(FALSE)
{
m_pMarkupContext = NULL;
m_pUIElement = NULL;
m_rcBorder.SetRect(3, 3, 3, 3);
m_rcPadding.SetRect(5, 0, 5, 0);
m_rcContent.SetRectEmpty();
m_pCommandBars = NULL;
m_pHotButton = NULL;
}
CXTPMessageBar::~CXTPMessageBar()
{
RemoveButtons();
XTPMarkupReleaseElement(m_pUIElement);
XTPMarkupReleaseContext(m_pMarkupContext);
}
BOOL CXTPMessageBar::Create(CXTPCommandBars* pCommandBars, DWORD dwStyle, UINT nID)
{
m_dwStyle = (dwStyle & CBRS_ALL);
m_pCommandBars = pCommandBars;
if (!CWnd::Create(AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)), NULL, dwStyle, CRect(0, 0, 0, 0), pCommandBars->GetSite(), nID))
return FALSE;
if (m_pCommandBars->IsLayoutRTL())
{
ModifyStyleEx(0, WS_EX_LAYOUTRTL);
}
return TRUE;
}
void CXTPMessageBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
// update the dialog controls added to the status bar
UpdateDialogControls(pTarget, bDisableIfNoHndler);
}
void CXTPMessageBar::SetHeight(int nHeight)
{
m_nHeight = nHeight;
}
void CXTPMessageBar::SetAutoSize(BOOL bAutoSize)
{
m_bAutoSize = bAutoSize;
}
CSize CXTPMessageBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
UNREFERENCED_PARAMETER(bStretch);
UNREFERENCED_PARAMETER(bHorz);
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
CSize size(32767, m_nHeight);
if (m_bAutoSize) // Auto expand height
{
CClientDC dc(this);
CSize szMeasure = MeasureContent(&dc);
size.cy = szMeasure.cy;
size.cy += m_rcBorder.top + m_rcBorder.bottom;
size.cy += m_rcPadding.top + m_rcPadding.bottom;
size.cy += 4;
}
size.cy = max(size.cy, m_nHeight);
return size;
}
void CXTPMessageBar::EnableMarkup(BOOL bEnableMarkup)
{
XTPMarkupReleaseContext(m_pMarkupContext);
if (bEnableMarkup)
{
m_pMarkupContext = XTPMarkupCreateContext(m_hWnd);
}
}
void CXTPMessageBar::AddButton(UINT nID, LPCTSTR lpszCaption, LPCTSTR lpszToolTop)
{
CXTPMessageBarButton* pButton = new CXTPMessageBarButton();
pButton->m_nID = nID;
pButton->m_strCaption = lpszCaption;
pButton->m_strToolTip = lpszToolTop;
pButton->m_pUIElement = XTPMarkupParseText(m_pMarkupContext, lpszCaption);
m_arrButtons.Add(pButton);
Invalidate(FALSE);
}
void CXTPMessageBar::RemoveButtons()
{
for (int i = 0; i < m_arrButtons.GetSize(); i++)
{
delete m_arrButtons[i];
}
m_arrButtons.RemoveAll();
m_pHotButton = NULL;
if (m_hWnd) Invalidate(FALSE);
}
void CXTPMessageBar::SetMessage(LPCTSTR lpszMessage)
{
m_strContent = lpszMessage;
XTPMarkupReleaseElement(m_pUIElement);
if (m_pMarkupContext)
{
m_pUIElement = XTPMarkupParseText(m_pMarkupContext, lpszMessage);
}
Invalidate(FALSE);
}
CXTPPaintManager* CXTPMessageBar::GetPaintManager() const
{
return m_pCommandBars->GetPaintManager();
}
BEGIN_MESSAGE_MAP(CXTPMessageBar, CControlBar)
//{{AFX_MSG_MAP(CXTPMessageBar)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CXTPMessageBar message handlers
void CXTPMessageBar::OnPaint()
{
CPaintDC dcPaint(this); // device context for painting
CXTPBufferDC dc(dcPaint);
CXTPFontDC font(&dc, GetPaintManager()->GetRegularFont());
RecalcLayout(&dc);
FillMessageBar(&dc);
DrawContent(&dc);
DrawButtons(&dc);
}
void CXTPMessageBar::DrawButtons(CDC* pDC)
{
for (int i = 0; i < m_arrButtons.GetSize(); i++)
{
CXTPMessageBarButton* pButton = m_arrButtons.GetAt(i);
DrawButton(pDC, pButton);
}
};
void CXTPMessageBar::DrawButton(CDC* pDC, CXTPMessageBarButton* pButton)
{
BOOL bCloseButton = (pButton->m_nID == SC_CLOSE);
GetPaintManager()->DrawMessageBarButton(pDC, pButton);
if (!bCloseButton)
{
COLORREF clrText = GetPaintManager()->m_clrMessageBarText;
if (pButton->m_pUIElement)
{
XTPMarkupSetDefaultFont(m_pMarkupContext, (HFONT)GetPaintManager()->GetRegularFont()->GetSafeHandle(), clrText);
CSize sz = XTPMarkupMeasureElement(pButton->m_pUIElement);
CPoint pt((pButton->m_rcButton.left + pButton->m_rcButton.right - sz.cx) / 2,
(pButton->m_rcButton.top + pButton->m_rcButton.bottom - sz.cy) / 2);
XTPMarkupRenderElement(pButton->m_pUIElement, pDC->GetSafeHdc(), CRect(pt, sz));
}
else
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(clrText);
pDC->DrawText(pButton->m_strCaption, pButton->m_rcButton, DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
}
}
}
void CXTPMessageBar::FillMessageBar(CDC* pDC)
{
GetPaintManager()->FillMessageBar(pDC, this);
}
void CXTPMessageBar::DrawContent(CDC* pDC)
{
COLORREF clrText = GetPaintManager()->m_clrMessageBarText;
if (m_pUIElement)
{
XTPMarkupSetDefaultFont(m_pMarkupContext, (HFONT)GetPaintManager()->GetRegularFont()->GetSafeHandle(), clrText);
XTPMarkupRenderElement(m_pUIElement, pDC->GetSafeHdc(), m_rcContent);
}
else
{
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(clrText);
pDC->DrawText(m_strContent, m_rcContent, DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOPREFIX);
}
}
CRect CXTPMessageBar::GetMessageRect()
{
BOOL bCloseButton = FindButton(SC_CLOSE) != NULL;
CXTPClientRect rc(this);
rc.left += m_rcBorder.left;
rc.top += m_rcBorder.top;
rc.right -= m_rcBorder.right + (bCloseButton ? 18 : 0);
rc.bottom -= m_rcBorder.bottom;
return rc;
}
CSize CXTPMessageBar::MeasureContent(CDC* pDC)
{
if (m_pUIElement)
{
XTPMarkupSetDefaultFont(m_pMarkupContext, (HFONT)GetPaintManager()->GetRegularFont()->GetSafeHandle(), COLORREF_NULL);
CSize sz = XTPMarkupMeasureElement(m_pUIElement);
return sz;
}
CSize sz = pDC->GetTextExtent(m_strContent);
return sz;
}
CSize CXTPMessageBar::MeasureButton(CDC* pDC, CXTPMessageBarButton* pButton)
{
if (pButton->m_nID == SC_CLOSE)
return CSize(18, 18);
CSize sz;
if (pButton->m_pUIElement)
{
XTPMarkupSetDefaultFont(m_pMarkupContext, (HFONT)GetPaintManager()->GetRegularFont()->GetSafeHandle(), COLORREF_NULL);
sz = XTPMarkupMeasureElement(pButton->m_pUIElement);
}
else
{
sz = pDC->GetTextExtent(pButton->m_strCaption);
}
sz.cy = max(sz.cy + 2, 23);
sz.cx = max(89, sz.cx + 10);
return sz;
}
void CXTPMessageBar::RecalcLayout(CDC* pDC)
{
if (!m_hWnd)
return;
CXTPClientRect rcClient(this);
CSize szContent = MeasureContent(pDC);
m_rcContent = CRect(CPoint(m_rcBorder.left + m_rcPadding.left, (rcClient.Height() - szContent.cy) /2), szContent);
int nLeft = m_rcContent.right, i;
CXTPMessageBarButton* pCloseButton = NULL;
for (i = 0; i < m_arrButtons.GetSize(); i++)
{
CXTPMessageBarButton* pButton = m_arrButtons.GetAt(i);
if (pButton->m_nID == SC_CLOSE)
{
pCloseButton = pButton;
continue;
}
CSize szButton = MeasureButton(pDC, pButton);
pButton->m_rcButton = CRect(CPoint(nLeft + m_rcPadding.right, (rcClient.Height() - szButton.cy) /2), szButton);
nLeft = pButton->m_rcButton.right;
}
int nRight = rcClient.right - m_rcBorder.right - m_rcPadding.right - (pCloseButton ? 18 : 0);
if (nLeft > nRight)
{
nLeft = m_rcBorder.left + m_rcPadding.left;
for (i = (int)m_arrButtons.GetSize() - 1; i >= 0; i--)
{
CXTPMessageBarButton* pButton = m_arrButtons.GetAt(i);
if (pButton->m_nID == SC_CLOSE)
continue;
int nWidth = pButton->m_rcButton.Width();
pButton->m_rcButton.right = nRight;
pButton->m_rcButton.left = nRight - nWidth;
if (pButton->m_rcButton.left < nLeft)
{
pButton->m_rcButton.SetRectEmpty();
}
else
{
nRight = nRight - nWidth - m_rcPadding.right;
}
}
m_rcContent.right = nRight;
}
if (pCloseButton)
{
CSize szButton = MeasureButton(pDC, pCloseButton);
pCloseButton->m_rcButton = CRect(CPoint(rcClient.right - szButton.cx - 1, m_rcBorder.top), szButton);
}
};
void CXTPMessageBar::OnSize(UINT nType, int cx, int cy)
{
CControlBar::OnSize(nType, cx, cy);
Invalidate(FALSE);
}
BOOL CXTPMessageBar::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (m_pUIElement)
{
if (XTPMarkupRelayMessage(m_pUIElement, message, wParam, lParam, pResult))
return TRUE;
}
m_pCommandBars->GetToolTipContext()->FilterToolTipMessage(this, message, wParam, lParam);
return CControlBar::OnWndMsg(message, wParam, lParam, pResult);
}
CXTPMessageBarButton* CXTPMessageBar::FindButton(UINT nID) const
{
for (int i = 0; i < m_arrButtons.GetSize(); i++)
{
CXTPMessageBarButton* pButton = m_arrButtons.GetAt(i);
if (pButton->m_nID == nID)
return pButton;
}
return NULL;
}
CXTPMessageBarButton* CXTPMessageBar::HitTestButton(CPoint point) const
{
for (int i = 0; i < m_arrButtons.GetSize(); i++)
{
CXTPMessageBarButton* pButton = m_arrButtons.GetAt(i);
if (pButton->m_rcButton.PtInRect(point))
return pButton;
}
return NULL;
}
void CXTPMessageBar::OnMouseLeave()
{
OnMouseMove(0, CPoint(-1, -1));
}
void CXTPMessageBar::OnMouseMove(UINT nFlags, CPoint point)
{
CXTPMessageBarButton* pButton = HitTestButton(point);
if (pButton != m_pHotButton)
{
if (m_pHotButton) m_pHotButton->m_bHot = FALSE;
m_pHotButton = pButton;
if (m_pHotButton) m_pHotButton->m_bHot = TRUE;
if (m_pHotButton)
{
TRACKMOUSEEVENT tme =
{
sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd
};
_TrackMouseEvent(&tme);
}
Invalidate(FALSE);
}
CControlBar::OnMouseMove(nFlags, point);
}
void CXTPMessageBar::OnLButtonDown(UINT nFlags, CPoint point)
{
if (m_pHotButton)
{
m_pHotButton->PerformClick(this, point);
return;
}
CControlBar::OnLButtonDown(nFlags, point);
}
INT_PTR CXTPMessageBar::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
// check child windows first by calling CControlBar
INT_PTR nHit = CControlBar::OnToolHitTest(point, pTI);
if (nHit != -1)
return nHit;
if (m_pHotButton)
{
nHit = m_pHotButton->m_nID;
CString strTip = m_pHotButton->m_strToolTip;
if (strTip.IsEmpty())
return -1;
CXTPToolTipContext::FillInToolInfo(pTI, m_hWnd, m_pHotButton->m_rcButton, nHit, strTip, strTip, _T(""), m_pCommandBars->GetImageManager());
return nHit;
}
return -1;
}
void CXTPMessageBar::Click(CXTPMessageBarButton* pButton)
{
if (pButton->m_nID == SC_CLOSE)
{
SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_HIDEWINDOW);
m_pCommandBars->RecalcFrameLayout();
}
else
{
m_pCommandBars->GetSite()->SendMessage(WM_COMMAND, pButton->m_nID);
}
}