Server Visualization
ServerTextControl has no user interface, but the classes of the TXTextControl.ServerVisualization namespace give it one in the form of images. A TextViewGenerator renders any part of a document as an image, takes keyboard and mouse input for it and tells you which part of the image changed; further generators render ruler bars, a status bar and the built-in dialog boxes. With them, an application can show and edit a document in a user interface of its own.
To render complete pages, for example as thumbnails or for a comparison, you don't need these classes: Page.GetImage does it, as Pages shows. The namespace was introduced with version 21.0.
What the Namespace Contains
Every generator manages two objects: a View, which defines the part that is rendered and returns its image, and a UserInput, which passes keyboard and mouse input to the generator. When the input changes the image, the view raises its Changed event.
| Class | Renders | Created |
|---|---|---|
| TextViewGenerator | The text of the document. It is derived from ServerTextControl, so it loads, changes and saves documents like one | With new and Create |
| RulerBarViewGenerator | A horizontal or vertical ruler bar that shows the formatting at the input position of a connected TextViewGenerator | With new and Create |
| StatusBarViewGenerator | A status bar with the page, line, column, section and zoom factor of a connected TextViewGenerator | With new and Create |
| DialogViewGenerator | One of the built-in dialog boxes | By TextViewGenerator.GetDialogBox |
TextViewGenerator also has settings that ServerTextControl doesn't have. One of them records tracked changes, as Record Changes on the Server describes.
Render a Part of a Document
The view's Location and Size, both in twips (1/1440 inch), define the part of the document that is rendered, and its ZoomFactor the zoom factor in percent, from 10 up. The following program saves the top of a document as a PNG file:
using System.Drawing;
using TXTextControl;
using TXTextControl.ServerVisualization;
using (TextViewGenerator tx = new TextViewGenerator())
{
tx.Create();
tx.Load("Documents/sample.docx", StreamType.WordprocessingML);
// The part of the document to render, in twips: 8.5 x 5 inches
tx.View.Location = new Point(0, 0);
tx.View.Size = new Size(12240, 7200);
tx.View.ZoomFactor = 100;
if (tx.View.GetImage(out byte[] png))
{
File.WriteAllBytes("view.png", png);
Console.WriteLine($"view.png: {png.Length} bytes");
}
}
The code works as follows:
TextViewGeneratoris created and loaded like aServerTextControl:Createcomes first.- TextViewGenerator.View returns the view of the generator.
- View.GetImage with an
out byte[]parameter returns the image in PNG format andtrueif it succeeded.
GetImage has these overloads:
| Overload | Returns |
|---|---|
GetImage(), GetImage(Rectangle clipRectangle) | The image or a clipping of it as a System.Drawing.Imaging.Bitmap |
GetImage(out byte[] arImage), GetImage(out byte[] arImage, Rectangle clipRectangle) | The image or a clipping of it as a byte array in PNG format |
GetImage(Rectangle clipRectangle, int iFirstInvalidLine, int iLastInvalidLine, int iMaxImageResolution) | A clipping as a string in SVG format, with the characters as outlines. The clipping is a range of one-based line numbers, or the rectangle when both line numbers are 0. Images are embedded as PNG with at most the given resolution |
A clipping rectangle is in pixels, relative to the top-left corner of the view's image. The Bitmap overloads need System.Drawing.Common, which the Classic package TXTextControl.TextControl.ASP.SDK depends on and the Core package doesn't. The resolution of the images, in dots per inch, is set with TextViewGenerator.Resolution; 0 uses the resolution of the system. TextViewGenerator.Zoom zooms with a factor or a ZoomOption value.
Pass User Input and Update the Image
The methods of UserInput pass keyboard and mouse events to a generator, which reacts as an editor would: a click moves the input position, a key press inserts a character. Each method returns true if the generator handled the event. When the image of the view changes, View.Changed reports the part that has to be drawn again:
using System.Drawing;
using TXTextControl;
using TXTextControl.ServerVisualization;
using (TextViewGenerator tx = new TextViewGenerator())
{
tx.Create();
tx.Load("Documents/sample.docx", StreamType.WordprocessingML);
tx.View.Location = new Point(0, 0);
tx.View.Size = new Size(12240, 7200);
// Report each part of the image that changes
tx.View.Changed += (sender, e) =>
Console.WriteLine($"Changed: {e.ClipRectangle}, scrolled: {e.ScrollOrientation}");
// A click at 100, 100 pixels in the view, then two typed characters
Point click = new Point(100, 100);
tx.UserInput.SendMouseDown(click, UserInput.MouseButtons.Left, UserInput.ModifierKeys.None);
tx.UserInput.SendMouseUp(click, UserInput.MouseButtons.Left, UserInput.ModifierKeys.None);
tx.UserInput.SendKeyPress('O', UserInput.ModifierKeys.Shift);
tx.UserInput.SendKeyPress('k', UserInput.ModifierKeys.None);
// Only the changed part is rendered again
Rectangle update = tx.View.GetUpdateRectangle(true);
if (!update.IsEmpty && tx.View.GetImage(out byte[] png, update))
{
File.WriteAllBytes("update.png", png);
}
}
The code works as follows:
- TextViewGenerator.UserInput returns the
UserInputobject of the generator. - SendMouseDown and SendMouseUp take a location in pixels, relative to the top-left corner of the view, a MouseButtons value and a combination of ModifierKeys values.
SendMouseMove,SendMouseDoubleClickandSendMouseWheelwork the same way; the wheel's distance is a multiple of 120. - SendKeyPress takes the translated character code, and SendKeyDown and SendKeyUp the virtual key code, for keys such as the arrow keys.
- The
Changedevent passes a ViewChangedEventArgs object. ClipRectangle is the changed area in pixels. ScrollOrientation isNonefor a change of the content, andHorizontalScrollorVerticalScrollwhen the view was scrolled; ScrollDistance is then the distance, which is less than zero when the document was scrolled down or to the right. - Changes of the content are collected in an update region. GetUpdateRectangle returns the smallest rectangle around it, and with
trueresets the region. Scrolling doesn't add to the region.
When the input position leaves the view, the view scrolls by itself and raises AutoHScroll or AutoVScroll. A changed zoom factor raises Zoomed. View.GetCursorKind returns the mouse cursor to show at a location, as a CursorKind value.
The Changed Event Since Version 24.0
In version 24.0, the handler type of View.Changed changed from System.EventHandler to ViewChangedEventHandler, which passes the ViewChangedEventArgs described above. A handler written for an earlier version as (object sender, EventArgs e) doesn't compile any longer: change its second parameter to ViewChangedEventArgs.
Connect Ruler Bars and a Status Bar
A RulerBarViewGenerator or a StatusBarViewGenerator connected to a TextViewGenerator follows its input position automatically. The following program renders the text, a horizontal ruler bar and a status bar:
using System.Drawing;
using TXTextControl;
using TXTextControl.ServerVisualization;
using (RulerBarViewGenerator ruler = new RulerBarViewGenerator())
using (StatusBarViewGenerator statusBar = new StatusBarViewGenerator())
using (TextViewGenerator tx = new TextViewGenerator())
{
// Each generator must be created before it is used
ruler.Create();
statusBar.Create();
tx.Create();
tx.Load("Documents/sample.docx", StreamType.WordprocessingML);
tx.View.Size = new Size(12240, 7200);
// Connect the bars with the text
tx.RulerBar = ruler;
tx.StatusBar = statusBar;
statusBar.ShowPage = true;
statusBar.ShowPageCounter = true;
statusBar.ShowZoom = true;
SaveImage(ruler.View, "ruler.png");
SaveImage(tx.View, "text.png");
SaveImage(statusBar.View, "statusbar.png");
}
static void SaveImage(View view, string fileName)
{
if (view.GetImage(out byte[] png))
{
File.WriteAllBytes(fileName, png);
}
}
The code works as follows:
- TextViewGenerator.RulerBar connects a horizontal ruler bar, VerticalRulerBar a vertical one and StatusBar a status bar.
nulldisconnects them. - The
Showproperties of the status bar choose its areas: ShowPage, ShowPageCounter,ShowSection,ShowSectionCounter,ShowLine,ShowColumn,ShowLanguage,ShowKeyStates, ShowZoom andShowZoomTrackBar. The labels of the areas are set withPageText,PageCounterText,SectionText,SectionCounterText,LineTextandColumnText, and their font withFont. - Each generator has its own
View, and the images are drawn next to each other. TheLocationproperties of TextViewGenerator and RulerBarViewGenerator, in pixels, place the text image relative to the ruler image, so that the ruler marks line up with the text.
A ruler bar has further settings:
| Property | Sets |
|---|---|
| Alignment | Top for a horizontal ruler, Left for a vertical one |
| ScaleUnit | Inch, Centimeter, Millimeter, or Auto for inch or millimeter depending on the culture |
| ReadOnly | Whether the ruler only shows the formatting and doesn't change it |
| EnablePageMargins | Whether page margins can be set with the ruler |
| FormulaMode | Whether the ruler shows cell references in tables: None (the default), Always, Auto in cells with a formula, or Fixed relative to one cell |
BorderStyle sets the design of both bars. Their colors, set with DisplayColors as a RulerBarViewGenerator.Colors or StatusBarViewGenerator.Colors object, are only used with the border style ColorScheme, and ResetDisplayColors restores the defaults. Both bars have a Resolution property like TextViewGenerator.
Show Built-In Dialog Boxes
TextViewGenerator.GetDialogBox returns a DialogViewGenerator for one of the built-in dialog boxes, such as the font, paragraph, table or section dialog box. The parameter is a DialogBoxKind value, and a second parameter selects a tab of the dialog boxes that have tabs. Two further overloads open the dialog box of a PageNumberField or of a FormField.
using TXTextControl;
using TXTextControl.ServerVisualization;
using (TextViewGenerator tx = new TextViewGenerator())
{
tx.Create();
tx.Load("Documents/sample.docx", StreamType.WordprocessingML);
// Null if a dialog box returned before hasn't been disposed
using (DialogViewGenerator dialog = tx.GetDialogBox(TextViewGenerator.DialogBoxKind.FontDialog))
{
if (dialog != null)
{
dialog.Closed += (sender, e) => Console.WriteLine("The dialog box was closed");
if (dialog.View.GetImage(out byte[] png))
{
File.WriteAllBytes("font-dialog.png", png);
Console.WriteLine($"{dialog.Caption}: font-dialog.png");
}
}
}
}
The code works as follows:
- The dialog box has its own View and UserInput. Clicks and key presses sent to it change the settings of the dialog box.
- Caption is the title of the dialog box.
- Closed occurs when the user closes the dialog box with OK or Cancel.
- Dispose the
DialogViewGeneratorwhen the dialog box is closed. Until then,GetDialogBoxreturnsnull.
A dialog box that opens another one, such as a color dialog box, raises ShowDialogBox; its ShowDialogBoxEventArgs.DialogBox is the generator of the child dialog box. A message for the user raises ShowErrorMessage with the ErrorMessage and a Caption, and CaretStateChanged reports where the caret of an input box is. TextViewGenerator has a ShowDialogBox and a ShowErrorMessage event of its own, for dialog boxes and messages that user input opens in the text. DialogUnit sets the unit of sizes and distances in all dialog boxes.
Control What the View Shows
Properties of TextViewGenerator decide how the document looks in its images and what users can do:
| Property | Sets |
|---|---|
| ViewMode | PageView with pages, gaps and headers and footers, Normal, FloatingText or SimpleControl |
| EditMode | Edit, ReadAndSelect with the restrictions of DocumentPermissions, or ReadOnly |
| CommentHighlightMode | Which commented texts are highlighted: Activated (the default) the one at the input position, Always all of them, Never none |
| EditableRegionHighlightMode | The same for editable regions whose own highlight mode is Auto |
| UserNames | The users whose editable regions can be edited in a read-only document |
| ControlChars, TextFrameMarkerLines | Whether control characters and the outlines of text frames without a border are shown |
| DisplayColors | The colors of the area around the pages, the page shadows, the header and footer labels and form fields, as a TextViewGenerator.Colors object |
Auto can't be set for CommentHighlightMode and EditableRegionHighlightMode. Whether conditional instructions are applied to form fields in a read-only document is set with IsFormFieldValidationEnabled. Undo is available too, with Undo, Redo and BeginUndoAction and EndUndoAction to group changes into one undo step.
Events of TextViewGenerator
Besides the events of ServerTextControl, a TextViewGenerator reports what user input does. The events fall into these groups:
| Group | Events |
|---|---|
| Drawing the user interface | CaretStateChanged with the location, size and visibility of the caret; DocumentSizeChanged with the size of the document in twips, for scroll bars; TextContextMenuOpening with the MenuItem objects of a context menu after a right click; DrawCombobox, DrawDateControl, RemoveCombobox and RemoveDateControl for the controls of selection and date form fields; DrawShape for additional parts during an interaction |
| Input position | InputPositionChanged, InputParagraphChanged, InputFormattingStyleChanged, and the Entered and Left events of text fields, subtextparts, editable regions, commented texts and tables of contents |
| Footnotes | FootnoteReferenceMarkEntered, FootnoteReferenceMarkLeft, FootnoteSectionActivated and FootnoteSectionDeactivated, since version 32.0 |
| Parts of the document | MainTextActivated, HeaderFooterActivated and HeaderFooterDeactivated, TextFrameActivated and TextFrameDeactivated |
| Selected objects | Selected and Deselected events of images, text frames, charts, barcodes, drawings, signature fields and frames in general, and FrameMoved and FrameSized |
| Clicks | TextFieldClicked, SubTextPartClicked, SubTextPartDoubleClicked, HypertextLinkClicked and DocumentLinkClicked |
| Changes | Changed, CharFormatChanged, ParagraphFormatChanged, PageFormatChanged, FormattingStyleChanged, FormattingStyleListChanged, the FormField events for changed values and settings, CommentChanged, CommentStateChanged, TrackedChangeChanged, TrackedChangeStateChanged and CannotTrackChange |
The ServerVisualization namespace in the reference lists every member with its description.
Next Steps
- Pages: render complete pages as SVG images.
- Track Changes: read, accept and reject tracked changes, and record them with
TextViewGenerator. - Document Protection: mark the editable regions that
UserNamesunlocks. - Viewing and Printing in the Document Editor: set the display colors in the browser.