3172 lines
78 KiB
C++
3172 lines
78 KiB
C++
#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)>, (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
|