Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CFunctionEdit - A custom control for n-tuple input v1.2

0.00/5 (No votes)
17 Nov 2003 1  
A custom control for n-tuple input.

Sample screenshot

Introduction

CFunctionEdit is a custom control written using pure Win32 API that allows the user to input n-tuple data (mathematical functions, vectors, etc.).

Features

CFunctionEdit does not restrict the tuple size, however changing the tuple size is not supported at runtime yet. Tuple size is determined when creating the control. Once the control is created, you can set and get the text, limit the text size for each tuple, change the font used to render the text, background color and define your own text formatting function for colorized and styled text rendering.

  • Version 1.1 supports text selection and cut, copy, paste operations.
  • Version 1.2 has popup menu and readonly style.

Initializing and Using the control

First, call the Init() member of the class with the HINSTANCE of your application. Init() function merely registers the window class if it has not been registered yet. After that you can create an instance of the control with Create() member function by supplying the appropriate parameters. You can either declare your CFunctionEdit variable static or create dynamically with new.

CFunctionEdit theEdit;
CFunctionEdit *pEdit;
    
void CreateControls()
{
    // Call this only once before creating your controls

    CFunctionEdit::Init(hInstance); 
        
    theEdit.Create(50, 20, 100, 40, hwndParent);
        
    pFunctionEdit = new CFunctionEdit;
    pFunctionEdit->Create(50, 120, 100, 40, hwndParent);
}

After having created the control, you can change the contents with SetText() and get them with GetText().

int CFunctionEdit::SetText(int nIndex, const TCHAR *szText);
int CFunctionEdit::GetText(int nIndex, TCHAR *szText);

Here nIndex is the index of the tuple. Indexes start from 0 and go up to number of tuples minus one. An exception is, if index is equal to -1, given text is assigned to all the tuples in the control.

// Assume we have a CFunctionEdit object

// called theEdit for all the following examples.


theEdit.SetText(-1, TEXT("")); // Clears all the tuples.


theEdit.GetText(0, szText); // Gets the text of the first tuple.

You can limit the text size for each tuple with the SetTextLimit() function.

for(int a = 0; a < nTupleCount; a++)
{
    // At most 3 characters can be entered in each tuple.

    theEdit.SetTextLimit(a, 3);
}

CFunctionEdit has the following style flags that have effect on input and rendering of the control:

#define FES_NUMERIC      1 // Allows only the input of numbers.

#define FES_UPPERCASE    2 // Converts lowercase characters to uppercase.

#define FES_LOWERCASE    4 // Converts uppercase characters to lowercase.

#define FES_DISABLESPACE 8 // Space character is ignored.

#define FES_CENTERTEXT  16 // The text is centered in the view.

#define FES_READONLY    32 // Space character is ignored.

By default FES_CENTERTEXT, FES_DISABLESPACE and FES_LOWERCASE styles are set if you do not explicitly supply a style parameter with the Create() function.

theEdit.SetStyle(FES_CENTERTEXT | FES_NUMERIC);

Visualization features

Background color can be changed with SetBackgroundColor() function.

theEdit.SetBackgroundColor(RGB(255, 255, 255)); // White background

The font used to render the text can be changed with SetFont() function.

// Last two parameters are optional

theEdit.SetFont(TEXT("Courier New"), 24, ANSI_CHARSET); 

Rendering the text and changing the default text formatting function

When the user changes the text buffer by pressing a key, FormatText() function is called to format the text. This function is responsible for creating a list consisting of FORMATTEDTEXTBLOCK structures. It first adds " ( " as bold style and then calls formatting function for each tuple and adds " ) " as the last FORMATTEDTEXTBLOCK. The whole text rendered is a list of FORMATTEDTEXTBLOCKs.

typedef struct _tagFormattedTextBlock
{ 
    #ifndef UNICODE 
        std::string strBlock;
    #else 
        std::wstring strBlock;
    #endif
        COLORREF clColor;
        DWORD dwStyle;

} FORMATTEDTEXTBLOCK, *LPFORMATTEDTEXTBLOCK;

typedef std::list<FORMATTEDTEXTBLOCK> FormattedText;

As you see, FORMATTEDTEXTBLOCK is used to define a string which has its own color and style. dwStyle member can be zero or one of the following. (not the combination)

#define TEXTFORMAT_BOLD 1
#define TEXTFORMAT_ITALIC 2 
#define TEXTFORMAT_UNDERLINE 4

This is the default formatting function:

LRESULT CFunctionEdit::DefFormatTextProc(int nIndex, 
            const TCHAR *szText, FormattedText &ft) 
{
    FORMATTEDTEXTBLOCK fmttext; 
    
    if(*szText == TEXT('\0')) return 0; 
        
    // Default formatting : black, normal font 

    fmttext.dwStyle = 0;
    fmttext.clColor = RGB(0, 0, 0); 
    fmttext.strBlock = szText; 

    ft.push_back(fmttext);

    return 0;
}

This function merely adds the text as black-normal style to the FormattedText list. You can parse the szText passed to this function, and split the text into multiple FORMATTEDTEXTBLOCKs each having different styles. I have supplied a custom formatting function within the class that renders numbers blue, punctuations bold-green, and other characters red.

Text Selection

You can make a selection with SetSelection().

int CFunctionEdit::SetSelection(TUPLEPOS start, TUPLEPOS end);

typedef struct _tagTuplePos
{ 
    int nTupleIndex;
    int nPosition;

} TUPLEPOS, *LPTUPLEPOS;

TUPLEPOS structure identifies a unique position in the control. First member of the structure, nTupleIndex, is the tuple index where we want the cursor to move. And nPosition is the position of the cursor within this tuple.

TUPLEPOS selstart, selend;

selstart.nTupleIndex = 1;
selstart.nPosition   = 0;

selend.nTupleIndex = 2;
selend.nPosition   = 3;

// selects from 2nd tuple's beginning to 3rd tuple's 3rd position.

theEdit.SetSelection(selstart, selend);

Retrieving the selection

Selected text can be retrieved by GetSelection().

theEdit.GetSelection(szBuffer);

Positioning the cursor

SetCaretPos() function positions the cursor. Its prototype is:

int CFunctionEdit::SetCaretPos(TUPLEPOS tuplepos);
TUPLEPOS tuplepos;

tuplepos.nTupleIndex = 0;
tuplepos.nPosition   = 0;

// Moves the cursor to the first position of the first tuple;

theEdit.SetCaretPos(tuplepos);

tuplepos.nTupleIndex = 1;
tuplepos.nPosition   = 5;

// Moves the cursor to the 5th position of the second tuple.

theEdit.SetCaretPos(tuplepos);

Message Routing

Finally I want to say a few words about how the message routing is done in the class.

typedef struct _tagWindowListEntry 
{ 
    HWND hWnd;
    CFunctionEdit *pEdit;
        
} WINDOWLISTENTRY, *LPWINDOWLISTENTRY;

typedef std::list<WINDOWLISTENTRY> WindowList;

We have a list that holds window handles and associated object pointers. Each time a window is created with Create() function, the window handle and the pointer to the instance of the class is added to a global variable called Windows which is of type WindowList. So we know which handle belongs to which CFunctionEdit object. When Windows sends a message to our WindowProc, we find the associated CFunctionEdit* with GetEditWindow() function. This function traverses the list to find the object pointer of the given handle. Having found the pointer, we call the handler of that object.

MFC and Unicode

Although I haven't created the control to use in an MFC or Unicode project, I've tested it in a sample MFC-Unicode project and everything seemed to work fine. However it's too difficult for me to test all the functionality of the control and find out if special handling should be done for these types of projects.

Version history

  • Version 1.0 : November 9, 2003
    • First release
  • Version 1.1 : November 10, 2003
    • Positioning the cursor
    • Selection
    • Cut, Copy, Paste
  • Version 1.2 : November 16, 2003
    • Readonly style
    • Popup menu

Support and Feedback

For any comments and suggestions send me an e-mail via e110870@metu.edu.tr.

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