Marked Text Fields are markers which are inserted in the text. They can be used to implement a wide range of special functions in a text processor. To name just a few:
Any group of characters within the text can be a marked text field. The maximum number of fields is 65,535. Text Control maintains the positions and numbers of the fields. It also takes care of loading, saving and clipboard operations.
Additional information about text fields can be found in the Technical Articles part in the chapter Text Fields and Hypertext Links.
The source code for this example is contained in the following directories:
Used TX Text Control controls:
This first sample program will show you how fields are created and what happens when they are clicked on. The code shown here is contained in the following directories:
The program consists of a form with just one menu item, Insert Field!, with an exclamation mark to say that clicking on this item will cause an immediate action instead of dropping a menu.
The following code is executed when the menu item is clicked on:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
TXTextControl.TextField NewField = new TXTextControl.TextField();
// Insert a new field and increase field ID
NewField.Text = "[TextField" + fieldID.ToString() + "]";
NewField.ID = fieldID;
NewField.DoubledInputPosition = true;
fieldID += 1;
textControl1.TextFields.Add(NewField);
}
Private Sub MenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim NewField As New TXTextControl.TextField()
' Insert a new field and increase field ID
NewField.Text = "[TextField" & fieldID.ToString() & "]"
NewField.ID = fieldID
NewField.DoubledInputPosition = True
fieldID += 1
textControl1.TextFields.Add(NewField)
End Sub
This inserts a field at the current caret position and assigns a unique number to the fields ID property. If you move the cursor over the field, Text Control changes the mouse pointer to a hand cursor to indicate that there is something to click on.
If you click on the field, the application receives a TextFieldClicked event, to which it responds by popping up a window which displays the field number.
Only two lines of code are required for this:
private void textControl1_TextFieldClicked(object sender, TXTextControl.TextFieldEventArgs e)
{
MessageBox.Show("Field " + fieldID.ToString() + " has been clicked.");
}
Private Sub textControl1_TextFieldClicked(ByVal sender As Object, ByVal e As TXTextControl.TextFieldEventArgs)
MessageBox.Show("Field " & fieldID.ToString() & " has been clicked.")
End Sub
This example shows you how to use text fields to create bookmarks. The first version will reference the bookmarks simply by their field numbers. The source code for this example is contained in the following directories:
The sample application has a Bookmark menu with two items which are named Insert and Go to.... Clicking Insert creates a text field at the current caret position. If a text selection exists, the selected text is converted into a text field.
private void MenuItem_Click_1(object sender, RoutedEventArgs e)
{
if (textControl1.Text == "")
{
MessageBox.Show("Cannot insert a bookmark if the Text Control is empty.");
return;
}
else if (textControl1.Selection.Length == 0)
{
textControl1.Selection.Length = 1;
}
// Now turn the selected text into a new field
TXTextControl.TextField NewField = new TXTextControl.TextField();
NewField.ID = fieldID;
NewField.Text = textControl1.Selection.Text;
textControl1.Selection.Text = "";
fieldID += 1;
textControl1.TextFields.Add(NewField);
textControl1.Focus();
}
Private Sub MenuItem_Click_1(ByVal sender As Object, ByVal e As RoutedEventArgs)
If textControl1.Text = "" Then
MessageBox.Show("Cannot insert a bookmark if the Text Control is empty.")
ElseIf textControl1.Selection.Length = 0 Then
textControl1.Selection.Length = 1
Else
' Now turn the selected text into a new field
Dim NewField As New TXTextControl.TextField()
NewField.ID = fieldID
NewField.Text = textControl1.Selection.Text
textControl1.Selection.Text = ""
fieldID += 1
textControl1.TextFields.Add(NewField)
End If
End Sub
After typing in some text and inserting a few bookmarks, select the Go To... menu item. This will launch a dialog box which allows you to enter the number of the bookmark to jump to.
Clicking the OK button executes the following procedure:
private void button2_Click(object sender, RoutedEventArgs e)
{
if (Convert.ToInt32(textBox1.Text) > tx.TextFields.Count)
{
MessageBox.Show("Invalid bookmark number!");
}
else
{
foreach (TXTextControl.TextField Field in tx.TextFields)
{
if (Field.ID == Convert.ToInt32(textBox1.Text))
{
tx.Selection.Start = Field.Start - 1;
tx.Selection.Length = Field.Length;
}
}
}
}
Private Sub button2_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
If Convert.ToInt32(textBox1.Text) > tx.TextFields.Count Then
MessageBox.Show("Invalid bookmark number!")
Else
For Each Field As TXTextControl.TextField In tx.TextFields
If Field.ID = Convert.ToInt32(textBox1.Text) Then
tx.Selection.Start = Field.Start - 1
tx.Selection.Length = Field.Length
End If
Next
End If
End Sub
In commercial word processors, bookmarks are normally referenced by names, not just by numbers. The names are typed in by the user when he creates a bookmark. The Goto Bookmark dialog box then presents a listbox or combobox in which one of the strings can be selected.
The source code for this example is contained in the following directories:
The Insert Bookmark... menu item in this version of the program creates a dialog box where the user can enter a label for the bookmark.
When the OK button is clicked, the following code is executed:
private void btnOK_Click(object sender, RoutedEventArgs e)
{
TXTextControl.TextField Field = new TXTextControl.TextField();
Field.Name = tbFieldName.Text;
Field.Text = tx.Selection.Text;
tx.Selection.Text = "";
if (!tx.TextFields.Add(Field))
MessageBox.Show("Could not insert a bookmark. The cursor is probably inside a text field.");
this.Close();
}
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Dim Field As New TXTextControl.TextField()
Field.Name = tbFieldName.Text
Field.Text = tx.Selection.Text
tx.Selection.Text = ""
If Not tx.TextFields.Add(Field) Then
MessageBox.Show("Could not insert a bookmark. The cursor is probably inside a text field.")
End If
Me.Close()
End Sub
First, a marked text field is created at the current caret position. Second, the name of the bookmark, which is the text that has been typed in by the user, is stored in the TextField.Name property.
The Goto Bookmark dialog box contains a combo box which lists all of the bookmarks which have been created so far.
The combo box is filled with the bookmark titles when its Window is loaded:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
foreach (TXTextControl.TextField Field in tx.TextFields)
{
lbFields.Items.Add(Field.Name);
}
}
Private Sub Window_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
For Each Field As TXTextControl.TextField In tx.TextFields
lbFields.Items.Add(Field.Name)
Next
End Sub
When the OK button is clicked, the bookmark list is searched for the string which has been selected in the combo box, and the corresponding marked text field is selected.
private void btnOK_Click(object sender, RoutedEventArgs e)
{
foreach (TXTextControl.TextField Field in tx.TextFields)
{
if (Field.Name == lbFields.SelectedItem.ToString())
{
tx.Selection.Start = Field.Start - 1;
tx.Selection.Length = Field.Length;
}
}
this.Close();
}
Private Sub btnOK_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
For Each Field As TXTextControl.TextField In tx.TextFields
If Field.Name = lbFields.SelectedItem.ToString() Then
tx.Selection.Start = Field.Start - 1
tx.Selection.Length = Field.Length
End If
Next
Me.Close()
End Sub
TX Text Control imports and exports all fields that can be inserted into an MS Word document. As described in the technical article, the ApplicationField class provides a special interface to get and set the data and parameters of these fields.
The following two samples show how to use the two most common used fields of MS Word: MERGEFIELD and FORMTEXTBOX.
The source code for these samples is contained in the following directory:
Used TX Text Control controls:
The MS Word MergeField is the most commonly used field in MS Word and RTF documents. It enables template designers to add additional information to a text field, such as a specific text that should be displayed before or after the field text or the format of the text.
To handle these fields and it's functionality, this sample uses the DocumentServer.Fields.FieldAdapter implemented in the TXTextControl.DocumentServer. These adapters can be used to modify the TextControl.ApplicationFields directly.
After starting the sample, click on File / Load to load a sample document, which contains several merge fields. Set the input position inside an existing field, for sample [COMPANY].
Open the implemented merge field dialog by choosing Edit... from the MergeField main menu.
Using this dialog, it is possible to manipulate all properties of the MergeField instance. Add some text that should be inserted after the field by checking the checkbox Text to be inserted after. Type some text in the appropriate text box and close the dialog by clicking OK.
Open the customer list view form by clicking Merge fields... from the Merge menu entry. Choose a customer by clicking on a specific row and click Merge to merge all merge fields with the database content.
In this process, the ApplicationFieldCollection is used to loop through all inserted fields to replace the text. The following code shows this loop:
DataRow drCustomer = m_customers.Tables[0].Rows[listBox1.SelectedIndex];
foreach (TXTextControl.ApplicationField curField in _tx.ApplicationFields)
{
if (curField.TypeName != "MERGEFIELD")
return;
MergeField mfCurField = new MergeField(curField);
if(drCustomer.Table.Columns.Contains(mfCurField.Name))
mfCurField.Text = drCustomer[mfCurField.Name].ToString();
}
Dim drCustomer As DataRow = m_customers.Tables(0).Rows(listBox1.SelectedIndex)
For Each curField As TXTextControl.ApplicationField In _tx.ApplicationFields
If curField.TypeName <> "MERGEFIELD" Then
Return
End If
Dim mfCurField As New MergeField(curField)
If drCustomer.Table.Columns.Contains(mfCurField.Name) Then
mfCurField.Text = drCustomer(mfCurField.Name).ToString()
End If
Next
The FormText field is used in MS Word to create fillable documents. In many applications, such documents are automated, so that these fields must be readable to be completed automatically. An ApplicationField object acts like a container for all settings (switches) of these fields.
This sample uses the DocumentServer.Fields.FormText field adapter to handle the ApplicationField. Everytime, an ApplicationField of type FORMTEXT should be edited, a new DocumentServer.Fields.FormText field is created:
FormText curFormText = new FormText(textControl1.ApplicationFields.GetItem());
Dim curFormText As New FormText(TextControl1.ApplicationFields.GetItem())
A reference to the ApplicationField is stored in the FormText instance. Similar to the first sample, this ApplicationField is used to get or set the parameters that are mapped to the properties of the new implemented FormText object.
A dialog box is implemented to change the properties of the specific form text field. The dialog represents the properties of the implemented FormText field:
After clicking OK, the specified values in the dialog box are set in the implemented FormText object which writes the parameters of the referenced ApplicationField automatically.
This sample program shows how to use Text Control in office applications. The main task of an office application typically is to create documents from information taken from a set of databases. For instance, a quote is generated from a record in an address database and one or more records in an article database.
The program is built up in two steps, starting very simple with only a single address database, and adding more features later on.
The source code for this example is contained in the subfolders Step1 and Step2 of the following directories:
Used TX Text Control controls:
When the program is started, it displays an address database in a list view control.
The database is a simple XML file, which is displayed with just a few lines of ADO code:
dsAddress.ReadXml(@"..\..\..\address.xml");
dsArticle.ReadXml(@"..\..\..\article.xml");
lbCustomers.DataContext = dsAddress;
lbArticles.DataContext = dsArticle;
lbCustomers.SelectedIndex = 0;
dsAddress.ReadXml(@"..\..\..\address.xml");
dsArticle.ReadXml(@"..\..\..\article.xml");
lbCustomers.DataContext = dsAddress;
lbArticles.DataContext = dsArticle;
lbCustomers.SelectedIndex = 0;
Selecting the File/New Quote menu item takes the current record from the database and creates a document from it. This is done in the following way:
A form containing a Text Control is opened, and a stylesheet is loaded. A stylesheet is a file that serves as a template for the final document. It contains all text parts which are equal to all documents, for instance a phrase like "In reply to your inquiry and according to our general terms of business we are pleased to..", and placeholders for information that is to be inserted from a database, like Address, Date, and so forth. It also defines the font, font size, company logo, and layout, so that all files will have the same look.
Once the stylesheet has been loaded, the placeholders are updated from the database, so that they now contain the real address, name, customer number, and date.
The stylesheet can be edited with the Advanced menu.
Before you read everything about how it is programmed, you may want to run it and see what it does, so here is a short user's guide first.
The first thing we need to do in order to add article descriptions and pricing to our quotes from Step 1 is to add another database. We call it the article database, and display it on the main form beside the address database.
That's it for the main form. On the editor form, we now add a menu item which lets us insert items from the article data into a quote.
A list of articles is best displayed in a table, and Text Control offers all required table functions to let us insert product IDs, descriptions, and prices into the respective cells, as well as to perform calculations. We therefore add a table to the style sheet and adjust its column widths, text distances, and caption text so that later only the plain text needs to be filled in.
This is what the style sheet now looks like:
A new menu item has been added to the Advanced menu, which allows to insert a table. Also, a Format/Table menu item has been created which calls Text Control's table attribute dialog box, so that we can adjust the table grid lines and background shading. The table's column widths and tabs are adjusted in the ruler bar. Note that the 2 rightmost columns have decimal tabs, so that the currency values they will contain will be properly aligned at the decimal sign.
We are now ready to fill in text from the article database into the table. Have a look at the sample program's ArticleTable class, which shows how to use the various table, row, columns and cell collections and objects.
After the user has selected a product in the article database, the program performs these steps: