www.pudn.com > RichEditGrid_src.zip > InPlaceRichEdit.cpp


// InPlaceRichEdit.cpp : implementation file 
// 
// GridCellRich Demonstration 
// ************************** 
// 
// Written by Mathieu DUBAËLE (mathieu@appstmd.com) 
// 
// Feel free to send me all the changes you can made to this code. 
////////////////////////////////////////////////////////////////////// 
#include "stdafx.h" 
#include "gridctrl_src/gridctrl.h" 
#include "RichEditGrid.h" 
#include "InPlaceRichEdit.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
// callback for read from control 
DWORD CALLBACK StreamOutCallback( DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb ) 
{ 
	CString* strWholeString = reinterpret_cast(dwCookie); 
	 
	// I hope this allocation/deallocation better then manipulation with CStrings 
	char* szInThisCall = new char[cb+1]; 
	memcpy( szInThisCall, reinterpret_cast(pbBuff), cb ); 
	szInThisCall[cb] = '\0'; 
 
	// This is the main trik! Control can call this function for just a part of string! 
	(*strWholeString ) += szInThisCall; 
	 
	delete	[] szInThisCall; 
	 
	*pcb = cb; 
 	return 0; 
} 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CInPlaceRichEdit message handlers 
CInPlaceRichEdit::CInPlaceRichEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID, 
                           int nRow, int nColumn, CString sInitText,  
                           UINT nFirstChar) 
{ 
    m_sInitText     = sInitText; 
    m_nRow          = nRow; 
    m_nColumn       = nColumn; 
    m_nLastChar     = 0;  
    m_bExitOnArrows = (nFirstChar != VK_LBUTTON);    // If mouse click brought us here, 
                                                     // then no exit on arrows 
 
    m_Rect = rect;  // For bizarre CE bug. 
     
    DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE| ES_AUTOHSCROLL //|ES_MULTILINE 
        | dwStyle; 
    if (!Create(dwEditStyle, rect, pParent, nID)) return; 
     
    SetFont(pParent->GetFont()); 
     
    SetWindowText(sInitText); 
    SetFocus(); 
     
    switch (nFirstChar){ 
        case VK_LBUTTON:  
        case VK_RETURN:   SetSel((int)_tcslen(m_sInitText), -1); return; 
        case VK_BACK:     SetSel((int)_tcslen(m_sInitText), -1); break; 
        case VK_TAB: 
        case VK_DOWN:  
        case VK_UP:    
        case VK_RIGHT: 
        case VK_LEFT:   
        case VK_NEXT:   
        case VK_PRIOR:  
        case VK_HOME: 
        case VK_SPACE: 
        case VK_END:      SetSel(0,-1); return; 
        default:          SetSel(0,-1); 
    } 
 
    // Added by KiteFly. When entering DBCS chars into cells the first char was being lost 
    // SenMessage changed to PostMessage (John Lagerquist) 
    if( nFirstChar < 0x80) 
        PostMessage(WM_CHAR, nFirstChar);    
    else 
        PostMessage(WM_IME_CHAR, nFirstChar); 
} 
 
CInPlaceRichEdit::~CInPlaceRichEdit() 
{ 
} 
 
BEGIN_MESSAGE_MAP(CInPlaceRichEdit, CRichEditCtrl) 
    //{{AFX_MSG_MAP(CInPlaceRichEdit) 
    ON_WM_KILLFOCUS() 
    ON_WM_CHAR() 
    ON_WM_KEYDOWN() 
    ON_WM_GETDLGCODE() 
    ON_WM_CREATE() 
    //}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
//////////////////////////////////////////////////////////////////////////// 
// CInPlaceRichEdit message handlers 
 
// If an arrow key (or associated) is pressed, then exit if 
//  a) The Ctrl key was down, or 
//  b) m_bExitOnArrows == TRUE 
void CInPlaceRichEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{ 
    if ((nChar == VK_PRIOR || nChar == VK_NEXT || 
        nChar == VK_DOWN  || nChar == VK_UP   || 
        nChar == VK_RIGHT || nChar == VK_LEFT) && 
        (m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0)) 
    { 
        m_nLastChar = nChar; 
        GetParent()->SetFocus(); 
        return; 
    } 
     
    CRichEditCtrl::OnKeyDown(nChar, nRepCnt, nFlags); 
} 
 
// As soon as this edit loses focus, kill it. 
void CInPlaceRichEdit::OnKillFocus(CWnd* pNewWnd) 
{ 
    CRichEditCtrl::OnKillFocus(pNewWnd); 
    EndEdit(); 
} 
 
void CInPlaceRichEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{ 
    if (nChar == VK_TAB || nChar == VK_RETURN) 
    { 
        m_nLastChar = nChar; 
        GetParent()->SetFocus();    // This will destroy this window 
        return; 
    } 
    if (nChar == VK_ESCAPE)  
    { 
        SetWindowText(m_sInitText);    // restore previous text 
        m_nLastChar = nChar; 
        GetParent()->SetFocus(); 
        return; 
    } 
     
    CRichEditCtrl::OnChar(nChar, nRepCnt, nFlags); 
     
    // Resize edit control if needed 
     
    // Get text extent 
    CString str; 
    GetWindowText( str ); 
 
    // add some extra buffer 
    str += _T("  "); 
     
    CWindowDC dc(this); 
    CFont *pFontDC = dc.SelectObject(GetFont()); 
    CSize size = dc.GetTextExtent( str ); 
    dc.SelectObject( pFontDC ); 
        
    // Get client rect 
    CRect ParentRect; 
    GetParent()->GetClientRect( &ParentRect ); 
     
    // Check whether control needs to be resized 
    // and whether there is space to grow 
    if (size.cx > m_Rect.Width()) 
    { 
        if( size.cx + m_Rect.left < ParentRect.right ) 
            m_Rect.right = m_Rect.left + size.cx; 
        else 
            m_Rect.right = ParentRect.right; 
        MoveWindow( &m_Rect ); 
    } 
} 
 
UINT CInPlaceRichEdit::OnGetDlgCode()  
{ 
    return DLGC_WANTALLKEYS; 
} 
 
//////////////////////////////////////////////////////////////////////////// 
// CInPlaceRichEdit overrides 
 
// Stoopid win95 accelerator key problem workaround - Matt Weagle. 
BOOL CInPlaceRichEdit::PreTranslateMessage(MSG* pMsg)  
{ 
    // Catch the Alt key so we don't choke if focus is going to an owner drawn button 
    if (pMsg->message == WM_SYSCHAR) 
        return TRUE; 
     
    return CWnd::PreTranslateMessage(pMsg); 
} 
 
// Auto delete 
void CInPlaceRichEdit::PostNcDestroy()  
{ 
    CRichEditCtrl::PostNcDestroy(); 
     
    delete this;	 
} 
 
//////////////////////////////////////////////////////////////////////////// 
// CInPlaceRichEdit implementation 
 
void CInPlaceRichEdit::EndEdit() 
{ 
    CString str; 
 
    // EFW - BUG FIX - Clicking on a grid scroll bar in a derived class 
    // that validates input can cause this to get called multiple times 
    // causing assertions because the edit control goes away the first time. 
    static BOOL bAlreadyEnding = FALSE; 
 
    if(bAlreadyEnding) 
        return; 
 
    bAlreadyEnding = TRUE; 
	EDITSTREAM es = {(DWORD)&str, 0, StreamOutCallback}; 
	StreamOut(SF_RTF, es); 
 
 
    // Send Notification to parent 
    GV_DISPINFO dispinfo; 
 
    dispinfo.hdr.hwndFrom = GetSafeHwnd(); 
    dispinfo.hdr.idFrom   = GetDlgCtrlID(); 
    dispinfo.hdr.code     = GVN_ENDLABELEDIT; 
 
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM; 
    dispinfo.item.row     = m_nRow; 
    dispinfo.item.col     = m_nColumn; 
    dispinfo.item.strText  = str; 
    dispinfo.item.lParam  = (LPARAM) m_nLastChar; 
 
    CWnd* pOwner = GetOwner(); 
    if (pOwner) 
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo ); 
 
    // Close this window (PostNcDestroy will delete this) 
    if (IsWindow(GetSafeHwnd())) 
        SendMessage(WM_CLOSE, 0, 0); 
    bAlreadyEnding = FALSE; 
}