822 lines
20 KiB
C++
822 lines
20 KiB
C++
|
|
// XTPMarkupContext.cpp: implementation of the CXTPMarkupContext class.
|
||
|
|
//
|
||
|
|
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
|
||
|
|
// (c)1998-2008 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/XTPToolTipContext.h"
|
||
|
|
|
||
|
|
|
||
|
|
#include "XTPMarkupObject.h"
|
||
|
|
|
||
|
|
#include "XTPMarkupContext.h"
|
||
|
|
|
||
|
|
#include "XTPMarkupFrameworkElement.h"
|
||
|
|
#include "XTPMarkupInline.h"
|
||
|
|
|
||
|
|
#include "XTPMarkupUIElement.h"
|
||
|
|
#include "XTPMarkupInline.h"
|
||
|
|
#include "XTPMarkupBorder.h"
|
||
|
|
#include "XTPMarkupStackPanel.h"
|
||
|
|
#include "XTPMarkupGrid.h"
|
||
|
|
#include "XTPMarkupCanvas.h"
|
||
|
|
#include "XTPMarkupImage.h"
|
||
|
|
#include "XTPMarkupPage.h"
|
||
|
|
#include "XTPMarkupShape.h"
|
||
|
|
#include "XTPMarkupTextBlock.h"
|
||
|
|
#include "XTPMarkupButton.h"
|
||
|
|
#include "XTPMarkupScrollViewer.h"
|
||
|
|
#include "XTPMarkupResourceDictionary.h"
|
||
|
|
|
||
|
|
#include "XTPMarkupBuilder.h"
|
||
|
|
#include "XTPMarkupParser.h"
|
||
|
|
#include "XTPMarkupDrawingContext.h"
|
||
|
|
#include "XTPMarkupKeyboardNavigation.h"
|
||
|
|
|
||
|
|
#ifdef _DEBUG
|
||
|
|
#undef THIS_FILE
|
||
|
|
static char THIS_FILE[]=__FILE__;
|
||
|
|
#define new DEBUG_NEW
|
||
|
|
#endif
|
||
|
|
|
||
|
|
|
||
|
|
class CXTPMarkupContext::CXTPMarkupFontArray : public CXTPMarkupTypedSimpleStack<CXTPMarkupFont>
|
||
|
|
{
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
CXTPMarkupFont::CXTPMarkupFont()
|
||
|
|
{
|
||
|
|
m_pMarkupContext = NULL;
|
||
|
|
m_hFont = NULL;
|
||
|
|
m_pNextChain = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupFont::~CXTPMarkupFont()
|
||
|
|
{
|
||
|
|
if (m_pMarkupContext)
|
||
|
|
{
|
||
|
|
VERIFY(m_pMarkupContext->m_pFonts->Remove(this));
|
||
|
|
}
|
||
|
|
DeleteObject(m_hFont);
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////
|
||
|
|
// CXTPMarkupDelegateMap
|
||
|
|
|
||
|
|
class CXTPMarkupDelegateMap
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
CXTPMarkupDelegateMap();
|
||
|
|
~CXTPMarkupDelegateMap();
|
||
|
|
|
||
|
|
public:
|
||
|
|
void RemoveAll();
|
||
|
|
void Add(LPCWSTR lpszDelegate, CXTPMarkupDelegate* pDelegate);
|
||
|
|
CXTPMarkupDelegate* Lookup(LPCWSTR lpszDelegate) const;
|
||
|
|
|
||
|
|
protected:
|
||
|
|
CMap<LPCWSTR, LPCWSTR, CXTPMarkupDelegate*, CXTPMarkupDelegate*> m_mapDelegates;
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
CXTPMarkupDelegateMap::CXTPMarkupDelegateMap()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupDelegateMap::~CXTPMarkupDelegateMap()
|
||
|
|
{
|
||
|
|
RemoveAll();
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupDelegateMap::RemoveAll()
|
||
|
|
{
|
||
|
|
POSITION pos = m_mapDelegates.GetStartPosition();
|
||
|
|
while (pos)
|
||
|
|
{
|
||
|
|
LPCWSTR lpszDelegate;
|
||
|
|
CXTPMarkupDelegate* pDelegate;
|
||
|
|
m_mapDelegates.GetNextAssoc(pos, lpszDelegate, pDelegate);
|
||
|
|
|
||
|
|
MARKUP_RELEASE(pDelegate);
|
||
|
|
}
|
||
|
|
m_mapDelegates.RemoveAll();
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupDelegateMap::Add(LPCWSTR lpszDelegate, CXTPMarkupDelegate* pDelegate)
|
||
|
|
{
|
||
|
|
m_mapDelegates.SetAt(lpszDelegate, pDelegate);
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupDelegate* CXTPMarkupDelegateMap::Lookup(LPCWSTR lpszDelegate) const
|
||
|
|
{
|
||
|
|
CXTPMarkupDelegate* pDelegate = NULL;
|
||
|
|
if (!m_mapDelegates.Lookup(lpszDelegate, pDelegate))
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
return pDelegate;
|
||
|
|
}
|
||
|
|
|
||
|
|
template<> inline BOOL AFXAPI CompareElements(const LPCWSTR* pElement1, const LPCWSTR* pElement2)
|
||
|
|
{
|
||
|
|
return wcscmp(*pElement1, *pElement2) == 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
class CXTPMarkupContext::CInputElementCollection : public CXTPMarkupCollection
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
CInputElementCollection()
|
||
|
|
{
|
||
|
|
m_pElementType = MARKUP_TYPE(CXTPMarkupInputElement);
|
||
|
|
m_bLogicalParent = FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
public:
|
||
|
|
CXTPMarkupInputElement* GetItem(int nIndex) const {
|
||
|
|
return (CXTPMarkupInputElement*)m_arrItems[nIndex];
|
||
|
|
}
|
||
|
|
CXTPMarkupInputElement* GetTailItem() const {
|
||
|
|
return (CXTPMarkupInputElement*)m_arrItems[GetCount() - 1];
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
class CXTPMarkupContext::CTooltipContext : public CXTPToolTipContext
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
CTooltipContext(CXTPMarkupContext* pMarkupContext)
|
||
|
|
{
|
||
|
|
m_pMarkupContext = pMarkupContext;
|
||
|
|
}
|
||
|
|
|
||
|
|
INT_PTR OnToolHitTest(CWnd* /*pWnd*/, CPoint point, TOOLINFO* pToolInfo)
|
||
|
|
{
|
||
|
|
return m_pMarkupContext->OnToolHitTest(point, pToolInfo);
|
||
|
|
}
|
||
|
|
protected:
|
||
|
|
CXTPMarkupContext* m_pMarkupContext;
|
||
|
|
};
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////
|
||
|
|
// CXTPMarkupContext
|
||
|
|
|
||
|
|
CXTPMarkupContext::CXTPMarkupContext()
|
||
|
|
{
|
||
|
|
NONCLIENTMETRICS ncm = { sizeof(NONCLIENTMETRICS) };
|
||
|
|
VERIFY(::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
|
||
|
|
|
||
|
|
m_dwRef = 1;
|
||
|
|
m_logFont = ncm.lfMessageFont;
|
||
|
|
|
||
|
|
m_clrForeground = 0;
|
||
|
|
m_pImageManager = NULL;
|
||
|
|
|
||
|
|
m_pMouseOver = NULL;
|
||
|
|
m_pMouseCapture = NULL;
|
||
|
|
m_pActiveElement = NULL;
|
||
|
|
m_hContextWnd = NULL;
|
||
|
|
|
||
|
|
m_pHandlers = NULL;
|
||
|
|
m_pDelegates = NULL;
|
||
|
|
|
||
|
|
m_pFonts = NULL;
|
||
|
|
m_pKeyboardNavigation = new CXTPMarkupKeyboardNavigation(this);
|
||
|
|
|
||
|
|
m_pTooltipContext = new CTooltipContext(this);
|
||
|
|
m_pTooltipContext->SetStyle(xtpToolTipMarkup);
|
||
|
|
|
||
|
|
|
||
|
|
RegisterClasses();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void CXTPMarkupContext::RegisterClasses()
|
||
|
|
{
|
||
|
|
static BOOL bRegistered = FALSE;
|
||
|
|
if (bRegistered)
|
||
|
|
return;
|
||
|
|
|
||
|
|
bRegistered = TRUE;
|
||
|
|
|
||
|
|
CXTPMarkupType::RegisterAll();
|
||
|
|
|
||
|
|
CXTPMarkupSetter::RegisterType();
|
||
|
|
CXTPMarkupFrameworkElement::RegisterType();
|
||
|
|
CXTPMarkupUIElement::RegisterType();
|
||
|
|
CXTPMarkupTextElement::RegisterType();
|
||
|
|
CXTPMarkupBorder::RegisterType();
|
||
|
|
CXTPMarkupCanvas::RegisterType();
|
||
|
|
CXTPMarkupSolidColorBrush::RegisterType();
|
||
|
|
CXTPMarkupGradientStop::RegisterType();
|
||
|
|
CXTPMarkupLinearGradientBrush::RegisterType();
|
||
|
|
CXTPMarkupColumnDefinition::RegisterType();
|
||
|
|
CXTPMarkupRowDefinition::RegisterType();
|
||
|
|
CXTPMarkupGrid::RegisterType();
|
||
|
|
CXTPMarkupImage::RegisterType();
|
||
|
|
CXTPMarkupPanel::RegisterType();
|
||
|
|
CXTPMarkupControl::RegisterType();
|
||
|
|
CXTPMarkupContentControl::RegisterType();
|
||
|
|
CXTPMarkupButtonBase::RegisterType();
|
||
|
|
CXTPMarkupToggleButton::RegisterType();
|
||
|
|
CXTPMarkupButton::RegisterType();
|
||
|
|
CXTPMarkupFrameworkContentElement::RegisterType();
|
||
|
|
CXTPMarkupInline::RegisterType();
|
||
|
|
CXTPMarkupRun::RegisterType();
|
||
|
|
CXTPMarkupHyperlink::RegisterType();
|
||
|
|
CXTPMarkupInputElement::RegisterType();
|
||
|
|
CXTPMarkupPage::RegisterType();
|
||
|
|
CXTPMarkupShape::RegisterType();
|
||
|
|
CXTPMarkupPolygon::RegisterType();
|
||
|
|
CXTPMarkupPolyline::RegisterType();
|
||
|
|
CXTPMarkupLine::RegisterType();
|
||
|
|
CXTPMarkupStackPanel::RegisterType();
|
||
|
|
CXTPMarkupWrapPanel::RegisterType();
|
||
|
|
CXTPMarkupTextBlock::RegisterType();
|
||
|
|
CXTPMarkupScrollViewer::RegisterType();
|
||
|
|
CXTPMarkupStyle::RegisterType();
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupContext::~CXTPMarkupContext()
|
||
|
|
{
|
||
|
|
if (m_pImageManager)
|
||
|
|
{
|
||
|
|
((CCmdTarget*)m_pImageManager)->InternalRelease();
|
||
|
|
}
|
||
|
|
|
||
|
|
ASSERT(m_dwRef <= 1);
|
||
|
|
|
||
|
|
MARKUP_RELEASE(m_pMouseOver);
|
||
|
|
MARKUP_RELEASE(m_pKeyboardNavigation);
|
||
|
|
|
||
|
|
ASSERT(m_pFonts == NULL || m_pFonts->IsEmpty());
|
||
|
|
|
||
|
|
SAFE_DELETE(m_pHandlers);
|
||
|
|
SAFE_DELETE(m_pDelegates);
|
||
|
|
SAFE_DELETE(m_pFonts);
|
||
|
|
|
||
|
|
CMDTARGET_RELEASE(m_pTooltipContext);
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupObject* CXTPMarkupContext::CreateMarkupObject(CXTPMarkupType* pType)
|
||
|
|
{
|
||
|
|
CXTPMarkupObject* pObject = pType->CreateObject();
|
||
|
|
if (!pObject)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
if (pObject->IsKindOf(MARKUP_TYPE(CXTPMarkupInputElement)))
|
||
|
|
{
|
||
|
|
((CXTPMarkupInputElement*)pObject)->m_pMarkupContext = this;
|
||
|
|
m_dwRef++;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (CXTPMarkupObject*)pObject;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::FinalizeMarkupObject(CXTPMarkupInputElement* pInputElement)
|
||
|
|
{
|
||
|
|
if (pInputElement == m_pMouseOver)
|
||
|
|
m_pMouseOver = NULL;
|
||
|
|
|
||
|
|
if (pInputElement == m_pActiveElement)
|
||
|
|
m_pActiveElement = NULL;
|
||
|
|
|
||
|
|
pInputElement->m_pMarkupContext = NULL;
|
||
|
|
Release();
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupUIElement* CXTPMarkupContext::Parse(LPCSTR lpszBuffer)
|
||
|
|
{
|
||
|
|
if (!lpszBuffer)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
CXTPMarkupParser sc;
|
||
|
|
sc.SetBuffer(lpszBuffer, lpszBuffer + strlen(lpszBuffer));
|
||
|
|
|
||
|
|
CXTPMarkupBuilder builder(this);
|
||
|
|
return builder.Parse(&sc);
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupUIElement* CXTPMarkupContext::Parse(LPCWSTR lpszBuffer)
|
||
|
|
{
|
||
|
|
if (!lpszBuffer)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
CXTPMarkupParser sc;
|
||
|
|
sc.SetBuffer(lpszBuffer, lpszBuffer + wcslen(lpszBuffer));
|
||
|
|
|
||
|
|
CXTPMarkupBuilder builder(this);
|
||
|
|
return builder.Parse(&sc);
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CXTPMarkupContext::CompareFont(LOGFONT* pLogFont1, LOGFONT* pLogFont2)
|
||
|
|
{
|
||
|
|
if (pLogFont1->lfHeight != pLogFont2->lfHeight)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
if (pLogFont1->lfWeight != pLogFont2->lfWeight)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
if (pLogFont1->lfItalic != pLogFont2->lfItalic)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
if (_tcscmp(pLogFont1->lfFaceName, pLogFont2->lfFaceName) != 0)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupFont* CXTPMarkupContext::GetFont(LOGFONT* pLogFont)
|
||
|
|
{
|
||
|
|
if (m_pFonts == NULL)
|
||
|
|
m_pFonts = new CXTPMarkupFontArray();
|
||
|
|
|
||
|
|
CXTPMarkupFont* pFont;
|
||
|
|
|
||
|
|
for (pFont = m_pFonts->GetHead(); pFont != NULL; pFont = pFont->m_pNextChain)
|
||
|
|
{
|
||
|
|
if (CompareFont(&pFont->m_lf, pLogFont))
|
||
|
|
{
|
||
|
|
pFont->AddRef();
|
||
|
|
return pFont;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pFont = new CXTPMarkupFont();
|
||
|
|
m_pFonts->AddTail(pFont);
|
||
|
|
pFont->m_lf = *pLogFont;
|
||
|
|
pFont->m_hFont = ::CreateFontIndirect(pLogFont);
|
||
|
|
pFont->m_pMarkupContext = this;
|
||
|
|
|
||
|
|
return pFont;
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CXTPMarkupContext::IsVisualChild(CXTPMarkupObject* pParent, CXTPMarkupObject* pChild) const
|
||
|
|
{
|
||
|
|
while (pChild)
|
||
|
|
{
|
||
|
|
if (pChild == pParent)
|
||
|
|
return TRUE;
|
||
|
|
|
||
|
|
pChild = pChild->GetLogicalParent();
|
||
|
|
}
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::BuildInputList(CXTPMarkupObject* pUIElement, CInputElementCollection* arrObjects)
|
||
|
|
{
|
||
|
|
CXTPMarkupObject* pParent = pUIElement;
|
||
|
|
while (pParent)
|
||
|
|
{
|
||
|
|
if (pParent->IsKindOf(MARKUP_TYPE(CXTPMarkupInputElement)))
|
||
|
|
{
|
||
|
|
arrObjects->Add((CXTPMarkupInputElement*)pParent);
|
||
|
|
pParent->AddRef();
|
||
|
|
}
|
||
|
|
|
||
|
|
pParent = pParent->GetLogicalParent();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
INT_PTR CXTPMarkupContext::OnToolHitTest(CPoint /*point*/, TOOLINFO* pToolInfo)
|
||
|
|
{
|
||
|
|
CInputElementCollection listMouseOver;
|
||
|
|
BuildInputList(m_pMouseOver, &listMouseOver);
|
||
|
|
|
||
|
|
for (int i = 0; i < listMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
CXTPMarkupObject* pToolTip = pInputElement->GetToolTip();
|
||
|
|
if (pToolTip && IsStringObject(pToolTip))
|
||
|
|
{
|
||
|
|
CXTPToolTipContext::FillInToolInfo(pToolInfo, m_hContextWnd, GetClientBoundingRect(pInputElement),
|
||
|
|
(INT_PTR)pInputElement, (LPCWSTR)*((CXTPMarkupString*)pToolTip));
|
||
|
|
return pToolInfo->uId;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::HandleMouseEnter(CXTPMarkupInputElement* pMouseOver, CPoint point)
|
||
|
|
{
|
||
|
|
if (m_pMouseOver == pMouseOver)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!pMouseOver)
|
||
|
|
m_pActiveElement = NULL;
|
||
|
|
|
||
|
|
CInputElementCollection listOldMouseOver;
|
||
|
|
CInputElementCollection listNewMouseOver;
|
||
|
|
|
||
|
|
BuildInputList(m_pMouseOver, &listOldMouseOver);
|
||
|
|
BuildInputList(pMouseOver, &listNewMouseOver);
|
||
|
|
|
||
|
|
while (listOldMouseOver.GetCount() > 0 && listNewMouseOver.GetCount() > 0 &&
|
||
|
|
listOldMouseOver.GetTailItem() == listNewMouseOver.GetTailItem())
|
||
|
|
{
|
||
|
|
listNewMouseOver.Remove(listNewMouseOver.GetCount() - 1);
|
||
|
|
listOldMouseOver.Remove(listOldMouseOver.GetCount() - 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupMouseEventArgs eMouseLeaveEventArgs(CXTPMarkupInputElement::m_pMouseLeaveEvent);
|
||
|
|
CXTPMarkupMouseEventArgs eMouseEnterEventArgs(CXTPMarkupInputElement::m_pMouseEnterEvent);
|
||
|
|
|
||
|
|
eMouseLeaveEventArgs.SetSource(m_pMouseOver);
|
||
|
|
eMouseLeaveEventArgs.m_hWnd = m_hContextWnd;
|
||
|
|
eMouseLeaveEventArgs.m_point = point;
|
||
|
|
|
||
|
|
eMouseEnterEventArgs.SetSource(pMouseOver);
|
||
|
|
eMouseEnterEventArgs.m_hWnd = m_hContextWnd;
|
||
|
|
eMouseEnterEventArgs.m_point = point;
|
||
|
|
|
||
|
|
|
||
|
|
MARKUP_RELEASE(m_pMouseOver);
|
||
|
|
m_pMouseOver = pMouseOver;
|
||
|
|
MARKUP_ADDREF(m_pMouseOver);
|
||
|
|
|
||
|
|
int i;
|
||
|
|
for (i = 0; i < listOldMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listOldMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
pInputElement->RaiseEvent(&eMouseLeaveEventArgs);
|
||
|
|
if (eMouseLeaveEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
|
||
|
|
pInputElement->OnMouseLeave(&eMouseLeaveEventArgs);
|
||
|
|
if (eMouseLeaveEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (i = 0; i < listNewMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listNewMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
pInputElement->RaiseEvent(&eMouseEnterEventArgs);
|
||
|
|
if (eMouseEnterEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
|
||
|
|
pInputElement->OnMouseEnter(&eMouseEnterEventArgs);
|
||
|
|
if (eMouseEnterEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void CXTPMarkupContext::HandleMouseMove(CXTPMarkupUIElement* pUIElement, CPoint point)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pObject = pUIElement->InputHitTest(point);
|
||
|
|
if (m_pMouseCapture)
|
||
|
|
{
|
||
|
|
if ((pObject == NULL) || !IsVisualChild(m_pMouseCapture, pObject))
|
||
|
|
pObject = NULL;
|
||
|
|
else
|
||
|
|
pObject = m_pMouseCapture;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (m_pMouseOver != pObject)
|
||
|
|
{
|
||
|
|
HandleMouseEnter(pObject, point);
|
||
|
|
|
||
|
|
if (m_pMouseOver)
|
||
|
|
{
|
||
|
|
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hContextWnd, 0 };
|
||
|
|
_TrackMouseEvent (&tme);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!HandleSetCursor())
|
||
|
|
{
|
||
|
|
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
m_pActiveElement = m_pMouseOver ? pUIElement : NULL;
|
||
|
|
|
||
|
|
if (m_pMouseOver)
|
||
|
|
{
|
||
|
|
CInputElementCollection listNewMouseOver;
|
||
|
|
BuildInputList(m_pMouseOver, &listNewMouseOver);
|
||
|
|
|
||
|
|
CXTPMarkupMouseEventArgs eMouseMoveEventArgs(CXTPMarkupInputElement::m_pMouseMoveEvent);
|
||
|
|
eMouseMoveEventArgs.SetSource(m_pMouseOver);
|
||
|
|
eMouseMoveEventArgs.m_hWnd = m_hContextWnd;
|
||
|
|
eMouseMoveEventArgs.m_point = point;
|
||
|
|
|
||
|
|
for (int i = 0; i < listNewMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listNewMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
pInputElement->RaiseEvent(&eMouseMoveEventArgs);
|
||
|
|
if (eMouseMoveEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
|
||
|
|
pInputElement->OnMouseMove(&eMouseMoveEventArgs);
|
||
|
|
if (eMouseMoveEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CXTPMarkupContext::HandleSetCursor()
|
||
|
|
{
|
||
|
|
if (m_pMouseOver)
|
||
|
|
{
|
||
|
|
CInputElementCollection listNewMouseOver;
|
||
|
|
BuildInputList(m_pMouseOver, &listNewMouseOver);
|
||
|
|
|
||
|
|
CXTPMarkupQueryCursorEventArgs eQueryCursorEventArgs;
|
||
|
|
eQueryCursorEventArgs.SetSource(m_pMouseOver);
|
||
|
|
|
||
|
|
for (int i = 0; i < listNewMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listNewMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
pInputElement->OnQueryCursor(&eQueryCursorEventArgs);
|
||
|
|
if (!eQueryCursorEventArgs.IsHandled())
|
||
|
|
continue;
|
||
|
|
|
||
|
|
if (eQueryCursorEventArgs.m_hCursor)
|
||
|
|
{
|
||
|
|
::SetCursor(eQueryCursorEventArgs.m_hCursor);
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CXTPMarkupContext::HandleMouseWheel(int nDelta)
|
||
|
|
{
|
||
|
|
if (m_pMouseOver)
|
||
|
|
{
|
||
|
|
CInputElementCollection listNewMouseOver;
|
||
|
|
BuildInputList(m_pMouseOver, &listNewMouseOver);
|
||
|
|
|
||
|
|
CXTPMarkupMouseWheelEventArgs eMouseWheelEventArgs;
|
||
|
|
eMouseWheelEventArgs.m_nDelta = nDelta;
|
||
|
|
eMouseWheelEventArgs.SetSource(m_pMouseOver);
|
||
|
|
|
||
|
|
for (int i = 0; i < listNewMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listNewMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
pInputElement->OnMouseWheel(&eMouseWheelEventArgs);
|
||
|
|
if (eMouseWheelEventArgs.IsHandled())
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CXTPMarkupContext::HandleMouseUpDown(UINT message, WPARAM /*wParam*/, LPARAM lParam)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pMouseOver = m_pMouseOver;
|
||
|
|
if (m_pMouseCapture)
|
||
|
|
pMouseOver = m_pMouseCapture;
|
||
|
|
|
||
|
|
if (!pMouseOver)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
CInputElementCollection listNewMouseOver;
|
||
|
|
BuildInputList(pMouseOver, &listNewMouseOver);
|
||
|
|
|
||
|
|
CXTPMarkupMouseButtonEventArgs eMouseButtonEventArgs(
|
||
|
|
message == WM_LBUTTONDOWN || message == WM_LBUTTONDBLCLK ? CXTPMarkupInputElement::m_pMouseLeftButtonDownEvent :
|
||
|
|
message == WM_LBUTTONUP ? CXTPMarkupInputElement::m_pMouseLeftButtonUpEvent :
|
||
|
|
message == WM_RBUTTONDOWN ? CXTPMarkupInputElement::m_pMouseRightButtonDownEvent :
|
||
|
|
message == WM_RBUTTONUP ? CXTPMarkupInputElement::m_pMouseRightButtonUpEvent : NULL);
|
||
|
|
|
||
|
|
eMouseButtonEventArgs.SetSource(pMouseOver);
|
||
|
|
eMouseButtonEventArgs.m_hWnd = m_hContextWnd;
|
||
|
|
eMouseButtonEventArgs.m_point = lParam;
|
||
|
|
|
||
|
|
for (int i = 0; i < listNewMouseOver.GetCount(); i++)
|
||
|
|
{
|
||
|
|
CXTPMarkupInputElement* pInputElement = listNewMouseOver.GetItem(i);
|
||
|
|
|
||
|
|
pInputElement->RaiseEvent(&eMouseButtonEventArgs);
|
||
|
|
if (eMouseButtonEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
|
||
|
|
if (message == WM_LBUTTONDOWN || message == WM_LBUTTONDBLCLK)
|
||
|
|
{
|
||
|
|
pInputElement->OnMouseLeftButtonDown(&eMouseButtonEventArgs);
|
||
|
|
}
|
||
|
|
else if (message == WM_LBUTTONUP)
|
||
|
|
{
|
||
|
|
pInputElement->OnMouseLeftButtonUp(&eMouseButtonEventArgs);
|
||
|
|
}
|
||
|
|
else if (message == WM_RBUTTONDOWN)
|
||
|
|
{
|
||
|
|
pInputElement->OnMouseRightButtonDown(&eMouseButtonEventArgs);
|
||
|
|
}
|
||
|
|
else if (message == WM_RBUTTONUP)
|
||
|
|
{
|
||
|
|
pInputElement->OnMouseRightButtonUp(&eMouseButtonEventArgs);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (eMouseButtonEventArgs.IsHandled())
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return eMouseButtonEventArgs.IsHandled();
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::CaptureMouse(CXTPMarkupInputElement* pUIElement)
|
||
|
|
{
|
||
|
|
m_pMouseCapture = pUIElement;
|
||
|
|
::SetCapture(m_hContextWnd);
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::ReleaseMouseCapture(CXTPMarkupInputElement* /*pUIElement*/)
|
||
|
|
{
|
||
|
|
m_pMouseCapture = NULL;
|
||
|
|
::ReleaseCapture();
|
||
|
|
}
|
||
|
|
|
||
|
|
BOOL CXTPMarkupContext::OnWndMsg(CXTPMarkupUIElement* pUIElement, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
||
|
|
{
|
||
|
|
if (!m_hContextWnd)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
if (m_pActiveElement && m_pActiveElement != pUIElement)
|
||
|
|
return FALSE;
|
||
|
|
|
||
|
|
if (message == WM_MOUSEMOVE)
|
||
|
|
{
|
||
|
|
HandleMouseMove(pUIElement, CPoint(lParam));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (message == WM_DESTROY || message == WM_MOUSELEAVE)
|
||
|
|
{
|
||
|
|
HandleMouseEnter(NULL, CPoint(-1, -1));
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) || (message == WM_MOUSELEAVE))
|
||
|
|
{
|
||
|
|
m_pTooltipContext->FilterToolTipMessage(CWnd::FromHandle(m_hContextWnd), message, wParam, lParam);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (message == WM_SETCURSOR)
|
||
|
|
{
|
||
|
|
if (HandleSetCursor())
|
||
|
|
{
|
||
|
|
*pResult = TRUE;
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (message == WM_MOUSEWHEEL)
|
||
|
|
{
|
||
|
|
if (HandleMouseWheel((short) HIWORD(wParam)))
|
||
|
|
{
|
||
|
|
*pResult = TRUE;
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN || message == WM_LBUTTONUP || message == WM_RBUTTONUP || message == WM_LBUTTONDBLCLK)
|
||
|
|
{
|
||
|
|
if (HandleMouseUpDown(message, wParam, lParam))
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (message == WM_CAPTURECHANGED && m_pMouseCapture)
|
||
|
|
{
|
||
|
|
CXTPMarkupMouseEventArgs eLostMouseCaptureEventArgs(CXTPMarkupInputElement::m_pLostMouseCaptureEvent);
|
||
|
|
eLostMouseCaptureEventArgs.SetSource(m_pMouseCapture);
|
||
|
|
|
||
|
|
CXTPMarkupInputElement* pInputElement = m_pMouseCapture;
|
||
|
|
|
||
|
|
pInputElement->RaiseEvent(&eLostMouseCaptureEventArgs);
|
||
|
|
|
||
|
|
if (!eLostMouseCaptureEventArgs.IsHandled())
|
||
|
|
{
|
||
|
|
pInputElement->OnLostMouseCapture(&eLostMouseCaptureEventArgs);
|
||
|
|
}
|
||
|
|
m_pMouseCapture = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (message == WM_KEYDOWN || message == WM_SETFOCUS || message == WM_KILLFOCUS)
|
||
|
|
{
|
||
|
|
if (m_pKeyboardNavigation->OnWndMsg(message, wParam, lParam, pResult))
|
||
|
|
return TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
return FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::RaiseEvent(CXTPMarkupObject* pSource, CXTPMarkupRoutedEventArgs* pEventArgs)
|
||
|
|
{
|
||
|
|
if (m_pHandlers) m_pHandlers->Raise(pSource, pEventArgs);
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::AddHandler(CXTPMarkupRoutedEvent* pEvent, CXTPMarkupDelegate* pDelegate)
|
||
|
|
{
|
||
|
|
if (m_pHandlers == NULL)
|
||
|
|
m_pHandlers = new CXTPMarkupEventHandlerMap();
|
||
|
|
|
||
|
|
m_pHandlers->Add(pEvent, pDelegate);
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::SetDelegate(LPWSTR lpszHandler, CXTPMarkupDelegate* pDelegate)
|
||
|
|
{
|
||
|
|
if (m_pDelegates == NULL)
|
||
|
|
m_pDelegates = new CXTPMarkupDelegateMap();
|
||
|
|
|
||
|
|
m_pDelegates->Add(lpszHandler, pDelegate);
|
||
|
|
}
|
||
|
|
|
||
|
|
CXTPMarkupDelegate* CXTPMarkupContext::LookupDelegate(LPCWSTR lpszDelegate) const
|
||
|
|
{
|
||
|
|
if (m_pDelegates == NULL)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
return m_pDelegates->Lookup(lpszDelegate);
|
||
|
|
}
|
||
|
|
|
||
|
|
CRect CXTPMarkupContext::GetClientBoundingRect(CXTPMarkupInputElement* pInputElement) const
|
||
|
|
{
|
||
|
|
CRect rc(0, 0, 0, 0);
|
||
|
|
|
||
|
|
if (!pInputElement)
|
||
|
|
return rc;
|
||
|
|
|
||
|
|
CXTPMarkupVisual* pVisual = NULL;
|
||
|
|
if (pInputElement->IsKindOf(MARKUP_TYPE(CXTPMarkupVisual)))
|
||
|
|
{
|
||
|
|
pVisual = (CXTPMarkupVisual*)pInputElement;
|
||
|
|
rc = pVisual->GetBoundRect();
|
||
|
|
}
|
||
|
|
else if (pInputElement->IsKindOf(MARKUP_TYPE(CXTPMarkupFrameworkContentElement)))
|
||
|
|
{
|
||
|
|
pVisual = ((CXTPMarkupFrameworkContentElement*)pInputElement)->GetParent();
|
||
|
|
rc = ((CXTPMarkupFrameworkContentElement*)pInputElement)->GetBoundRect();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!pVisual)
|
||
|
|
return rc;
|
||
|
|
|
||
|
|
while (pVisual != 0)
|
||
|
|
{
|
||
|
|
rc.OffsetRect(pVisual->GetVisualOffset());
|
||
|
|
pVisual = pVisual->GetVisualParent();
|
||
|
|
}
|
||
|
|
|
||
|
|
return rc;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void CXTPMarkupContext::OnInvalidateVisual(CXTPMarkupUIElement* pUIElement)
|
||
|
|
{
|
||
|
|
//TRACE(_T("OnInvalidateVisual\n"));
|
||
|
|
|
||
|
|
if (m_hContextWnd)
|
||
|
|
{
|
||
|
|
InvalidateRect(m_hContextWnd, GetClientBoundingRect(pUIElement), FALSE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::OnInvalidateArrange(CXTPMarkupUIElement* /*pUIElement*/)
|
||
|
|
{
|
||
|
|
//TRACE(_T("OnInvalidateArrange\n"));
|
||
|
|
if (m_hContextWnd)
|
||
|
|
{
|
||
|
|
InvalidateRect(m_hContextWnd, NULL, FALSE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void CXTPMarkupContext::Release()
|
||
|
|
{
|
||
|
|
if (m_dwRef == 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
LONG lResult = InterlockedDecrement(&m_dwRef);
|
||
|
|
if (lResult == 0)
|
||
|
|
{
|
||
|
|
delete this;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|