Skip to content

WinForms Application

Gary edited this page Mar 10, 2015 · 4 revisions



Table of Contents

WinForms applications in ATF can have a Main() function with a standard, simple structure, especially for applications with a GUI. Most of the ATF Code Samples have a structure similar to that described in this section.

ATF applications with a Form typically use a MainForm class derived from System.Windows.Forms, which allows ATF to have more control over the Form.

Initial Setup

This initial section of code is from the ATF FSM Editor Sample:

static void Main()
{
    // It's important to call these before starting the app; otherwise theming and bitmaps
    //  may not render correctly.
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.DoEvents(); // see http://www.codeproject.com/buglist/EnableVisualStylesBug.asp?df=100&forumid=25268&exp=0&select=984714

    // Set up localization support early on, so that user-readable strings will be localized
    //  during the initialization phase below. Use XML files that are embedded resources.
    Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentCulture;
    Localizer.SetStringLocalizer(new EmbeddedResourceStringLocalizer());

    // Enable metadata driven property editing for the DOM
    DomNodeType.BaseOfAllTypes.AddAdapterCreator(new AdapterCreator<CustomTypeDescriptorNodeAdapter>());

Application Methods

The Application class methods called here are used by many applications to provide general Windows® capabilities.

The comment on DoEvents() notes that this call must occur early to avoid problems with Controls for certain Windows® versions.

Localization Support

These methods are called early so that user-readable strings are localized correctly in soon to follow initialization code.

Metadata Driven Property Editing

If the application uses the ATF DOM, a call to AddAdapterCreator ensures that you can edit the properties of data types defined in the DOM for the application data. This statement (used in several samples) adds a DOM adapter to allow all DOM nodes to adapt to an appropriate property descriptor, if any. The adapter is called on BaseOfAllTypes, so it applies to all types:

DomNodeType.BaseOfAllTypes.AddAdapterCreator(new AdapterCreator<CustomTypeDescriptorNodeAdapter>());

AddAdapterCreator() adds an adapter creator onto every type for CustomTypeDescriptorNodeAdapter, which implements ICustomTypeDescriptor. This means that an adapter can be found for ICustomTypeDescriptor for every type in the application. That is, every DomNode can be adapted to ICustomTypeDescriptor. This is useful in extracting attribute information from the DomNode.

This statement enables metadata-driven property editing in the application. That is, the properties that appear in property editors are determined by the metadata provided about the properties in property descriptors. If this statement were removed, the properties visible in a property editor for an object would be properties of the object and classes it derives from—not the properties you provide in your type definition.

For more details, see "Defining DOM Extensions and Adapters" in the ATF Programmer’s Guide: Document Object Model (DOM), which you can download at ATF Documentation. For information on property editors and descriptors, see Property Editing in ATF.

MEF Processing

This MEF handling is from the ATF Target Manager Sample. It includes part of the application getting its main form, because this object is also used by MEF.

var catalog = new TypeCatalog(
    typeof(SettingsService),            // persistent settings and user preferences dialog
    typeof(FileDialogService),          // proivdes standard Windows&reg; file dialogs, to let the user open and close files. Used by SkinService.
    typeof(SkinService),                // allows for customization of an application's appearance by using inheritable properties that can be applied at run-time
    typeof(StatusService),              // status bar at bottom of main Form
    typeof(CommandService),             // handles commands in menus and toolbars
    typeof(ControlHostService),         // docking control host

    typeof(StandardFileExitCommand),    // standard File exit menu command
    typeof(HelpAboutCommand),           // Help -> About command
    typeof(AtfUsageLogger),             // logs computer info to an ATF server
    typeof(CrashLogger),                // logs unhandled exceptions to an ATF server

    typeof(ContextRegistry),            // component that tracks application contexts; needed for context menu

    // add target info plugins and TargetEnumerationService
    typeof(Deci4pTargetProvider),       // provides information about development devices available via Deci4p
    typeof(TcpIpTargetProvider),        // provides information about development devices available via TCP/IP
    typeof(TargetCommands),             // commands to operate on currently selected targets.
    typeof(TargetEnumerationService)    // queries and enumerates target objects, consuming target providers created by the application
    );

// Set up the MEF container with these components
var container = new CompositionContainer(catalog);

// Configure the main Form
var batch = new CompositionBatch();
var mainForm = new MainForm(new ToolStripContainer());
mainForm.Text = @"ATF TargetManager Sample";

// Add the main Form instance to the container
AttributedModelServices.AddPart(batch, mainForm);
container.Compose(batch);

...

// Initialize components that require it. Initialization often can't be done in the constructor,
//  or even after imports have been satisfied by MEF, since we allow circular dependencies between
//  components, via the System.Lazy class. IInitializable allows components to defer some operations
//  until all MEF composition has been completed.
container.InitializeAll();

// Show the main form and start message handling. The main Form Load event provides a final chance
//  for components to perform initialization and configuration.
Application.Run(mainForm);

// Give components a chance to clean up.
container.Dispose();

Briefly, this code block creates a TypeCatalog listing all the ATF components used. This catalog is used to create a CompositionContainer. The new MainForm is added to a new CompositionBatch, which is then used to compose the MEF components. InitializeAll() initializes the MEF components. When the application ends, Dispose() performs final MEF cleanup on the container. For a more detailed explanation of these operations, see How MEF is Used in ATF.

MainForm Creation and Running the Application

The previous code sample showed creating the MainForm as well as MEF manipulation. Here is a similar segment from the ATF Code Editor Sample that does additional things:

var container = new CompositionContainer(catalog);

var toolStripContainer = new ToolStripContainer();
toolStripContainer.Dock = DockStyle.Fill;

var mainForm = new MainForm(toolStripContainer);
var image = GdiUtil.GetImage("CodeEditor.Resources.File_edit.ico");
mainForm.Icon = GdiUtil.CreateIcon(image, 32, true);

mainForm.Text = "Code Editor".Localize();

var batch = new CompositionBatch();
batch.AddPart(mainForm);
batch.AddPart(new WebHelpCommands("https://github.com/SonyWWS/ATF/wiki/ATF-Code-Editor-Sample".Localize()));
container.Compose(batch);
...
// Initialize components that require it. Initialization often can't be done in the constructor,
//  or even after imports have been satisfied by MEF, since we allow circular dependencies between
//  components, via the System.Lazy class. IInitializable allows components to defer some operations
//  until all MEF composition has been completed.
container.InitializeAll();

// Show the main form and start message handling. The main Form Load event provides a final chance
//  for components to perform initialization and configuration.
Application.Run(mainForm);

container.Dispose();

A System.Windows.Forms.ToolStripContainer is created and its docking style is set.

A new MainForm is constructed with the ToolStripContainer and the MainForm object's Icon and Text properties are set.

MainForm is also a MEF component, so it can be added to the CompositionBatch by AttributedModelServices.AddPart().

The final operation needed is to call Application.Run() with the MainForm object to run the application. After the application terminates, container is disposed of.

Topics in this section

Clone this wiki locally