|
|
/******************************************************************************/ /* Tedit.CPP: IMPLEMENTATION OF THE CTedit CLASS */ /* */ /* */ /******************************************************************************/ /* */ /* Methods in this file */ /* */ /* Edit Control Object */ /* CAttrEdit::OnPaint */ /* CAttrEdit::OnEraseBkgnd */ /* CAttrEdit::OnRButtonDown */ /* CAttrEdit::OnChar */ /* CAttrEdit::OnMouseMove */ /* */ /******************************************************************************/ /* */ /* Text Edit Control Parent Window (Parent of Edit Control) */ /* CTedit::CTedit */ /* CTedit::CTedit */ /* CTedit::~CTedit */ /* */ /* Miscellaneous Methods */ /* CTedit::RefreshWindow */ /* CTedit::SetTextColor */ /* CTedit::SetBackColor */ /* CTedit::SetTransparentMode */ /* CTedit::Undo */ /* CTedit::ShowFontPalette */ /* CTedit::IsFontPaletteVisible */ /* CTedit::GetBitmap */ /* CTedit::PostNcDestroy */ /* CTedit::GetDefaultMinSize */ /* */ /* Edit Control Notification and processing methods */ /* CTedit::OnAttrEditEnChange */ /* CTedit::OnAttrEditFontChange */ /* */ /* Control Notification/Window Messages */ /* CTedit::OnEraseBkgnd */ /* CTedit::OnSize */ /* CTedit::OnMove */ /* CTedit::OnCtlColor */ /* CTedit::OnNcCalcSize */ /* CTedit::OnNcPaint */ /* CTedit::OnNcHitTest */ /* CTedit::OnRButtonDown */ /* */ /* Popup Menu Control Notification/Window Messages */ /* CTedit::OnTextPlain */ /* CTedit::OnTextBold */ /* CTedit::OnTextItalic */ /* CTedit::OnTextUnderline */ /* CTedit::OnTextSelectfont */ /* CTedit::OnTextSelectpointsize */ /* CTedit::OnEditCut */ /* CTedit::OnEditCopy */ /* CTedit::OnEditPaste */ /* CTedit::OnTextDelete */ /* CTedit::OnTextSelectall */ /* CTedit::OnTextPlace */ /* CTedit::OnTextTexttool */ /* */ /* CTedit::OnUpdateTextPlain */ /* CTedit::OnUpdateTextBold */ /* CTedit::OnUpdateTextItalic */ /* CTedit::OnUpdateTextUnderline */ /* CTedit::OnUpdateTextTexttool */ /* */ /******************************************************************************/
// TEDIT.CPP: IMPLEMENTATION OF THE CTEDIT CLASS
//
#include "stdafx.h"
#include "global.h"
#include "pbrush.h"
#include "pbrusvw.h"
#include "pbrusfrm.h"
#include "imgwnd.h"
#include "pictures.h"
#include "minifwnd.h"
#include "tfont.h"
#include "tedit.h"
#include "tracker.h"
#include <imm.h>
#include "imgsuprt.h"
#ifndef WM_SYSTIMER
#define WM_SYSTIMER 0x118
#endif //WM_SYSTIMER
#ifdef _DEBUG
#undef THIS_FILE
static CHAR BASED_CODE THIS_FILE[] = __FILE__; #endif
IMPLEMENT_DYNCREATE( CAttrEdit, CEdit ) IMPLEMENT_DYNCREATE( CTedit, CWnd )
#include "memtrace.h"
/******************************************************************************/ // CAttrEdit
BEGIN_MESSAGE_MAP( CAttrEdit, CEdit ) //{{AFX_MSG_MAP(CAttrEdit)
ON_WM_PAINT() ON_WM_ERASEBKGND() ON_WM_RBUTTONDOWN() ON_WM_CHAR()
ON_MESSAGE(WM_IME_CHAR, OnImeChar) ON_MESSAGE(WM_IME_COMPOSITION, OnImeComposition) ON_MESSAGE(WM_INPUTLANGCHANGE, OnInputLangChange) ON_WM_KILLFOCUS()
ON_WM_NCHITTEST() ON_WM_SETFOCUS() ON_WM_SIZE() ON_WM_LBUTTONDBLCLK() ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_WM_KEYDOWN() ON_MESSAGE(WM_SYSTIMER, OnSysTimer)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/******************************************************************************/
CAttrEdit::CAttrEdit() { m_bBackgroundTransparent = TRUE; m_pParentWnd = NULL; m_uiLastChar[0] = 32; m_uiLastChar[1] = 32;
m_rectUpdate.SetRectEmpty();
m_strResult.Empty(); m_bMouseDown = FALSE; m_hHCursor = theApp.LoadStandardCursor( IDC_IBEAM ); m_hVCursor = theApp.LoadCursor( IDCUR_HIBEAM ); m_hOldCursor = NULL; m_rectFmt.SetRectEmpty(); m_iPrevStart = -1; m_bResizeOnly = FALSE;
}
/******************************************************************************/
void CAttrEdit::OnPaint() { GetUpdateRect( &m_rectUpdate );
if ( !m_pParentWnd->m_bVertEdit ) { Default(); return; } else { CFont* pFont; CFont* pOldFont = NULL; CPalette* ppalOld = NULL; int OldBkMode; COLORREF OldTxtColor; CRect rc = m_rectFmt; int cnt = 0; int i = 0, h = 0; int nLen; CString cStr; LPTSTR lpStr; int nStart, nEnd; CDC* pDC = NULL; PAINTSTRUCT ps;
const MSG *pCurrentMessage = GetCurrentMessage(); //wParam is DC
if ( pCurrentMessage->wParam ) { HDC hDC = (HDC) pCurrentMessage->wParam; pDC = CDC::FromHandle( hDC ); } else pDC = BeginPaint( &ps );
if (pDC == NULL || pDC->m_hDC == NULL) { theApp.SetGdiEmergency(); return; }
OldBkMode = pDC->GetBkMode(); OldTxtColor = pDC->GetTextColor(); ppalOld = PBSelectPalette(pDC, theApp.m_pPalette, FALSE);
m_pParentWnd->SendMessage( WM_CTLCOLOREDIT, (WPARAM)pDC->m_hDC, (LPARAM) m_hWnd );
pFont = GetFont(); pOldFont = pDC->SelectObject( pFont );
h = m_pParentWnd->m_iLineHeight;
cnt = GetLineCount();
GetSel( nStart, nEnd ); if ( nStart == nEnd ) { for ( i = 0; i < cnt; i++ ) { nLen = LineLength( LineIndex( i ) ); lpStr = cStr.GetBufferSetLength( nLen ); GetLine( i, lpStr, nLen ); TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0, (LPTSTR)lpStr, nLen, FALSE ); } } else { int nStartLn, nEndLn; int nMaxText = GetWindowTextLength(); int nChar = 0;
nStartLn = LineFromChar( nStart ); nEndLn = LineFromChar( nEnd );
//Before Start
for ( i = 0; i < nStartLn; i++ ) { nLen = LineLength( LineIndex( i ) ); lpStr = cStr.GetBufferSetLength( nLen ); GetLine( i, lpStr, nLen ); TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0, (LPTSTR)lpStr, nLen, FALSE ); nChar = LineIndex( i + 1 ); } nLen = LineLength( LineIndex( i ) ); lpStr = cStr.GetBufferSetLength( nLen ); GetLine( i, lpStr, nLen ); TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0, (LPTSTR)lpStr, nStart - nChar, FALSE );
//Selected Text
COLORREF bkColor = pDC->SetBkColor( GetSysColor(COLOR_HIGHLIGHT) ); COLORREF txtColor = pDC->SetTextColor( GetSysColor(COLOR_HIGHLIGHTTEXT) ); int bkMode = pDC->SetBkMode( OPAQUE );
CPoint ptStart( (DWORD)SendMessage( EM_POSFROMCHAR, nStart ) ); if ( nStartLn == nEndLn ) { TabTextOut( pDC, nStart, rc.right - h * i, ptStart.x, (LPTSTR)lpStr + (nStart - nChar), nEnd - nStart, TRUE ); } else { TabTextOut( pDC, nStart, rc.right - h * i, ptStart.x, (LPTSTR)lpStr + (nStart - nChar), nLen + nChar - nStart, TRUE ); nChar = LineIndex( i + 1 );
for ( i++; i < nEndLn; i++ ) { nLen = LineLength( LineIndex( i ) ); lpStr = cStr.GetBufferSetLength( nLen ); GetLine( i, lpStr, nLen ); TabTextOut( pDC, nChar, rc.right - h * i, 0, (LPTSTR)lpStr, nLen, TRUE ); nChar = LineIndex( i + 1 ); }
nLen = LineLength( LineIndex( i ) ); lpStr = cStr.GetBufferSetLength( nLen ); GetLine( i, lpStr, nLen ); TabTextOut( pDC, nChar, rc.right - h * i, 0, (LPTSTR)lpStr, nEnd - nChar, TRUE ); }
pDC->SetBkColor( bkColor ); pDC->SetTextColor( txtColor ); pDC->SetBkMode( bkMode );
//After End
if ( nEnd < nMaxText ) { CPoint ptEnd( (DWORD)SendMessage( EM_POSFROMCHAR, nEnd ) ); TabTextOut( pDC, nEnd, rc.right - h * i, ptEnd.x, (LPTSTR)lpStr + (nEnd - nChar), nChar + nLen - nEnd, FALSE ); for ( i++; i < cnt; i++ ) { nLen = LineLength( LineIndex( i ) ); lpStr = cStr.GetBufferSetLength( nLen ); GetLine( i, lpStr, nLen ); TabTextOut( pDC, LineIndex( i ), rc.right - h * i, 0, (LPTSTR)lpStr, nLen, FALSE ); } } }
cStr.Empty();
if (pOldFont) pDC->SelectObject( pOldFont ); if (ppalOld) pDC->SelectPalette( ppalOld, FALSE ); pDC->SetBkMode( OldBkMode ); pDC->SetTextColor( OldTxtColor );
if ( !pCurrentMessage->wParam ) EndPaint( &ps ); } }
/******************************************************************************/
BOOL CAttrEdit::OnEraseBkgnd( CDC* pDC ) { if (m_pParentWnd == NULL) return CEdit::OnEraseBkgnd( pDC );
ASSERT( m_pParentWnd->m_pImgWnd->m_pImg != NULL ); ASSERT( m_pParentWnd->m_pImgWnd->m_pImg->hDC != NULL );
CPalette* ppalOld = NULL;
if (m_rectUpdate.IsRectEmpty()) { if (! GetUpdateRect( &m_rectUpdate, FALSE )) GetClientRect( &m_rectUpdate );
ValidateRect( &m_rectUpdate ); } CRect destRect = m_rectUpdate;
ClientToScreen( &m_rectUpdate );
m_pParentWnd->m_pImgWnd->ScreenToClient( &m_rectUpdate );
ppalOld = PBSelectPalette(pDC, theApp.m_pPalette, FALSE);
if (m_bBackgroundTransparent) m_pParentWnd->m_pImgWnd->DrawImage( pDC, &m_rectUpdate, &destRect ); else pDC->FillRect( &destRect, &m_pParentWnd->m_hbrBkColor );
if (ppalOld) pDC->SelectPalette( ppalOld, FALSE );
m_rectUpdate.SetRectEmpty();
return TRUE; }
/******************************************************************************/
void CAttrEdit::OnRButtonDown(UINT nFlags, CPoint point) { const MSG *pCurrentMessage = GetCurrentMessage();
m_pParentWnd->SendMessage( pCurrentMessage->message, pCurrentMessage->wParam, pCurrentMessage->lParam); }
/******************************************************************************/
void CAttrEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {
m_uiLastChar[0] = m_uiLastChar[1];
#ifndef UNICODE
//
// For DBCS we have to peek for the trail byte if the current
// byte is a lead byte
//
if (IsDBCSLeadByte((BYTE)nChar)) { MSG msg; ZeroMemory (&msg, sizeof(msg)); ::PeekMessage (&msg, m_hWnd, WM_CHAR, WM_CHAR, PM_NOREMOVE); m_uiLastChar[1] = (UINT)MAKEWORD((BYTE)msg.wParam, (BYTE)nChar); } else #endif // UNICODE
m_uiLastChar[1] = nChar;
if ( m_pParentWnd->m_bVertEdit ) { SetCaretPosition( TRUE, NULL, -1 ); UpdateInput(); HideCaret(); }
CEdit::OnChar( nChar, nRepCnt, nFlags );
if ( m_pParentWnd->m_bVertEdit ) { SetCaretShape(); UpdateInput(); ShowCaret(); }
BOOL bRefresh = FALSE;
switch (nChar) { case VK_BACK: case VK_DELETE: case VK_INSERT: bRefresh = TRUE;
break; }
if (bRefresh) m_pParentWnd->RefreshWindow(); /* enhance to do only the character involved */
//
// The edit control may have to resize
//
m_bResizeOnly = TRUE; m_pParentWnd->OnEnMaxText (); m_bResizeOnly = FALSE;
}
/******************************************************************************/
LRESULT CAttrEdit::OnInputLangChange( WPARAM wParam, LPARAM lParam ) { LRESULT lRet = Default();
if ( m_pParentWnd->m_bVertEdit ) { SetCaretPosition( TRUE, NULL, -1 ); } return lRet; }
/******************************************************************************/
LRESULT CAttrEdit::OnImeChar( WPARAM wParam, LPARAM lParam ) {
if ( m_pParentWnd->m_bVertEdit ) { SetCaretPosition( TRUE, NULL, -1 ); UpdateInput(); HideCaret(); }
return Default();
}
/******************************************************************************/
LRESULT CAttrEdit::OnImeComposition( WPARAM wParam, LPARAM lParam ) { // Use Faster Way undr Japanese Keyboard Layout (Japanese IME)
// Japanese IME may generate lots of chars at one time.
// This way is better than waiting WM_CHAR.
DWORD dwKeyboardLayout = PRIMARYLANGID(LOWORD(GetKeyboardLayout(0)));
if ( dwKeyboardLayout == LANG_JAPANESE) { if (lParam & GCS_RESULTSTR) { HIMC hIMC = ImmGetContext(m_hWnd);
DWORD dwSize; if (hIMC && (dwSize = ImmGetCompositionString(hIMC,GCS_RESULTSTR,NULL,0L))) { // ImmGetCompositionString returns the buffer size, IN BYTES.
// even if Unicode version.
LPTSTR lp = m_strResult.GetBufferSetLength(dwSize); ImmGetCompositionString(hIMC,GCS_RESULTSTR,lp,dwSize+sizeof(TCHAR)); *(lp + dwSize/sizeof(TCHAR)) = TEXT('\0'); ReplaceSel(lp); m_strResult.Empty(); }
ImmReleaseContext(m_hWnd, hIMC);
lParam &= ~( GCS_RESULTREADSTR | GCS_RESULTREADCLAUSE | GCS_RESULTSTR | GCS_RESULTCLAUSE); if (lParam) DefWindowProc(WM_IME_COMPOSITION,wParam,lParam);
// We'are not sure, how IME hide its composiiton window.
m_pParentWnd->RefreshWindow(); return 0; } } else if ( dwKeyboardLayout == LANG_KOREAN) { if ( m_pParentWnd->m_bVertEdit ) {
Default();
SetCaretPosition( FALSE, NULL, -2);
// We should update current composition string.
UpdateInput(); return 0; } else { // We should update current composition string.
UpdateInput(); return Default(); } }
return Default(); }
/******************************************************************************/
void CAttrEdit::OnKillFocus(CWnd* pNewWnd) { HIMC hIMC = ImmGetContext(m_hWnd); ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0L); ImmReleaseContext(m_hWnd, hIMC);
CEdit::OnKillFocus(pNewWnd);
if ( m_pParentWnd->m_bVertEdit ) { SetFmtRect(); Repaint(); }
}
/******************************************************************************/
UINT CAttrEdit::OnNcHitTest( CPoint point ) { const MSG *pCurrentMessage = GetCurrentMessage(); UINT uiHitTestCode = (UINT)DefWindowProc( pCurrentMessage->message, pCurrentMessage->wParam, pCurrentMessage->lParam);
if ( (uiHitTestCode == HTCLIENT) ) { if ( (m_pParentWnd->m_bVertEdit) ) SetVCursorShape(); else SetHCursorShape(); }
return uiHitTestCode; }
/******************************************************************************/
void CAttrEdit::OnSetFocus( CWnd* pOldWnd ) { Default();
if ( m_pParentWnd->m_bVertEdit ) { SetCaretShape(); SetCaretPosition( FALSE, NULL, -1 ); Repaint(); } }
/******************************************************************************/
void CAttrEdit::OnSize( UINT nType, int cx, int cy ) { Default();
m_rectFmt.left = m_rectFmt.top = 0; m_rectFmt.right = cx; m_rectFmt.bottom = cy;
SetFmtRect(); }
/******************************************************************************/
void CAttrEdit::OnLButtonDblClk(UINT nFlags, CPoint point) {
if ( !m_pParentWnd->m_bVertEdit ) { Default(); return; }
HideCaret(); UpdateSel(); SetStartSelect();
int tt = point.y; point.y = m_rectFmt.right - point.x; point.x = tt;
const MSG *pCurrentMessage = GetCurrentMessage(); DefWindowProc( pCurrentMessage->message, pCurrentMessage->wParam, MAKELPARAM( point.x, point.y ));
SetCaretPosition( TRUE, &point, -1 ); ShowCaret(); UpdateSel(); UpdateWindow(); }
/******************************************************************************/
void CAttrEdit::OnLButtonDown(UINT nFlags, CPoint point) {
if ( !m_pParentWnd->m_bVertEdit ) { Default(); return; }
HideCaret(); UpdateSel(); SetStartSelect();
int iPrevEnd; GetSel( m_iPrevStart, iPrevEnd );
int tt = point.y; point.y = m_rectFmt.right - point.x; point.x = tt;
//reset caret position to get correct caret position
CPoint pt( -20000, -20000 ); SetCaretPos( pt );
const MSG *pCurrentMessage = GetCurrentMessage(); DefWindowProc( pCurrentMessage->message, pCurrentMessage->wParam, MAKELPARAM( point.x, point.y ));
SetCaretPosition( TRUE, &point, m_iPrevStart ); if ( GetKeyState(VK_SHIFT) >= 0 ) //not extend selection
GetSel( m_iPrevStart, iPrevEnd ); ShowCaret(); UpdateSel(); UpdateWindow();
m_bMouseDown = TRUE;
}
/******************************************************************************/
void CAttrEdit::OnLButtonUp(UINT nFlags, CPoint point) {
if ( !m_pParentWnd->m_bVertEdit ) { Default(); return; }
m_bMouseDown = FALSE;
HideCaret(); UpdateSel(); SetStartSelect();
int tt = point.y; point.y = m_rectFmt.right - point.x; point.x = tt;
const MSG *pCurrentMessage = GetCurrentMessage(); DefWindowProc( pCurrentMessage->message, pCurrentMessage->wParam, MAKELPARAM( point.x, point.y ));
SetCaretPosition( TRUE, &point, m_iPrevStart ); ShowCaret(); UpdateSel(); UpdateWindow(); }
/******************************************************************************/
void CAttrEdit::OnMouseMove(UINT nFlags, CPoint point) {
if ( !m_pParentWnd->m_bVertEdit ) { Default(); return; }
if ( m_bMouseDown ) { HideCaret(); UpdateSel(); SetStartSelect();
int tt = point.y; point.y = m_rectFmt.right - point.x; point.x = tt;
const MSG *pCurrentMessage = GetCurrentMessage(); DefWindowProc( pCurrentMessage->message, pCurrentMessage->wParam, MAKELPARAM( point.x, point.y ));
SetCaretPosition( TRUE, &point, m_iPrevStart ); ShowCaret(); UpdateSel(); UpdateWindow(); } else CEdit::OnMouseMove( nFlags, point );
}
/******************************************************************************/
void CAttrEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
if ( !m_pParentWnd->m_bVertEdit ) { CEdit::OnKeyDown(nChar, nRepCnt, nFlags); return; }
BOOL bPrev = FALSE;
HideCaret();
switch (nChar) { case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: case VK_HOME: case VK_END: { UpdateSel();
CPoint ptCaretPos = GetCaretPos(); if ( ptCaretPos.y != 0 ) bPrev = TRUE;
int iPrevEnd; GetSel( m_iPrevStart, iPrevEnd );
SetStartSelect(); //for VK_RETURN
//reset caret position to get correct caret position
CPoint pt( -20000, -20000 ); SetCaretPos( pt );
break; } }
switch (nChar) { case VK_LEFT: nChar = VK_DOWN; break; case VK_RIGHT: nChar = VK_UP; break; case VK_UP: nChar = VK_LEFT; bPrev = FALSE; break; case VK_DOWN: nChar = VK_RIGHT; bPrev = FALSE; break; case VK_HOME: bPrev = FALSE; break; case VK_END: bPrev = TRUE; break; }
const MSG *pCurrentMessage = GetCurrentMessage(); DefWindowProc( pCurrentMessage->message, nChar, pCurrentMessage->lParam);
switch (nChar) { case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: case VK_HOME: case VK_END: { SetCaretPosition( bPrev, NULL, m_iPrevStart ); UpdateSel(); UpdateWindow(); break; } case VK_HANJA: // For Korea hanja conversion.
SetCaretPosition( FALSE, NULL, -2); break;
}
ShowCaret(); }
/******************************************************************************/ void CAttrEdit::SetStartSelect( void ) { int nStart, nEnd;
CPoint ptCaretPos = GetCaretPos();
if ( ptCaretPos.y == 0 ) { GetSel( nStart, nEnd ); if ( nStart == nEnd ) SetSel( nStart, nEnd ); } }
/******************************************************************************/ void CAttrEdit::SetCaretPosition( BOOL bPrev, CPoint* ptMouse, int iPrevStart ) {
HideCaret();
// Get Caret Position
CPoint ptCaretPos;
// Get End Selected Position to be Caret Position
int nStart, nEnd;
GetSel( nStart, nEnd );
if ( iPrevStart != -1 && nStart < iPrevStart ) nEnd = nStart; #ifdef UNICODE
// When NT bug 116057 is fixed, remove this code
// For composition string support
if ( m_pParentWnd->m_bVertEdit && iPrevStart == -2) nEnd -= 1 * sizeof(WCHAR)/sizeof(TCHAR); #endif //UNICODE
CPoint ptPos( (DWORD)SendMessage( EM_POSFROMCHAR, nEnd ) );
if ( nEnd >= GetWindowTextLength() || ( ptPos.x == 0 && (bPrev) && (ptMouse == NULL || ptMouse->y < ptPos.y ) ) ) { CString cStr; CDC* pDC = GetDC(); CFont* pFont = GetFont(); CFont* pOldFont; int nLine = ( (ptPos.x < 0) ? GetLineCount() : LineFromChar( nEnd ) ) - 1; int nChar = LineIndex( nLine ); int nLen = LineLength( nChar ); LPTSTR lpStr = cStr.GetBufferSetLength( nLen ); TEXTMETRIC tm;
pOldFont = pDC->SelectObject( pFont ); GetLine( nLine, lpStr, nLen );
pDC->GetTextMetrics( &tm );
if ( !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH) ) m_iTabPos = tm.tmAveCharWidth; else { CPoint len( pDC->GetTextExtent( TEXT("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52) ); m_iTabPos = (len.x / 26 + 1) / 2; if ( m_iTabPos <= 0 ) m_iTabPos = tm.tmAveCharWidth; }
m_iTabPos *= 8; if ( m_iTabPos <= 0 ) m_iTabPos = 1;
CPoint tt( 0, 0 ); if ( nLen > 0 ) { if ( *(lpStr + nLen - 1) == TEXT('\t') ) { tt = (CPoint) (DWORD)SendMessage( EM_POSFROMCHAR, nChar + nLen - 1 ); tt.x = min( (tt.x / m_iTabPos + 1) * m_iTabPos, m_rectFmt.bottom - 1 ); } else { LPTSTR lpChar = lpStr + nLen - 1; int nCnt;
for ( nCnt = 0; nCnt < nLen && *lpChar != TEXT('\t'); nCnt++, lpChar-- ); lpChar++; tt = (CPoint) (DWORD)SendMessage( EM_POSFROMCHAR, nChar + nLen - nCnt ); tt.Offset( pDC->GetTextExtent( lpChar, nCnt ) ); } } cStr.Empty(); ptCaretPos.x = tt.x; ptCaretPos.y = m_pParentWnd->m_iLineHeight * nLine; pDC->SelectObject( pOldFont );
ReleaseDC( pDC ); } else { ptCaretPos.x = ptPos.x; ptCaretPos.y = ptPos.y; }
// H -> V
CPoint pt( m_rectFmt.right - ptCaretPos.y - m_pParentWnd->m_iLineHeight, ptCaretPos.x ); //
// for some reason, typing spaces pushes the caret beyond the bottom of the rect.
// Cover that case by forcing the caret to be at the bottom of the rect.
//
if (pt.y > m_rectFmt.bottom) { pt.y = m_rectFmt.bottom-2; } SetCaretPos( pt );
//Set IME composition window position
HIMC himc;
if (himc=ImmGetContext(m_hWnd)) { COMPOSITIONFORM cf; RECT rcClient;
cf.dwStyle = CFS_RECT; cf.ptCurrentPos.x = m_rectFmt.right - ptCaretPos.y - 1; cf.ptCurrentPos.y = pt.y; GetClientRect( &rcClient ); cf.rcArea = rcClient;
ImmSetCompositionWindow(himc,&cf); ImmReleaseContext(m_hWnd, himc); }
#ifndef WINNT // don't call ImmSetCompositionWindow at this time.
SetFmtRect(); //it should be called after set IME position
#endif
ShowCaret(); }
/******************************************************************************/ void CAttrEdit::SetCaretShape( void ) { HideCaret(); ::DestroyCaret(); ::CreateCaret( m_hWnd, NULL, m_pParentWnd->m_iLineHeight, 2 ); ShowCaret(); }
/******************************************************************************/ void CAttrEdit::SetFmtRect() { RECT rc;
rc.left = rc.top = 0; if ( m_pParentWnd->m_bVertEdit ) { rc.right = m_rectFmt.bottom; rc.bottom = m_rectFmt.right; } else { rc.right = m_rectFmt.right; rc.bottom = m_rectFmt.bottom; } HIMC himc; COMPOSITIONFORM cf; BOOL bResult = FALSE;
if (himc=ImmGetContext(m_hWnd)) { bResult = ImmGetCompositionWindow(himc,&cf); } SetRectNP( &rc ); if (himc && bResult) { ImmSetCompositionWindow(himc,&cf); }
}
/******************************************************************************/ void CAttrEdit::Repaint(void) { InvalidateRect( NULL, TRUE ); UpdateWindow(); }
/******************************************************************************/ void CAttrEdit::UpdateSel(void) { int nStart, nEnd;
GetSel( nStart, nEnd );
if (nStart != nEnd ) { RECT rc = m_rectFmt;
if ( nStart > nEnd ) { int tt = nStart; nStart = nEnd; nEnd = tt; }
CPoint ptStart( (DWORD)SendMessage( EM_POSFROMCHAR, nStart ) ); rc.right -= ptStart.y;
if ( nEnd < GetWindowTextLength() ) { CPoint ptEnd( (DWORD)SendMessage( EM_POSFROMCHAR, nEnd ) ); rc.left = m_rectFmt.right - ptEnd.y - m_pParentWnd->m_iLineHeight; }
InvalidateRect( &rc ); } }
/******************************************************************************/ void CAttrEdit::UpdateInput(void) { RECT rc = m_rectFmt;
CPoint pt( GetCaretPos() ); rc.right = pt.x + m_pParentWnd->m_iLineHeight;
InvalidateRect( &rc ); }
/******************************************************************************/
LRESULT CAttrEdit::OnSysTimer( WPARAM wParam, LPARAM lParam ) {
if ( !m_pParentWnd->m_bVertEdit ) { Default(); return 1L; }
return 1L; }
/******************************************************************************/ void CAttrEdit::SetHCursorShape(void) { if ( GetSafeHwnd() ) { ShowCursor( FALSE ); SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_hHCursor ); ShowCursor( TRUE ); } }
/******************************************************************************/ void CAttrEdit::SetVCursorShape(void) { if ( GetSafeHwnd() ) { ShowCursor( FALSE ); SetClassLongPtr( m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_hVCursor ); ShowCursor( TRUE ); } }
/******************************************************************************/ void CAttrEdit::TabTextOut( CDC* pDC, int nCharIndex, int x, int y, LPCTSTR lpStr, int nCount, BOOL bSelect ) { int i, nCnt; LPCTSTR lpChar = lpStr; CPoint pt; CPoint ptEnd; RECT rc; BOOL bReverse;
CSize s1 = pDC->GetTextExtent( TEXT("a"), 1 ); CSize s2 = pDC->GetTextExtent( TEXT("aa"), 2 ); bReverse = (s1.cx == s2.cx);
rc.left = x - m_pParentWnd->m_iLineHeight; rc.right = x;
for ( i = 0, nCnt = 0; i < nCount; i++, nCnt++, lpStr++ ) { if ( *lpStr == TEXT('\t') ) { pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex ); if ( nCnt > 0 ) { pDC->TextOut( x, pt.x, lpChar, nCnt ); }
nCharIndex += nCnt + 1; nCnt = -1; lpChar = lpStr + 1; if ( bSelect ) { pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex - 1 ); rc.top = pt.x;
if ( i < (nCount - 1) ) { pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex ); rc.bottom = pt.x; } else { rc.bottom = min( (pt.x / m_iTabPos + 1) * m_iTabPos, m_rectFmt.bottom - 1 ); }
pDC->ExtTextOut( x, rc.top, 0 /*ETO_OPAQUE*/, &rc, NULL, 0, NULL ); } } }
if ( nCnt > 0 ) { pt = (CPoint)(DWORD)SendMessage( EM_POSFROMCHAR, nCharIndex ); pDC->TextOut( x, pt.x, lpChar, nCnt ); } }
/******************************************************************************/ /******************************************************************************/ // CTedit
BEGIN_MESSAGE_MAP( CTedit, CWnd ) //{{AFX_MSG_MAP(CTedit)
ON_WM_SIZE() ON_WM_MOVE() ON_WM_CTLCOLOR() ON_WM_NCCALCSIZE() ON_WM_NCPAINT() ON_WM_NCHITTEST() ON_WM_RBUTTONDOWN() ON_COMMAND(ID_TEXT_PLAIN, OnTextPlain) ON_COMMAND(ID_TEXT_BOLD, OnTextBold) ON_COMMAND(ID_TEXT_ITALIC, OnTextItalic) ON_COMMAND(ID_TEXT_UNDERLINE, OnTextUnderline) ON_COMMAND(ID_TEXT_SELECTFONT, OnTextSelectfont) ON_COMMAND(ID_TEXT_SELECTPOINTSIZE, OnTextSelectpointsize) ON_COMMAND(ID_EDIT_CUT, OnEditCut) ON_COMMAND(ID_EDIT_COPY, OnEditCopy) ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) ON_COMMAND(ID_EDIT_CLEAR, OnTextDelete) ON_COMMAND(ID_EDIT_SELECT_ALL, OnTextSelectall) ON_COMMAND(ID_EDIT_UNDO, OnTextUndo) ON_COMMAND(ID_TEXT_PLACE, OnTextPlace) ON_COMMAND(ID_VIEW_TEXT_TOOLBAR, OnTextTexttool) ON_WM_LBUTTONDOWN() //}}AFX_MSG_MAP
ON_WM_GETMINMAXINFO() ON_MESSAGE(WM_MOVING, OnMoving) ON_EN_CHANGE(IDC_ATTREDIT, OnAttrEditEnChange) ON_EN_MAXTEXT(IDC_ATTREDIT, OnEnMaxText) ON_EN_UPDATE(IDC_ATTREDIT, OnEnUpdate)
ON_WM_DESTROY()
END_MESSAGE_MAP()
/******************************************************************************/ // CTedit construction/destruction
CTedit::CTedit() { m_eLastAction = eNO_CHANGE; m_bCleanupBKBrush = FALSE; m_bStarting = TRUE; m_bPasting = FALSE; m_bExpand = FALSE; m_bChanged = FALSE; m_uiHitArea = HTNOWHERE; m_crFGColor = ::GetSysColor( COLOR_WINDOWTEXT ); m_crBKColor = ::GetSysColor( COLOR_WINDOW );
// Need to be initialized during first GETMINMAXINFO call
m_SizeMinimum.cx = 1; m_SizeMinimum.cy = 1;
m_bBackgroundTransparent = TRUE;
m_cRectOldPos.SetRectEmpty(); m_cRectWindow.SetRectEmpty();
m_bVertEdit = FALSE; m_bAssocIMC = FALSE; m_hIMCEdit = NULL; m_hIMCFace = NULL; m_hIMCSize = NULL; m_hWndFace = NULL; m_hWndSize = NULL;
}
/******************************************************************************/
CTedit::~CTedit() { if (m_bCleanupBKBrush) { m_hbrBkColor.DeleteObject(); //Set in SetTransparentMode
m_bCleanupBKBrush = FALSE; } }
/******************************************************************************/
BOOL CTedit::Create( CImgWnd* pParentWnd, COLORREF crefForeground, COLORREF crefBackground, CRect& rectPos, BOOL bBackTransparent ) { if (! m_bStarting) return FALSE;
// Initialize member variables
m_pImgWnd = pParentWnd; m_crBKColor = crefBackground; m_crFGColor = crefForeground; m_bBackgroundTransparent = bBackTransparent; // Do this or else
SetTransparentMode( bBackTransparent );
CRect rectText = rectPos;
rectText.InflateRect( CTracker::HANDLE_SIZE, CTracker::HANDLE_SIZE ); rectText.right += CTracker::HANDLE_SIZE * 2; rectText.bottom += CTracker::HANDLE_SIZE * 2;
if (! CWnd::Create( NULL, TEXT(""), WS_CHILD | WS_THICKFRAME, rectText, pParentWnd, IDC_ATTREDIT + 1 )) return FALSE;
CRect rectEditArea;
GetClientRect( &rectEditArea );
m_cEdit.m_pParentWnd = this;
if (! m_cEdit.Create( WS_CHILD | ES_LEFT | ES_MULTILINE | ES_NOHIDESEL | ES_WANTRETURN, rectEditArea, this, IDC_ATTREDIT )) { theApp.SetMemoryEmergency();
DestroyWindow(); return FALSE; }
ClientToScreen( &rectEditArea ); // use this to let the font tool where not to cover
m_pcTfont = new CTfont( this ); // this is the class Text Font Pallette
// it is derived from cframewnd and will
ASSERT( m_pcTfont != NULL ); // auto destruct when this window
// 'CTedit' is Destroyed
if (m_pcTfont == NULL || ! m_pcTfont->Create( rectEditArea )) { theApp.SetMemoryEmergency();
DestroyWindow();
m_pcTfont = NULL; return FALSE; }
// reset the width and height to the minimum if nessesary
CSize size = GetDefaultMinSize(); // must call after ctfont object created (it sets our font).
m_cRectWindow = CRect( rectText.TopLeft(), size ); SetWindowPos( &wndTop, 0, 0, size.cx, size.cy, SWP_NOACTIVATE | SWP_NOMOVE );
ShowWindow( SW_SHOWNOACTIVATE );
GetClientRect( &rectEditArea );
m_cEdit.SetWindowPos( &wndTopMost, 0, 0, rectEditArea.Width(), rectEditArea.Height(), 0 ); m_cEdit.ShowWindow( SW_SHOWNOACTIVATE );
m_bStarting = FALSE;
//get all control windows on ToolBar for controling IME
CWnd* pcWndFace = m_pcTfont->GetFontFaceControl(); if ( (pcWndFace != NULL) && (pcWndFace->GetSafeHwnd() != NULL) ) m_hWndFace = pcWndFace->m_hWnd; //static
CWnd* pcWndSize = m_pcTfont->GetFontSizeControl(); if ( (pcWndSize != NULL) && ( pcWndSize->GetSafeHwnd() != NULL) ) { CWnd* pcWndEditSize = pcWndSize->GetWindow( GW_CHILD ); //edit
if ( (pcWndEditSize != NULL) && ( pcWndEditSize->GetSafeHwnd() != NULL) ) m_hWndSize = pcWndEditSize->m_hWnd; //edit
}
//save original Edit control
if ( m_cEdit.GetSafeHwnd() ) m_cEdit.m_hOldCursor = (HCURSOR) SetClassLongPtr( m_cEdit.m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_cEdit.m_hHCursor );
//only DBCS font would enable IME
CFont* pcFont = m_cEdit.GetFont(); LOGFONT lf; pcFont->GetObject( sizeof( LOGFONT ), &lf ); if ( !IS_DBCS_CHARSET( lf.lfCharSet ) ) { m_bAssocIMC = TRUE; if (!IsCUAS()) m_hIMCEdit = DisableIme( m_cEdit.m_hWnd ); m_hIMCFace = DisableIme( m_hWndFace ); m_hIMCSize = DisableIme( m_hWndSize ); }
//initial Caret Position
if ( m_bVertEdit ) { CPoint pt( 0, 0 ); m_cEdit.SetCaretPos( pt ); m_cEdit.SetCaretPosition( FALSE, NULL, -1 ); }
m_cEdit.SetFocus();
return TRUE; }
/******************************************************************************/
BOOL CTedit::PreCreateWindow( CREATESTRUCT& cs ) { cs.dwExStyle |= WS_EX_TRANSPARENT;
return CWnd::PreCreateWindow( cs ); }
/******************************************************************************/
void CTedit::RefreshWindow( CRect* prect, BOOL bErase ) { if (! m_bStarting) { UINT flags = RDW_INVALIDATE;
if (bErase) flags |= RDW_ERASE;
if ( m_bVertEdit ) { m_cEdit.SetFmtRect(); m_cEdit.Repaint(); }
else m_cEdit.RedrawWindow( prect, NULL, flags ); } }
/******************************************************************************/
void CTedit::SetTextColor( COLORREF crColor ) { m_crFGColor = crColor; RefreshWindow( NULL, FALSE ); }
/******************************************************************************/
void CTedit::SetBackColor( COLORREF crColor ) { m_crBKColor = crColor;
if (! m_bBackgroundTransparent) { m_bBackgroundTransparent = TRUE; // just fake it out
SetTransparentMode( FALSE ); // to setup the background brush when in opaque mode
} }
/******************************************************************************/
void CTedit::SetTransparentMode( BOOL bTransparent ) { BOOL bRefresh = ((! m_bBackgroundTransparent && bTransparent) || ( m_bBackgroundTransparent && ! bTransparent));
m_cEdit.m_bBackgroundTransparent = bTransparent; m_bBackgroundTransparent = bTransparent;
if (m_bCleanupBKBrush) { m_hbrBkColor.DeleteObject(); m_bCleanupBKBrush = FALSE; }
if (! m_bBackgroundTransparent) { m_hbrBkColor.CreateSolidBrush( m_crBKColor ); m_bCleanupBKBrush = TRUE; }
if (bRefresh) { InvalidateRect( NULL ); UpdateWindow();
RefreshWindow(); } }
/******************************************************************************/
void CTedit::Undo() {
if ( m_bVertEdit ) m_cEdit.HideCaret();
switch(m_eLastAction) { case eEBOX_CHANGE: m_cEdit.Undo(); break;
case eFONT_CHANGE: ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { m_pcTfont->Undo(); } break;
case eSIZE_MOVE_CHANGE: if (! m_cRectOldPos.IsRectEmpty()) MoveWindow( m_cRectOldPos ); break;
default: break; }
if ( m_bVertEdit ) { m_cEdit.SetCaretShape(); m_cEdit.SetCaretPosition( TRUE, NULL, -1 ); m_cEdit.ShowCaret(); }
}
/******************************************************************************/
void CTedit::ShowFontPalette(int nCmdShow) { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { theApp.m_bShowTextToolbar = ! theApp.m_bShowTextToolbar;
m_pcTfont->ShowWindow(nCmdShow); } }
/******************************************************************************/
BOOL CTedit::IsFontPaletteVisible(void) { BOOL bWindowVisible = FALSE;
ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { bWindowVisible = m_pcTfont->IsWindowVisible(); }
return bWindowVisible; }
/******************************************************************************/
void CTedit::ShowFontToolbar(BOOL bActivate) { // FEATURE: Remove ShowFontPalette after RTM
if (m_pcTfont == NULL) { return; }
m_pcTfont->ShowWindow(bActivate ? SW_SHOW : SW_SHOWNOACTIVATE); }
/******************************************************************************/
void CTedit::HideFontToolbar(void) { if (m_pcTfont == NULL) { return; }
m_pcTfont->ShowWindow(SW_HIDE); }
/******************************************************************************/ // Returns a Ptr to a discardable bitmap (CBitmap object) or NULL on error
void CTedit::GetBitmap( CDC* pDC, CRect* prectImg ) { if (! m_bBackgroundTransparent) pDC->FillRect( prectImg, &m_hbrBkColor );
m_cEdit.SetSel( -1, 0 );
if ( m_bVertEdit ) { m_cEdit.SetFmtRect(); m_cEdit.UpdateWindow(); }
CPoint ptViewOrgOld = pDC->SetViewportOrg( prectImg->left, prectImg->top );
m_cEdit.SendMessage( WM_PAINT, (WPARAM)(pDC->m_hDC) );
pDC->SetViewportOrg( ptViewOrgOld ); pDC->SelectClipRgn( NULL ); }
/******************************************************************************/
void CTedit::PostNcDestroy() {
// If m_pcTfont is destroyed by shutdown before CTedit,
// m_pcTfont will be null
if (m_pcTfont != NULL) { m_pcTfont->DestroyWindow(); m_pcTfont = NULL; }
delete this; }
/******************************************************************************/
CSize CTedit::GetDefaultMinSize( void ) { CRect cRectClient; int iWidth; int iHeight;
// edit control takes up the whole client area of the ctedit
// object/window, so width of client of ctedit is same as widht of edit
// control window. Edit control window has no border.
GetClientRect( &cRectClient );
iWidth = cRectClient.Width(); iHeight = cRectClient.Height();
CDC* pDC = m_cEdit.GetDC(); CFont* pcFont = m_cEdit.GetFont();
if (pDC != NULL && pcFont != NULL) { TEXTMETRIC tm; CFont* pcFontOld = NULL;
pcFontOld = pDC->SelectObject( pcFont );
pDC->GetTextMetrics( &tm );
BOOL bUpdateSize = FALSE;
m_SizeMinimum.cx = tm.tmAveCharWidth * MIN_CHARS_DISPLAY_SIZE + CTracker::HANDLE_SIZE * 2; m_SizeMinimum.cy = tm.tmHeight + CTracker::HANDLE_SIZE * 2;
if (m_SizeMinimum.cx > iWidth) // must be able to at least display MIN_CHARS_DISPLAY_SIZE
{ iWidth = m_SizeMinimum.cx; bUpdateSize = TRUE; }
if (m_SizeMinimum.cy > iHeight) // must be able to at least 1 char high
{ iHeight = m_SizeMinimum.cy; bUpdateSize = TRUE; }
if (bUpdateSize) m_eLastAction = eNO_CHANGE; // don't want user to be able to undo this
if (pcFontOld != NULL) { pDC->SelectObject( pcFontOld ); } } if (pDC != NULL) m_cEdit.ReleaseDC( pDC );
cRectClient.SetRect( 0, 0, iWidth - 1, iHeight - 1 );
ClientToScreen( &cRectClient ); m_pImgWnd->ScreenToClient( &cRectClient );
CRect rectDrawing = m_pImgWnd->GetDrawingRect();
if (cRectClient.right > rectDrawing.right) iWidth -= (cRectClient.right - rectDrawing.right) - CTracker::HANDLE_SIZE;
if (cRectClient.bottom > rectDrawing.bottom) iHeight -= (cRectClient.bottom - rectDrawing.bottom) - CTracker::HANDLE_SIZE;
m_SizeMinimum.cx = iWidth; m_SizeMinimum.cy = iHeight;
return CSize( iWidth, iHeight ); }
/******************************************************************************/
void CTedit::OnAttrEditEnChange(void) { m_eLastAction = eEBOX_CHANGE;
if (m_bRefresh) m_cEdit.UpdateWindow();
if ( m_bVertEdit ) { m_cEdit.SetCaretPosition( TRUE, NULL, -1 ); m_cEdit.UpdateWindow(); }
}
/******************************************************************************/
void CTedit::OnEnUpdate() { CPoint ptCaretPos = m_cEdit.GetCaretPos(); CPoint ptLastChar( (DWORD)m_cEdit.SendMessage( EM_POSFROMCHAR, (WPARAM)(m_cEdit.GetWindowTextLength() - 1) ) ); CRect rect; m_cEdit.GetClientRect( &rect ); rect.top = ptCaretPos.y; rect.bottom = ptLastChar.y + m_iLineHeight; m_cEdit.InvalidateRect( &rect, TRUE );
m_bChanged = TRUE; }
/******************************************************************************/
void CTedit::OnEnMaxText() {
if (m_bPasting) { if (!m_cEdit.m_bResizeOnly) { AfxMessageBox( IDS_UNABLE_TO_PASTE, MB_OK | MB_ICONEXCLAMATION ); } return; }
CFont* pfntEdit = m_cEdit.GetFont();
if (pfntEdit == NULL) return;
CClientDC dc( &m_cEdit );
CFont* pfntOld = dc.SelectObject( pfntEdit );
TEXTMETRIC tm;
dc.GetTextMetrics( &tm );
CRect rectText; CRect rectImg;
GetWindowRect( &rectText );
m_pImgWnd->ScreenToClient( &rectText );
POINT pt; ::GetCaretPos (&pt); //
// If the next character would extend past the end of the
// edit window, grow the window
if (!m_bVertEdit && m_cEdit.m_bResizeOnly && ((rectText.left + pt.x + 2*tm.tmMaxCharWidth < rectText.right) || (rectText.top + pt.y + 2*tm.tmHeight < rectText.bottom)) ) { return; } else if (m_bVertEdit && m_cEdit.m_bResizeOnly && ((pt.x - tm.tmMaxCharWidth > 0) || (rectText.top + pt.y + 2*tm.tmHeight < rectText.bottom)) ) { return; } m_pImgWnd->GetClientRect ( &rectImg );
if (m_cEdit.m_strResult.IsEmpty()) {
if (m_bVertEdit) rectText.left -= tm.tmHeight; else rectText.bottom += tm.tmHeight; } else { CRect rectTmp = rectText; int nLen = m_cEdit.m_strResult.GetLength();
if (m_bVertEdit) rectText.left -= dc.DrawText(m_cEdit.m_strResult.GetBuffer(nLen), nLen,&rectTmp, DT_CALCRECT | DT_LEFT | DT_WORDBREAK); else rectText.bottom += dc.DrawText(m_cEdit.m_strResult.GetBuffer(nLen), nLen,&rectTmp, DT_CALCRECT | DT_LEFT | DT_WORDBREAK); }
CRect rectDrawing = m_pImgWnd->GetDrawingRect();
if ( ((m_bVertEdit) && rectText.left>=rectDrawing.left && rectText.left >= rectImg.left) || ((!m_bVertEdit) && rectText.bottom<=rectDrawing.bottom && rectText.bottom<=rectImg.bottom) ) { MoveWindow( &rectText ); m_cEdit.UpdateWindow();
if ( m_bVertEdit ) m_cEdit.UpdateInput();
if (!m_cEdit.m_bResizeOnly) { if (m_cEdit.m_strResult.IsEmpty()) { #ifdef UNICODE
WCHAR ch[3];
ch[0] = (WCHAR)m_cEdit.m_uiLastChar[0]; ch[1] = L'\0'; #else
BYTE ch[3]; //
// Put lead and trail bytes in proper place for DBCS characters.
//
if (IsDBCSLeadByte (HIBYTE(LOWORD(m_cEdit.m_uiLastChar[0])))) { ch[0] = HIBYTE(LOWORD(m_cEdit.m_uiLastChar[0])); ch[1] = LOBYTE(LOWORD(m_cEdit.m_uiLastChar[0])); ch[2] = '\0'; } else { ch[0] = LOBYTE(LOWORD(m_cEdit.m_uiLastChar[0])); ch[1] = '\0'; } #endif // UNICODE
if (ch[0] == VK_RETURN) { lstrcpy((LPTSTR)ch, TEXT("\r\n")); }
m_cEdit.ReplaceSel((LPCTSTR) ch ); } else { int nLen = m_cEdit.m_strResult.GetLength();
m_cEdit.ReplaceSel( m_cEdit.m_strResult.GetBuffer(nLen)); } } }
if (pfntOld) dc.SelectObject( pfntOld ); }
/******************************************************************************/
void CTedit::OnAttrEditFontChange(void) { CClientDC editDC( &m_cEdit ); CFont* pcFont = m_cEdit.GetFont(); if (!pcFont) { return; // this happens when you "escape" from the font
// selection listbox
} CFont* pFontOld = editDC.SelectObject( pcFont);
TEXTMETRIC tm;
editDC.GetTextMetrics( &tm );
m_iLineHeight = tm.tmHeight;
#ifdef _DEBUG
TRACE1( "New font line height %d.\n", m_iLineHeight ); #endif
//only DBCS associated font would enable IME
if ( !m_bStarting ) {
LOGFONT lf;
pcFont->GetObject( sizeof( LOGFONT ), &lf ); if ( IS_DBCS_CHARSET( lf.lfCharSet ) )
{
if (m_bAssocIMC) {
m_bAssocIMC = FALSE; if (!IsCUAS()) { EnableIme( m_cEdit.m_hWnd, m_hIMCEdit ); m_hIMCEdit = NULL; } EnableIme( m_hWndFace, m_hIMCFace ); EnableIme( m_hWndSize, m_hIMCSize ); m_hIMCFace = NULL; m_hIMCSize = NULL; m_pcTfont->SetFocus(); } } else {
if (!m_bAssocIMC) {
m_bAssocIMC = TRUE; if (!IsCUAS()) m_hIMCEdit = DisableIme( m_cEdit.m_hWnd ); m_hIMCFace = DisableIme( m_hWndFace ); m_hIMCSize = DisableIme( m_hWndSize ); m_pcTfont->SetFocus(); } } }
if (pFontOld != NULL) editDC.SelectObject( pFontOld );
m_eLastAction = eFONT_CHANGE; }
/******************************************************************************/
void CTedit::OnSize( UINT nType, int cx, int cy ) { if (! m_bStarting) ShowWindow( SW_HIDE );
// need to do this if transparent to force see through
m_cRectOldPos = m_cRectWindow; GetWindowRect( &m_cRectWindow ); m_pImgWnd->ScreenToClient( m_cRectWindow );
m_eLastAction = eSIZE_MOVE_CHANGE;
// could be NULL when main window is created and child edit window
// has not been created yet.
if (m_cEdit.GetSafeHwnd() != NULL) { m_cEdit.MoveWindow( 0, 0, cx, cy ); m_cEdit.SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); } InvalidateRect( NULL ); UpdateWindow();
if (m_bBackgroundTransparent) { RefreshWindow(); } if (! m_bStarting) ShowWindow( SW_SHOW );
if ( m_bVertEdit ) { m_cEdit.SetFmtRect(); CPoint pt( -20000, -20000 ); m_cEdit.SetCaretPos( pt ); m_cEdit.SetCaretPosition( FALSE, NULL, -1 ); m_cEdit.Repaint(); }
}
/******************************************************************************/
void CTedit::OnMove( int x, int y ) { // need to do this if transparent to force see through
m_cRectOldPos = m_cRectWindow; GetWindowRect( &m_cRectWindow ); m_pImgWnd->ScreenToClient( m_cRectWindow );
if (m_cRectOldPos.Width() != m_cRectWindow.Width() || m_cRectOldPos.Height() != m_cRectWindow.Height()) { //reset back to previous, since new will be updated in onsize, due to
// size and move happening both (e.g. sizing either left or top side
// causes an onmove then an onsize
m_cRectWindow = m_cRectOldPos; } m_eLastAction = eSIZE_MOVE_CHANGE;
if (m_cEdit.GetSafeHwnd() != NULL) { m_cEdit.SetWindowPos( &wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); }
InvalidateRect( NULL ); UpdateWindow();
if (m_bBackgroundTransparent) { RefreshWindow(); } }
/******************************************************************************/
LRESULT CTedit::OnMoving( WPARAM, LPARAM lprc ) { LRESULT lResult = 0; CRect rectEdit = *((LPRECT)lprc); CRect rectImage = m_pImgWnd->GetDrawingRect();
m_pImgWnd->ClientToScreen( &rectImage );
int iX = 0; int iY = 0;
if (rectEdit.left < rectImage.left) iX = rectImage.left - rectEdit.left; else if (rectEdit.right > rectImage.right) iX = -(rectEdit.right - rectImage.right);
if (rectEdit.top < rectImage.top) iY = rectImage.top - rectEdit.top; else if (rectEdit.bottom > rectImage.bottom) iY = -(rectEdit.bottom - rectImage.bottom);
if (iX || iY) { rectEdit.OffsetRect( iX, iY ); *((LPRECT)lprc) = rectEdit; lResult = 1; } return lResult; }
/******************************************************************************/
void CTedit::OnGetMinMaxInfo( MINMAXINFO FAR* lpMMI ) { CRect rectImage = m_pImgWnd->GetDrawingRect(); CSize Size = rectImage.Size();
lpMMI->ptMaxSize.x = Size.cx; lpMMI->ptMaxSize.y = Size.cy; lpMMI->ptMaxPosition = rectImage.TopLeft(); lpMMI->ptMinTrackSize.x = m_SizeMinimum.cx; lpMMI->ptMinTrackSize.y = m_SizeMinimum.cy;
CRect rectClient;
GetWindowRect( &rectClient ); m_pImgWnd->ScreenToClient( &rectClient );
switch (m_uiHitArea) { case HTTOP: case HTLEFT: case HTTOPLEFT: break;
case HTRIGHT: case HTTOPRIGHT: case HTBOTTOMRIGHT: lpMMI->ptMaxSize.x -= (rectClient.left - rectImage.left);
if (m_uiHitArea == HTBOTTOMRIGHT) ; // fall thru and do the bottom
else break;
case HTBOTTOMLEFT: case HTBOTTOM: lpMMI->ptMaxSize.y -= (rectClient.top - rectImage.top); break; }
lpMMI->ptMaxTrackSize = lpMMI->ptMaxSize; }
/******************************************************************************/
HBRUSH CTedit::OnCtlColor (CDC* pDC, CWnd* pWnd, UINT nCtlColor ) { HBRUSH hbrBack = NULL;
if (pWnd == &m_cEdit) { PBSelectPalette( pDC, theApp.m_pPalette, FALSE ); pDC->SetTextColor( m_crFGColor );
//set the background color and transparent mode
// if (m_bBackgroundTransparent)
// {
pDC->SetBkMode( TRANSPARENT );
hbrBack = (HBRUSH)::GetStockObject( NULL_BRUSH ); // }
// else
// {
// pDC->SetBkMode( OPAQUE );
// pDC->SetBkColor( m_crBKColor );
// hbrBack = (HBRUSH)m_hbrBkColor.GetSafeHandle();
// }
} if (hbrBack == NULL) return (HBRUSH)Default();
return hbrBack; }
/******************************************************************************/ //void CTedit::OnLButtonDown(UINT nFlags, CPoint point )
// {
// SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x, point.y));
// SetFocus();
// CEdit::OnLButtonDown(nFlags, point);
// }
/******************************************************************************/
void CTedit::OnNcCalcSize( BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp ) { /* Increase by an extra width height of the border*/ lpncsp->rgrc[0].left += CTracker::HANDLE_SIZE; lpncsp->rgrc[0].top += CTracker::HANDLE_SIZE; lpncsp->rgrc[0].right -= CTracker::HANDLE_SIZE; lpncsp->rgrc[0].bottom -= CTracker::HANDLE_SIZE; }
/******************************************************************************/
void CTedit::OnNcPaint() { CDC *pdcWindow = GetWindowDC();
ASSERT(pdcWindow != NULL);
if (pdcWindow != NULL) { CRgn rgnClipping; CRect cWinRect; int iWindowWidth; int iWindowHeight;
GetWindowRect( &cWinRect );
iWindowWidth = cWinRect.Width(); iWindowHeight = cWinRect.Height();
CRect cBorderRect( 0, 0, iWindowWidth, iWindowHeight );
CTracker::DrawBorder ( pdcWindow, cBorderRect, CTracker::all ); CTracker::DrawHandles( pdcWindow, cBorderRect, CTracker::all );
ReleaseDC( pdcWindow ); } }
/******************************************************************************/
UINT CTedit::OnNcHitTest( CPoint point ) { CRect cClientRect; UINT uiHitTestCode = HTCAPTION;
ScreenToClient( &point );
GetClientRect(&cClientRect);
//Test to see if the pt is in THE CLIENT AREA
if (cClientRect.PtInRect(point)) { uiHitTestCode = HTCLIENT; }
m_uiHitArea = HTNOWHERE;
switch (CTracker::HitTest( cClientRect, point, CTracker::nil )) { case CTracker::resizingTop: m_uiHitArea = HTTOP; break;
case CTracker::resizingLeft: m_uiHitArea = HTLEFT; break;
case CTracker::resizingRight: m_uiHitArea = HTRIGHT; break;
case CTracker::resizingBottom: m_uiHitArea = HTBOTTOM; break;
case CTracker::resizingTopLeft: m_uiHitArea = HTTOPLEFT; break;
case CTracker::resizingTopRight: m_uiHitArea = HTTOPRIGHT; break;
case CTracker::resizingBottomLeft: m_uiHitArea = HTBOTTOMLEFT; break;
case CTracker::resizingBottomRight: m_uiHitArea = HTBOTTOMRIGHT; break; }
if (m_uiHitArea != HTNOWHERE) uiHitTestCode = m_uiHitArea;
m_cEdit.SetHCursorShape();
return uiHitTestCode; }
/******************************************************************************/
void CTedit::OnRButtonDown(UINT nFlags, CPoint point) { CMenu cMenuPopup; CMenu *pcContextMenu; CRect cRectClient; BOOL bRC = cMenuPopup.LoadMenu( IDR_TEXT_POPUP );
ASSERT( bRC );
if (bRC) { GetClientRect( &cRectClient );
pcContextMenu = cMenuPopup.GetSubMenu( ID_EBOX_POPUPMENU_POS );
ASSERT( pcContextMenu != NULL );
if (pcContextMenu != NULL) { // update the check marks
OnUpdateTextPlain ( pcContextMenu ); OnUpdateTextBold ( pcContextMenu ); OnUpdateTextItalic ( pcContextMenu ); OnUpdateTextUnderline( pcContextMenu ); OnUpdateTextTexttool ( pcContextMenu );
ClientToScreen( &point ); ClientToScreen( &cRectClient );
// the frame actually has a clue about what items to enable...
CWnd *notify = GetParentFrame();
if( !notify ) notify = this; // oh well...
pcContextMenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, notify, &cRectClient ); } } }
/******************************************************************************/
void CTedit::OnTextPlain() { ASSERT( m_pcTfont != NULL );
if (m_pcTfont != NULL) { if (m_pcTfont->IsBoldOn()) { m_pcTfont->OnBold(); }
if (m_pcTfont->IsItalicOn()) { m_pcTfont->OnItalic(); }
if (m_pcTfont->IsUnderlineOn()) { m_pcTfont->OnUnderline(); }
if (m_pcTfont->IsShadowOn()) { m_pcTfont->OnShadow(); }
m_pcTfont->RefreshToolBar();
RefreshWindow(); } }
/******************************************************************************/
void CTedit::OnTextBold() { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { m_pcTfont->OnBold(); m_pcTfont->RefreshToolBar();
RefreshWindow(); } }
/******************************************************************************/
void CTedit::OnTextItalic() { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { m_pcTfont->OnItalic(); m_pcTfont->RefreshToolBar();
RefreshWindow(); } }
/******************************************************************************/
void CTedit::OnTextUnderline() { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { m_pcTfont->OnUnderline(); m_pcTfont->RefreshToolBar();
RefreshWindow(); } }
/******************************************************************************/
void CTedit::OnTextSelectfont() { if (m_pcTfont != NULL) { if (! IsFontPaletteVisible()) ShowFontPalette( SW_SHOW ); else m_pcTfont->SetFocus(); } }
/******************************************************************************/
void CTedit::OnTextSelectpointsize() { if (m_pcTfont != NULL) { if (! IsFontPaletteVisible()) ShowFontPalette( SW_SHOW ); else m_pcTfont->SetFocus();
CWnd* pWnd = m_pcTfont->GetFontSizeControl();
if (pWnd != NULL) { pWnd->SetFocus(); } } }
/******************************************************************************/
void CTedit::OnEditCut() {
if ( m_bVertEdit ) HideCaret();
m_cEdit.Cut(); RefreshWindow();
if ( m_bVertEdit ) { m_cEdit.SetCaretShape(); ShowCaret(); }
}
/******************************************************************************/
void CTedit::OnEditCopy() { m_cEdit.Copy(); }
/******************************************************************************/
void CTedit::OnEditPaste() { m_bPasting = TRUE;
#ifdef _DEBUG
TRACE0( "OnEditPaste Start\n" ); #endif
m_cEdit.Paste();
#ifdef _DEBUG
TRACE0( "OnEditPaste End\n" ); #endif
m_bPasting = FALSE;
RefreshWindow(); }
/******************************************************************************/
void CTedit::OnTextDelete() { int iLength = m_cEdit.GetWindowTextLength(); int iStart = iLength; int iEnd = iLength;
if ( m_bVertEdit ) m_cEdit.HideCaret();
m_cEdit.GetSel( iStart, iEnd );
if (iStart == iEnd) { if (iLength == iStart) return;
CString strText; m_cEdit.GetWindowText(strText); if (!strText.IsEmpty() && (IsDBCSLeadByte((CHAR)strText[iStart]) || strText[iStart]==TEXT('\r'))) iEnd += 2; else iEnd += 1;
m_cEdit.SetSel( iStart, iEnd, TRUE ); } m_cEdit.Clear();
if ( m_bVertEdit ) { m_cEdit.SetCaretShape(); m_cEdit.SetCaretPosition( TRUE, NULL, -1 ); m_cEdit.ShowCaret(); m_cEdit.Repaint(); } else {
UpdateWindow(); RefreshWindow();
}
}
/******************************************************************************/
void CTedit::OnTextSelectall() { m_cEdit.SetSel( 0, -1, TRUE );
RefreshWindow(); }
/******************************************************************************/
void CTedit::OnTextUndo() { Undo();
RefreshWindow(); }
/******************************************************************************/
void CTedit::OnTextPlace() { CWnd* cwndParent = GetParent();
cwndParent->PostMessage( WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM( CTracker::HANDLE_SIZE + 1, CTracker::HANDLE_SIZE + 1 ) ); cwndParent->PostMessage( WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM( CTracker::HANDLE_SIZE + 1, CTracker::HANDLE_SIZE + 1 ) ); }
/******************************************************************************/
void CTedit::OnTextTexttool() { if (IsFontPaletteVisible()) { ShowFontPalette( SW_HIDE ); } else { ShowFontPalette( SW_SHOWNOACTIVATE ); } }
/******************************************************************************/
void CTedit::OnUpdateTextPlain( CMenu *pcMenu ) { ASSERT( m_pcTfont != NULL );
if (m_pcTfont != NULL) { if (! m_pcTfont->IsBoldOn() && ! m_pcTfont->IsItalicOn() && ! m_pcTfont->IsUnderlineOn() && ! m_pcTfont->IsShadowOn()) { pcMenu->CheckMenuItem(ID_TEXT_PLAIN, MF_BYCOMMAND | MF_CHECKED); } else { pcMenu->CheckMenuItem(ID_TEXT_PLAIN, MF_BYCOMMAND | MF_UNCHECKED); } } }
/******************************************************************************/
void CTedit::OnUpdateTextBold(CMenu *pcMenu) { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { if (m_pcTfont->IsBoldOn()) { pcMenu->CheckMenuItem(ID_TEXT_BOLD, MF_BYCOMMAND | MF_CHECKED); } else { pcMenu->CheckMenuItem(ID_TEXT_BOLD, MF_BYCOMMAND | MF_UNCHECKED); } } }
/******************************************************************************/
void CTedit::OnUpdateTextItalic(CMenu *pcMenu) { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { if (m_pcTfont->IsItalicOn()) { pcMenu->CheckMenuItem(ID_TEXT_ITALIC, MF_BYCOMMAND | MF_CHECKED); } else { pcMenu->CheckMenuItem(ID_TEXT_ITALIC, MF_BYCOMMAND | MF_UNCHECKED); } } }
/******************************************************************************/
void CTedit::OnUpdateTextUnderline(CMenu *pcMenu) { ASSERT(m_pcTfont != NULL);
if (m_pcTfont != NULL) { if (m_pcTfont->IsUnderlineOn()) { pcMenu->CheckMenuItem(ID_TEXT_UNDERLINE, MF_BYCOMMAND | MF_CHECKED); } else { pcMenu->CheckMenuItem(ID_TEXT_UNDERLINE, MF_BYCOMMAND | MF_UNCHECKED); } } }
/******************************************************************************/
void CTedit::OnUpdateTextTexttool(CMenu *pcMenu) { if (IsFontPaletteVisible()) { pcMenu->CheckMenuItem(ID_VIEW_TEXT_TOOLBAR, MF_BYCOMMAND | MF_CHECKED); } else { pcMenu->CheckMenuItem(ID_VIEW_TEXT_TOOLBAR, MF_BYCOMMAND | MF_UNCHECKED); } }
/******************************************************************************/
/******************************************************************************/
void CTedit::OnDestroy(void) { if ( m_cEdit.GetSafeHwnd() ) { if ( m_cEdit.m_hOldCursor ) SetClassLongPtr( m_cEdit.m_hWnd, GCLP_HCURSOR, (LONG_PTR) m_cEdit.m_hOldCursor );
//restore original edit IMC
if (m_bAssocIMC) { m_bAssocIMC = FALSE; EnableIme( m_cEdit.m_hWnd, m_hIMCEdit ); EnableIme( m_hWndFace, m_hIMCFace ); EnableIme( m_hWndSize, m_hIMCSize ); m_hIMCEdit = NULL; m_hIMCFace = NULL; m_hIMCSize = NULL; } }
Default(); return; }
/******************************************************************************/
HIMC CTedit::DisableIme( HWND hWnd ) { HIMC hIMC = NULL;
if ( (hWnd) && (::IsWindow( hWnd )) ) hIMC = ImmAssociateContext( hWnd, NULL );
return hIMC; }
/******************************************************************************/
void CTedit::EnableIme( HWND hWnd, HIMC hIMC ) { if ( (hWnd) && (::IsWindow( hWnd )) ) ImmAssociateContext( hWnd, hIMC ); }
/******************************************************************************/
//
// Tablet PC.
//
// Is CUAS (Cicero Unaware App Support) is on, we need to use hIMC even on
// Ansi Font. The string from English HW/Speech TIPs will be delivered
// through hIMC.
//
BOOL CTedit::IsCUAS() { BOOL bRet = FALSE;
typedef BOOL (*PFNCTFIMMISCICEROENABLED)(void);
static PFNCTFIMMISCICEROENABLED pfn = NULL;
if (!pfn) { HMODULE hMod = LoadLibrary(TEXT("imm32.dll")); if (hMod) { pfn = (PFNCTFIMMISCICEROENABLED)GetProcAddress(hMod, "CtfImmIsCiceroEnabled");
} } if (pfn) bRet = pfn(); return bRet; }
/******************************************************************************/
|