TX Text Control .NET Server

Server Visualization

Topic

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.

ClassRendersCreated
TextViewGeneratorThe text of the document. It is derived from ServerTextControl, so it loads, changes and saves documents like oneWith new and Create
RulerBarViewGeneratorA horizontal or vertical ruler bar that shows the formatting at the input position of a connected TextViewGeneratorWith new and Create
StatusBarViewGeneratorA status bar with the page, line, column, section and zoom factor of a connected TextViewGeneratorWith new and Create
DialogViewGeneratorOne of the built-in dialog boxesBy 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:

  • TextViewGenerator is created and loaded like a ServerTextControl: Create comes first.
  • TextViewGenerator.View returns the view of the generator.
  • View.GetImage with an out byte[] parameter returns the image in PNG format and true if it succeeded.

GetImage has these overloads:

OverloadReturns
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 UserInput object 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, SendMouseDoubleClick and SendMouseWheel work 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 Changed event passes a ViewChangedEventArgs object. ClipRectangle is the changed area in pixels. ScrollOrientation is None for a change of the content, and HorizontalScroll or VerticalScroll when 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 true resets 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. null disconnects them.
  • The Show properties of the status bar choose its areas: ShowPage, ShowPageCounter, ShowSection, ShowSectionCounter, ShowLine, ShowColumn, ShowLanguage, ShowKeyStates, ShowZoom and ShowZoomTrackBar. The labels of the areas are set with PageText, PageCounterText, SectionText, SectionCounterText, LineText and ColumnText, and their font with Font.
  • Each generator has its own View, and the images are drawn next to each other. The Location properties 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:

PropertySets
AlignmentTop for a horizontal ruler, Left for a vertical one
ScaleUnitInch, Centimeter, Millimeter, or Auto for inch or millimeter depending on the culture
ReadOnlyWhether the ruler only shows the formatting and doesn't change it
EnablePageMarginsWhether page margins can be set with the ruler
FormulaModeWhether 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 DialogViewGenerator when the dialog box is closed. Until then, GetDialogBox returns null.

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:

PropertySets
ViewModePageView with pages, gaps and headers and footers, Normal, FloatingText or SimpleControl
EditModeEdit, ReadAndSelect with the restrictions of DocumentPermissions, or ReadOnly
CommentHighlightModeWhich commented texts are highlighted: Activated (the default) the one at the input position, Always all of them, Never none
EditableRegionHighlightModeThe same for editable regions whose own highlight mode is Auto
UserNamesThe users whose editable regions can be edited in a read-only document
ControlChars, TextFrameMarkerLinesWhether control characters and the outlines of text frames without a border are shown
DisplayColorsThe 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:

GroupEvents
Drawing the user interfaceCaretStateChanged 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 positionInputPositionChanged, InputParagraphChanged, InputFormattingStyleChanged, and the Entered and Left events of text fields, subtextparts, editable regions, commented texts and tables of contents
FootnotesFootnoteReferenceMarkEntered, FootnoteReferenceMarkLeft, FootnoteSectionActivated and FootnoteSectionDeactivated, since version 32.0
Parts of the documentMainTextActivated, HeaderFooterActivated and HeaderFooterDeactivated, TextFrameActivated and TextFrameDeactivated
Selected objectsSelected and Deselected events of images, text frames, charts, barcodes, drawings, signature fields and frames in general, and FrameMoved and FrameSized
ClicksTextFieldClicked, SubTextPartClicked, SubTextPartDoubleClicked, HypertextLinkClicked and DocumentLinkClicked
ChangesChanged, 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 UserNames unlocks.
  • Viewing and Printing in the Document Editor: set the display colors in the browser.