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.
451 lines
10 KiB
C++
451 lines
10 KiB
C++
2 years ago
|
// XTPRichRender.cpp: implementation of the CXTPRichRender class.
|
||
|
//
|
||
|
// This file is a part of the XTREME TOOLKIT PRO 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 "XTPVC80Helpers.h"
|
||
|
#include "XTPRichRender.h"
|
||
|
#include "XTPResourceManager.h"
|
||
|
|
||
|
const IID IID_XTPITextServices =
|
||
|
{
|
||
|
0x8d33f740, 0xcf58, 0x11ce, {0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5}
|
||
|
};
|
||
|
|
||
|
const IID IID_XTPITextHost =
|
||
|
{
|
||
|
0xc5bdd8d0, 0xd26e, 0x11ce, {0xa8, 0x9e, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5}
|
||
|
};
|
||
|
|
||
|
CXTPRichRender::CXTPRichRender()
|
||
|
{
|
||
|
NONCLIENTMETRICS ncm;
|
||
|
::ZeroMemory(&ncm, sizeof(ncm));
|
||
|
ncm.cbSize = sizeof(ncm);
|
||
|
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
|
||
|
|
||
|
HDC hDC = ::GetDC(NULL);
|
||
|
|
||
|
::ZeroMemory(&m_charformat, sizeof(m_charformat));
|
||
|
m_charformat.cbSize = sizeof(m_charformat);
|
||
|
m_charformat.dwMask = CFM_BOLD | CFM_CHARSET | CFM_COLOR |CFM_FACE | CFM_ITALIC |
|
||
|
CFM_SIZE | CFM_STRIKEOUT | CFM_UNDERLINE;
|
||
|
m_charformat.yHeight = -MulDiv(ncm.lfMessageFont.lfHeight, 1440, ::GetDeviceCaps(hDC, LOGPIXELSY));
|
||
|
m_charformat.crTextColor = ::GetSysColor(COLOR_BTNTEXT);
|
||
|
m_charformat.bPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
|
||
|
WCSNCPY_S(m_charformat.szFaceName, LF_FACESIZE, XTP_CT2CW(ncm.lfMessageFont.lfFaceName), LF_FACESIZE);
|
||
|
|
||
|
::ReleaseDC(NULL,hDC);
|
||
|
|
||
|
::ZeroMemory(&m_paraformat, sizeof(m_paraformat));
|
||
|
m_paraformat.cbSize = sizeof(m_paraformat);
|
||
|
m_paraformat.dwMask = PFM_ALIGNMENT | PFM_NUMBERING | PFM_OFFSET | PFM_OFFSETINDENT |
|
||
|
PFM_RIGHTINDENT | PFM_RTLPARA | PFM_STARTINDENT | PFM_TABSTOPS;
|
||
|
m_paraformat.wAlignment = PFA_LEFT;
|
||
|
|
||
|
m_pTextService = NULL;
|
||
|
|
||
|
m_hModule = LoadLibraryA("RICHED20.dll");
|
||
|
if (!m_hModule)
|
||
|
return;
|
||
|
|
||
|
// Get an interface to the windowless rich edit control
|
||
|
IUnknown* pUnknown = NULL;
|
||
|
PCreateTextServices lpCreateTextServices = (PCreateTextServices)GetProcAddress(m_hModule, "CreateTextServices");
|
||
|
HRESULT hr = lpCreateTextServices(NULL, &m_xTextHost, &pUnknown);
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
pUnknown->QueryInterface(IID_XTPITextServices, (void**)&m_pTextService);
|
||
|
pUnknown->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CXTPRichRender::~CXTPRichRender()
|
||
|
{
|
||
|
if (m_hModule)
|
||
|
{
|
||
|
FreeLibrary(m_hModule);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::SetDefaultCharFormat(CHARFORMATW* pcf)
|
||
|
{
|
||
|
if (!pcf)
|
||
|
return;
|
||
|
|
||
|
m_charformat = *pcf;
|
||
|
|
||
|
if (m_pTextService)
|
||
|
{
|
||
|
LRESULT lResult = 0;
|
||
|
m_pTextService->TxSendMessage(EM_SETCHARFORMAT, 0, (LPARAM)pcf, &lResult);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DWORD CALLBACK CXTPRichRender::RichTextCtrlCallbackIn(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb)
|
||
|
{
|
||
|
CFile* pFile = (CFile*) dwCookie;
|
||
|
*pcb = pFile->Read(pbBuff, cb);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
LRESULT CXTPRichRender::SetText(LPCTSTR lpszText)
|
||
|
{
|
||
|
if (!m_pTextService)
|
||
|
return 0;
|
||
|
|
||
|
if (lpszText == 0 || lpszText[0] == 0)
|
||
|
{
|
||
|
m_pTextService->TxSetText(L"");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
LRESULT nResult = 0;
|
||
|
|
||
|
EDITSTREAM es;
|
||
|
es.pfnCallback = &CXTPRichRender::RichTextCtrlCallbackIn;
|
||
|
|
||
|
if (lpszText[0] == _T('{'))
|
||
|
{
|
||
|
#ifdef _UNICODE
|
||
|
CXTPResourceManager::CXTPW2A _lpa(lpszText);
|
||
|
LPSTR lpBuffer = (LPSTR)(LPCSTR)_lpa;
|
||
|
#else
|
||
|
LPSTR lpBuffer = (LPSTR)lpszText;
|
||
|
#endif
|
||
|
|
||
|
CMemFile cFile((BYTE*)lpBuffer, (UINT)strlen(lpBuffer));
|
||
|
es.dwCookie = (DWORD_PTR)&cFile;
|
||
|
|
||
|
m_pTextService->TxSendMessage(EM_STREAMIN, SF_RTF, (LPARAM)&es, &nResult);
|
||
|
if (nResult > 0)
|
||
|
{
|
||
|
return nResult;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CMemFile cFile((BYTE*)lpszText, (UINT)_tcslen(lpszText) * sizeof(TCHAR));
|
||
|
es.dwCookie = (DWORD_PTR)&cFile;
|
||
|
|
||
|
m_pTextService->TxSendMessage(EM_STREAMIN, SF_TEXT | (sizeof(TCHAR) > 1 ? SF_UNICODE : 0), (LPARAM)&es, &nResult);
|
||
|
|
||
|
return nResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
CSize CXTPRichRender::GetTextExtent(CDC* pDC, int nMaxWidth)
|
||
|
{
|
||
|
if (!m_pTextService)
|
||
|
return CSize(0);
|
||
|
|
||
|
LRESULT lResult = 0;
|
||
|
|
||
|
m_pTextService->TxSendMessage(EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE, &lResult);
|
||
|
m_sizeEditMin.cx = m_sizeEditMin.cy = 0;
|
||
|
|
||
|
// Performing the binary search for the best dimension
|
||
|
int cxFirst = 0;
|
||
|
int cxLast = nMaxWidth;
|
||
|
int cyMin = 0;
|
||
|
|
||
|
cxLast *= 2; // cos the first thing we do it divide it by two
|
||
|
RECT rcUpdate = {0, 0, 0, 0};
|
||
|
do
|
||
|
{
|
||
|
// Taking a guess
|
||
|
int cx = (cxFirst + cxLast) / 2;
|
||
|
|
||
|
// Testing this guess
|
||
|
RECTL rc = {0, 0, cx, 1};
|
||
|
|
||
|
m_pTextService->TxDraw(DVASPECT_CONTENT, 0, NULL, NULL, pDC->GetSafeHdc(), 0,
|
||
|
&rc, NULL, &rcUpdate, NULL, 0, 0);
|
||
|
|
||
|
// If it's the first time, take the result anyway.
|
||
|
// This is the minimum height the control needs
|
||
|
if (cyMin == 0)
|
||
|
cyMin = m_sizeEditMin.cy;
|
||
|
|
||
|
// Iterating
|
||
|
if (m_sizeEditMin.cy > cyMin)
|
||
|
{
|
||
|
// If the control required a larger height, then
|
||
|
// it's too narrow.
|
||
|
cxFirst = cx + 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If the control didn't required a larger height,
|
||
|
// then it's too wide.
|
||
|
cxLast = cx - 1;
|
||
|
}
|
||
|
}
|
||
|
while (cxFirst < cxLast);
|
||
|
|
||
|
if (m_sizeEditMin.cy > cyMin)
|
||
|
{
|
||
|
RECTL rc = {0, 0, cxLast + 1, 1};
|
||
|
m_pTextService->TxDraw(DVASPECT_CONTENT, 0, NULL, NULL, pDC->GetSafeHdc(), 0,
|
||
|
&rc, NULL, &rcUpdate, NULL, 0, 0);
|
||
|
}
|
||
|
|
||
|
return m_sizeEditMin;
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::DrawText(CDC* pDC, LPCRECT lpRect)
|
||
|
{
|
||
|
if (!m_pTextService)
|
||
|
return;
|
||
|
|
||
|
m_pTextService->TxDraw(DVASPECT_CONTENT, 0, NULL, NULL, pDC->GetSafeHdc(), 0,
|
||
|
(LPCRECTL)lpRect, NULL, NULL, NULL, 0, 0);
|
||
|
}
|
||
|
|
||
|
BEGIN_INTERFACE_MAP(CXTPRichRender, CCmdTarget)
|
||
|
INTERFACE_PART(CXTPRichRender, IID_XTPITextHost, TextHost)
|
||
|
END_INTERFACE_MAP()
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CXTPRichRender::XTextHost::AddRef()
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CXTPRichRender::XTextHost::Release()
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CXTPRichRender::XTextHost::QueryInterface(REFIID iid, LPVOID* ppvObj)
|
||
|
{
|
||
|
METHOD_PROLOGUE(CXTPRichRender, TextHost)
|
||
|
return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
|
||
|
}
|
||
|
|
||
|
HDC CXTPRichRender::XTextHost::TxGetDC()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
INT CXTPRichRender::XTextHost::TxReleaseDC(HDC /*hdc*/)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxShowScrollBar(INT /*fnBar*/, BOOL /*fShow*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxEnableScrollBar(INT /*fuSBFlags*/, INT /*fuArrowflags*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxSetScrollRange(INT /*fnBar*/, LONG /*nMinPos*/, INT /*nMaxPos*/, BOOL /*fRedraw*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxSetScrollPos(INT /*fnBar*/, INT /*nPos*/, BOOL /*fRedraw*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxInvalidateRect(LPCRECT /*prc*/, BOOL /*fMode*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxViewChange(BOOL /*fUpdate*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxCreateCaret(HBITMAP /*hbmp*/, INT /*xWidth*/, INT /*yHeight*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxShowCaret(BOOL /*fShow*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxSetCaretPos(INT /*x*/, INT /*y*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxSetTimer(UINT /*idTimer*/, UINT /*uTimeout*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxKillTimer(UINT /*idTimer*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxScrollWindowEx(INT /*dx*/, INT /*dy*/, LPCRECT /*lprcScroll*/,
|
||
|
LPCRECT /*lprcClip*/, HRGN /*hrgnUpdate*/, LPRECT /*lprcUpdate*/, UINT /*fuScroll*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxSetCapture(BOOL /*fCapture*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxSetFocus()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxSetCursor(HCURSOR /*hcur*/, BOOL /*fText*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxScreenToClient(LPPOINT /*lppt*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPRichRender::XTextHost::TxClientToScreen(LPPOINT /*lppt*/)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxActivate(LONG* /*plOldState*/)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxDeactivate(LONG /*lNewState*/)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetClientRect(LPRECT /*prc*/)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetViewInset(LPRECT prc)
|
||
|
{
|
||
|
*prc = CRect(0,0,0,0);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetCharFormat(const CHARFORMATW **ppCF)
|
||
|
{
|
||
|
METHOD_PROLOGUE(CXTPRichRender, TextHost)
|
||
|
|
||
|
*ppCF = &(pThis->m_charformat);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetParaFormat(const PARAFORMAT **ppPF)
|
||
|
{
|
||
|
METHOD_PROLOGUE(CXTPRichRender, TextHost)
|
||
|
|
||
|
*ppPF = &(pThis->m_paraformat);
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
COLORREF CXTPRichRender::XTextHost::TxGetSysColor(int nIndex)
|
||
|
{
|
||
|
return ::GetSysColor(nIndex);
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetBackStyle(TXTBACKSTYLE *pstyle)
|
||
|
{
|
||
|
*pstyle = TXTBACK_TRANSPARENT;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetMaxLength(DWORD *plength)
|
||
|
{
|
||
|
*plength = 1024*1024*16;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetScrollBars(DWORD *pdwScrollBar)
|
||
|
{
|
||
|
*pdwScrollBar = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetPasswordChar(TCHAR* /*pch*/)
|
||
|
{
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetAcceleratorPos(LONG *pcp)
|
||
|
{
|
||
|
*pcp = -1;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetExtent(LPSIZEL /*lpExtent*/)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::OnTxCharFormatChange(const CHARFORMATW * /*pcf*/)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::OnTxParaFormatChange(const PARAFORMAT * /*ppf*/)
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits)
|
||
|
{
|
||
|
DWORD bits = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP;
|
||
|
*pdwBits = bits & dwMask;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxNotify(DWORD iNotify, void* pv)
|
||
|
{
|
||
|
METHOD_PROLOGUE(CXTPRichRender, TextHost)
|
||
|
if (iNotify == EN_REQUESTRESIZE)
|
||
|
{
|
||
|
REQRESIZE* prr = (REQRESIZE*)pv;
|
||
|
pThis->m_sizeEditMin.cx = prr->rc.right - prr->rc.left;
|
||
|
pThis->m_sizeEditMin.cy = prr->rc.bottom - prr->rc.top;
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
XTP_HIMC CXTPRichRender::XTextHost::TxImmGetContext()
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void CXTPRichRender::XTextHost::TxImmReleaseContext(XTP_HIMC /*himc*/)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
HRESULT CXTPRichRender::XTextHost::TxGetSelectionBarWidth(LONG* lSelBarWidth)
|
||
|
{
|
||
|
*lSelBarWidth = 0;
|
||
|
return S_OK;
|
||
|
}
|