#include "StdAfx.h" #include "UEditExt.h" #include "boost/regex.hpp" INT getHexVal(char c) { if(c >= '0' && c <= '9') return c - '0'; else if(c >= 'A' && c <= 'Z') return c - 'A' + 10; else if(c >= 'a' && c <= 'z') return c - 'a' + 10; return -1; } struct BlockContent { BlockContent(){SetBlock(0, 0, 0, 0);} UINT realIndex;//宽字符长度,未解析真实位置 UINT realLength;//宽字符长度,未解析真是长度 UINT ParseIndex;//宽字符长度,解析后位置 UINT ParseLength;//宽字符长度,解析后长度 void SetBlock(UINT ri, UINT rl, UINT pi, UINT pl) { realIndex = ri; realLength = rl; ParseIndex = pi; ParseLength = pl; }; UINT DeleteBlock(UStringW& realBuff, UStringW& ParseBuff) { if (realBuff.GetBuffer()) { if(realIndex < realBuff.GetLength() &&realIndex+realLength <= realBuff.GetLength()) realBuff.Cut(realIndex,realLength); } if (ParseBuff.GetBuffer()) { if(ParseIndex < ParseBuff.GetLength() &&ParseIndex+ParseLength <= ParseBuff.GetLength()) ParseBuff.Cut(ParseIndex,ParseLength); } UINT index = ParseIndex; SetBlock(0, 0, 0, 0); return index; } }; UIMP_CLASS(UChatEdit,UControl) UChatEdit::UChatEdit(void) { m_SourceBuff.Resize(0); m_ParseBuff.Resize(0); mCaretPos = 0; mCaretXPos = 0; mInsertOn = TRUE; m_nMaxLength = MAX_TEXT_LENGTH; m_spFont = NULL; mCaretLeftWidth = 0; mTimeLastCursorFlipped = 0.0f; fun = NULL; } UChatEdit::~UChatEdit(void) { mCaretPos = 0; mCaretXPos = 0; mInsertOn = TRUE; m_nMaxLength = MAX_TEXT_LENGTH; m_spFont = NULL; } void UChatEdit::StaticInit() { } BOOL UChatEdit::OnCreate() { if (!UControl::OnCreate()) { return FALSE; } if (m_spFont == NULL) { m_spFont = m_Style->m_spFont; if (!m_spFont) { return FALSE; } } mFontColor = m_Style->m_FontColor; PlaceCaretPos(0); return TRUE; } void UChatEdit::OnDestroy() { m_spFont = NULL; UControl::OnDestroy(); } BOOL UChatEdit::OnKeyDown(UINT nKeyCode, UINT nRepCnt, UINT nFlags) { if(!m_Active ) return FALSE; UINT KeyCode = nKeyCode; UINT Flags = nFlags; UINT stringLen = m_ParseBuff.GetLength(); // 优先处理退格操作. if(KeyCode == LK_BACKSPACE) { if (mSelEnd > 0 && mSelBegin < mSelEnd) { ClearSelection(); return TRUE; } if (mCaretPos > 0) // 如果当前光标不在起点 { //删除一个字符 std::vector::iterator it = m_BlockList.begin(); while(it != m_BlockList.end()) { if (mCaretPos == it->ParseLength + it->ParseIndex) { PlaceCaretPos(it->ParseIndex); it->DeleteBlock(m_SourceBuff, m_ParseBuff); m_BlockList.erase(it); Parse(); PlaceCaretPos(mCaretPos); return TRUE; } ++it; } m_SourceBuff.Cut(CalSourceCaret(mCaretPos -1), 1); Parse(); PlaceCaretPos(mCaretPos - 1); } return TRUE; }else if (KeyCode == LK_RETURN || KeyCode == LK_NUMPADENTER) { DispatchNotify(UED_UPDATE); if (m_Style->mReturnTab) { OnLostFocus(); } return TRUE; }else if (Flags & LKM_SHIFT) { switch (KeyCode) { case LK_TAB: //if ( mTabComplete ) //{ // DispatchNotify(UED_UPDATE); // return( TRUE ); //} break; case LK_HOME: // 光标移到起点 mSelBegin = 0; mSelEnd = mCaretPos; PlaceCaretPos(0); return TRUE; case LK_END: // 光标移到终点 mSelBegin = mCaretPos; mSelEnd = stringLen; PlaceCaretPos(stringLen); return TRUE; case LK_LEFT: if (mCaretPos > 0 && stringLen > 0) { if (mCaretPos == mSelEnd) { for (UINT i = 0 ; i < m_BlockList.size() ; i++) { if(mCaretPos == m_BlockList[i].ParseIndex + m_BlockList[i].ParseLength) { PlaceCaretPos(m_BlockList[i].ParseIndex); mSelEnd = mCaretPos; if (mSelBegin == mSelEnd) { mSelBegin = 0; mSelEnd = 0; } return TRUE; } } PlaceCaretPos(mCaretPos - 1); mSelEnd--; if (mSelEnd == mSelBegin) { // 取消选择 mSelBegin = 0; mSelEnd = 0; } } else { if (mSelEnd == 0) { mSelBegin = mCaretPos; mSelEnd = mCaretPos; } for (UINT i = 0 ; i < m_BlockList.size() ; i++) { if(mCaretPos == m_BlockList[i].ParseIndex + m_BlockList[i].ParseLength) { PlaceCaretPos(m_BlockList[i].ParseIndex); mSelBegin = mCaretPos; if (mSelBegin == mSelEnd) { mSelBegin = 0; mSelEnd = 0; } return TRUE; } } PlaceCaretPos(mCaretPos - 1); mSelBegin = mCaretPos; if (mSelEnd == 0) { mSelEnd = mCaretPos + 1; } } } return TRUE; case LK_RIGHT: if (mCaretPos < stringLen) { if ((mCaretPos == mSelBegin) && (mSelEnd > 0)) { for (UINT i = 0 ; i < m_BlockList.size() ; i++) { if(mCaretPos == m_BlockList[i].ParseIndex) { PlaceCaretPos(m_BlockList[i].ParseIndex + m_BlockList[i].ParseLength); mSelBegin = mCaretPos; if (mSelBegin == mSelEnd) { mSelBegin = 0; mSelEnd = 0; } return TRUE; } } PlaceCaretPos(mCaretPos + 1); mSelBegin++; if (mSelBegin == mSelEnd) { mSelBegin = 0; mSelEnd = 0; } } else { if (mSelEnd == 0) { mSelBegin = mCaretPos; mSelEnd = mCaretPos; } for (UINT i = 0 ; i < m_BlockList.size() ; i++) { if(mCaretPos == m_BlockList[i].ParseIndex) { PlaceCaretPos(m_BlockList[i].ParseIndex + m_BlockList[i].ParseLength); mSelEnd = mCaretPos; if (mSelBegin == mSelEnd) { mSelBegin = 0; mSelEnd = 0; } return TRUE; } } PlaceCaretPos(mCaretPos + 1); mSelEnd++; if (mSelBegin == mSelEnd) { mSelBegin = 0; mSelEnd = 0; } } } return TRUE; } } else if (Flags & LKM_CTRL) { switch(KeyCode) { case LK_A: { return TRUE; } case LK_C: { Copy(); return TRUE; } case LK_X: { Cut(); return TRUE; } case LK_V: { Paste(); return TRUE; } case LK_Z: if (!mDragHit) { Undo(); return TRUE; } case LK_DELETE: case LK_BACKSPACE: Clear(); return TRUE; } } else { switch(KeyCode) { case LK_UP: if (fun) { return (*fun)(KeyCode, Flags); } return TRUE; case LK_DOWN: if (fun) { return (*fun)(KeyCode, Flags); } return TRUE; //case LK_RETURN: //case LK_NUMPADENTER: // //first validate // DispatchNotify(UED_UPDATE); // if (m_Style->mReturnTab) // { // OnLostFocus(); // } // //if (m_Style->mReturnTab) // //{ // // UDesktop* root = (UDesktop*)GetRoot(); // // if (root) // // { // // root->TabNext(); // // return TRUE; // // } // //} // return TRUE; //case LK_UP: //case LK_DOWN: case LK_LEFT: mSelBegin = 0; mSelEnd = 0; for (UINT i = 0 ; i < m_BlockList.size() ; i++) { if(mCaretPos == (m_BlockList[i].ParseLength + m_BlockList[i].ParseIndex)) { PlaceCaretPos(m_BlockList[i].ParseIndex); return TRUE; } } if (mCaretPos > 0) { PlaceCaretPos(mCaretPos - 1); } return TRUE; case LK_RIGHT: mSelBegin = 0; mSelEnd = 0; for (UINT i = 0 ; i < m_BlockList.size() ; i++) { if(mCaretPos == m_BlockList[i].ParseIndex) { PlaceCaretPos(m_BlockList[i].ParseIndex + m_BlockList[i].ParseLength); return TRUE; } } if (mCaretPos < stringLen) { PlaceCaretPos(mCaretPos + 1); } return TRUE; case LK_DELETE: ClearSelection(); if (mCaretPos < stringLen) // 删除后面一个字符 { std::vector::iterator it = m_BlockList.begin(); while(it != m_BlockList.end()) { if (mCaretPos == it->ParseIndex) { it->DeleteBlock(m_SourceBuff, m_ParseBuff); m_BlockList.erase(it); Parse(); PlaceCaretPos(mCaretPos); return TRUE; } ++it; } m_SourceBuff.Cut(CalSourceCaret(mCaretPos), 1); Parse(); } return TRUE; case LK_INSERT: mInsertOn = !mInsertOn; return TRUE; case LK_HOME: mSelBegin = 0; mSelEnd = 0; PlaceCaretPos(0); return TRUE; case LK_END: mSelBegin = 0; mSelEnd = 0; PlaceCaretPos(stringLen); return TRUE; } } //switch ( KeyCode ) //{ //case LK_TAB: // if ( mTabComplete ) // { // DispatchNotify(UED_UPDATE); // return( TRUE ); // } //case LK_UP: //case LK_DOWN: //case LK_ESCAPE: // return UControl::OnKeyDown( nKeyCode, nRepCnt, nFlags ); //} return TRUE; } BOOL UChatEdit::OnKeyUp(UINT nKeyCode, UINT nRepCnt, UINT nFlags) { return UControl::OnKeyUp(nKeyCode,nRepCnt,nFlags); } BOOL UChatEdit::OnChar(UINT nCharCode, UINT nRepCnt, UINT nFlags) { if (!m_Active) { return FALSE; } ClearSelection(); /*UINT TextLen = m_SourceBuff.GetAnsiLength();*/ UINT TextLen = m_SourceBuff.GetLength(); BOOL IsApp = FALSE; if ( ( mInsertOn && ( TextLen < m_nMaxLength ) ) || ( !mInsertOn && ( mCaretPos < m_nMaxLength ) ) ) { if ( CalSourceCaret(mCaretPos) == TextLen ) { m_SourceBuff.Append(nCharCode); IsApp = TRUE; } else { if ( mInsertOn ) { m_SourceBuff.Insert(CalSourceCaret(mCaretPos), nCharCode); IsApp = TRUE; } else { m_SourceBuff.Cut(mCaretPos, 1); m_SourceBuff.Insert(CalSourceCaret(mCaretPos), nCharCode); IsApp = TRUE; } } if (nCharCode == 32) { DispatchNotify(UED_CHANGED); } } if (IsApp) { Parse(); PlaceCaretPos(mCaretPos + 1); } return TRUE; } void UChatEdit::PlaceCaretPos(UINT pos) { if(m_ParseBuff.GetLength() == 0) { mCaretPos = 0; mCaretLeftWidth = 0; UPoint Position = WindowToScreen(UPoint(0, 0)); mTextOffset.x = Position.x; mCaretXPos = Position.x; return; } for(UINT i = 0 ; i < m_BlockList.size() ; i++) { if (pos > m_BlockList[i].ParseIndex && pos < (m_BlockList[i].ParseLength + m_BlockList[i].ParseIndex)) { if (pos > (m_BlockList[i].ParseLength + m_BlockList[i].ParseIndex * 2) / 2) { PlaceCaretPos(m_BlockList[i].ParseLength + m_BlockList[i].ParseIndex + 1); } else { PlaceCaretPos(m_BlockList[i].ParseIndex); } return; } } UPoint Position = WindowToScreen(UPoint(0, 0)); INT Padding = m_Style->mTextOffset.x == 0 ? 3 : m_Style->mTextOffset.x; INT ClientWidth = m_Size.x; INT ClientHeight = m_Size.y; INT ClientRight = Position.x + ClientWidth; INT ClientPaddedRight = ClientRight - Padding; INT ClientPaddedLeft = Position.x + Padding; INT TextClientWidth = ClientWidth - Padding; pos = pos < 0 ? 0 : ( pos > m_ParseBuff.GetLength() ? m_ParseBuff.GetLength() : pos); mCaretPos = pos; INT textWidth = 0; textWidth = m_spFont->GetStrNWidth(m_ParseBuff, m_ParseBuff.GetLength()); WCHAR CaretChar = m_ParseBuff[mCaretPos]; INT CaretLeftStrWidth = 0; INT CaretCharWidth; if(mCaretPos > 0) { CaretLeftStrWidth = m_spFont->GetStrNWidth(m_ParseBuff, mCaretPos); } else { CaretLeftStrWidth = 0; } if ( CaretChar ) { CaretCharWidth = m_spFont->GetCharWidth( CaretChar ); } else CaretCharWidth = Padding; if( (mTextOffset.x + CaretLeftStrWidth + CaretCharWidth) >= ClientPaddedRight) { INT skipForward = m_Size.x / 4; if ( CaretLeftStrWidth + skipForward > textWidth ) { mTextOffset.x = ClientPaddedRight - textWidth; } else { mTextOffset.x -= skipForward; } } else if( mTextOffset.x + CaretLeftStrWidth < ClientPaddedLeft ) { INT skipBackward = m_Size.x/ 4; if ((CaretLeftStrWidth - skipBackward) < 0 ) { mTextOffset.x = ClientPaddedLeft; } else { mTextOffset.x += skipBackward; } } mCaretLeftWidth = CaretLeftStrWidth; mCaretXPos = mTextOffset.x + CaretLeftStrWidth; } INT UChatEdit::PlaceCatetXPos(const UPoint& offset) { if(m_ParseBuff.GetLength() == 0) { if (mCaretPos != 0) { PlaceCaretPos(0); } return 0; } UPoint ctrlOffset = WindowToScreen( UPoint( 0, 0 ) ); INT charLength = 0; INT curX = offset.x - ctrlOffset.x; if ( curX < 0 ) return -1; if ( curX >= ctrlOffset.x + m_Size.x ) return -2; curX = offset.x - mTextOffset.x; UINT count = 0; assert(m_spFont); for(count = 0; count < m_ParseBuff.GetLength(); count++) { WCHAR c = m_ParseBuff[count]; if(!m_ParseBuff && !m_spFont->IsValidChar(c)) continue; charLength += m_spFont->GetCharXIncrement( c ); if ( charLength > curX ) break; } PlaceCaretPos(count); return count; } void UChatEdit::Parse() { boost::regex reg("(.*?)"); char buf[2048]; int nRet = WideCharToMultiByte(CP_UTF8, 0, m_SourceBuff.GetBuffer(),m_SourceBuff.GetLength(),buf,2048, NULL, NULL); buf[nRet] = '\0'; std::string mText = buf; boost::smatch m; //Parse Block m_BlockList.clear(); std::string::const_iterator start = mText.begin(); std::string::const_iterator end = mText.end(); UINT nextSourceIndex = 0; UINT nextParseIndex = 0; UINT ALLPrevSourcelength = 0; while(boost::regex_search(start,end,m,reg)) { std::string msg(m[1].first, m[1].second); std::string text(m.base(),m.base() + m.position()); nextSourceIndex += MultiByteToWideChar(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0); nextParseIndex += MultiByteToWideChar(CP_UTF8, 0, text.c_str(), text.length(), NULL, 0); BlockContent newBlock; UINT StrPos = m.position() + ALLPrevSourcelength; UINT StrLen = m.length(); ALLPrevSourcelength += m.position() + StrLen; std::string Cstr = mText.substr(StrPos,StrLen); UINT soucelength = MultiByteToWideChar(CP_UTF8,0,Cstr.c_str(),StrLen,NULL,0); UINT Parselength = MultiByteToWideChar(CP_UTF8,0,msg.c_str(),msg.length(),NULL,0); newBlock.SetBlock(nextSourceIndex, soucelength, nextParseIndex, Parselength); m_BlockList.push_back(newBlock); nextSourceIndex += soucelength;//m.length(); nextParseIndex += Parselength; start = m[0].second; } //Parse ParseBuff mText = boost::regex_replace(mText,reg,"$1"); m_ParseBuff.Set(mText.c_str()); } void UChatEdit::ParseFaceBuffer(std::string &str) { boost::regex reg("\\[\\/(.*?)\\]"); str = boost::regex_replace(str,reg,""); } UINT UChatEdit::CalSourceCaret(UINT CP) { UINT SourceCaret = CP; for (UINT i = 0; i < m_BlockList.size() ; i++) { if (m_BlockList[i].ParseLength + m_BlockList[i].ParseIndex <= CP) { SourceCaret -= m_BlockList[i].ParseLength; SourceCaret += m_BlockList[i].realLength; } } return SourceCaret; } void UChatEdit::SetText(const char* txt) { if(txt && txt[0] != 0) { m_SourceBuff.Set( txt ); } else { m_SourceBuff.SetEmpty(); } Parse(); int nCaretCP = m_ParseBuff.GetLength(); PlaceCaretPos(nCaretCP); } void UChatEdit::SetText(const WCHAR* txt) { if(txt && txt[0] != 0) { m_SourceBuff.Set(txt); } else { m_SourceBuff.SetEmpty(); } Parse(); int nCaretCP = m_ParseBuff.GetLength(); PlaceCaretPos(nCaretCP); } void UChatEdit::InsertText(const char* txt) { WCHAR wBuf[1024]; int nRet = MultiByteToWideChar(CP_UTF8, 0, txt, strlen(txt), wBuf, 1024); wBuf[nRet] = 0; InsertText(wBuf); } void UChatEdit::InsertText(const WCHAR* txt) { ClearSelection(); int addl = m_ParseBuff.GetLength(); UINT _length = WideCharToMultiByte(CP_UTF8, 0, txt, wcslen(txt), NULL, NULL, NULL, NULL); _length += m_SourceBuff.GetAnsiLength(); if (txt && txt[0] != 0 && _length < 1024) { m_SourceBuff.Insert(CalSourceCaret(mCaretPos),txt); Parse(); if (m_ParseBuff.GetAnsiLength() > m_nMaxLength) { m_SourceBuff.Cut(CalSourceCaret(mCaretPos),wcslen(txt)); } else { addl = m_ParseBuff.GetLength() - addl; PlaceCaretPos(mCaretPos + addl); } } } int UChatEdit::GetText(char* dest, UINT nMaxLen, UINT nPos) { return m_SourceBuff.GetAnsi(dest, nMaxLen, nPos); } int UChatEdit::GetText(WCHAR* dest, UINT nMaxLen, UINT nPos) { if(nPos >= m_SourceBuff.GetLength() || nMaxLen == 0) { return 0; } assert(nMaxLen > 0); nMaxLen = __min(nMaxLen, m_SourceBuff.GetLength() - nPos ); for(UINT i = 0; i < nMaxLen; i++) { dest[i] = m_SourceBuff[nPos + i]; } return nMaxLen; } void UChatEdit::SetMaxLength(UINT length) { if (length > MAX_TEXT_LENGTH) { m_nMaxLength = MAX_TEXT_LENGTH; } else { m_nMaxLength = length; } } void UChatEdit::Clear() { m_BlockList.clear(); m_ParseBuff.SetEmpty(); m_SourceBuff.SetEmpty(); PlaceCaretPos(0); mSelBegin = mSelEnd = 0; } void UChatEdit::OnTimer(float fDeltaTime) { if (IsFocused()) { //控制输入框光标闪烁 mTimeLastCursorFlipped += (fDeltaTime*0.5f); if (mTimeLastCursorFlipped > 10) { mTimeLastCursorFlipped = 0.0f; } UINT pIndex = UINT(mTimeLastCursorFlipped * 60 / 10); mCursorOn = pIndex % 2; } } void UChatEdit::DrawContext(const URect &drawRect, BOOL isFocused ) { UPoint drawPoint(drawRect.left, drawRect.top); UPoint Padding; Padding.Set(( m_Style->mTextOffset.x != 0 ? m_Style->mTextOffset.x : 3 ), m_Style->mTextOffset.y); INT ClientWidth = drawRect.GetWidth(); INT ClientHeight = drawRect.GetHeight(); INT TextClientWidth = ClientWidth - Padding.x; drawPoint.y += (( ( ClientHeight - m_spFont->GetHeight() ) / 2 ) + Padding.y); mTextOffset.y = drawPoint.y; mFontColor = m_Active ? mFontColor : m_Style->m_FontColorNA; UPoint cursorStart, cursorEnd; if ( isFocused ) { cursorStart.x = mTextOffset.x + mCaretLeftWidth; cursorEnd.x = cursorStart.x; INT cursorHeight = m_spFont->GetHeight(); if ( cursorHeight < drawRect.GetHeight() ) { cursorStart.y = drawPoint.y; cursorEnd.y = cursorStart.y + cursorHeight; } else { cursorStart.y = drawRect.top; cursorEnd.y = drawRect.bottom; } } if ( !isFocused ) mSelBegin = mSelEnd = 0; if (mSelBegin > m_ParseBuff.GetLength() || mSelEnd > m_ParseBuff.GetLength() || mSelBegin > mSelEnd ) { mSelBegin = mSelEnd = 0; } UPoint tempOffset = mTextOffset; if ( mSelBegin > 0 ) { int nWidth = sm_UiRender->DrawTextN(m_spFont, tempOffset, m_ParseBuff, mSelBegin, NULL, mFontColor); int StrWidth = m_spFont->GetStrNWidth(m_ParseBuff, mSelBegin); tempOffset.x += StrWidth; } if ( mSelEnd > 0 ) { const WCHAR* HLText = m_ParseBuff.GetBuffer() + mSelBegin; UINT HLLen = mSelEnd - mSelBegin; INT StrWidth = m_spFont->GetStrNWidth(HLText, HLLen); URect HLRect; HLRect.left = tempOffset.x; HLRect.top = drawRect.top; HLRect.right = HLRect.left + StrWidth; HLRect.bottom = drawRect.bottom -1; sm_UiRender->DrawRectFill(HLRect, m_Style->m_FontColorSEL); sm_UiRender->DrawTextN(m_spFont, tempOffset, HLText, HLLen, NULL, m_Style->m_FontColorHL ); tempOffset.x += StrWidth; } if(mSelEnd < m_ParseBuff.GetLength()) { const WCHAR* Tail = m_ParseBuff.GetBuffer() + mSelEnd; UINT ToDraw = m_ParseBuff.GetLength() - mSelEnd; sm_UiRender->DrawTextN(m_spFont, tempOffset,Tail, ToDraw, NULL, mFontColor); } if ( isFocused && mCursorOn ) { sm_UiRender->DrawRectFill( URect(cursorStart, UPoint(4, cursorEnd.y - cursorStart.y)), m_Style->mCursorColor ); //sm_UiRender->DrawLine( cursorStart, cursorEnd, m_Style->mCursorColor ); } } void UChatEdit::OnRender(const UPoint& offset,const URect &updateRect) { g_pRenderInterface->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); g_pRenderInterface->SetScissorRect(sm_UiRender->GetClipRect()); URect ctrlRect( offset, m_Size); DrawContext( ctrlRect, IsFocused() ); g_pRenderInterface->SetRenderState(D3DRS_SCISSORTESTENABLE,FALSE); } void UChatEdit::OnGetFocus() { UControl::OnGetFocus(); sm_System->SetIMEEnable(TRUE); } void UChatEdit::OnLostFocus() { sm_System->SetIMEEnable(FALSE); } void UChatEdit::OnMouseDown(const UPoint& point, UINT nRepCnt, UINT uFlags) { mDragHit = FALSE; if (nRepCnt == 2) { SelAll(); }else { mSelBegin = mSelEnd = 0; } INT pos = PlaceCatetXPos( point ); if ( pos == -1 ) mCaretPos = 0; else if ( pos == -2 ) mCaretPos = m_ParseBuff.GetLength(); else PlaceCaretPos(pos); mMouseDragStart = mCaretPos; CaptureControl(); mDragHit = TRUE; SetFocusControl(); } void UChatEdit::OnMouseUp(const UPoint& position, UINT flags) { mDragHit = FALSE; ReleaseCapture(); } void UChatEdit::OnMouseDragged(const UPoint& pt, UINT uFlags) { INT pos = PlaceCatetXPos(pt); mSelBegin = __min( mCaretPos, mMouseDragStart ); mSelEnd = __max( mCaretPos, mMouseDragStart ); if ( mSelBegin < 0 ) mSelBegin = 0; if ( mSelBegin == mSelEnd ) mSelBegin = mSelEnd = 0; UControl::OnMouseDragged(pt, uFlags); } void UChatEdit::OnMove(const UPoint& NewOffsetDelta) { mTextOffset += NewOffsetDelta; PlaceCaretPos(mCaretPos); } void UChatEdit::ClearSelection() { if (mSelEnd > 0 && mSelBegin < mSelEnd) { PlaceCaretPos(mSelBegin); if (m_SourceBuff.GetBuffer()) { m_SourceBuff.Cut(CalSourceCaret(mSelBegin),CalSourceCaret(mSelEnd) - CalSourceCaret(mSelBegin)); } if (m_ParseBuff.GetBuffer()) { m_ParseBuff.Cut(mSelBegin,mSelEnd - mSelBegin); } mSelBegin = mSelEnd = 0; Parse(); } } void UChatEdit::SetSel(int nStartCP, int nEndCP) { int Len = m_ParseBuff.GetLength(); mSelBegin = LClamp(nStartCP, 0, Len); mSelEnd = LClamp(nEndCP, 0, Len); if (mSelBegin == mSelEnd) { mSelBegin = mSelEnd = 0; } } void UChatEdit::SelAll() { mSelBegin = 0; mSelEnd = m_ParseBuff.GetLength(); } BOOL UChatEdit::Undo() { //TODO return TRUE; } void UChatEdit::Copy() { if (mSelEnd > 0 ) { if (!OpenClipboard(NULL)) { return; } if(!EmptyClipboard()) { UTRACE("can't empty clipboard."); return; } //BOOL bSupport = IsClipboardFormatAvailable(CF_UNICODETEXT); //if (!bSupport) //{ // return ; //} HGLOBAL hBlock = GlobalAlloc( GMEM_MOVEABLE, (mSelEnd - mSelBegin + 1 )*sizeof(WCHAR) ); if( hBlock ) { WCHAR *pszText = (WCHAR*)GlobalLock( hBlock ); if( pszText ) { m_ParseBuff.SubStr(pszText, mSelBegin, mSelEnd - mSelBegin); GlobalUnlock( hBlock ); } HANDLE hcbData = SetClipboardData(CF_UNICODETEXT, hBlock ); if (hcbData == NULL) { DWORD Error = GetLastError(); UTRACE("SetClipboardData failed , err : %d ", Error); } } CloseClipboard(); if( hBlock ) GlobalFree( hBlock ); } } void UChatEdit::Cut() { if (mSelEnd > 0 && OpenClipboard(NULL)) { EmptyClipboard(); HGLOBAL hBlock = GlobalAlloc( GMEM_MOVEABLE, ( mSelEnd - mSelBegin + 1 )*sizeof(WCHAR) ); if( hBlock ) { WCHAR *pszText = (WCHAR*)GlobalLock( hBlock ); if( pszText ) { m_ParseBuff.Cut(mSelBegin, mSelEnd - mSelBegin, pszText); m_SourceBuff.Cut(CalSourceCaret(mSelBegin), CalSourceCaret(mSelEnd - mSelBegin)); Parse(); GlobalUnlock( hBlock ); } SetClipboardData( CF_UNICODETEXT, hBlock ); } CloseClipboard(); if( hBlock ) GlobalFree( hBlock ); PlaceCaretPos(mSelBegin); mSelBegin = 0; mSelEnd = 0; } } void UChatEdit::Paste() { if( OpenClipboard( NULL ) ) { HANDLE handle = GetClipboardData( CF_UNICODETEXT ); if( handle ) { WCHAR *pwszText = (WCHAR*)GlobalLock( handle ); if( pwszText ) { // 首先删除选择内容. int InsertCP = 0; if (mSelEnd > 0) { ClearSelection(); } else { InsertCP = mCaretPos; } UStringW wszText; wszText.Set(pwszText); UINT SrcLen = wszText.GetAnsiLength()/*wcslen(pwszText)*/; UINT CurLen = m_SourceBuff.GetAnsiLength()/*m_wstrBuffer.GetLength()*/; if (SrcLen + CurLen <= m_nMaxLength) { INT WLen = wcslen(pwszText); m_SourceBuff.Insert(CalSourceCaret(InsertCP), pwszText, WLen); Parse(); PlaceCaretPos(InsertCP + WLen); } else { SrcLen = m_nMaxLength - CurLen/* - 1*/; char buf[1024]; int nRet = WideCharToMultiByte(CP_UTF8, 0, pwszText,wcslen(pwszText), buf,SrcLen, NULL, NULL); buf[SrcLen] = 0; WCHAR Wbuf[1024]; nRet = MultiByteToWideChar(CP_UTF8, 0, buf, SrcLen, Wbuf, SrcLen); Wbuf[nRet] =0; m_SourceBuff.Insert(CalSourceCaret(InsertCP), Wbuf, -1); Parse(); PlaceCaretPos(InsertCP + nRet); } GlobalUnlock( handle ); } }else { DWORD ec = GetLastError(); UTRACE("Can't get clipboard data %d.", ec); } CloseClipboard(); } } void UChatEdit::SetFontColor(UColor color) { mFontColor = color; } void UChatEdit::SetFontColor(const char * color) { int num = 0; while (color[num++] != '\0'); num--; if (num != 6 && num != 8) return; mFontColor.r = getHexVal(color[0]) * 16 + getHexVal(color[1]); mFontColor.g = getHexVal(color[2]) * 16 + getHexVal(color[3]); mFontColor.b = getHexVal(color[4]) * 16 + getHexVal(color[5]); if (num == 8) mFontColor.a = getHexVal(color[6]) * 16 + getHexVal(color[7]); else mFontColor.a = 255; } UIMP_CLASS(UEditExt,UControl); UBEGIN_MESSAGE_MAP(UEditExt,UCmdTarget) UON_UEDIT_UPDATE(0,&UEditExt::UpdataEdit) UON_UEDIT_CHANGED(0,&UEditExt::EditChanged) UEND_MESSAGE_MAP() void UEditExt::StaticInit() { } UEditExt::UEditExt(void) { m_BodyEdit = NULL; m_TextOffset.Set(0,0); } UEditExt::~UEditExt(void) { } UEditExt * UEditExt::CreateEditExt(UPoint size,const char * style) { UEditExt * _temp = (UEditExt *)UEditExt::CreateObject(); _temp->SetField("style",style); _temp->SetSize(size); return _temp; } void UEditExt::SetHeadFontColor(UColor color) { m_HeadEditFontColor = color; } void UEditExt::SetHeadFontColor(const char * color) { int num = 0; while (color[num++] != '\0'); num--; if (num != 6 && num != 8) return; m_HeadEditFontColor.r = getHexVal(color[0]) * 16 + getHexVal(color[1]); m_HeadEditFontColor.g = getHexVal(color[2]) * 16 + getHexVal(color[3]); m_HeadEditFontColor.b = getHexVal(color[4]) * 16 + getHexVal(color[5]); if (num == 8) m_HeadEditFontColor.a = getHexVal(color[6]) * 16 + getHexVal(color[7]); else m_HeadEditFontColor.a = 255; } void UEditExt::SetBodyFontColor(UColor color) { if (m_BodyEdit) m_BodyEdit->SetFontColor(color); } void UEditExt::SetBodyFontColor(const char * color) { if (m_BodyEdit) m_BodyEdit->SetFontColor(color); } BOOL UEditExt::OnCreate() { if (!UControl::OnCreate()) { return FALSE; } m_Style->mTextOffset = UPoint(0,0); if (m_BodyEdit == NULL) { m_BodyEdit = (UChatEdit *)UChatEdit::CreateObject(); m_HeadEditFontColor = m_Style->m_FontColor; if (!m_BodyEdit) { return FALSE; } m_BodyEdit->SetId(0); m_BodyEdit->SetControlStyle(m_Style); m_BodyEdit->SetSize(GetWindowSize()); AddChild(m_BodyEdit); } return TRUE; } void UEditExt::OnDestroy() { m_BodyEdit->Clear(); UControl::OnDestroy(); } void UEditExt::OnGetFocus() { if (m_BodyEdit && m_BodyEdit->IsActive()) { m_BodyEdit->SetFocusControl(); } } void UEditExt::OnLostFocus() { if (m_BodyEdit) { m_BodyEdit->ClearFocus(); } } void UEditExt::SetHeadText(const WCHAR * text,int flag) { m_wstr.Set(text); int width = m_Style->m_spFont->GetStrWidth(m_wstr); if (m_BodyEdit) { //if (flag) //m_BodyEdit->SetTextAlignment(UT_RIGHT); m_BodyEdit->SetWidth(GetWidth()-width); m_BodyEdit->SetLeft(width); } } void UEditExt::SetHeadText(const char * text,int flag) { m_wstr.Set(text); int width = m_Style->m_spFont->GetStrWidth(m_wstr); if (m_BodyEdit) { //if (flag) //m_BodyEdit->SetTextAlignment(UT_RIGHT); m_BodyEdit->SetWidth(GetWidth()-width); m_BodyEdit->SetLeft(width); } } void UEditExt::OnRender(const UPoint& offset,const URect &updateRect) { UPoint textpoint = offset + m_TextOffset; sm_UiRender->DrawTextN(m_Style->m_spFont,textpoint,m_wstr,m_wstr.GetLength(),NULL,m_HeadEditFontColor); UControl::OnRender(offset,updateRect); } void UEditExt::SetTextOffset(UPoint point) { m_TextOffset = point; } void UEditExt::SetBodyText(const char * text) { if (m_BodyEdit) { m_BodyEdit->Clear(); m_BodyEdit->SetText(text); } } void UEditExt::SetBodyText(const WCHAR *text) { if (m_BodyEdit) { m_BodyEdit->Clear(); m_BodyEdit->SetText(text); } } void UEditExt::Clear() { m_wstr.Clear(); if (m_BodyEdit) { m_BodyEdit->Clear(); } } void UEditExt::UpdataEdit() { DispatchNotify(UED_UPDATE); } void UEditExt::EditChanged() { DispatchNotify(UED_CHANGED); }