nim_duilib/duilib/Control/RichEdit.cpp
jiajia_deng 4933d1f2bc Remove dependency on shared
Signed-off-by: jiajia_deng <2894220@gmail.com>
2019-09-20 16:27:58 +08:00

3172 lines
78 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "base/win32/path_util.h"
#include "base/thread/thread_manager.h"
// These constants are for backward compatibility. They are the
// sizes used for initialization and reset in RichEdit 1.0
namespace ui {
const LONG cInitTextMax = (32 * 1024) - 1;
EXTERN_C const IID IID_ITextServices = { // 8d33f740-cf58-11ce-a89d-00aa006cadc5
0x8d33f740,
0xcf58,
0x11ce,
{0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5}
};
EXTERN_C const IID IID_ITextHost = { /* c5bdd8d0-d26e-11ce-a89e-00aa006cadc5 */
0xc5bdd8d0,
0xd26e,
0x11ce,
{0xa8, 0x9e, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5}
};
#ifndef LY_PER_INCH
#define LY_PER_INCH 1440
#endif
#ifndef HIMETRIC_PER_INCH
#define HIMETRIC_PER_INCH 2540
#endif
#include <textserv.h>
class CTxtWinHost : public ITextHost
{
public:
CTxtWinHost();
BOOL Init(RichEdit *re , const CREATESTRUCT *pcs);
virtual ~CTxtWinHost();
ITextServices* GetTextServices(void) { return pserv; }
void SetClientRect(UiRect *prc);
UiRect* GetClientRect() { return &rcClient; }
BOOL GetWordWrap(void) { return fWordWrap; }
void SetWordWrap(BOOL fWordWrap);
BOOL GetReadOnly();
void SetReadOnly(BOOL fReadOnly);
BOOL IsPassword();
void SetPassword(BOOL bPassword);
void SetFont(HFONT hFont);
void SetColor(DWORD dwColor);
SIZEL* GetExtent();
void SetExtent(SIZEL *psizelExtent);
void LimitText(LONG nChars);
BOOL IsCaptured();
BOOL GetAllowBeep();
void SetAllowBeep(BOOL fAllowBeep);
WORD GetDefaultAlign();
void SetDefaultAlign(WORD wNewAlign);
BOOL GetRichTextFlag();
void SetRichTextFlag(BOOL fNew);
LONG GetDefaultLeftIndent();
void SetDefaultLeftIndent(LONG lNewIndent);
BOOL SetSaveSelection(BOOL fSaveSelection);
HRESULT OnTxInPlaceDeactivate();
HRESULT OnTxInPlaceActivate(LPCRECT prcClient);
BOOL GetActiveState(void) { return fInplaceActive; }
BOOL DoSetCursor(UiRect *prc, POINT *pt);
void SetTransparent(BOOL fTransparent);
void GetControlRect(LPRECT prc);
LONG SetAccelPos(LONG laccelpos);
WCHAR SetPasswordChar(WCHAR chPasswordChar);
void SetDisabled(BOOL fOn);
LONG SetSelBarWidth(LONG lSelBarWidth);
BOOL GetTimerState();
void SetCharFormat(CHARFORMAT2W &c);
void SetParaFormat(PARAFORMAT2 &p);
ITextHost * GetTextHost()
{
AddRef();
return this;
}
ITextServices * GetTextServices2()
{
if (NULL == pserv)
return NULL;
pserv->AddRef();
return pserv;
}
BOOL SetOleCallback(IRichEditOleCallback* pCallback)
{
if (NULL == pserv)
return FALSE;
LRESULT lRes = 0;
pserv->TxSendMessage(EM_SETOLECALLBACK, 0, (LPARAM)pCallback, &lRes);
return (BOOL)lRes;
}
BOOL CanPaste(UINT nFormat = 0)
{
if (NULL == pserv)
return FALSE;
LRESULT lRes = 0;
pserv->TxSendMessage(EM_CANPASTE, nFormat, 0L, &lRes);
return (BOOL)lRes;
}
void PasteSpecial(UINT uClipFormat, DWORD dwAspect = 0, HMETAFILE hMF = 0)
{
if (NULL == pserv)
return;
REPASTESPECIAL reps = { dwAspect, (DWORD_PTR)hMF };
pserv->TxSendMessage(EM_PASTESPECIAL, uClipFormat, (LPARAM)&reps, NULL);
}
// -----------------------------
// IUnknown interface
// -----------------------------
virtual HRESULT _stdcall QueryInterface(REFIID riid, void **ppvObject);
virtual ULONG _stdcall AddRef(void);
virtual ULONG _stdcall Release(void);
// -----------------------------
// ITextHost interface
// -----------------------------
virtual HDC TxGetDC();
virtual INT TxReleaseDC(HDC hdc);
virtual BOOL TxShowScrollBar(INT fnBar, BOOL fShow);
virtual BOOL TxEnableScrollBar (INT fuSBFlags, INT fuArrowflags);
virtual BOOL TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw);
virtual BOOL TxSetScrollPos (INT fnBar, INT nPos, BOOL fRedraw);
virtual void TxInvalidateRect(LPCRECT prc, BOOL fMode);
virtual void TxViewChange(BOOL fUpdate);
virtual BOOL TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight);
virtual BOOL TxShowCaret(BOOL fShow);
virtual BOOL TxSetCaretPos(INT x, INT y);
virtual BOOL TxSetTimer(UINT idTimer, UINT uTimeout);
virtual void TxKillTimer(UINT idTimer);
virtual void TxScrollWindowEx (INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate, UINT fuScroll);
virtual void TxSetCapture(BOOL fCapture);
virtual void TxSetFocus();
virtual void TxSetCursor(HCURSOR hcur, BOOL fText);
virtual BOOL TxScreenToClient (LPPOINT lppt);
virtual BOOL TxClientToScreen (LPPOINT lppt);
virtual HRESULT TxActivate( LONG * plOldState );
virtual HRESULT TxDeactivate( LONG lNewState );
virtual HRESULT TxGetClientRect(LPRECT prc);
virtual HRESULT TxGetViewInset(LPRECT prc);
virtual HRESULT TxGetCharFormat(const CHARFORMATW **ppCF );
virtual HRESULT TxGetParaFormat(const PARAFORMAT **ppPF);
virtual COLORREF TxGetSysColor(int nIndex);
virtual HRESULT TxGetBackStyle(TXTBACKSTYLE *pstyle);
virtual HRESULT TxGetMaxLength(DWORD *plength);
virtual HRESULT TxGetScrollBars(DWORD *pdwScrollBar);
virtual HRESULT TxGetPasswordChar(TCHAR *pch);
virtual HRESULT TxGetAcceleratorPos(LONG *pcp);
virtual HRESULT TxGetExtent(LPSIZEL lpExtent);
virtual HRESULT OnTxCharFormatChange (const CHARFORMATW * pcf);
virtual HRESULT OnTxParaFormatChange (const PARAFORMAT * ppf);
virtual HRESULT TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits);
virtual HRESULT TxNotify(DWORD iNotify, void *pv);
virtual HIMC TxImmGetContext(void);
virtual void TxImmReleaseContext(HIMC himc);
virtual HRESULT TxGetSelectionBarWidth (LONG *lSelBarWidth);
private:
RichEdit *m_re;
ULONG cRefs; // Reference Count
ITextServices *pserv; // pointer to Text Services object
// Properties
DWORD dwStyle; // style bits
unsigned fEnableAutoWordSel :1; // enable Word style auto word selection?
unsigned fWordWrap :1; // Whether control should word wrap
unsigned fAllowBeep :1; // Whether beep is allowed
unsigned fRich :1; // Whether control is rich text
unsigned fSaveSelection :1; // Whether to save the selection when inactive
unsigned fInplaceActive :1; // Whether control is inplace active
unsigned fTransparent :1; // Whether control is transparent
unsigned fTimer :1; // A timer is set
unsigned fCaptured :1;
LONG lSelBarWidth; // Width of the selection bar
LONG cchTextMost; // maximum text size
DWORD dwEventMask; // HandleMessage mask to pass on to parent window
LONG icf;
LONG ipf;
UiRect rcClient; // Client Rect for this control
SIZEL sizelExtent; // Extent array
CHARFORMAT2W cf; // Default character format
PARAFORMAT2 pf; // Default paragraph format
LONG laccelpos; // Accelerator position
WCHAR chPasswordChar; // Password character
};
// Convert Pixels on the X axis to Himetric
LONG DXtoHimetricX(LONG dx, LONG xPerInch)
{
return (LONG) MulDiv(dx, HIMETRIC_PER_INCH, xPerInch);
}
// Convert Pixels on the Y axis to Himetric
LONG DYtoHimetricY(LONG dy, LONG yPerInch)
{
return (LONG) MulDiv(dy, HIMETRIC_PER_INCH, yPerInch);
}
HRESULT InitDefaultCharFormat(RichEdit* re, CHARFORMAT2W* pcf, HFONT hfont)
{
memset(pcf, 0, sizeof(CHARFORMAT2W));
LOGFONT lf;
if( !hfont )
hfont = GlobalManager::GetFont(re->GetFont());
::GetObject(hfont, sizeof(LOGFONT), &lf);
DWORD dwColor = GlobalManager::GetTextColor(re->GetTextColor());
pcf->cbSize = sizeof(CHARFORMAT2W);
pcf->crTextColor = RGB(GetBValue(dwColor), GetGValue(dwColor), GetRValue(dwColor));
LONG yPixPerInch = GetDeviceCaps(re->GetWindow()->GetPaintDC(), LOGPIXELSY);
if (yPixPerInch == 0)
yPixPerInch = 96;
pcf->yHeight = -lf.lfHeight * LY_PER_INCH / yPixPerInch;
pcf->yOffset = 0;
pcf->dwEffects = 0;
pcf->dwMask = CFM_SIZE | CFM_OFFSET | CFM_FACE | CFM_CHARSET | CFM_COLOR | CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE;
if(lf.lfWeight >= FW_BOLD)
pcf->dwEffects |= CFE_BOLD;
if(lf.lfItalic)
pcf->dwEffects |= CFE_ITALIC;
if(lf.lfUnderline)
pcf->dwEffects |= CFE_UNDERLINE;
pcf->bCharSet = lf.lfCharSet;
pcf->bPitchAndFamily = lf.lfPitchAndFamily;
#ifdef _UNICODE
_tcscpy(pcf->szFaceName, lf.lfFaceName);
#else
//need to thunk pcf->szFaceName to a standard char string.in this case it's easy because our thunk is also our copy
MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, LF_FACESIZE, pcf->szFaceName, LF_FACESIZE) ;
#endif
return S_OK;
}
HRESULT InitDefaultParaFormat(RichEdit* re, PARAFORMAT2* ppf)
{
memset(ppf, 0, sizeof(PARAFORMAT2));
ppf->cbSize = sizeof(PARAFORMAT2);
ppf->dwMask = PFM_ALL;
ppf->wAlignment = PFA_LEFT;
ppf->cTabCount = 1;
ppf->rgxTabs[0] = lDefaultTab;
return S_OK;
}
HRESULT CreateHost(RichEdit *re, const CREATESTRUCT *pcs, CTxtWinHost **pptec)
{
HRESULT hr = E_FAIL;
//GdiSetBatchLimit(1);
CTxtWinHost *phost = new CTxtWinHost();
if(phost)
{
if (phost->Init(re, pcs))
{
*pptec = phost;
hr = S_OK;
}
}
if (FAILED(hr))
{
delete phost;
}
return TRUE;
}
CTxtWinHost::CTxtWinHost() : m_re(NULL)
{
::ZeroMemory(&cRefs, sizeof(CTxtWinHost) - offsetof(CTxtWinHost, cRefs));
cchTextMost = cInitTextMax;
laccelpos = -1;
}
CTxtWinHost::~CTxtWinHost()
{
pserv->OnTxInPlaceDeactivate();
pserv->Release();
}
////////////////////// Create/Init/Destruct Commands ///////////////////////
BOOL CTxtWinHost::Init(RichEdit *re, const CREATESTRUCT *pcs)
{
PCreateTextServices TextServicesProc = nullptr;
IUnknown *pUnk = nullptr;
HMODULE hmod = NULL;
HRESULT hr;
std::wstring edit_dll(L"msftedit.dll");
m_re = re;
// Initialize Reference count
cRefs = 1;
// Create and cache CHARFORMAT for this control
if(FAILED(InitDefaultCharFormat(re, &cf, NULL)))
goto err;
// Create and cache PARAFORMAT for this control
if(FAILED(InitDefaultParaFormat(re, &pf)))
goto err;
// edit controls created without a window are multiline by default
// so that paragraph formats can be
dwStyle = ES_MULTILINE;
// edit controls are rich by default
fRich = re->IsRich();
cchTextMost = re->GetLimitText();
if (pcs )
{
dwStyle = pcs->style;
if ( !(dwStyle & (ES_AUTOHSCROLL | WS_HSCROLL)) )
{
fWordWrap = TRUE;
}
}
if( !(dwStyle & ES_LEFT) )
{
if(dwStyle & ES_CENTER)
pf.wAlignment = PFA_CENTER;
else if(dwStyle & ES_RIGHT)
pf.wAlignment = PFA_RIGHT;
}
fInplaceActive = TRUE;
// Create Text Services component
//if(FAILED(CreateTextServices(NULL, this, &pUnk)))
// goto err;
//<2F><><EFBFBD><EFBFBD>32λϵͳ<CFB5>¿細<C2BF>ڼ<EFBFBD><DABC><EFBFBD>ק<EFBFBD><D7A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>win7<6E><37>win7<6E><37><EFBFBD><EFBFBD>ϵͳ<CFB5>ϻ<EFBFBD><CFBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⣨64λ<34>ݲ<EFBFBD><DDB2>޸<EFBFBD><DEB8><EFBFBD> lty 20170714
#if defined(_M_X64) || defined(__x86_64__)
edit_dll = L"msftedit.dll";
#else
edit_dll = nbase::win32::GetCurrentModuleDirectory() + L"msftedit50.dll";
if (!(::GetFileAttributesW(edit_dll.c_str()) != INVALID_FILE_ATTRIBUTES))
edit_dll = L"msftedit.dll";
#endif
hmod = LoadLibraryW(edit_dll.c_str()); //msftedit.dll
if (hmod)
{
TextServicesProc = (PCreateTextServices)GetProcAddress(hmod,"CreateTextServices");
}
if (TextServicesProc)
{
TextServicesProc(NULL, this, &pUnk);
}
hr = pUnk->QueryInterface(IID_ITextServices,(void **)&pserv);
// Whether the previous call succeeded or failed we are done
// with the private interface.
pUnk->Release();
if(FAILED(hr))
{
goto err;
}
// Set window text
if(pcs && pcs->lpszName)
{
#ifdef _UNICODE
if(FAILED(pserv->TxSetText((TCHAR *)pcs->lpszName)))
goto err;
#else
std::size_t iLen = _tcslen(pcs->lpszName);
LPWSTR lpText = new WCHAR[iLen + 1];
::ZeroMemory(lpText, (iLen + 1) * sizeof(WCHAR));
::MultiByteToWideChar(CP_ACP, 0, pcs->lpszName, -1, (LPWSTR)lpText, iLen) ;
if(FAILED(pserv->TxSetText((LPWSTR)lpText))) {
delete[] lpText;
goto err;
}
delete[] lpText;
#endif
}
return TRUE;
err:
return FALSE;
}
///////////////////////////////// IUnknown ////////////////////////////////
HRESULT CTxtWinHost::QueryInterface(REFIID riid, void **ppvObject)
{
HRESULT hr = E_NOINTERFACE;
*ppvObject = NULL;
if (IsEqualIID(riid, IID_IUnknown)
|| IsEqualIID(riid, IID_ITextHost))
{
AddRef();
*ppvObject = (ITextHost *) this;
hr = S_OK;
}
return hr;
}
ULONG CTxtWinHost::AddRef(void)
{
return ++cRefs;
}
ULONG CTxtWinHost::Release(void)
{
ULONG c_Refs = --cRefs;
if (c_Refs == 0)
{
delete this;
}
return c_Refs;
}
///////////////////////////////// Far East Support //////////////////////////////////////
HIMC CTxtWinHost::TxImmGetContext(void)
{
return NULL;
}
void CTxtWinHost::TxImmReleaseContext(HIMC himc)
{
//::ImmReleaseContext( hwnd, himc );
}
//////////////////////////// ITextHost Interface ////////////////////////////
HDC CTxtWinHost::TxGetDC()
{
return m_re->GetWindow()->GetPaintDC();
}
int CTxtWinHost::TxReleaseDC(HDC hdc)
{
return 1;
}
BOOL CTxtWinHost::TxShowScrollBar(INT fnBar, BOOL fShow)
{
ASSERT(FALSE); //<2F><>ʱע<CAB1>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɶ<EFBFBD><C9B6> by panqinke 2014.5.6
//ScrollBar* pVerticalScrollBar = m_re->GetVerticalScrollBar();
//ScrollBar* pHorizontalScrollBar = m_re->GetHorizontalScrollBar();
//if( fnBar == SB_VERT && pVerticalScrollBar ) {
// pVerticalScrollBar->SetVisible(fShow == TRUE);
//}
//else if( fnBar == SB_HORZ && pHorizontalScrollBar ) {
// pHorizontalScrollBar->SetVisible(fShow == TRUE);
//}
//else if( fnBar == SB_BOTH ) {
// if( pVerticalScrollBar ) pVerticalScrollBar->SetVisible(fShow == TRUE);
// if( pHorizontalScrollBar ) pHorizontalScrollBar->SetVisible(fShow == TRUE);
//}
return TRUE;
}
BOOL CTxtWinHost::TxEnableScrollBar (INT fuSBFlags, INT fuArrowflags)
{
if( fuSBFlags == SB_VERT ) {
if (fuArrowflags == ESB_DISABLE_BOTH) {
m_re->GetVerticalScrollBar()->SetScrollRange(0);
}
}
else if( fuSBFlags == SB_HORZ ) {
if (fuArrowflags == ESB_DISABLE_BOTH) {
m_re->GetHorizontalScrollBar()->SetScrollRange(0);
}
}
else if( fuSBFlags == SB_BOTH ) {
if (fuArrowflags == ESB_DISABLE_BOTH) {
m_re->GetVerticalScrollBar()->SetScrollRange(0);
}
if (fuArrowflags == ESB_DISABLE_BOTH) {
m_re->GetHorizontalScrollBar()->SetScrollRange(0);
}
}
m_re->SetPos(m_re->GetPos());
return TRUE;
}
BOOL CTxtWinHost::TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw)
{
ScrollBar* pVerticalScrollBar = m_re->GetVerticalScrollBar();
ScrollBar* pHorizontalScrollBar = m_re->GetHorizontalScrollBar();
bool bArrange = false;
if( fnBar == SB_VERT && pVerticalScrollBar ) {
if( nMaxPos - nMinPos - rcClient.bottom + rcClient.top <= 0 ) {
pVerticalScrollBar->SetScrollRange(0);
}
else {
if (!pVerticalScrollBar->IsValid()) {
bArrange = true;
}
pVerticalScrollBar->SetScrollRange(nMaxPos - nMinPos - rcClient.bottom + rcClient.top);
}
}
else if( fnBar == SB_HORZ && pHorizontalScrollBar ) {
if( nMaxPos - nMinPos - rcClient.right + rcClient.left <= 0 ) {
pHorizontalScrollBar->SetScrollRange(0);
}
else {
if (!pHorizontalScrollBar->IsValid()) {
bArrange = true;
}
pHorizontalScrollBar->SetScrollRange(nMaxPos - nMinPos - rcClient.right + rcClient.left);
}
}
if (bArrange) {
m_re->SetPos(m_re->GetPos());
}
return TRUE;
}
BOOL CTxtWinHost::TxSetScrollPos (INT fnBar, INT nPos, BOOL fRedraw)
{
ScrollBar* pVerticalScrollBar = m_re->GetVerticalScrollBar();
ScrollBar* pHorizontalScrollBar = m_re->GetHorizontalScrollBar();
if( fnBar == SB_VERT && pVerticalScrollBar ) {
pVerticalScrollBar->SetScrollPos(nPos);
}
else if( fnBar == SB_HORZ && pHorizontalScrollBar ) {
pHorizontalScrollBar->SetScrollPos(nPos);
}
return TRUE;
}
void CTxtWinHost::TxInvalidateRect(LPCRECT prc, BOOL fMode)
{
CPoint scrollOffset = m_re->GetScrollOffset();
if( prc == NULL ) {
UiRect newRcClient = rcClient;
newRcClient.Offset(-scrollOffset.x, -scrollOffset.y);
m_re->GetWindow()->Invalidate(newRcClient);
return;
}
UiRect rc = *prc;
rc.Offset(-scrollOffset.x, -scrollOffset.y);
m_re->GetWindow()->Invalidate(rc);
}
void CTxtWinHost::TxViewChange(BOOL fUpdate)
{
}
BOOL CTxtWinHost::TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight)
{
return m_re->CreateCaret(xWidth, yHeight);
}
BOOL CTxtWinHost::TxShowCaret(BOOL fShow)
{
return true; // m_re->ShowCaret(fShow);
}
BOOL CTxtWinHost::TxSetCaretPos(INT x, INT y)
{
return m_re->SetCaretPos(x, y);
}
BOOL CTxtWinHost::TxSetTimer(UINT idTimer, UINT uTimeout)
{
fTimer = TRUE;
m_re->SetTimer(idTimer, uTimeout);
return TRUE;
}
void CTxtWinHost::TxKillTimer(UINT idTimer)
{
m_re->KillTimer(idTimer);
fTimer = FALSE;
}
void CTxtWinHost::TxScrollWindowEx (INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate, UINT fuScroll)
{
return;
}
void CTxtWinHost::TxSetCapture(BOOL fCapture)
{
if (fCapture) m_re->GetWindow()->SetCapture();
else m_re->GetWindow()->ReleaseCapture();
fCaptured = fCapture;
}
void CTxtWinHost::TxSetFocus()
{
m_re->SetFocus();
}
void CTxtWinHost::TxSetCursor(HCURSOR hcur, BOOL fText)
{
::SetCursor(hcur);
}
BOOL CTxtWinHost::TxScreenToClient(LPPOINT lppt)
{
return ::ScreenToClient(m_re->GetWindow()->GetHWND(), lppt);
}
BOOL CTxtWinHost::TxClientToScreen(LPPOINT lppt)
{
return ::ClientToScreen(m_re->GetWindow()->GetHWND(), lppt);
}
HRESULT CTxtWinHost::TxActivate(LONG *plOldState)
{
return S_OK;
}
HRESULT CTxtWinHost::TxDeactivate(LONG lNewState)
{
return S_OK;
}
HRESULT CTxtWinHost::TxGetClientRect(LPRECT prc)
{
*prc = rcClient;
GetControlRect(prc);
return NOERROR;
}
HRESULT CTxtWinHost::TxGetViewInset(LPRECT prc)
{
prc->left = prc->right = prc->top = prc->bottom = 0;
return NOERROR;
}
HRESULT CTxtWinHost::TxGetCharFormat(const CHARFORMATW **ppCF)
{
*ppCF = &cf;
return NOERROR;
}
HRESULT CTxtWinHost::TxGetParaFormat(const PARAFORMAT **ppPF)
{
*ppPF = &pf;
return NOERROR;
}
COLORREF CTxtWinHost::TxGetSysColor(int nIndex)
{
return ::GetSysColor(nIndex);
}
HRESULT CTxtWinHost::TxGetBackStyle(TXTBACKSTYLE *pstyle)
{
*pstyle = !fTransparent ? TXTBACK_OPAQUE : TXTBACK_TRANSPARENT;
return NOERROR;
}
HRESULT CTxtWinHost::TxGetMaxLength(DWORD *pLength)
{
*pLength = cchTextMost;
return NOERROR;
}
HRESULT CTxtWinHost::TxGetScrollBars(DWORD *pdwScrollBar)
{
*pdwScrollBar = dwStyle & (WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL |
ES_AUTOHSCROLL | ES_DISABLENOSCROLL);
return NOERROR;
}
HRESULT CTxtWinHost::TxGetPasswordChar(TCHAR *pch)
{
#ifdef _UNICODE
*pch = chPasswordChar;
#else
::WideCharToMultiByte(CP_ACP, 0, &chPasswordChar, 1, pch, 1, NULL, NULL) ;
#endif
return NOERROR;
}
HRESULT CTxtWinHost::TxGetAcceleratorPos(LONG *pcp)
{
*pcp = laccelpos;
return S_OK;
}
HRESULT CTxtWinHost::OnTxCharFormatChange(const CHARFORMATW *pcf)
{
return S_OK;
}
HRESULT CTxtWinHost::OnTxParaFormatChange(const PARAFORMAT *ppf)
{
return S_OK;
}
HRESULT CTxtWinHost::TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits)
{
DWORD dwProperties = 0;
if (fRich)
{
dwProperties = TXTBIT_RICHTEXT;
}
if (dwStyle & ES_MULTILINE)
{
dwProperties |= TXTBIT_MULTILINE;
}
if (dwStyle & ES_READONLY)
{
dwProperties |= TXTBIT_READONLY;
}
if (dwStyle & ES_PASSWORD)
{
dwProperties |= TXTBIT_USEPASSWORD;
}
if (!(dwStyle & ES_NOHIDESEL))
{
dwProperties |= TXTBIT_HIDESELECTION;
}
if (fEnableAutoWordSel)
{
dwProperties |= TXTBIT_AUTOWORDSEL;
}
if (fWordWrap)
{
dwProperties |= TXTBIT_WORDWRAP;
}
if (fAllowBeep)
{
dwProperties |= TXTBIT_ALLOWBEEP;
}
if (fSaveSelection)
{
dwProperties |= TXTBIT_SAVESELECTION;
}
*pdwBits = dwProperties & dwMask;
return NOERROR;
}
HRESULT CTxtWinHost::TxNotify(DWORD iNotify, void *pv)
{
if( iNotify == EN_REQUESTRESIZE ) {
UiRect rc;
REQRESIZE *preqsz = (REQRESIZE *)pv;
GetControlRect(&rc);
rc.bottom = rc.top + preqsz->rc.bottom;
rc.right = rc.left + preqsz->rc.right;
SetClientRect(&rc);
}
m_re->OnTxNotify(iNotify, pv);
return S_OK;
}
HRESULT CTxtWinHost::TxGetExtent(LPSIZEL lpExtent)
{
*lpExtent = sizelExtent;
return S_OK;
}
HRESULT CTxtWinHost::TxGetSelectionBarWidth (LONG *plSelBarWidth)
{
*plSelBarWidth = lSelBarWidth;
return S_OK;
}
void CTxtWinHost::SetWordWrap(BOOL fWordWrap)
{
fWordWrap = fWordWrap;
pserv->OnTxPropertyBitsChange(TXTBIT_WORDWRAP, fWordWrap ? TXTBIT_WORDWRAP : 0);
}
BOOL CTxtWinHost::GetReadOnly()
{
return (dwStyle & ES_READONLY) != 0;
}
void CTxtWinHost::SetReadOnly(BOOL fReadOnly)
{
if (fReadOnly)
{
dwStyle |= ES_READONLY;
}
else
{
dwStyle &= ~ES_READONLY;
}
pserv->OnTxPropertyBitsChange(TXTBIT_READONLY,
fReadOnly ? TXTBIT_READONLY : 0);
}
BOOL CTxtWinHost::IsPassword()
{
return (dwStyle & ES_PASSWORD) != 0;
}
void CTxtWinHost::SetPassword(BOOL bPassword)
{
if (bPassword)
{
dwStyle |= ES_PASSWORD;
}
else
{
dwStyle &= ~ES_PASSWORD;
}
pserv->OnTxPropertyBitsChange(TXTBIT_USEPASSWORD,
bPassword ? TXTBIT_USEPASSWORD : 0);
}
void CTxtWinHost::SetFont(HFONT hFont)
{
if( hFont == NULL ) return;
LOGFONT lf;
::GetObject(hFont, sizeof(LOGFONT), &lf);
LONG yPixPerInch = ::GetDeviceCaps(m_re->GetWindow()->GetPaintDC(), LOGPIXELSY);
if (yPixPerInch == 0)
yPixPerInch = 96;
cf.yHeight = -lf.lfHeight * LY_PER_INCH / yPixPerInch;
if(lf.lfWeight >= FW_BOLD)
cf.dwEffects |= CFE_BOLD;
if(lf.lfItalic)
cf.dwEffects |= CFE_ITALIC;
if(lf.lfUnderline)
cf.dwEffects |= CFE_UNDERLINE;
cf.bCharSet = lf.lfCharSet;
cf.bPitchAndFamily = lf.lfPitchAndFamily;
#ifdef _UNICODE
_tcscpy(cf.szFaceName, lf.lfFaceName);
#else
//need to thunk pcf->szFaceName to a standard char string.in this case it's easy because our thunk is also our copy
MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, LF_FACESIZE, cf.szFaceName, LF_FACESIZE) ;
#endif
pserv->OnTxPropertyBitsChange(TXTBIT_CHARFORMATCHANGE,
TXTBIT_CHARFORMATCHANGE);
}
void CTxtWinHost::SetColor(DWORD dwColor)
{
cf.crTextColor = RGB(GetBValue(dwColor), GetGValue(dwColor), GetRValue(dwColor));
pserv->OnTxPropertyBitsChange(TXTBIT_CHARFORMATCHANGE,
TXTBIT_CHARFORMATCHANGE);
}
SIZEL* CTxtWinHost::GetExtent()
{
return &sizelExtent;
}
void CTxtWinHost::SetExtent(SIZEL *psizelExtent)
{
sizelExtent = *psizelExtent;
pserv->OnTxPropertyBitsChange(TXTBIT_EXTENTCHANGE, TXTBIT_EXTENTCHANGE);
}
void CTxtWinHost::LimitText(LONG nChars)
{
cchTextMost = nChars;
if( cchTextMost <= 0 ) cchTextMost = cInitTextMax;
pserv->OnTxPropertyBitsChange(TXTBIT_MAXLENGTHCHANGE, TXTBIT_MAXLENGTHCHANGE);
}
BOOL CTxtWinHost::IsCaptured()
{
return fCaptured;
}
BOOL CTxtWinHost::GetAllowBeep()
{
return fAllowBeep;
}
void CTxtWinHost::SetAllowBeep(BOOL fAllowBeep)
{
fAllowBeep = fAllowBeep;
pserv->OnTxPropertyBitsChange(TXTBIT_ALLOWBEEP,
fAllowBeep ? TXTBIT_ALLOWBEEP : 0);
}
WORD CTxtWinHost::GetDefaultAlign()
{
return pf.wAlignment;
}
void CTxtWinHost::SetDefaultAlign(WORD wNewAlign)
{
pf.wAlignment = wNewAlign;
// Notify control of property change
pserv->OnTxPropertyBitsChange(TXTBIT_PARAFORMATCHANGE, 0);
}
BOOL CTxtWinHost::GetRichTextFlag()
{
return fRich;
}
void CTxtWinHost::SetRichTextFlag(BOOL fNew)
{
fRich = fNew;
pserv->OnTxPropertyBitsChange(TXTBIT_RICHTEXT,
fNew ? TXTBIT_RICHTEXT : 0);
}
LONG CTxtWinHost::GetDefaultLeftIndent()
{
return pf.dxOffset;
}
void CTxtWinHost::SetDefaultLeftIndent(LONG lNewIndent)
{
pf.dxOffset = lNewIndent;
pserv->OnTxPropertyBitsChange(TXTBIT_PARAFORMATCHANGE, 0);
}
void CTxtWinHost::SetClientRect(UiRect *prc)
{
rcClient = *prc;
LONG xPerInch = ::GetDeviceCaps(m_re->GetWindow()->GetPaintDC(), LOGPIXELSX);
LONG yPerInch = ::GetDeviceCaps(m_re->GetWindow()->GetPaintDC(), LOGPIXELSY);
if (xPerInch == 0)
xPerInch = 96;
if (yPerInch == 0)
yPerInch = 96;
sizelExtent.cx = DXtoHimetricX(rcClient.right - rcClient.left, xPerInch);
sizelExtent.cy = DYtoHimetricY(rcClient.bottom - rcClient.top, yPerInch);
pserv->OnTxPropertyBitsChange(TXTBIT_VIEWINSETCHANGE, TXTBIT_VIEWINSETCHANGE);
}
BOOL CTxtWinHost::SetSaveSelection(BOOL f_SaveSelection)
{
BOOL fResult = f_SaveSelection;
fSaveSelection = f_SaveSelection;
// notify text services of property change
pserv->OnTxPropertyBitsChange(TXTBIT_SAVESELECTION,
fSaveSelection ? TXTBIT_SAVESELECTION : 0);
return fResult;
}
HRESULT CTxtWinHost::OnTxInPlaceDeactivate()
{
HRESULT hr = pserv->OnTxInPlaceDeactivate();
if (SUCCEEDED(hr))
{
fInplaceActive = FALSE;
}
return hr;
}
HRESULT CTxtWinHost::OnTxInPlaceActivate(LPCRECT prcClient)
{
fInplaceActive = TRUE;
HRESULT hr = pserv->OnTxInPlaceActivate(prcClient);
if (FAILED(hr))
{
fInplaceActive = FALSE;
}
return hr;
}
BOOL CTxtWinHost::DoSetCursor(UiRect *prc, POINT *pt)
{
UiRect rc = (prc != NULL) ? *prc : rcClient;
// Is this in our rectangle?
CPoint newPt = *pt;
newPt.Offset(m_re->GetScrollOffset());
if (PtInRect(&rc, newPt))
{
UiRect *prcClient = (!fInplaceActive || prc) ? &rc : NULL;
pserv->OnTxSetCursor(DVASPECT_CONTENT, -1, NULL, NULL, m_re->GetWindow()->GetPaintDC(),
NULL, prcClient, newPt.x, newPt.y);
return TRUE;
}
return FALSE;
}
void CTxtWinHost::GetControlRect(LPRECT prc)
{
UiRect rc = rcClient;
VerAlignType alignType = m_re->GetTextVerAlignType();
if (alignType != kVerAlignTop) {
LONG iWidth = rc.right - rc.left;
LONG iHeight = 0;
SIZEL szExtent = { -1, -1 };
GetTextServices()->TxGetNaturalSize(
DVASPECT_CONTENT,
m_re->GetWindow()->GetPaintDC(),
NULL,
NULL,
TXTNS_FITTOCONTENT,
&szExtent,
&iWidth,
&iHeight);
if (alignType == kVerAlignCenter) {
rc.Offset(0, (rc.bottom - rc.top - iHeight) / 2);
}
else if (alignType == kVerAlignBottom) {
rc.Offset(0, prc->bottom - prc->top - iHeight);
}
}
prc->left = rc.left;
prc->top = rc.top;
prc->right = rc.right;
prc->bottom = rc.bottom;
}
void CTxtWinHost::SetTransparent(BOOL f_Transparent)
{
fTransparent = f_Transparent;
// notify text services of property change
pserv->OnTxPropertyBitsChange(TXTBIT_BACKSTYLECHANGE, 0);
}
LONG CTxtWinHost::SetAccelPos(LONG l_accelpos)
{
LONG laccelposOld = l_accelpos;
laccelpos = l_accelpos;
// notify text services of property change
pserv->OnTxPropertyBitsChange(TXTBIT_SHOWACCELERATOR, 0);
return laccelposOld;
}
WCHAR CTxtWinHost::SetPasswordChar(WCHAR ch_PasswordChar)
{
WCHAR chOldPasswordChar = chPasswordChar;
chPasswordChar = ch_PasswordChar;
// notify text services of property change
pserv->OnTxPropertyBitsChange(TXTBIT_USEPASSWORD,
(chPasswordChar != 0) ? TXTBIT_USEPASSWORD : 0);
return chOldPasswordChar;
}
void CTxtWinHost::SetDisabled(BOOL fOn)
{
cf.dwMask |= CFM_COLOR | CFM_DISABLED;
cf.dwEffects |= CFE_AUTOCOLOR | CFE_DISABLED;
if( !fOn )
{
cf.dwEffects &= ~CFE_DISABLED;
}
pserv->OnTxPropertyBitsChange(TXTBIT_CHARFORMATCHANGE,
TXTBIT_CHARFORMATCHANGE);
}
LONG CTxtWinHost::SetSelBarWidth(LONG l_SelBarWidth)
{
LONG lOldSelBarWidth = lSelBarWidth;
lSelBarWidth = l_SelBarWidth;
if (lSelBarWidth)
{
dwStyle |= ES_SELECTIONBAR;
}
else
{
dwStyle &= (~ES_SELECTIONBAR);
}
pserv->OnTxPropertyBitsChange(TXTBIT_SELBARCHANGE, TXTBIT_SELBARCHANGE);
return lOldSelBarWidth;
}
BOOL CTxtWinHost::GetTimerState()
{
return fTimer;
}
void CTxtWinHost::SetCharFormat(CHARFORMAT2W &c)
{
cf = c;
}
void CTxtWinHost::SetParaFormat(PARAFORMAT2 &p)
{
pf = p;
}
/////////////////////////////////////////////////////////////////////////////////////
//
//
RichEdit::RichEdit() :
ScrollableBox(new Layout),
m_pTwh(nullptr),
m_bVScrollBarFixing(false),
m_bWantTab(true),
m_bNeedReturnMsg(false),
m_bReturnMsgWantCtrl(false),
m_bRich(false),
m_bReadOnly(false),
m_bPassword(false),
m_bWordWrap(false),
m_bNumberOnly(false),
m_bInited(false),
m_bAllowPrompt(false),
m_bSelAllEver(false),
m_bNoSelOnKillFocus(true),
m_bSelAllOnFocus(false),
m_bNoCaretReadonly(false),
m_bIsCaretVisiable(false),
m_bIsComposition(false),
m_iCaretPosX(0),
m_iCaretPosY(0),
m_iCaretWidth(0),
m_iCaretHeight(0),
m_sFontId(),
m_iLimitText(0),
m_lTwhStyle(ES_MULTILINE),
m_textVerAlignType(kVerAlignTop),
m_sCurrentColor(),
m_sTextColor(),
m_sDisabledTextColor(),
m_sPromptColor(),
m_sText(),
m_sPromptText(),
m_drawCaretFlag(),
m_timeFlagMap(),
m_linkInfo(),
m_sFocusedImage()
{
m_iLimitText = cInitTextMax;
m_sCurrentColor = GlobalManager::GetDefaultTextColor();
m_sTextColor = m_sCurrentColor;
m_sDisabledTextColor = m_sCurrentColor;
}
RichEdit::~RichEdit()
{
if( m_pTwh ) {
m_pTwh->Release();
}
}
bool RichEdit::IsWantTab()
{
return m_bWantTab;
}
void RichEdit::SetWantTab(bool bWantTab)
{
m_bWantTab = bWantTab;
}
bool RichEdit::IsNeedReturnMsg()
{
return m_bNeedReturnMsg;
}
void RichEdit::SetNeedReturnMsg(bool bNeedReturnMsg)
{
m_bNeedReturnMsg = bNeedReturnMsg;
}
bool RichEdit::IsReturnMsgWantCtrl()
{
return m_bReturnMsgWantCtrl;
}
void RichEdit::SetReturnMsgWantCtrl(bool bReturnMsgWantCtrl)
{
m_bReturnMsgWantCtrl = bReturnMsgWantCtrl;
}
bool RichEdit::IsRich()
{
return m_bRich;
}
void RichEdit::SetRich(bool bRich)
{
m_bRich = bRich;
if( m_pTwh ) m_pTwh->SetRichTextFlag(bRich);
}
bool RichEdit::IsReadOnly()
{
return m_bReadOnly;
}
void RichEdit::SetReadOnly(bool bReadOnly)
{
m_bReadOnly = bReadOnly;
if( m_pTwh ) m_pTwh->SetReadOnly(bReadOnly);
}
bool RichEdit::IsPassword()
{
return m_bPassword;
}
void RichEdit::SetPassword( bool bPassword )
{
m_bPassword = bPassword;
if( m_pTwh ) m_pTwh->SetPassword(bPassword);
}
bool RichEdit::GetWordWrap()
{
return m_bWordWrap;
}
void RichEdit::SetWordWrap(bool bWordWrap)
{
m_bWordWrap = bWordWrap;
if( m_pTwh ) m_pTwh->SetWordWrap(bWordWrap);
}
std::wstring RichEdit::GetFont() const
{
return m_sFontId;
}
void RichEdit::SetFont(const std::wstring& strFontId)
{
m_sFontId = strFontId;
if( m_pTwh ) {
m_pTwh->SetFont(GlobalManager::GetFont(m_sFontId));
}
}
void RichEdit::SetFont(const std::wstring& pStrFontName, int nSize, bool bBold, bool bUnderline, bool bItalic)
{
if( m_pTwh ) {
LOGFONT lf = { 0 };
::GetObject(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
_tcscpy(lf.lfFaceName, pStrFontName.c_str());
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfHeight = -nSize;
if( bBold ) lf.lfWeight += FW_BOLD;
if( bUnderline ) lf.lfUnderline = TRUE;
if( bItalic ) lf.lfItalic = TRUE;
HFONT hFont = ::CreateFontIndirect(&lf);
if( hFont == NULL ) return;
m_pTwh->SetFont(hFont);
::DeleteObject(hFont);
}
}
void RichEdit::SetFont(HFONT font)
{
if (m_pTwh) {
m_pTwh->SetFont(font);
}
}
LONG RichEdit::GetWinStyle()
{
return m_lTwhStyle;
}
void RichEdit::SetWinStyle(LONG lStyle)
{
m_lTwhStyle = lStyle;
}
ui::VerAlignType RichEdit::GetTextVerAlignType()
{
return m_textVerAlignType;
}
void RichEdit::SetTextColor(const std::wstring& dwTextColor)
{
if(m_sCurrentColor == dwTextColor)
return;
m_sCurrentColor = dwTextColor;
DWORD dwTextColor2 = GlobalManager::GetTextColor(dwTextColor);
if( m_pTwh ) {
m_pTwh->SetColor(dwTextColor2);
}
}
void RichEdit::SetTextColor(DWORD color)
{
if (m_pTwh) {
m_pTwh->SetColor(color);
}
}
std::wstring RichEdit::GetTextColor()
{
return m_sCurrentColor;
}
int RichEdit::GetLimitText()
{
return m_iLimitText;
}
void RichEdit::SetLimitText(int iChars)
{
m_iLimitText = iChars;
if( m_pTwh ) {
m_pTwh->LimitText(m_iLimitText);
}
}
long RichEdit::GetTextLength(DWORD dwFlags) const
{
GETTEXTLENGTHEX textLenEx;
textLenEx.flags = dwFlags;
#ifdef _UNICODE
textLenEx.codepage = 1200;
#else
textLenEx.codepage = CP_ACP;
#endif
LRESULT lResult;
TxSendMessage(EM_GETTEXTLENGTHEX, (WPARAM)&textLenEx, 0, &lResult);
return (long)lResult;
}
std::wstring RichEdit::GetText() const
{
long lLen = GetTextLength(GTL_DEFAULT);
LPTSTR lpText = NULL;
GETTEXTEX gt;
gt.flags = GT_DEFAULT;
#ifdef _UNICODE
gt.cb = sizeof(TCHAR) * (lLen + 1) ;
gt.codepage = 1200;
lpText = new TCHAR[lLen + 1];
::ZeroMemory(lpText, (lLen + 1) * sizeof(TCHAR));
#else
gt.cb = sizeof(TCHAR) * lLen * 2 + 1;
gt.codepage = CP_ACP;
lpText = new TCHAR[lLen * 2 + 1];
::ZeroMemory(lpText, (lLen * 2 + 1) * sizeof(TCHAR));
#endif
gt.lpDefaultChar = NULL;
gt.lpUsedDefChar = NULL;
TxSendMessage(EM_GETTEXTEX, (WPARAM)&gt, (LPARAM)lpText, 0);
std::wstring sText(lpText);
delete[] lpText;
return sText;
}
std::string RichEdit::GetUTF8Text() const
{
std::string strOut;
StringHelper::UnicodeToMBCS(GetText(), strOut, CP_UTF8);
return strOut;
}
void RichEdit::SetText(const std::wstring& strText)
{
m_sText = strText;
if( !m_bInited )
return;
SetSel(0, -1);
ReplaceSel(strText, FALSE);
m_linkInfo.clear();
}
void RichEdit::SetTextId(const std::wstring& strTextId)
{
MutiLanSupport* mutilan = MutiLanSupport::GetInstance();
if (mutilan)
{
std::wstring strText = mutilan->GetStringViaID(strTextId);
SetText(strText);
}
}
void RichEdit::SetUTF8Text( const std::string& strText )
{
std::wstring strOut;
StringHelper::MBCSToUnicode(strText, strOut, CP_UTF8);
SetText(strOut);
}
bool RichEdit::GetModify() const
{
if( !m_pTwh ) return false;
LRESULT lResult;
TxSendMessage(EM_GETMODIFY, 0, 0, &lResult);
return (BOOL)lResult == TRUE;
}
void RichEdit::SetModify(bool bModified) const
{
TxSendMessage(EM_SETMODIFY, bModified, 0, 0);
}
void RichEdit::GetSel(CHARRANGE &cr) const
{
TxSendMessage(EM_EXGETSEL, 0, (LPARAM)&cr, 0);
}
void RichEdit::GetSel(long& nStartChar, long& nEndChar) const
{
CHARRANGE cr;
TxSendMessage(EM_EXGETSEL, 0, (LPARAM)&cr, 0);
nStartChar = cr.cpMin;
nEndChar = cr.cpMax;
}
int RichEdit::SetSel(CHARRANGE &cr)
{
LRESULT lResult;
TxSendMessage(EM_EXSETSEL, 0, (LPARAM)&cr, &lResult);
return (int)lResult;
}
int RichEdit::SetSel(long nStartChar, long nEndChar)
{
CHARRANGE cr;
cr.cpMin = nStartChar;
cr.cpMax = nEndChar;
LRESULT lResult;
TxSendMessage(EM_EXSETSEL, 0, (LPARAM)&cr, &lResult);
return (int)lResult;
}
void RichEdit::ReplaceSel(const std::wstring& lpszNewText, bool bCanUndo)
{
#ifdef _UNICODE
TxSendMessage(EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText.c_str(), 0);
#else
std::wstring strOut;
StringHelper::MBCSToUnicode(lpszNewText, strOut, CP_ACP);
TxSendMessage(EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)strOut.c_str(), 0);
#endif
}
void RichEdit::ReplaceSelW(LPCWSTR lpszNewText, bool bCanUndo)
{
TxSendMessage(EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText, 0);
}
std::wstring RichEdit::GetSelText() const
{
if( !m_pTwh ) return std::wstring();
CHARRANGE cr;
cr.cpMin = cr.cpMax = 0;
TxSendMessage(EM_EXGETSEL, 0, (LPARAM)&cr, 0);
LPWSTR lpText = NULL;
lpText = new WCHAR[cr.cpMax - cr.cpMin + 1];
::ZeroMemory(lpText, (cr.cpMax - cr.cpMin + 1) * sizeof(WCHAR));
TxSendMessage(EM_GETSELTEXT, 0, (LPARAM)lpText, 0);
std::wstring sText;
sText = (LPCWSTR)lpText;
delete[] lpText;
return sText;
}
int RichEdit::SetSelAll()
{
return SetSel(0, -1);
}
int RichEdit::SetSelNone()
{
return SetSel(-1, 0);
}
bool RichEdit::GetZoom(int& nNum, int& nDen) const
{
LRESULT lResult;
TxSendMessage(EM_GETZOOM, (WPARAM)&nNum, (LPARAM)&nDen, &lResult);
return (BOOL)lResult == TRUE;
}
bool RichEdit::SetZoom(int nNum, int nDen)
{
if (nNum < 0 || nNum > 64) return false;
if (nDen < 0 || nDen > 64) return false;
LRESULT lResult;
TxSendMessage(EM_SETZOOM, nNum, nDen, &lResult);
return (BOOL)lResult == TRUE;
}
bool RichEdit::SetZoomOff()
{
LRESULT lResult;
TxSendMessage(EM_SETZOOM, 0, 0, &lResult);
return (BOOL)lResult == TRUE;
}
WORD RichEdit::GetSelectionType() const
{
LRESULT lResult;
TxSendMessage(EM_SELECTIONTYPE, 0, 0, &lResult);
return (WORD)lResult;
}
bool RichEdit::GetAutoURLDetect() const
{
LRESULT lResult;
TxSendMessage(EM_GETAUTOURLDETECT, 0, 0, &lResult);
return (BOOL)lResult == TRUE;
}
bool RichEdit::SetAutoURLDetect(bool bAutoDetect)
{
LRESULT lResult;
TxSendMessage(EM_AUTOURLDETECT, bAutoDetect, 0, &lResult);
return (BOOL)lResult == FALSE;
}
DWORD RichEdit::GetEventMask() const
{
LRESULT lResult;
TxSendMessage(EM_GETEVENTMASK, 0, 0, &lResult);
return (DWORD)lResult;
}
DWORD RichEdit::SetEventMask(DWORD dwEventMask)
{
LRESULT lResult;
TxSendMessage(EM_SETEVENTMASK, 0, dwEventMask, &lResult);
return (DWORD)lResult;
}
std::wstring RichEdit::GetTextRange(long nStartChar, long nEndChar) const
{
TEXTRANGEW tr = { 0 };
tr.chrg.cpMin = nStartChar;
tr.chrg.cpMax = nEndChar;
LPWSTR lpText = NULL;
lpText = new WCHAR[nEndChar - nStartChar + 1];
::ZeroMemory(lpText, (nEndChar - nStartChar + 1) * sizeof(WCHAR));
tr.lpstrText = lpText;
TxSendMessage(EM_GETTEXTRANGE, 0, (LPARAM)&tr, 0);
std::wstring sText;
sText = (LPCWSTR)lpText;
delete[] lpText;
return sText;
}
void RichEdit::HideSelection(bool bHide, bool bChangeStyle)
{
TxSendMessage(EM_HIDESELECTION, bHide, bChangeStyle, 0);
}
void RichEdit::ScrollCaret()
{
TxSendMessage(EM_SCROLLCARET, 0, 0, 0);
}
int RichEdit::InsertText(long nInsertAfterChar, LPCTSTR lpstrText, bool bCanUndo)
{
int nRet = SetSel(nInsertAfterChar, nInsertAfterChar);
ReplaceSel(lpstrText, bCanUndo);
return nRet;
}
int RichEdit::AppendText(const std::wstring& strText, bool bCanUndo)
{
int nRet = SetSel(-1, -1);
ReplaceSel(strText, bCanUndo);
return nRet;
}
DWORD RichEdit::GetDefaultCharFormat(CHARFORMAT2 &cf) const
{
cf.cbSize = sizeof(CHARFORMAT2);
LRESULT lResult;
TxSendMessage(EM_GETCHARFORMAT, 0, (LPARAM)&cf, &lResult);
return (DWORD)lResult;
}
bool RichEdit::SetDefaultCharFormat(CHARFORMAT2 &cf)
{
if( !m_pTwh ) return false;
cf.cbSize = sizeof(CHARFORMAT2);
LRESULT lResult;
TxSendMessage(EM_SETCHARFORMAT, 0, (LPARAM)&cf, &lResult);
if( (BOOL)lResult == TRUE ) {
CHARFORMAT2W cfw;
cfw.cbSize = sizeof(CHARFORMAT2W);
TxSendMessage(EM_GETCHARFORMAT, 1, (LPARAM)&cfw, 0);
m_pTwh->SetCharFormat(cfw);
return true;
}
return false;
}
DWORD RichEdit::GetSelectionCharFormat(CHARFORMAT2 &cf) const
{
cf.cbSize = sizeof(CHARFORMAT2);
LRESULT lResult;
TxSendMessage(EM_GETCHARFORMAT, 1, (LPARAM)&cf, &lResult);
return (DWORD)lResult;
}
bool RichEdit::SetSelectionCharFormat(CHARFORMAT2 &cf)
{
if( !m_pTwh ) return false;
cf.cbSize = sizeof(CHARFORMAT2);
LRESULT lResult;
TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf, &lResult);
return (BOOL)lResult == TRUE;
}
bool RichEdit::SetWordCharFormat(CHARFORMAT2 &cf)
{
if( !m_pTwh ) return false;
cf.cbSize = sizeof(CHARFORMAT2);
LRESULT lResult;
TxSendMessage(EM_SETCHARFORMAT, SCF_SELECTION|SCF_WORD, (LPARAM)&cf, &lResult);
return (BOOL)lResult == TRUE;
}
DWORD RichEdit::GetParaFormat(PARAFORMAT2 &pf) const
{
pf.cbSize = sizeof(PARAFORMAT2);
LRESULT lResult;
TxSendMessage(EM_GETPARAFORMAT, 0, (LPARAM)&pf, &lResult);
return (DWORD)lResult;
}
bool RichEdit::SetParaFormat(PARAFORMAT2 &pf)
{
if( !m_pTwh ) return false;
pf.cbSize = sizeof(PARAFORMAT2);
LRESULT lResult;
TxSendMessage(EM_SETPARAFORMAT, 0, (LPARAM)&pf, &lResult);
if( (BOOL)lResult == TRUE ) {
m_pTwh->SetParaFormat(pf);
return true;
}
return false;
}
bool RichEdit::Redo()
{
if( !m_pTwh ) return false;
LRESULT lResult;
TxSendMessage(EM_REDO, 0, 0, &lResult);
return (BOOL)lResult == TRUE;
}
bool RichEdit::Undo()
{
if( !m_pTwh ) return false;
LRESULT lResult;
TxSendMessage(EM_UNDO, 0, 0, &lResult);
return (BOOL)lResult == TRUE;
}
void RichEdit::Clear()
{
TxSendMessage(WM_CLEAR, 0, 0, 0);
}
void RichEdit::Copy()
{
TxSendMessage(WM_COPY, 0, 0, 0);
}
void RichEdit::Cut()
{
TxSendMessage(WM_CUT, 0, 0, 0);
}
void RichEdit::Paste()
{
TxSendMessage(WM_PASTE, 0, 0, 0);
}
BOOL RichEdit::CanPaste(UINT nFormat/* = 0*/)
{
if (NULL == m_pTwh)
return FALSE;
return m_pTwh->CanPaste(nFormat);
}
void RichEdit::PasteSpecial(UINT uClipFormat, DWORD dwAspect/* = 0*/, HMETAFILE hMF/* = 0*/)
{
if (NULL == m_pTwh)
return;
m_pTwh->PasteSpecial(uClipFormat, dwAspect, hMF);
}
int RichEdit::GetLineCount() const
{
if( !m_pTwh ) return 0;
LRESULT lResult;
TxSendMessage(EM_GETLINECOUNT, 0, 0, &lResult);
return (int)lResult;
}
std::wstring RichEdit::GetLine(int nIndex, int nMaxLength) const
{
LPWSTR lpText = NULL;
lpText = new WCHAR[nMaxLength + 1];
::ZeroMemory(lpText, (nMaxLength + 1) * sizeof(WCHAR));
*(LPWORD)lpText = (WORD)nMaxLength;
TxSendMessage(EM_GETLINE, nIndex, (LPARAM)lpText, 0);
std::wstring sText;
sText = (LPCWSTR)lpText;
delete[] lpText;
return sText;
}
int RichEdit::LineIndex(int nLine) const
{
LRESULT lResult;
TxSendMessage(EM_LINEINDEX, nLine, 0, &lResult);
return (int)lResult;
}
int RichEdit::LineLength(int nLine) const
{
LRESULT lResult;
TxSendMessage(EM_LINELENGTH, nLine, 0, &lResult);
return (int)lResult;
}
bool RichEdit::LineScroll(int nLines, int nChars)
{
LRESULT lResult;
TxSendMessage(EM_LINESCROLL, nChars, nLines, &lResult);
return (BOOL)lResult == TRUE;
}
CPoint RichEdit::GetCharPos(long lChar) const
{
CPoint pt;
TxSendMessage(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)lChar, 0);
return pt;
}
long RichEdit::LineFromChar(long nIndex) const
{
if( !m_pTwh ) return 0L;
LRESULT lResult;
TxSendMessage(EM_EXLINEFROMCHAR, 0, nIndex, &lResult);
return (long)lResult;
}
CPoint RichEdit::PosFromChar(UINT nChar) const
{
POINTL pt;
TxSendMessage(EM_POSFROMCHAR, (WPARAM)&pt, nChar, 0);
return CPoint(pt.x, pt.y);
}
int RichEdit::CharFromPos(CPoint pt) const
{
POINTL ptl = {pt.x, pt.y};
if( !m_pTwh ) return 0;
LRESULT lResult;
TxSendMessage(EM_CHARFROMPOS, 0, (LPARAM)&ptl, &lResult);
return (int)lResult;
}
void RichEdit::EmptyUndoBuffer()
{
TxSendMessage(EM_EMPTYUNDOBUFFER, 0, 0, 0);
}
UINT RichEdit::SetUndoLimit(UINT nLimit)
{
if( !m_pTwh ) return 0;
LRESULT lResult;
TxSendMessage(EM_SETUNDOLIMIT, (WPARAM) nLimit, 0, &lResult);
return (UINT)lResult;
}
long RichEdit::StreamIn(int nFormat, EDITSTREAM &es)
{
if( !m_pTwh ) return 0L;
LRESULT lResult;
TxSendMessage(EM_STREAMIN, nFormat, (LPARAM)&es, &lResult);
return (long)lResult;
}
long RichEdit::StreamOut(int nFormat, EDITSTREAM &es)
{
if( !m_pTwh ) return 0L;
LRESULT lResult;
TxSendMessage(EM_STREAMOUT, nFormat, (LPARAM)&es, &lResult);
return (long)lResult;
}
HRESULT RichEdit::TxSendMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plresult) const
{
if( m_pTwh ) {
LRESULT lr = m_pTwh->GetTextServices()->TxSendMessage(msg, wParam, lParam, plresult);
return lr;
}
return S_FALSE;
}
IDropTarget* RichEdit::GetTxDropTarget()
{
IDropTarget *pdt = NULL;
if( m_pTwh->GetTextServices()->TxGetDropTarget(&pdt) == NOERROR ) return pdt;
return NULL;
}
bool RichEdit::SetDropAcceptFile(bool bAccept)
{
LRESULT lResult;
TxSendMessage(EM_SETEVENTMASK, 0, ENM_DROPFILES | ENM_LINK, // ENM_CHANGE| ENM_CORRECTTEXT | ENM_DRAGDROPDONE | ENM_DROPFILES | ENM_IMECHANGE | ENM_LINK | ENM_OBJECTPOSITIONS | ENM_PROTECTED | ENM_REQUESTRESIZE | ENM_SCROLL | ENM_SELCHANGE | ENM_UPDATE,
&lResult);
return (BOOL)lResult == FALSE;
}
void RichEdit::OnTxNotify(DWORD iNotify, void *pv)
{
switch(iNotify)
{
case EN_LINK:
{
NMHDR* hdr = (NMHDR*) pv;
ENLINK* link = (ENLINK*)hdr;
if(link->msg == WM_LBUTTONUP) {
this->SetSel(link->chrg);
std::wstring url = GetSelText();
wprintf_s(L"[Link]%s\n", url.c_str());
HWND hwnd = this->GetWindow()->GetHWND();
SendMessage(hwnd, WM_NOTIFY, EN_LINK, (LPARAM)&url);
}
}
break;
case EN_CHANGE:
OnTxTextChanged();
break;
case EN_DROPFILES:
case EN_MSGFILTER:
case EN_OLEOPFAILED:
case EN_PROTECTED:
case EN_SAVECLIPBOARD:
case EN_SELCHANGE:
case EN_STOPNOUNDO:
case EN_OBJECTPOSITIONS:
case EN_DRAGDROPDONE:
{
if (pv) { // Fill out NMHDR portion of pv
LONG nId = GetWindowLong(this->GetWindow()->GetHWND(), GWL_ID);
NMHDR *phdr = (NMHDR *)pv;
phdr->hwndFrom = this->GetWindow()->GetHWND();
phdr->idFrom = nId;
phdr->code = iNotify;
SendMessage(this->GetWindow()->GetHWND(), WM_NOTIFY, (WPARAM)nId, (LPARAM)pv);
}
}
break;
}
}
bool RichEdit::OnTxTextChanged()
{
if (m_pWindow != NULL) {
m_pWindow->SendNotify(this, kEventTextChange);
}
return true;
}
ITextHost* RichEdit::GetTextHost()
{
if (NULL == m_pTwh)
return NULL;
return m_pTwh->GetTextHost();
}
ITextServices* RichEdit::GetTextServices()
{
if (NULL == m_pTwh)
return NULL;
return m_pTwh->GetTextServices2();
}
BOOL RichEdit::SetOleCallback(IRichEditOleCallback* pCallback)
{
if (NULL == m_pTwh)
return FALSE;
return m_pTwh->SetOleCallback(pCallback);
}
CSize RichEdit::GetNaturalSize(LONG width, LONG height)
{
if (width < 0) {
width = 0;
}
if (height < 0) {
height = 0;
}
CSize sz(0,0);
if (m_cbGetNaturalSize != nullptr && m_cbGetNaturalSize(width, height, sz))
return sz;
LONG lWidth = width;
LONG lHeight = height;
SIZEL szExtent = { -1, -1 };
if (m_pTwh) {
m_pTwh->GetTextServices()->TxGetNaturalSize(
DVASPECT_CONTENT,
GetWindow()->GetPaintDC(),
NULL,
NULL,
TXTNS_FITTOCONTENT,
&szExtent,
&lWidth,
&lHeight);
}
sz.cx = (int)lWidth;
sz.cy = (int)lHeight;
return sz;
}
void RichEdit::SetImmStatus(BOOL bOpen)
{
HWND hwnd = GetWindow()->GetHWND();
if (hwnd != NULL)
{
HIMC hImc = ::ImmGetContext(hwnd);
if (hImc != NULL) {
if (ImmGetOpenStatus(hImc)) {
if (!bOpen)
ImmSetOpenStatus(hImc, FALSE);
}
else {
if (bOpen)
ImmSetOpenStatus(hImc, TRUE);
}
ImmReleaseContext(hwnd, hImc);
}
}
}
void RichEdit::SetTimer(UINT idTimer, UINT uTimeout)
{
auto timeFlag = m_timeFlagMap.find(idTimer);
if (timeFlag != m_timeFlagMap.end()) {
timeFlag->second.Cancel();
}
auto callback = [this, idTimer]() {
this->TxSendMessage(WM_TIMER, idTimer, 0, 0);
};
TimerManager::GetInstance()->AddCancelableTimer(m_timeFlagMap[idTimer].GetWeakFlag(), callback, uTimeout, TimerManager::REPEAT_FOREVER);
}
void RichEdit::KillTimer(UINT idTimer)
{
auto timeFlag = m_timeFlagMap.find(idTimer);
if (timeFlag != m_timeFlagMap.end()) {
timeFlag->second.Cancel();
m_timeFlagMap.erase(timeFlag);
}
}
// <20><><EFBFBD>з<EFBFBD>rich<63><68>ʽ<EFBFBD><CABD>richedit<69><74>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>bug<75><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ǿ<EFBFBD><C7BF><EFBFBD>ʱ<EFBFBD><CAB1>LineDown<77><6E>SetScrollPos<6F>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD>iPos<6F><73><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>bug
void RichEdit::SetScrollPos(CSize szPos)
{
int cx = 0;
int cy = 0;
if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() ) {
int iLastScrollPos = m_pVerticalScrollBar->GetScrollPos();
m_pVerticalScrollBar->SetScrollPos(szPos.cy);
cy = m_pVerticalScrollBar->GetScrollPos() - iLastScrollPos;
}
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsValid() ) {
int iLastScrollPos = m_pHorizontalScrollBar->GetScrollPos();
m_pHorizontalScrollBar->SetScrollPos(szPos.cx);
cx = m_pHorizontalScrollBar->GetScrollPos() - iLastScrollPos;
}
if( cy != 0 ) {
int iPos = 0;
if( m_pTwh && !m_bRich && m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() )
iPos = m_pVerticalScrollBar->GetScrollPos();
WPARAM wParam = MAKEWPARAM(SB_THUMBPOSITION, m_pVerticalScrollBar->GetScrollPos());
TxSendMessage(WM_VSCROLL, wParam, 0L, 0);
if( m_pTwh && !m_bRich && m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() ) {
if( cy > 0 && m_pVerticalScrollBar->GetScrollPos() <= iPos )
m_pVerticalScrollBar->SetScrollPos(iPos);
}
}
if( cx != 0 ) {
WPARAM wParam = MAKEWPARAM(SB_THUMBPOSITION, m_pHorizontalScrollBar->GetScrollPos());
TxSendMessage(WM_HSCROLL, wParam, 0L, 0);
}
}
void RichEdit::LineUp()
{
TxSendMessage(WM_VSCROLL, SB_LINEUP, 0L, 0);
}
void RichEdit::LineDown()
{
int iPos = 0;
if( m_pTwh && !m_bRich && m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() )
iPos = m_pVerticalScrollBar->GetScrollPos();
TxSendMessage(WM_VSCROLL, SB_LINEDOWN, 0L, 0);
if( m_pTwh && !m_bRich && m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() ) {
if( m_pVerticalScrollBar->GetScrollPos() <= iPos )
m_pVerticalScrollBar->SetScrollPos(m_pVerticalScrollBar->GetScrollRange());
}
}
void RichEdit::PageUp()
{
TxSendMessage(WM_VSCROLL, SB_PAGEUP, 0L, 0);
}
void RichEdit::PageDown()
{
TxSendMessage(WM_VSCROLL, SB_PAGEDOWN, 0L, 0);
}
void RichEdit::HomeUp()
{
TxSendMessage(WM_VSCROLL, SB_TOP, 0L, 0);
}
void RichEdit::EndDown()
{
TxSendMessage(WM_VSCROLL, SB_BOTTOM, 0L, 0);
}
void RichEdit::LineLeft()
{
TxSendMessage(WM_HSCROLL, SB_LINELEFT, 0L, 0);
}
void RichEdit::LineRight()
{
TxSendMessage(WM_HSCROLL, SB_LINERIGHT, 0L, 0);
}
void RichEdit::PageLeft()
{
TxSendMessage(WM_HSCROLL, SB_PAGELEFT, 0L, 0);
}
void RichEdit::PageRight()
{
TxSendMessage(WM_HSCROLL, SB_PAGERIGHT, 0L, 0);
}
void RichEdit::HomeLeft()
{
TxSendMessage(WM_HSCROLL, SB_LEFT, 0L, 0);
}
void RichEdit::EndRight()
{
TxSendMessage(WM_HSCROLL, SB_RIGHT, 0L, 0);
}
void RichEdit::DoInit()
{
if (m_bInited)
return;
CREATESTRUCT cs;
cs.style = m_lTwhStyle;
cs.x = 0;
cs.y = 0;
cs.cy = 0;
cs.cx = 0;
cs.lpszName = m_sText.c_str();
CreateHost(this, &cs, &m_pTwh);
if (m_pTwh) {
m_pTwh->SetTransparent(TRUE);
LRESULT lResult;
m_pTwh->GetTextServices()->TxSendMessage(EM_SETLANGOPTIONS, 0, 0, &lResult);
m_pTwh->GetTextServices()->TxSendMessage(EM_SETEVENTMASK, 0, ENM_CHANGE, &lResult);
m_pTwh->OnTxInPlaceActivate(NULL);
if (m_pHorizontalScrollBar) {
m_pHorizontalScrollBar->SetScrollRange(0);
}
if (m_pVerticalScrollBar) {
m_pVerticalScrollBar->SetScrollRange(0);
}
}
m_bInited = true;
}
void RichEdit::SetEnabled(bool bEnable /*= true*/)
{
if (m_bEnabled == bEnable)
return;
m_bEnabled = bEnable;
if (bEnable) {
m_uButtonState = kControlStateNormal;
SetTextColor(m_sTextColor);
}
else {
m_uButtonState = kControlStateDisabled;
SetTextColor(m_sDisabledTextColor);
}
}
CSize RichEdit::EstimateSize(CSize szAvailable)
{
CSize size(GetFixedWidth(), GetFixedHeight());
if (size.cx == DUI_LENGTH_AUTO || size.cy == DUI_LENGTH_AUTO) {
LONG iWidth = size.cx;
LONG iHeight = size.cy;
if (size.cx == DUI_LENGTH_AUTO) {
ASSERT(size.cy != DUI_LENGTH_AUTO);
iWidth = 0;
}
else if (size.cy == DUI_LENGTH_AUTO) {
ASSERT(size.cx != DUI_LENGTH_AUTO);
iHeight = 0;
}
SIZEL szExtent = { -1, -1 };
m_pTwh->GetTextServices()->TxGetNaturalSize(
DVASPECT_CONTENT,
GetWindow()->GetPaintDC(),
NULL,
NULL,
TXTNS_FITTOCONTENT,
&szExtent,
&iWidth,
&iHeight);
if (size.cx == DUI_LENGTH_AUTO) {
size.cx = iWidth + m_pLayout->GetPadding().left + m_pLayout->GetPadding().right;
}
else if (size.cy == DUI_LENGTH_AUTO) {
size.cy = iHeight + m_pLayout->GetPadding().top + m_pLayout->GetPadding().bottom;
}
}
return size;
}
void RichEdit::SetPos(UiRect rc)
{
Control::SetPos(rc);
rc = m_rcItem;
rc.left += m_pLayout->GetPadding().left;
rc.top += m_pLayout->GetPadding().top;
rc.right -= m_pLayout->GetPadding().right;
rc.bottom -= m_pLayout->GetPadding().bottom;
bool bVScrollBarVisiable = false;
if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() ) {
bVScrollBarVisiable = true;
rc.right -= m_pVerticalScrollBar->GetFixedWidth();
}
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsValid() ) {
rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
}
if( m_pTwh ) {
m_pTwh->SetClientRect(&rc);
if( bVScrollBarVisiable && (!m_pVerticalScrollBar->IsValid() || m_bVScrollBarFixing) ) {
LONG lWidth = rc.right - rc.left + m_pVerticalScrollBar->GetFixedWidth();
LONG lHeight = 0;
SIZEL szExtent = { -1, -1 };
m_pTwh->GetTextServices()->TxGetNaturalSize(
DVASPECT_CONTENT,
GetWindow()->GetPaintDC(),
NULL,
NULL,
TXTNS_FITTOCONTENT,
&szExtent,
&lWidth,
&lHeight);
if( lHeight > rc.bottom - rc.top ) {
//m_pVerticalScrollBar->SetVisible(true);
m_pVerticalScrollBar->SetScrollPos(0);
m_bVScrollBarFixing = true;
}
else {
if( m_bVScrollBarFixing ) {
//m_pVerticalScrollBar->SetVisible(false);
m_pVerticalScrollBar->SetScrollRange(0);
m_bVScrollBarFixing = false;
}
}
}
}
if( m_pVerticalScrollBar != NULL && m_pVerticalScrollBar->IsValid() ) {
UiRect rcScrollBarPos(rc.right, rc.top, rc.right + m_pVerticalScrollBar->GetFixedWidth(), rc.bottom);
m_pVerticalScrollBar->SetPos(rcScrollBarPos);
}
if( m_pHorizontalScrollBar != NULL && m_pHorizontalScrollBar->IsValid() ) {
UiRect rcScrollBarPos(rc.left, rc.bottom, rc.right, rc.bottom + m_pHorizontalScrollBar->GetFixedHeight());
m_pHorizontalScrollBar->SetPos(rcScrollBarPos);
}
for( auto it = m_items.begin(); it != m_items.end(); it++ ) {
auto pControl = *it;
if( !pControl->IsVisible() ) continue;
if( pControl->IsFloat() ) {
Layout::SetFloatPos(pControl, GetPos());
}
else {
pControl->SetPos(rc); // <20><><EFBFBD>з<EFBFBD>float<61>ӿؼ<D3BF><D8BC>Ŵ<EFBFBD><C5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD>
}
}
}
UINT RichEdit::GetControlFlags() const
{
return IsEnabled() ? UIFLAG_TABSTOP : UIFLAG_DEFAULT;
}
void RichEdit::HandleMessage(EventArgs& event)
{
if ((!IsMouseEnabled() && event.Type > kEventMouseBegin && event.Type < kEventMouseEnd) ||
(!IsEnabled())){
if (m_pParent != NULL) m_pParent->HandleMessageTemplate(event);
else Control::HandleMessage(event);
return;
}
if (event.Type == kEventSetCursor)
{
OnSetCursor(event);
return;
}
if (event.Type == kEventChar) {
OnChar(event);
return;
}
if (event.Type == kEventKeyDown) {
OnKeyDown(event);
return;
}
if (event.Type == kEventMouseMove) {
OnMouseMessage(WM_MOUSEMOVE, event);
return;
}
if (event.Type == kEventMouseScrollWheel) {
if (::GetAsyncKeyState(VK_CONTROL) < 0)
return;
ScrollableBox::HandleMessage(event);
//OnMouseMessage(WM_MOUSEWHEEL, event);
return;
}
if (event.Type == kEventMouseButtonDown || event.Type == kEventPointDown) {
if (m_linkInfo.size() > 0) {
std::wstring strLink;
if (HittestCustomLink(event.ptMouse, strLink))
{
//::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)));
if (m_pWindow != NULL)
m_pWindow->SendNotify((Control*)this, kEventCustomLinkClick);
return;
}
}
if (event.Type == kEventPointDown) {
OnScreenKeyboardManager::GetInstance()->ShowOSK(true);
}
OnMouseMessage(WM_LBUTTONDOWN, event);
return;
}
if (event.Type == kEventMouseButtonUp || event.Type == kEventPointUp) {
if (m_bEnabled && !m_bSelAllEver) {
m_bSelAllEver = true;
if (m_bSelAllOnFocus) {
SetSelAll();
if (m_lTwhStyle & ES_MULTILINE)
HomeUp();
else
HomeLeft();
}
}
OnMouseMessage(WM_LBUTTONUP, event);
return;
}
if (event.Type == kEventInternalDoubleClick) {
if (m_bReadOnly) {
SetSelAll();
return;
}
OnMouseMessage(WM_LBUTTONDBLCLK, event);
return;
}
if (event.Type == kEventMouseRightButtonDown) {
OnMouseMessage(WM_RBUTTONDOWN, event);
return;
}
if (event.Type == kEventMouseRightButtonUp) {
OnMouseMessage(WM_RBUTTONUP, event);
return;
}
if (event.Type == kEventImeStartComposition) {
OnImeStartComposition(event);
return;
}
if (event.Type == kEventImeEndComposition) {
OnImeEndComposition(event);
return;
}
if (event.Type == kEventInternalSetFocus) {
OnSetFocus(event);
return;
}
if (event.Type == kEventInternalKillFocus) {
OnKillFocus(event);
OnScreenKeyboardManager::GetInstance()->ShowOSK(false);
return;
}
ScrollableBox::HandleMessage(event);
}
void RichEdit::OnSetCursor(EventArgs& event)
{
std::wstring strLink;
if (HittestCustomLink(event.ptMouse, strLink))
{
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)));
return;
}
if (m_pTwh && m_pTwh->DoSetCursor(NULL, &event.ptMouse)) {
return;
}
else {
::SetCursor(::LoadCursor(NULL, MAKEINTRESOURCE(IDC_IBEAM)));
}
}
void RichEdit::OnSetFocus(EventArgs& event)
{
if (m_pTwh) {
m_pTwh->OnTxInPlaceActivate(NULL);
m_pTwh->GetTextServices()->TxSendMessage(WM_SETFOCUS, 0, 0, 0);
ShowCaret(true);
}
m_bFocused = true;
Invalidate();
}
void RichEdit::OnKillFocus(EventArgs& event)
{
if (m_pTwh) {
m_pTwh->OnTxInPlaceActivate(NULL);
m_pTwh->GetTextServices()->TxSendMessage(WM_KILLFOCUS, 0, 0, 0);
ShowCaret(false);
}
m_bFocused = false;
m_bSelAllEver = false;
if (m_bNoSelOnKillFocus && m_bReadOnly && m_bEnabled) {
SetSelNone();
}
if (m_bSelAllOnFocus && m_bEnabled) {
SetSelNone();
}
Invalidate();
}
void RichEdit::OnChar(EventArgs& event)
{
//TAB
if (::GetKeyState(VK_TAB) < 0 && !m_bWantTab) {
if (m_pWindow != NULL)
m_pWindow->SendNotify((Control*)this, kEventTab);
return;
}
//Number
if (m_bNumberOnly) {
if (event.wParam < '0' || event.wParam > '9')
return;
}
TxSendMessage(WM_CHAR, event.wParam, event.lParam, NULL);
}
void RichEdit::OnKeyDown(EventArgs& event)
{
if (event.wParam == VK_RETURN && ::GetAsyncKeyState(VK_SHIFT) >= 0) {
if (m_bNeedReturnMsg && ((m_bReturnMsgWantCtrl && ::GetAsyncKeyState(VK_CONTROL) < 0) ||
(!m_bReturnMsgWantCtrl && ::GetAsyncKeyState(VK_CONTROL) >= 0)))
{
if (m_pWindow != NULL)
m_pWindow->SendNotify((Control*)this, kEventReturn);
return;
}
}
else if (m_bNumberOnly && event.wParam == 'V' && ::GetKeyState(VK_CONTROL) < 0) {
std::wstring strClipText;
GetClipboardText(strClipText);
if (!strClipText.empty()) {
std::wstring strNum;
for (auto it = strClipText.begin(); it != strClipText.end(); it++)
{
if ((*it) <= L'9' && (*it) >= L'0') {
strNum.push_back((*it));
}
}
if (strNum.empty())
return;
SetClipBoardText(strNum); //<2F>޸ļ<DEB8><C4BC>а<EFBFBD><D0B0><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
nbase::ThreadManager::PostTask([strClipText]() { SetClipBoardText(strClipText); }); //ճ<><D5B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ְѼ<D6B0><D1BC>а<EFBFBD><D0B0><EFBFBD><EFBFBD>ݸĻ<DDB8><C4BB><EFBFBD>
}
}
TxSendMessage(WM_KEYDOWN, event.wParam, event.lParam, NULL);
}
void RichEdit::OnImeStartComposition(EventArgs& event)
{
HWND hWnd = GetWindow()->GetHWND();
if (hWnd == NULL)
return;
HIMC hImc = ::ImmGetContext(hWnd);
if (hImc == NULL)
return;
COMPOSITIONFORM cfs;
CPoint ptScrollOffset = GetScrollOffset();
POINT pt;
pt.x = m_iCaretPosX - ptScrollOffset.x;
pt.y = m_iCaretPosY - ptScrollOffset.y;
//pt.y += (m_iCaretHeight + lf.lfHeight) / 4;
cfs.dwStyle = CFS_POINT;
if (pt.x < 1) pt.x = 1;
if (pt.y < 1) pt.y = 1;
cfs.ptCurrentPos = pt;
::ImmSetCompositionWindow(hImc, &cfs);
::ImmReleaseContext(hWnd, hImc);
m_bIsComposition = true;
}
void RichEdit::OnImeEndComposition(EventArgs& event)
{
m_bIsComposition = false;
}
void RichEdit::OnMouseMessage(UINT uMsg, EventArgs& event)
{
CPoint pt(GET_X_LPARAM(event.lParam), GET_Y_LPARAM(event.lParam));
pt.Offset(GetScrollOffset());
TxSendMessage(uMsg, event.wParam, MAKELPARAM(pt.x, pt.y), NULL);
}
void RichEdit::Paint(IRenderContext* pRender, const UiRect& rcPaint)
{
UiRect rcTemp;
if( !::IntersectRect(&rcTemp, &rcPaint, &m_rcItem) ) return;
Control::Paint(pRender, rcPaint);
if( m_pTwh ) {
UiRect rc;
m_pTwh->GetControlRect(&rc);
// Remember wparam is actually the hdc and lparam is the update
// rect because this message has been preprocessed by the window.
m_pTwh->GetTextServices()->TxDraw(
DVASPECT_CONTENT, // Draw Aspect
/*-1*/0, // Lindex
NULL, // Info for drawing optimazation
NULL, // target device information
pRender->GetDC(), // Draw device HDC
NULL, // Target device HDC
(RECTL*)&rc, // Bounding client rectangle
NULL, // Clipping rectangle for metafiles
(UiRect*)&rcPaint, // Update rectangle
NULL, // Call back function
NULL, // Call back parameter
0); // What view of the object
if( m_bVScrollBarFixing ) {
LONG lWidth = rc.right - rc.left + m_pVerticalScrollBar->GetFixedWidth();
//LONG lWidth = rc.right - rc.left;
LONG lHeight = 0;
SIZEL szExtent = { -1, -1 };
m_pTwh->GetTextServices()->TxGetNaturalSize(
DVASPECT_CONTENT,
GetWindow()->GetPaintDC(),
NULL,
NULL,
TXTNS_FITTOCONTENT,
&szExtent,
&lWidth,
&lHeight);
if (lHeight <= rc.bottom - rc.top) {
Arrange();
}
}
}
}
void RichEdit::PaintChild(IRenderContext* pRender, const UiRect& rcPaint)
{
UiRect rcTemp;
if (!::IntersectRect(&rcTemp, &rcPaint, &m_rcItem)) return;
PaintCaret(pRender, rcPaint);
if( m_items.size() > 0 ) {
UiRect rc = m_rcItem;
rc.left += m_pLayout->GetPadding().left;
rc.top += m_pLayout->GetPadding().top;
rc.right -= m_pLayout->GetPadding().right;
rc.bottom -= m_pLayout->GetPadding().bottom;
if( m_pVerticalScrollBar && m_pVerticalScrollBar->IsValid() ) rc.right -= m_pVerticalScrollBar->GetFixedWidth();
if( m_pHorizontalScrollBar && m_pHorizontalScrollBar->IsValid() ) rc.bottom -= m_pHorizontalScrollBar->GetFixedHeight();
if( !::IntersectRect(&rcTemp, &rcPaint, &rc) ) {
for( auto it = m_items.begin(); it != m_items.end(); it++ ) {
auto pControl = *it;
if( !pControl->IsVisible() ) continue;
UiRect controlPos = pControl->GetPos();
if (!::IntersectRect(&rcTemp, &rcPaint, &controlPos)) continue;
if( pControl ->IsFloat() ) {
if( !::IntersectRect(&rcTemp, &m_rcItem, &controlPos )) continue;
pControl->AlphaPaint(pRender, rcPaint);
}
}
}
else {
AutoClip childClip(pRender, rcTemp);
for( auto it = m_items.begin(); it != m_items.end(); it++ ) {
auto pControl = *it;
if( !pControl->IsVisible() ) continue;
UiRect controlPos = pControl->GetPos();
if (!::IntersectRect(&rcTemp, &rcPaint, &controlPos)) continue;
if( pControl ->IsFloat() ) {
if( !::IntersectRect(&rcTemp, &m_rcItem, &controlPos) ) continue;
pControl->AlphaPaint(pRender, rcPaint);
}
else {
if( !::IntersectRect(&rcTemp, &rc, &controlPos) ) continue;
pControl->AlphaPaint(pRender, rcPaint);
}
}
}
}
if( m_pVerticalScrollBar != NULL && m_pVerticalScrollBar->IsVisible() ) {
UiRect verBarPos = m_pVerticalScrollBar->GetPos();
if( ::IntersectRect(&rcTemp, &rcPaint, &verBarPos) ) {
m_pVerticalScrollBar->AlphaPaint(pRender, rcPaint);
}
}
if( m_pHorizontalScrollBar != NULL && m_pHorizontalScrollBar->IsVisible() ) {
UiRect horBarPos = m_pVerticalScrollBar->GetPos();
if( ::IntersectRect(&rcTemp, &rcPaint, &horBarPos) ) {
m_pHorizontalScrollBar->AlphaPaint(pRender, rcPaint);
}
}
}
void RichEdit::SetAttribute(const std::wstring& strName, const std::wstring& strValue)
{
if (strName == _T("vscrollbar")) {
if (strValue == _T("true")) {
m_lTwhStyle |= ES_DISABLENOSCROLL | WS_VSCROLL;
EnableScrollBar(true, GetHorizontalScrollBar() != NULL);
}
else {
m_lTwhStyle &= ~WS_VSCROLL;
if (!(m_lTwhStyle & WS_HSCROLL)) m_lTwhStyle &= ~ES_DISABLENOSCROLL;
EnableScrollBar(false, GetHorizontalScrollBar() != NULL);
}
}
else if (strName == _T("autovscroll")) {
if (strValue == _T("true")) m_lTwhStyle |= ES_AUTOVSCROLL;
else if (strValue == _T("false")) m_lTwhStyle &= ~ES_AUTOVSCROLL;
}
else if (strName == _T("hscrollbar")) {
if (strValue == _T("true")) {
m_lTwhStyle |= ES_DISABLENOSCROLL | WS_HSCROLL;
EnableScrollBar(GetVerticalScrollBar() != NULL, true);
}
else {
m_lTwhStyle &= ~WS_HSCROLL;
if (!(m_lTwhStyle & WS_VSCROLL)) m_lTwhStyle &= ~ES_DISABLENOSCROLL;
EnableScrollBar(GetVerticalScrollBar() != NULL, false);
}
}
else if (strName == _T("autohscroll")) {
if (strValue == _T("true")) m_lTwhStyle |= ES_AUTOHSCROLL;
else if (strValue == _T("false")) m_lTwhStyle &= ~ES_AUTOHSCROLL;
}
else if (strName == _T("multiline")) {
if (strValue == _T("false")) m_lTwhStyle &= ~ES_MULTILINE;
else if (strValue == _T("true")) m_lTwhStyle |= ES_MULTILINE;
}
else if (strName == _T("readonly")) {
if (strValue == _T("true")) {
m_lTwhStyle |= ES_READONLY;
m_bReadOnly = true;
}
else if (strValue == _T("false")) {
m_lTwhStyle &= ~ES_READONLY;
m_bReadOnly = false;
}
}
else if (strName == _T("password")) {
if (strValue == _T("true")) {
m_lTwhStyle |= ES_PASSWORD;
m_bPassword = true;
}
else if (strValue == _T("false")) {
m_lTwhStyle &= ~ES_PASSWORD;
m_bPassword = false;
}
}
else if (strName == _T("number")) {
if (strValue == _T("true")) {
m_lTwhStyle |= ES_NUMBER;
m_bNumberOnly = true;
}
else if (strValue == _T("false")){
m_lTwhStyle &= ~ES_NUMBER;
m_bNumberOnly = false;
}
}
else if (strName == _T("align")) {
if (strValue.find(_T("left")) != std::wstring::npos) {
m_lTwhStyle &= ~(ES_CENTER | ES_RIGHT);
m_lTwhStyle |= ES_LEFT;
}
if (strValue.find(_T("hcenter")) != std::wstring::npos) {
m_lTwhStyle &= ~(ES_LEFT | ES_RIGHT);
m_lTwhStyle |= ES_CENTER;
}
if (strValue.find(_T("right")) != std::wstring::npos) {
m_lTwhStyle &= ~(ES_LEFT | ES_CENTER);
m_lTwhStyle |= ES_RIGHT;
}
if (strValue.find(_T("top")) != std::wstring::npos) {
m_textVerAlignType = kVerAlignTop;
}
if (strValue.find(_T("vcenter")) != std::wstring::npos) {
m_textVerAlignType = kVerAlignCenter;
}
if (strValue.find(_T("bottom")) != std::wstring::npos) {
m_textVerAlignType = kVerAlignBottom;
}
}
else if (strName == _T("normaltextcolor")) {
LPCTSTR pValue = strValue.c_str();
while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
m_sTextColor = pValue;
if (m_bEnabled)
SetTextColor(m_sTextColor);
}
else if (strName == L"disabledtextcolor") {
LPCTSTR pValue = strValue.c_str();
while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
m_sDisabledTextColor = pValue;
if (!m_bEnabled)
SetTextColor(m_sDisabledTextColor);
}
else if (strName == L"caretcolor") {
LPCTSTR pValue = strValue.c_str();
while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
SetCaretColor(pValue);
}
else if (strName == _T("promptmode")) {
if (strValue == _T("true"))
m_bAllowPrompt = true;
}
else if (strName == _T("promptcolor")) {
LPCTSTR pValue = strValue.c_str();
while (*pValue > _T('\0') && *pValue <= _T(' ')) pValue = ::CharNext(pValue);
m_sPromptColor = pValue;
}
else if (strName == _T("prompttext")) SetPromptText(strValue);
else if (strName == _T("prompttextid")) SetPromptTextId(strValue);
else if (strName == _T("focusedimage")) SetFocusedImage(strValue);
else if (strName == _T("font")) SetFont(strValue);
else if (strName == _T("text")) SetText(strValue.c_str());
else if (strName == _T("textid")) SetTextId(strValue.c_str());
else if (strName == _T("wanttab")) SetWantTab(strValue == _T("true"));
else if (strName == _T("wantreturnmsg")) SetNeedReturnMsg(strValue == _T("true"));
else if (strName == _T("returnmsgwantctrl")) SetReturnMsgWantCtrl(strValue == _T("true"));
else if (strName == _T("rich")) SetRich(strValue == _T("true"));
else Box::SetAttribute(strName, strValue);
}
BOOL RichEdit::CreateCaret(INT xWidth, INT yHeight)
{
m_iCaretWidth = xWidth;
m_iCaretHeight = yHeight;
return true;
}
BOOL RichEdit::ShowCaret(BOOL fShow)
{
if (fShow) {
m_bIsCaretVisiable = true;
m_drawCaretFlag.Cancel();
std::function<void()> closure = nbase::Bind(&RichEdit::ChangeCaretVisiable, this);
TimerManager::GetInstance()->AddCancelableTimer(m_drawCaretFlag.GetWeakFlag(), closure, 500, TimerManager::REPEAT_FOREVER);
}
else {
m_bIsCaretVisiable = false;
m_drawCaretFlag.Cancel();
}
Invalidate();
return true;
}
void RichEdit::SetCaretColor(const std::wstring& dwColor)
{
m_sCaretColor = dwColor;
}
std::wstring RichEdit::GetCaretColor()
{
return m_sCaretColor;
}
RECT RichEdit::GetCaretRect()
{
RECT rc = { m_iCaretPosX, m_iCaretPosY, m_iCaretPosX + m_iCaretWidth, m_iCaretPosY + m_iCaretHeight };
return rc;
}
BOOL RichEdit::SetCaretPos(INT x, INT y)
{
m_iCaretPosX = x;
m_iCaretPosY = y;
ShowCaret(GetSelText().empty());
return true;
}
void RichEdit::ChangeCaretVisiable()
{
m_bIsCaretVisiable = !m_bIsCaretVisiable;
Invalidate();
}
void RichEdit::PaintCaret(IRenderContext* pRender, const UiRect& rcPaint)
{
if (m_bReadOnly && m_bNoCaretReadonly)
return;
if (m_bIsCaretVisiable && !m_bIsComposition) {
UiRect rect(m_iCaretPosX, m_iCaretPosY, m_iCaretPosX, m_iCaretPosY + m_iCaretHeight);
DWORD dwClrColor = 0xff000000;
if (!m_sCaretColor.empty())
dwClrColor = GlobalManager::GetTextColor(m_sCaretColor);
pRender->DrawLine(rect, m_iCaretWidth, dwClrColor);
}
}
void RichEdit::SetPromptMode(bool bPrompt)
{
if(bPrompt == m_bAllowPrompt)
return;
m_bAllowPrompt = bPrompt;
Invalidate();
}
std::wstring RichEdit::GetPromptText() const
{
std::wstring strText = m_sPromptText;
if (strText.empty() && !m_sPromptTextId.empty()) {
strText = MutiLanSupport::GetInstance()->GetStringViaID(m_sPromptTextId);
}
return strText;
}
std::string RichEdit::GetUTF8PromptText() const
{
std::string strOut;
StringHelper::UnicodeToMBCS(GetPromptText(), strOut, CP_UTF8);
return strOut;
}
void RichEdit::SetPromptText(const std::wstring& strText)
{
if (m_sPromptText == strText) return;
m_sPromptText = strText;
Invalidate();
}
void RichEdit::SetUTF8PromptText(const std::string& strText)
{
std::wstring strOut;
StringHelper::MBCSToUnicode(strText, strOut, CP_UTF8);
SetPromptText(strOut);
}
void RichEdit::SetPromptTextId(const std::wstring& strTextId)
{
if (m_sPromptTextId == strTextId) return;
m_sPromptTextId = strTextId;
Invalidate();
}
void RichEdit::SetUTF8PromptTextId(const std::string& strTextId)
{
std::wstring strOut;
StringHelper::MBCSToUnicode(strTextId, strOut, CP_UTF8);
SetPromptTextId(strOut);
}
void RichEdit::PaintPromptText(IRenderContext* pRender)
{
long len = GetTextLength(GTL_DEFAULT);
if (len != 0)
return;
if (!m_pTwh)
return;
std::wstring strPrompt = GetPromptText();
if (strPrompt.empty() || m_sPromptColor.empty())
return;
UiRect rc;
m_pTwh->GetControlRect(&rc);
DWORD dwClrColor = GlobalManager::GetTextColor(m_sPromptColor);
UINT dwStyle = DT_NOCLIP;
pRender->DrawText(rc, strPrompt, dwClrColor, m_sFontId, dwStyle);
}
std::wstring RichEdit::GetFocusedImage()
{
return m_sFocusedImage.imageAttribute.simageString;
}
void RichEdit::SetFocusedImage( const std::wstring& strImage )
{
m_sFocusedImage.SetImageString(strImage);
Invalidate();
}
void RichEdit::PaintStatusImage(IRenderContext* pRender)
{
if( IsReadOnly() )
return;
if(IsFocused()) {
DrawImage(pRender, m_sFocusedImage);
PaintPromptText(pRender);
return;
}
__super::PaintStatusImage(pRender);
PaintPromptText(pRender);
}
void RichEdit::SetNoSelOnKillFocus(bool bNoSel)
{
m_bNoSelOnKillFocus = bNoSel;
}
void RichEdit::SetSelAllOnFocus(bool bSelAll)
{
m_bSelAllOnFocus = bSelAll;
}
void RichEdit::SetNoCaretReadonly()
{
m_bNoCaretReadonly = true;
}
void RichEdit::AddColorText(const std::wstring &str, const std::wstring &color)
{
if( !m_bRich || str.empty() || color.empty() ) {
ASSERT(FALSE);
return;
}
DWORD dwColor = GlobalManager::GetTextColor(color);
CHARFORMAT2W cf;
ZeroMemory(&cf, sizeof(cf));
cf.cbSize = sizeof(CHARFORMAT2W);
cf.dwMask = CFM_COLOR;
cf.dwEffects = 0;
cf.crTextColor = RGB(GetBValue(dwColor), GetGValue(dwColor), GetRValue(dwColor));
this->ReplaceSel(str, FALSE);
int len = GetTextLength();
this->SetSel(len - (int)str.size(), len);
this->SetSelectionCharFormat(cf);
this->SetSelNone();
GetDefaultCharFormat(cf);
SetSelectionCharFormat(cf);
}
void RichEdit::AddLinkColorText(const std::wstring &str, const std::wstring &color, const std::wstring &linkInfo)
{
if( !m_bRich || str.empty() || color.empty() ) {
ASSERT(FALSE);
return;
}
DWORD dwColor = GlobalManager::GetTextColor(color);
CHARFORMAT2W cf;
ZeroMemory(&cf, sizeof(cf));
cf.cbSize = sizeof(CHARFORMAT2W);
cf.dwMask = CFM_COLOR;
cf.crTextColor = RGB(GetBValue(dwColor), GetGValue(dwColor), GetRValue(dwColor));
this->ReplaceSel(str, FALSE);
int len = GetTextLength();
this->SetSel(len - (int)str.size(), len);
this->SetSelectionCharFormat(cf);
LinkInfo info;
info.info = linkInfo;
TxSendMessage(EM_EXGETSEL, 0, (LPARAM)&(info.cr), NULL);
m_linkInfo.push_back(info);
this->SetSelNone();
GetDefaultCharFormat(cf);
SetSelectionCharFormat(cf);
}
void RichEdit::AddLinkColorTextEx(const std::wstring& str, const std::wstring &color, const std::wstring &linkInfo, const std::wstring& strFontId)
{
if (!m_bRich || str.empty() || color.empty()) {
ASSERT(FALSE);
return;
}
std::string link;
std::string text;
std::string font_face;
StringHelper::UnicodeToMBCS(linkInfo, link);
StringHelper::UnicodeToMBCS(str, text);
auto hFont = GlobalManager::GetFont(strFontId);
if (hFont == NULL)
hFont = GlobalManager::GetFont(m_sFontId);
if (hFont == NULL)
hFont = GlobalManager::GetFont(L"");
LOGFONT lf;
::GetObject(hFont, sizeof(LOGFONT), &lf);
StringHelper::UnicodeToMBCS(lf.lfFaceName, font_face);
DWORD dwTextColor = GlobalManager::GetTextColor(color);
static std::string font_format = "{\\fonttbl{\\f0\\fnil\\fcharset%d %s;}}";
static std::string color_format = "{\\colortbl ;\\red%d\\green%d\\blue%d;}";
static std::string link_format = "{\\rtf1%s%s\\f0\\fs%d{\\field{\\*\\fldinst{HYPERLINK \"%s\"}}{\\fldrslt{\\cf1 %s}}}}";
char sfont[255];
sprintf(sfont, font_format.c_str(), lf.lfCharSet, font_face.c_str());
char scolor[255];
sprintf(scolor, color_format.c_str(), GetBValue(dwTextColor), GetGValue(dwTextColor), GetRValue(dwTextColor));
char slinke[1024];
sprintf(slinke, link_format.c_str(), sfont, scolor, ((int)(-lf.lfHeight *1.5))/2*2, link.c_str(), text.c_str());
std::wstring temp;
StringHelper::MBCSToUnicode(slinke, temp);
SETTEXTEX st;
st.codepage = ((UINT32)~((UINT32)0));
st.flags = ST_SELECTION | ST_KEEPUNDO;
TxSendMessage(EM_SETTEXTEX, (WPARAM)&st, (LPARAM)(LPCTSTR)slinke, NULL);
return;
}
void RichEdit::AddLinkInfo(const CHARRANGE cr, const std::wstring &linkInfo)
{
LinkInfo info;
info.info = linkInfo;
info.cr = cr;
m_linkInfo.push_back(info);
}
//<2F><><EFBFBD><EFBFBD>point<6E><74>hittest<73>Զ<EFBFBD><D4B6><EFBFBD>link<6E><6B><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD>true<75><65>ʾ<EFBFBD><CABE>link<6E>ϣ<EFBFBD>info<66><6F>link<6E><6B><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool RichEdit::HittestCustomLink(CPoint pt, std::wstring& info)
{
bool bLink = false;
info.clear();
if (m_linkInfo.size() > 0) {
pt.Offset(GetScrollOffset());
int nCharIndex = CharFromPos(pt);
for (auto it = m_linkInfo.begin(); it != m_linkInfo.end(); it++)
{
if ((*it).cr.cpMin <= nCharIndex && (*it).cr.cpMax > nCharIndex) {
info = (*it).info;
bLink = true;
break;
}
}
}
return bLink;
}
void RichEdit::ClearImageCache()
{
__super::ClearImageCache();
m_sFocusedImage.ClearCache();
}
//----------------<2D><><EFBFBD><EFBFBD><E6BAAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool IsAsciiChar(const wchar_t ch)
{
return (ch <= 0x7e && ch >= 0x20);
}
int GetAsciiCharNumber(const std::wstring &str)
{
int len = (int)str.size(), sum = 0;
for( int i = 0; i < len; i++ )
{
if( IsAsciiChar(str[i]) )
sum += 1;
else
sum += 2;
}
return sum;
}
void LimitAsciiNumber(std::wstring &src, int limit)
{
int len = (int)src.size(), sum = 0;
for( int i = 0; i < len; i++ )
{
if( IsAsciiChar(src[i]) )
sum += 1;
else
sum += 2;
if( sum > limit ) {
src.erase(i);
break;
}
}
}
void GetClipboardText( std::wstring &out )
{
out.clear();
BOOL ret = ::OpenClipboard(NULL);
if(ret) {
if(::IsClipboardFormatAvailable(CF_UNICODETEXT)) {
HANDLE h = ::GetClipboardData(CF_UNICODETEXT);
if(h != INVALID_HANDLE_VALUE) {
wchar_t* buf = (wchar_t*)::GlobalLock(h);
if(buf != NULL) {
std::wstring str(buf, GlobalSize(h)/sizeof(wchar_t));
out = str;
::GlobalUnlock(h);
}
}
}
else if(::IsClipboardFormatAvailable(CF_TEXT)) {
HANDLE h = ::GetClipboardData(CF_TEXT);
if(h != INVALID_HANDLE_VALUE) {
char* buf = (char*)::GlobalLock(h);
if(buf != NULL) {
std::string str(buf, GlobalSize(h));
StringHelper::MBCSToUnicode(str, out);
::GlobalUnlock(h);
}
}
}
::CloseClipboard();
}
}
void SetClipBoardText(const std::wstring &str)
{
if (!::OpenClipboard(NULL))
return;
if (!::EmptyClipboard()) {
::CloseClipboard();
return;
}
size_t len = str.length();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, (len + 1) * sizeof(wchar_t)); //<2F><><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>ڴ<EFBFBD>
if (!hMem) {
::CloseClipboard();
return;
}
wchar_t* lpStr = (wchar_t*)::GlobalLock(hMem); //<2F><>ס<EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>
::memcpy(lpStr, str.c_str(), len * sizeof(wchar_t)); //<2F><><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>
lpStr[len] = wchar_t(0); //<2F>ַ<EFBFBD><D6B7><EFBFBD>ĩβ<C4A9><CEB2>Ϊ'\0'
::GlobalUnlock(hMem); //<2F>ͷ<EFBFBD><CDB7><EFBFBD>
::SetClipboardData(CF_UNICODETEXT, hMem); //<2F><><EFBFBD>ڴ<EFBFBD><DAB4>е<EFBFBD><D0B5><EFBFBD><EFBFBD>ݷŵ<DDB7><C5B5><EFBFBD><EFBFBD>а<EFBFBD><D0B0><EFBFBD>
::CloseClipboard(); //<2F>رռ<D8B1><D5BC>а<EFBFBD>
}
} // namespace ui