Click here to Skip to main content
15,895,084 members
Articles / Desktop Programming / MFC

Formula Editor

Rate me:
Please Sign up or sign in to vote.
4.98/5 (306 votes)
15 Apr 20039 min read 559.1K   14.7K   361  
Formula-editor for editing and exporting mathematical content
/////////////////////////////////////////////////////////////////////////////
//  File:       FormulaInPlaceEdit.cpp
//  Version:    1.0.0.0
//  Created:    03-april-2002
//
//  Author:     Thorsten Wack
//  E-mail:     wt@umsicht.fhg.de
//
//  parts of Code by Chris Maunder and Matt Weagle (from GridCtrl)
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is 
// not sold for profit without the authors written consent, and 
// providing that this notice and the authors name is included. If 
// the source code in  this file is used in any commercial application 
// then a simple email would be nice.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
//
// Version1.1: added OnUpdate(now flickerfree)
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TCHAR.h"
#include "FormulaInPlaceEdit.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define EDIT_MARGIN 10
/////////////////////////////////////////////////////////////////////////////
// CFormulaInPlaceEdit
void CFormulaInPlaceEdit::RepositionWindow(CRect ctrlRect) 
{
	ctrlRect.top-=EDIT_MARGIN/5;
	ctrlRect.bottom+=EDIT_MARGIN/5;
	ctrlRect.left-=EDIT_MARGIN;
	ctrlRect.right+=EDIT_MARGIN;
	MoveWindow(&ctrlRect);

	// Get the current selection
	int nStart, nEnd;
	GetSel(nStart, nEnd);
	// Scroll to the beginning
	SetSel(0,0);
	// Restore the old selection
	SetSel(nStart, nEnd);
}

CFormulaInPlaceEdit::CFormulaInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
                           CNode* pNode, CString strInitText, UINT nFirstChar)
{
    m_strInitText   = strInitText;
    m_nLastChar     = 0; 
    m_bExitOnArrows = (nFirstChar != VK_LBUTTON);    // If mouse click brought us here,
    m_pNode			= pNode;                         // then no exit on arrows
	CRect ctrlRect(rect);

	ctrlRect.top-=EDIT_MARGIN/5;
	ctrlRect.bottom+=EDIT_MARGIN/5;
	ctrlRect.right+=EDIT_MARGIN;
	ctrlRect.left-=EDIT_MARGIN;
 
	DWORD dwEditStyle = dwStyle | WS_BORDER | WS_CHILD | WS_VISIBLE | ES_LEFT| ES_AUTOHSCROLL;
    if (!Create(dwEditStyle, ctrlRect, pParent, nID)) 
		return;

	m_ctrlFont.CreatePointFontIndirect
	(
		pNode->GetLogFont(),
		NULL
	);
  
    SetFont(&m_ctrlFont);
    
    SetWindowText(strInitText);
    SetFocus();
    
    switch (nFirstChar){
        case VK_LBUTTON: 
        case VK_RETURN:   SetSel((int)_tcslen(m_strInitText), -1); return;
        case VK_BACK:     SetSel((int)_tcslen(m_strInitText), -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);
    }
    
    SendMessage(WM_CHAR, nFirstChar);
}

CFormulaInPlaceEdit::~CFormulaInPlaceEdit()
{
}

BEGIN_MESSAGE_MAP(CFormulaInPlaceEdit, CEdit)
    //{{AFX_MSG_MAP(CFormulaInPlaceEdit)
    ON_WM_KILLFOCUS()
    ON_WM_CHAR()
    ON_WM_KEYDOWN()
    ON_WM_GETDLGCODE()
    ON_WM_CREATE()
	ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

////////////////////////////////////////////////////////////////////////////
// CFormulaInPlaceEdit 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 CFormulaInPlaceEdit::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;
    }
	CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}

// As soon as this edit loses focus, kill it.
void CFormulaInPlaceEdit::OnKillFocus(CWnd* pNewWnd)
{
    CEdit::OnKillFocus(pNewWnd);
    EndEdit();
}

void CFormulaInPlaceEdit::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_strInitText);    // restore previous text
        m_nLastChar = nChar;
        GetParent()->SetFocus();
        return;
    }
    
    CEdit::OnChar(nChar, nRepCnt, nFlags);
}

UINT CFormulaInPlaceEdit::OnGetDlgCode() 
{
    return DLGC_WANTALLKEYS;
}

////////////////////////////////////////////////////////////////////////////
// CFormulaInPlaceEdit overrides

// Stoopid win95 accelerator key problem workaround - Matt Weagle.
BOOL CFormulaInPlaceEdit::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 CFormulaInPlaceEdit::PostNcDestroy() 
{
    CEdit::PostNcDestroy();
    
    delete this;	
}

////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit implementation

void CFormulaInPlaceEdit::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;
    GetWindowText(str);
	// Set the new shortcut
	m_pNode->SetShortCut(str);
	// reset the NE_INEDITMODE flag
	m_pNode->SetEditMode(m_pNode->GetEditMode() & ~NE_INEDITMODE); 

    // Send Notification to parent
    NMHDR hdr;
    hdr.hwndFrom = GetSafeHwnd();
    hdr.idFrom   = GetDlgCtrlID();
    hdr.code     = LVN_ENDLABELEDIT;

    CWnd* pOwner = GetOwner();
    if (pOwner)
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&hdr);

    // Close this window (PostNcDestroy will delete this)
    if (IsWindow(GetSafeHwnd()))
        SendMessage(WM_CLOSE, 0, 0);
    bAlreadyEnding = FALSE;
}


void CFormulaInPlaceEdit::OnUpdate() 
{
    // Set new node text
    CString str;
    GetWindowText(str);
	m_pNode->SetShortCut(str);

	// Invalidate Parent to resize node rect
	GetParent()->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
tbw
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions