Chapter 7: Developing Phase: Migrating the User Interface

This chapter describes how to migrate from a UNIX-based user interface (UI) to a Microsoft® Windows® UI using Windows Forms provided by Microsoft .NET. Windows Forms is a framework for building Windows rich-client applications that use the common language runtime (CLR). Because the overwhelming majority of UNIX graphical interfaces are built on X Windows and Motif, this chapter focuses on porting code from X Windows to .NET using Windows Forms.

This chapter covers the following topics:

  • Architectural and visual differences between the UNIX and .NET environments.

  • Programming principles used by X Windows and Windows Forms.

  • Migrating different types of graphical constructs from one environment to the other.

This chapter also includes sections on migrating from other UNIX UI types, including text-based and OpenGL-based interfaces, and provides code examples illustrating how to migrate the UIs.

*

On This Page

.NET Forms, Drawing, and GDI+ .NET Forms, Drawing, and GDI+
Comparing X Windows and Windows Forms Comparing X Windows and Windows Forms
User Interface Programming in X Windows and Windows Forms User Interface Programming in X Windows and Windows Forms
Window Management Window Management
Event Handling Event Handling
Graphics Device Interface Graphics Device Interface
Windows Character Data Types Windows Character Data Types
Drawing Drawing
Timers Timers
Migrating Character-based User Interfaces Migrating Character-based User Interfaces
Porting OpenGL Applications Porting OpenGL Applications
Mapping X Windows Terminology to Windows Forms Mapping X Windows Terminology to Windows Forms
Mapping X Windows Tools to Microsoft Windows Mapping X Windows Tools to Microsoft Windows
User Interface Coding Examples User Interface Coding Examples

.NET Forms, Drawing, and GDI+

This section covers Windows Forms that are used for developing rich client applications, Web Forms that are used for developing Web applications, and Drawing and GDI+ namespaces and classes provided by the .NET Framework for drawing and graphics.

Windows Forms

Windows Forms is the new platform for Windows application development, based on the .NET Framework. This framework provides a clear, object-oriented, extensible set of classes that enable you to develop rich Windows applications.

The System.Windows.Forms namespace contains the group of classes that form the Windows Forms technology. These classes include the following:

  • The Control class

  • The Form class

  • The Component class

  • The CommonDialog class

These classes are discussed in detail later in this chapter, where a particular X Windows functionality is mapped to its corresponding functionality in .NET.

Web Forms

Web Forms can be used to create programmable Web pages that serve as the user interface of your Web application. It presents information to the user in any browser or client device and implements application logic using server-side code.

The System.Web.UI namespace provides classes and interfaces that allow you to create various controls and pages that will appear in your Web applications as user interface elements. The namespace provides the following important features by its classes:

  • The Control class provides all the server controls with a common set of functionality.

  • The Page class represents the Web Forms page that is requested from the Web server and contains the related methods and properties.

  • The data binding classes provide the server controls with data binding functionality.

  • Classes like BaseParser provide parsing functionality for the controls.

Drawing and GDI+

GDI stands for Graphics Device Interface. GDI+ is a class-based application-programming interface (API) for C and C++ programs. GDI+ enables programmers to build applications that use graphics and formatted text on the screen as well as the printer. When using GDI+, you do not need to access the graphics hardware directly. Instead, GDI+ interacts with device drivers on behalf of applications. GDI+ is also supported by the 64-bit Windows operating system.

In the Microsoft .NET library, all the classes related to GDI+ are grouped under six namespaces and reside in the System.Drawing.dll assembly. The drawing namespace and the five subnamespaces are as follows:

  • System.Drawing

  • System.Drawing.Design

  • System.Drawing.Printing

  • System.Drawing.Imaging

  • System.Drawing.Drawing2D

  • System.Drawing.Text

These namespaces and the important classes associated with them are discussed in detail later in this chapter, where a particular X Windows functionality is mapped to its corresponding functionality in .NET.

Windows Forms Designer

Windows Forms, when used in conjunction with the Microsoft Visual Studio® .NET 2003 integrated development environment (IDE), enable Rapid Application Development (RAD) techniques for building applications. RAD enables you to just drag and drop controls onto your form, double-click that particular control, and write the code that corresponds to that particular event in the code editor. The Windows Forms Designer and the Visual Studio .NET 2003 IDE greatly facilitate the process of replicating the look of your graphical user interface (GUI) in the Windows environment.

Comparing X Windows and Windows Forms

The main UI type in use on the UNIX platform today builds on the X Windows set of standards, protocols, and libraries. To understand how to migrate such a UI, it is worth comparing the UI architecture and the resulting "look and feel" in the X Windows and Windows models. It is also useful to understand the similarities and differences in windowing terminology used in the two environments.

X Windows and Windows Forms are compared in the following concepts, which are explained in detail in the later subsections:

  • User interface architecture

  • Look and feel

  • Window types

User Interface Architecture

The architecture of X Windows-based interfaces differs significantly from Windows architecture. The first and most fundamental difference is the orientation of client and server. For X Windows, the client is the application that requests services and receives information from the UI. The user-facing elements of the interface are based on what is termed the X Server.

In the X Windows-based system, the client application sends requests to the server to display graphics and to send mouse and keyboard events. The X Server is responsible for doing all the work on behalf of the client. The client might run on a remote system with no graphics hardware or on the same physical computer as the server. In either case, the client does not interact with the display, mouse, or keyboard. Figure 7.1 shows the X Windows client-server architecture.

Figure 7.1. X Windows architectural model

Figure 7.1. X Windows architectural model

A standard .NET-based, rich client application is not responsible for dealing with the display, mouse, or hardware. Figure 7.2 shows the Windows UI architecture using Windows Forms. It shows the path from an application, through the layers, to the hardware in the .NET environment.

Figure 7.2. Windows UI architecture using Windows Forms

Figure 7.2. Windows UI architecture using Windows Forms

Look and Feel

X Windows is normally used with the Motif widget library, which is a library of UI components (such as scroll bars, buttons, drop-down lists, and dialog boxes) that can be used off the shelf. Motif is the most commonly used library to develop the UI component of X Windows applications.

According to the Motif Programming Manual and the Microsoft Official Guidelines for User Interface Developers and Designers, all applications that a user can run on the desktop should have a consistent "look and feel" as well as functional design. Otherwise, it is likely to confuse users, possibly to such an extent that they will not use the application.

Although there are many differences, UIs of both Microsoft Windows and X Windows with Motif have roots in the IBM Common User Access (CUA) guidelines. The resulting similarity in look and feel is not too surprising. Every windowing system needs to perform the same tasks, which are as follows:

  • Determine the font to be used to display text.

  • Determine the background color.

  • Specify the location where a check box appears.

  • Show that a user has clicked a particular button.

Given the task list, it just becomes a matter of the methodology used for accomplishing these tasks. Figure 7.3 and Figure 7.4 are examples of a Motif dialog box and a Windows dialog box respectively. Notice the similarities in terminology and appearance of dialog box elements in these two figures.

Figure 7.3. An example Motif dialog box

Figure 7.3. An example Motif dialog box

Figure 7.4. An example Windows dialog box

Figure 7.4. An example Windows dialog box

Note To ensure a consistent look and feel with other Windows-based applications, the development of a GUI on Windows using Windows Forms should be governed by the official Microsoft guidelines.

Window Types

Window types are very similar between the X Windows and Windows environments, as detailed in the following sections.

Desktop Window

The X Windows system automatically creates the desktop window. This is a system-defined window that is the base for all windows displayed by all applications. In X Windows, it can be thought of in the same general terms as the root window.

Application Window

The application window is the interface between the user and the application. Such elements as a menu bar, window menu, minimize and maximize buttons, Close button, title bar, sizing border, client area, and scroll bars typically appear in the application window.

Dialog Boxes

A dialog box is a temporary window, typically used by a user to create some additional input. A dialog box contains one or more controls, such as buttons and check boxes, to elicit user input.

Modeless Dialog Box

A modeless dialog box becomes the active window when the system creates it. The modeless dialog box neither disables its parent window nor sends messages to its parent window. However, it stays at the top of the z-order, even when the parent window becomes the active window. You use this mainly when you want to perform activities in the parent window and dialog box in any order. Applications can create a modeless dialog box by using the System.Windows.Forms.Form constructor and its various properties.

A modal dialog box becomes the active window when the system creates it and remains active until a call to System.Windows.Forms.Form.Close is made, which destroys the modal dialog box. Neither the application nor the user can make the parent window active. Form.Close must be called to close the modal dialog box. You use this mainly when you want to take some necessary action from the dialog box and want to make the decision before doing any other action.

An application uses the System.Windows.Forms.Form constructor, with the modal property set to true, to create a modal dialog box in Windows Forms.

Message Box

A message box is a special dialog box that displays a note, caution, or warning to the user. For example, a message box can inform the user of a problem that the application has encountered while performing a task.

An application uses System.Windows.Forms.MessageBox.Show to create a message box.

Reference Material

Table 7.1 lists the reference materials available for X Windows/Motif and Microsoft Windows. All of these Microsoft documents are available on the MSDN® Web site.

Table 7.1. References for X/Motif and Microsoft Windows

X Windows/Motif Reference

Microsoft Windows Reference

Motif Style Guide

Official Guidelines for User Interface Developers and Designers

Motif Programming Manual

<To be provided>

Motif Reference Manual

<To be provided>

Note   The Microsoft .NET Framework SDK is available for download at https://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&displaylang=en.

User Interface Programming in X Windows and Windows Forms

The core functionality offered by the X Windows environment is similar to the one that the Windows Forms environment offers. This section discusses the programming principles for developing UIs in both environments and provides information about libraries and include files. This section helps you in understanding Windows Forms programming and explains how to use these programming concepts to replace the X Windows UI.

Programming Principles

The basic structure of an X Windows–based application that uses Motif is very similar to the structure of a Microsoft Windows-based application.

To initiate an X Windows–based interface

  1. Initialize the toolkit.

  2. Create widgets.

  3. Manage widgets.

  4. Set up callbacks.

  5. Display widgets.

  6. Enter the main program event handler.

The following example code illustrates these steps.

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

topWidget = XtVaAppInitialize();
frame = XtVaCreateManagedwidget("frame",
xmFrameWidgetFrams, topWidget,,,);
button = XmCreatePushButton( frame, "EXIT", NULL, 0 );
XtManageChild(button)
XtAddCallback( button, XmNactivateCallback, 
myCallback, NULL );
XtRealizeWidget( topWidget );
XtAppMainLoop();

To initiate a Windows Forms-based application

  1. Write your own form class that inherits from the System.Windows.Forms.Form class.

  2. Instantiate the form class you have written.

  3. Call the static method Run() of the Application class with the instance of your class as argument to launch your Windows application.

The following C# example code illustrates these steps.

using System;
using System.Windows.Forms;
namespace FirstWinFormAppl
{
    public class Form1 : System.Windows.Forms.Form
    {    
        static void Main() 
        {
            Application.Run(new Form1());
        }
    }
}

After launching your application, you can instantiate new forms and display them using the show() method. The following example code illustrates this.

Form obForm = new Form();
obForm.Show();

Libraries and Include Files

Despite differences in their underlying architectures, many of the graphical functions used in X Windows and Windows Forms perform similar tasks. These include the core libraries and common dialog boxes.

Core Libraries

A number of functions exist to support the core API used in a GUI. X Windows includes the libraries X and Xlib and the X Windows Intrinsics toolkit. The .NET equivalent is the System.Windows.Forms namespace, which includes extensive UI-related classes. The namespace can be compared to the X Library and X Windows Intrinsics toolkit because they provide nearly all of the basic window management and two-dimensional graphics APIs.

Motif and Windows Forms Common Dialog Boxes

Dialog box functionality is provided by the Motif library in UNIX and by the Windows Forms dialog classes in .NET. If you migrate code from Motif, there is probably an equivalent Windows Forms common dialog box for each Motif function.

For example, the Motif function XmCreateFileSelectionDialog() is very similar to the OpenFileDialog.ShowDialog() function. The X Motif code must include the Xm/FileSB.h header file. The Windows Forms application must include the System.Windows.Forms namespace.

Calling the OpenFileDialog.ShowDialog() function displays the Open File dialog box, as shown in Figure 7.5.

Figure 7.5. The OpenFileDialog.ShowDialog() common dialog box

Figure 7.5. The OpenFileDialog.ShowDialog() common dialog box

Table 7.2 lists the common dialog boxes and related methods in .NET.

Table 7.2. Common Dialog Box and Related Methods in the .NET Framework API

Function

Description

System.Windows.Forms.ColorDialog constructor

Creates a Color dialog box that enables the user to select a color.

System.Windows.Forms.FontDialog constructor

Creates a Font dialog box that enables the user to choose attributes for a logical font.

System.IO.FileInfo.Name

Retrieves the name of the specified file.

System.Windows.Forms.OpenFileDialog.ShowDialog

Creates an Open dialog box that enables the user to specify the drive, the directory, and the name of a file or set of files to open.

System.Windows.Forms.SaveFileDialog.ShowDialog

Creates a Save dialog box that enables the user to specify the drive, the directory, and the name of a file to save.

System.Windows.Forms.PageSetupDialog.ShowDialog

Creates a Page Setup dialog box that enables the user to specify the attributes of a printed page.

System.Windows.Forms.PrintDialog.ShowDialog

Displays a Print dialog box.

PrintDlgEx()

Displays a Print property sheet that enables the user to specify the properties of a particular print job.

Note The Find and Replace dialog box, which enables the user to search for a text and replace it, is not readily available as part of the .NET Framework API. The API for the Find and Replace dialog box is available for download at https://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/commondialogboxlibrary/aboutcommondialogboxes/findandreplacedialogboxes.asp.

Window Management

Window management functions cover the creation, initialization, management, and eventual removal of dialog boxes and other window types. This section discusses the following activities in window management:

  • Creating windows.

  • Creating controls.

  • Identifying the control.

  • Communicating with the control.

You can use the information in this section to create windows, create and identify controls, and communicate with controls using Windows Forms.

Creating Windows

The sample code provided in this section illustrates some of the X Windows and .NET implementations of window management. It is unlikely that any large-scale X Windows client or .NET Windows Forms–based application would actually be implemented as these code examples are. However, it will help you understand the conceptual similarities and some differences between the X Windows and .NET implementation of window management.

An X Windows X11 client might use XtAppInitialize(), XtVaAppInitialize(), XtOpenApplication(), or XtVaOpenApplication to get a top-level widget to create a window, as shown in the following example code.

X Windows example: Creating a window

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

main (int argc, char *argv[] )
{
  Widget toplevel;     /* Conceptual Application Window */
  XtAppContext  app;   /* context of the app */
  toplevel = XtVaAppInitialize( &app,"myClassName",
NULL,0,&argc,argv,NULL,NULL );

The following is an alternative example code to get a top-level widget to create a window.

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

  toplevel = XtOpenApplication( &app,"myClassName",
  NULL,0,&argc, argv, NULL, whateverWidgetClass, NULL,0);
  ...
  ...

In the following example code, a .NET Windows Forms application creates a main window.

.NET example: Creating a window

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private void createWindow()
{
System.Windows.Forms.Form objForm = new 
System.Windows.Forms.Form();
objForm.Name = "myFormName";
objForm.Text = "myWindowName";
objForm.Height = 145;
objForm.Width = 500;
objForm.Show();
}

An X Windows client can create a control or widget, as shown in the following example code.

X Windows example: Creating a window with a control

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

main (int argc, char *argv[] )
{
  Widget toplevel;  /* Conceptual Application Window */
  Widget button;       
  XtAppContext  app;   /* context of the app */
  toplevel = XtVaAppInitialize( &app, "Example",
NULL,0,&argc,argv,NULL,NULL );
  button   = XtVaCreateManagedWidget( 
"command",
commandWidgetClass,/* class*/
toplevel,   /* parent */
XtNheight, 50,
XtNwidth, 100,
XtNlabel, "Press To Exit",
 NULL 
 );

A .NET Windows Forms application can create a control, as shown in the following example code.

.NET example: Creating a window with a control

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private void createWindow()
{
System.Windows.Forms.Form objForm  = new 
System.Windows.Forms.Form();
objForm.Name = "myFormName";
objForm.Text = "myWindowName";
objForm.Height = 145;
objForm.Width = 500;
objForm.Controls.Add(createButton());
objForm.Show();
}
private System.Windows.Forms.Button createButton()
{
System.Windows.Forms.Button objButton = new 
System.Windows.Forms.Button();
objButton.Name = "myButton";
objButton.Text = "Press To Exit";
objButton.Top = 50;
objButton.Left = 150;
objButton.Height = 20;
objButton.Width = 100;
return objButton;
}

Creating Controls

Controls, such as X Windows widgets, come in all shapes, sizes, colors, and functions. There are two ways to create controls in a .NET environment. The first and simplest method is by using the form designer in Visual Studio .NET 2003 or by writing the code to generate a control.

Using Visual Studio .NET 2003, you can drag and drop controls onto a form, which in X Windows is a widget itself.

Using a form designer in Visual Studio .NET 2003 produces the following code in the code editor.

Note The following code is generated by the form designer in the code editor for a sample application that has a window, a text box, and a button.

.NET example: Creating controls

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Configuration;
namespace WindowAppTest
{
    public class WindowsAppTestForm : 
System.Windows.Forms.Form
    {
        private System.Windows.Forms.TextBox Display;
        private System.Windows.Forms.Button ClickMe;
        private System.ComponentModel.Container components
= null;
        #region WindowsAppTestForm
        public WindowsAppTestForm()
        {
            InitializeComponent();
        }
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null) 
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }
        /// <summary>
        /// Required method for Designer support - do not 
modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.Display = new System.Windows.Forms.TextBox();
            this.ClickMe = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // Display
            // 
            this.Display.Location = new System.Drawing.Point(40, 32);
            this.Display.Name = "Display";
            this.Display.Size = new System.Drawing.Size(224, 20);
            this.Display.TabIndex = 0;
            this.Display.Text = "";
this.Display.TextChanged += new System.EventHandler
(this.Display_TextChanged);
            // 
            // ClickMe
            // 
            this.ClickMe.Location = new System.Drawing.Point(88, 80);
            this.ClickMe.Name = "ClickMe";
            this.ClickMe.Size = new System.Drawing.Size(96, 40);
            this.ClickMe.TabIndex = 1;
            this.ClickMe.Text = "Click Me";
this.ClickMe.Click += new System.EventHandler
(this.button1_Click);
            // 
            // WindowsAppTestForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 141);
            this.Controls.Add(this.ClickMe);
            this.Controls.Add(this.Display);
            this.Name = "WindowsAppTestForm";
            this.Text = "WindowsAppTestForm";
            this.ResumeLayout(false);
        }
        #endregion
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() 
        {
            Application.Run(new WindowsAppTestForm());
        }
private void ClickMe_Click(object sender,
System.EventArgs e)
        {
            System.Windows.Forms.MessageBox.Show
(Display.Text);
        }
private void Display_TextChanged(object sender,
System.EventArgs e)
        {
            String s = "Text Entered: ";
            s += Display.Text;
System.Windows.Forms.MessageBox.Show(s,"Now entered");
        }
    }
}

The second method is to instantiate the objects of the corresponding classes, such as System.Windows.Forms.Form and System.Windows.Forms.Button. To produce the desired control at the desired location inside a parent window, the properties of the objects can be set.

A sample code to produce a control in X Windows is as follows:

thisButton = 
    XtVaCreateManagedWidget("Fire Phasers",  <-- button text
                          commandWidgetClass, <-- the type of widget
                          parentWidget, <-- parent widget
                          NULL );

A sample code to produce a control in .NET Windows Forms is as follows:

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private System.Windows.Forms.Button createButton()
{
System.Windows.Forms.Button objButton = new 
System.Windows.Forms.Button();
objButton.Name = "myButton";
objButton.Text = "Press To Exit";
objButton.Top = 50;
objButton.Left = 150;
objButton.Height = 20;
objButton.Width = 100;
return objButton;
}

Identifying a Control

To communicate with or to respond to a control, it is necessary to identify the control. Controls are identified using the name property associated with the control object. For example:

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

System.Windows.Forms.Button objButton = new 
System.Windows.Forms.Button();
objButton.Name = "myButton";

The name property of the object can be used to get or set the name of the object.

Communicating with a Control

After the application identifies a control, it can communicate with it. The following are some examples of sending and receiving commands or messages from controls in .NET and X Windows.

.NET example: Adding strings to a list box

//+
//  programmatically add strings to the list box
//-
// .NET
//
private System.Windows.Forms.ListBox mylistBox;
mylistBox.Items.Add("one");
mylistBox.Items.Add("two");
mylistBox.Items.Add("three");

X Windows example: Adding strings to a list box

// X11/Motif
//
XmString newString;
newString = XmStringCreateLocalized(“String One”);
XmListAddItem( listWidget, newString, 0);
XmStringFree(newString);
newString = XmStringCreateLocalized(“String Two”);
XmListAddItem( listWidget, newString, 0);
XmStringFree(newString);
newString = XmStringCreateLocalized(“String Three”);
XmListAddItem( listWidget, newString, 0);
XmStringFree(newString);

.NET example: Setting the current focus

//+
//  programmatically force the current focus 
//  to this control, i.e., make the user select 
//  something now!
//-
// .NET
//
mylistBox.Focus();

X Windows example: Setting the current focus

// Xlib
// XSetInputFocus( display, listWidget, RevertToParent,
timeNow );

.NET example: Selecting a list box item

//+
//  programmatically pick a string for them!
//-
// .NET
// 
mylistBox.SelectedIndex = 2;

X Windows example: Selecting a list box item

// X11/Motif
//
XmListSelectPos( listWidget, 2, 0 );

The “Signals and Events” section in Chapter 6, “Infrastructure Services” of this volume has a detailed discussion on communicating with controls and handlers for the events generated. The next section also describes keyboard and mouse event handling in .NET.

Event Handling

UI devices include keyboards and mouse devices, tablets, touchpads, and other devices. The most frequently used devices in many applications are the mouse and the keyboard. The following sections cover the mouse and keyboard events in Windows Forms.

Capturing Mouse Events

Like X Windows, mouse events can be associated with controls in Windows Forms. These events occur depending on the various mouse operations over the controls. Table 7.3 lists the various mouse events that are available in Windows Forms.

Table 7.3. Mouse Events in Windows Forms

Event

Argument

Description

Click

EventArgs

Occurs when a control is clicked.

DoubleClick

EventArgs

Occurs when a control is double-clicked.

MouseEnter

EventArgs

Occurs when a mouse cursor enters a control.

MouseLeave

EventArgs

Occurs when a mouse cursor leaves a control.

MouseHover

EventArgs

Occurs when a mouse cursor hovers over a control.

MouseDown

MouseEventArgs

Occurs when the mouse cursor is over a control and the mouse button is pressed.

MouseUp

MouseEventArgs

Occurs when the mouse cursor is over a control and the mouse button is released.

MouseMove

MouseEventArgs

Occurs when the mouse cursor is moved over a control.

MouseWheel

MouseEventArgs

Occurs when the mouse wheel is rotated.

The MouseEventArgs class provides two properties X and Y, which return the x-coordinate and the y-coordinate of the mouse pointer in pixels relative to the window’s client area. There are two types of mouse events: the client-area mouse events and the nonclient-area mouse events. Client-area mouse events are those events that occur within the client area of the window or the form. Nonclient-area mouse events are those events that occur within the window but outside the client area. The nonclient area includes border, title bar, menu, scroll bars, and minimize and maximize buttons.

The following example code shows how the coordinates of the mouse are determined, whenever the MouseMove event occurs, using the MouseEventArgs class.

.NET example: Using the mouse coordinates

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private void panel1_MouseMove(object sender,
System.Windows.Forms.MouseEventArgs e)  {
        // Update the mouse path that is drawn onto 
        // the Panel.
           int mouseX = e.X;
           int mouseY = e.Y;
           }

Capturing Keyboard Events

In most applications, it may be necessary to capture keystrokes and perform some actions based on those keystrokes. Like X Motif, Windows Forms also provides a number of keyboard events. The KeyDown event occurs when a key is pressed and the KeyUp event occurs when the key is released. Table 7.4 lists the three keyboard events in Windows Forms.

Table 7.4. Key Events in Windows Forms

Event

Event Data

Description

KeyDown

KeyEventArgs

Occurs when a key is pressed.

KeyUp

KeyEventArgs

Occurs when a key is released.

KeyPress

KeyPressEventArgs

Occurs between the KeyDown and the KeyUp events and only when a character-generating key is pressed.

You can use the KeyEventArgs event data associated with the KeyDown and KeyUp events to obtain low-level information about the keystroke, such as determine the keycode (code that is used to uniquely identify a particular key) of the key that was pressed. It is also used to determine such things as whether any modifier keys (Alt, Ctrl, Shift keys, and the various combinations of these keys) were pressed or to determine whether a lowercase or an uppercase character was pressed.

You can use the KeyPressEventArgs event data associated with the KeyPress event to obtain a type that contains the ASCII character of the pressed key. The following example code shows how to catch the key events when text is entered in a text box control, named textBox1.

.NET example: Handling the KeyDown event

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

// Handle the KeyDown event to determine the type of
character entered into the control.
private void textBox1_KeyDown(object sender, 
System.Windows.Forms.KeyEventArgs e)
{
//Sample Handler code
switch(e.KeyCode)
{
case Keys.D0:
// Keystroke is number 0
..
..
case Keys.Back:
//Keystroke is backspace
..
..
}
}    
//Handle the KeyUp event
private void textBox1_KeyUp(object sender,
System.Windows.Forms.KeyEventArgs e)
{
    //Handler code
}
//Handle the KeyPress event
private void textBox1_KeyPress(object sender, 
System.Windows.Forms.KeyPressEventArgs e)
{
    //handler code.
}

For most purposes, the standard KeyUp, KeyDown, and KeyPress events are sufficient to capture and handle keystrokes. However, not all controls raise these events for all keystrokes under all conditions. Follow the steps in the following paragraph to capture keystrokes, regardless of the state of the control.

To capture keystrokes in a Windows Forms control, you must derive a new class that is based on the class of the control that you want and override the ProcessCmdKey method. In this overridden method, place the code to process the keystrokes that you want to capture.

The following sample code is an example of the basic structure for such a class. The code demonstrates how to catch the keystrokes UP ARROW, DOWN ARROW, TAB, CTRL+M, and ALT+Z. The code given here is written to work with the DataGrid because this feature is most frequently requested for the DataGrid control. You can use the same approach with other .NET controls as well.

.NET example: Processing keystrokes

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

protected override bool ProcessCmdKey(ref Message msg,
Keys keyData)    
{
   const int WM_KEYDOWN = 0x100;
   const int WM_SYSKEYDOWN = 0x104;
   if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
   {
      switch(keyData)
      {
         case Keys.Down:
            this.Parent.Text="Down Arrow Captured";
            break;
         case Keys.Up:
            this.Parent.Text="Up Arrow Captured";
            break;
         case Keys.Tab:
            this.Parent.Text="Tab Key Captured";
            break;
         case Keys.Control | Keys.M:
            this.Parent.Text="<CTRL> + M Captured";
            break;
         case Keys.Alt | Keys.Z:
            this.Parent.Text="<ALT> + Z Captured";
            break;
      }                
   }
   return base.ProcessCmdKey(ref msg,keyData);
}

The system passes two parameters to the ProcessCmdKey method: msg and keyData. The msg parameter contains the Windows message, such as WM_KEYDOWN. The keyData parameter contains the key code of the key that was pressed. If CTRL or ALT was also pressed, the keyData parameter contains the ModifierKey information.

Using the msg parameter is not mandatory. However, it is a good practice to test the message. In this example, test WM_KEYDOWN to verify that this is a keystroke event. Also, test WM_SYSKEYDOWN to ensure that it is possible to catch keystroke combinations that include control keys (primarily ALT and CTRL).

To capture specific keys, you can evaluate the keyCode by comparing it to the keys enumeration. The code demonstrates how to catch the keystrokes UP ARROW, DOWN ARROW, TAB, CTRL+M, and ALT+Z.

Keyboard Focus

Keyboard focus is a temporary property of a control or a widget. The window or widget that is listening is said to have the current focus, keyboard focus, or focus.

Setting focus in Windows Forms–based applications involves calling the focus method on a particular control for which focus is requested. For example, if you want to set focus to a particular text box, then you need to call the focus method on that text box. The Control.GotFocus() is the event that is raised when a control gains focus and the Control.LostFocus() is the event that is raised when a control loses focus. This is similar to using XmNfocusCallback and XmNlosingFocusCallback for focus callbacks set up within        X Motif.

The following example code shows how GotFocus and LostFocus events are handled for a text box named Textbox1.

.NET example: Textbox focus events

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

// This method handles the GotFocus event for TextBox1 
private void TextBox1_GotFocus(object sender, 
System.EventArgs e)
{
    //Perform operations that needs to be done when
TextBox1 gains focus
}
// This method handles the LostFocus event for TextBox1 
private void TextBox1_LostFocus(object sender,
System.EventArgs e)
{
    //Perform operations that needs to be done when
TextBox1 loses focus.
}

You can also manually raise the GotFocus event by using the Control.OnGotFocus() method. Table 7.5 lists the events for getting current focus in the X Windows and .NET Framework environments.

Table 7.5. Getting Current Focus in X Windows and .NET Framework API

X Windows

.NET Framework API

No equivalent

System.Windows.Forms.Form.ActiveForm

XGetInputFocus()

System.Windows.Forms.Form.ActiveForm

XmGetFocusWidget()

System.Windows.Forms.Control.Controls[].Focused

Table 7.6 lists the events for setting current focus in the X Windows and .NET Framework environments.

Table 7.6. Setting Current Focus in X Windows and .NET Framework API

X Windows

.NET Framework API

No equivalent

System.Windows.Forms.Form.Focus

No equivalent

System.Windows.Forms.Activate

XSetInputFocus()

System.Windows.Forms.Form.Activate

Graphics Device Interface

The Graphics Device Interface (GDI) is a set of classes and functions used to generate graphics for devices such as displays and printers. These classes help you in creating graphics objects such as Pens, Brush, and Palette and in drawing shapes such as lines, circles, and rectangles. This section describes the GDI-specific routines and functions used in X Windows applications and their corresponding replacements in the .NET environment. Using this information, you can identify the best approach to migrate the GDI-specific routines in your UNIX application to the .NET environment.

Getting the Graphics Object

Applications on both platforms use a context to control the drawing functions. In X Windows systems, this context is known as the graphics context (GC) and in Microsoft Win32®-based GDI systems, this context is known as the device context (DC). Windows Forms provides a Graphics class that encapsulates the GDI+ drawing surface and maintains its state.

You can obtain the Windows Forms graphics object in several ways.

To obtain the Windows Forms graphics object

  • Override the OnPaint event handler method. This method takes PaintEventArgs as a parameter. PaintEventArgs has a property that returns a graphics object. This is illustrated by the following example code:

    protected override void OnPaint (PaintEventArgs e)
    

{     Graphics g = e.Graphics; } Or

  • Call the CreateGraphics method on a control or a form, which would return the graphics object. The following example code illustrates this.

    Graphics g = this.CreateGraphics();

Device Context

Applications on both UNIX and Windows use a context that controls the behavior of drawing functions. Windows Forms provides a System.Drawing namespace, which includes the Graphics class that encapsulates the GDI+ drawing surface and maintains its state.

However, there are some differences in UNIX and Windows regarding the use of context. The first difference is the location where the operating system stores and manages drawing attributes such as the width of lines or the current font. In X Windows, these values belong to the graphics context. When using XCreateGC() or XtGetGC(), it is necessary to provide a values mask and values structure. These values are used to store settings such as line width, foreground color, background color, and font style.

The following code is an example of the process of setting the foreground and background colors in X Windows.

X Windows example: Setting the foreground and background colors

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

GC             gcRedBlue;
XGCValues      gcValues;
unsigned long  gcColorRed;
unsigned long  gcColorBlue;
unsigned long  gcColorWhite;
Widget         myWidget;
int main (int args, char **argv)
{ 
  // initialize colors - widget - etc. 
  gcValues.foreground = gcColorRed;
  gcValues.background = gcColorBlue;
  gcRedBlue = XtGetGC ( myWidget, GCForeground |
GCBackground, &gcValues);
}

The following code shows a .NET based method to set the foreground and background color of a form.

.NET example: Setting the foreground and background color of a form

private void setColor()
{
System.Windows.Forms.Form objForm = new Form();
objForm.ForeColor = System.Drawing.Color.White;
objForm.BackColor = System.Drawing.Color.Black;
objForm.Show();
}

.NET-based applications use a different approach. Apart from the Graphics class, the System.Drawing namespace also includes the classes for displaying text, a pen for line drawing, and a brush for painting and filling and drawing lines, rectangles, and text.

The following code shows a .NET based application that creates a pen and then uses it to draw lines.

.NET example: Creating a pen and drawing lines

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private void DrawBlueLine()
{
System.Drawing.Pen objBlue = new Pen
(System.Drawing.Color.Blue);
System.Drawing.Graphics objGraph = 
this.CreateGraphics();
objGraph.DrawLine(objBlue,0,0,100,200);
objBlue.Dispose();
objGraph.Dispose();
}

Windows Character Data Types

This section describes various routines and functions related to fonts and character sets used in X Windows applications and their alternatives in the .NET environment. The information provided in this section will enable you to identify the font- and text-specific routines in your UNIX applications and implement their replacements in the .NET environment. The subsections discuss the following topics in detail:

  • Displaying text

  • Text and drawing operations

  • Calculating text metrics

  • Text widgets and controls

Displaying Text

Ensuring that the visual display of text is as readable as possible requires creating and using the appropriate fonts and selecting the best mapping modes.

Using Fonts

Fonts control the display characteristics of text. An X Windows client application can use the XLoadQueryFont() and XSetFont() functions to apply a font to a given graphics context (GC), as shown in the following code.

X Windows example: Using the fonts

#define FONT1 "-*-lucida-medium-r-*-*-12-*-*-*-*-*-*-*"
Font           font1;
XFontStruct   *font1Info;
main() {
  Display  *pDisplay;
  int       iScreen;
  GC        gc;
  pDisplay  = XOpenDisplay(“myDisplay”);
  iScreen   = DefaultScreen(pDisplay);
  //+
  //  get the Graphics Context
  //- 
  gc        = DefaultGC(pDisplay,iScreen);
  //+ 
  //  attempt to load the font
  //-
  font1Info = XLoadQueryFont( pDisplay,FONT1 );
  font1     = font1Info->fid;
  //+
  //  Set the font in the GC
  //-
  XSetFont( pDisplay, gc,  font1 );
   ...

In .NET, the System.Drawing namespace provides a Font class, which defines the format and characteristics for text, including font face, size, and style attributes. In .NET, the graphics object is a high-level encapsulation of the graphics context. The text drawing function (DrawString ()) displays a text with a particular font on the form by taking that Font class object as one of its arguments.

All controls have a Font property, which defines the typeface, size, and style for any text displayed by that particular control. In addition, the Windows default font will be the default font for any control. To change the Windows default font, go to Control Panel, click Display, select Properties, and then click the Settings tab.

Note Windows provides several tools for adding and editing fonts. The Eudcedit.exe tool, which comes with the operating system, allows the user to create unique characters such as logos and special characters. Eudcedit Help provides guidance on how to create, store, and use these characters in the font library.
The Charmap.exe tool, which comes with the operating system, allows the user to view, find, and copy characters from the Windows, MS-DOS®, and Unicode character sets. Charmap Help provides guidance on how to copy these characters.
The Fontedit.exe tool, which comes with Visual Studio .NET 2003, allows the user to create and edit raster fonts.

Creating Fonts

The System.Drawing.Font constructor is used for creating logical fonts, based on the fonts loaded in the system. The following example code duplicates the Times New Roman Windows font of size 14 pt and Bold style.

.NET Windows example: Creating the fonts

Public Font CreateTimesNewRomanFont()
{
int size = 14;
FontFamily fontFamily = new FontFamily("TimesNewRoman");
Font font = new Font(fontFamily,size, FontStyle.Regular,
  GraphicsUnit.Point);
}

There are 13 overloaded types of the font constructor and you can use any one of these constructors to create logical fonts in your application. For further information on the Font class, refer to System.Drawing.Font in MSDN.

Device vs. Design Units

An application can retrieve font metrics for a particular family/style combination using the FontFamily class. The methods supported by this class are as follows:

  • GetEmHeight(FontStyle)

  • GetCellAscent(FontStyle)

  • GetCellDescent(FontStyle)

  • GetLineSpacing(FontStyle)

The numbers returned by these methods are in font design units; therefore, they are independent of the size and units of a particular Font object. The font metrics specific to the device are known as device units. Portable metrics in fonts are known as design units. To apply the design units to a specified device, convert design units to device units by using the following formula.

DeviceUnits = (DesignUnits/unitsPerEm) * (PointSize/72) * DeviceResolution

Note For a full explanation of device units, design units, and pixels, refer to the System.Drawing namespace at https://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDrawing.asp.

Fonts Example

The following example code overrides the OnPaint event of the form, creates a Font object (based on the Arial family) with size 16 pixels and displays the metrics (in pixels) for that particular Font object.

.NET example: Handling the OnPaint event

protected override void OnPaint (PaintEventArgs e)
{
string infoString = "";  // enough space for one line of output
int  ascent;             // font family ascent in design units
float  ascentPixel;      // ascent converted to pixels
int  descent;            // font family descent in design units
float  descentPixel;     // descent converted to pixels
int  lineSpacing;        // font family line spacing in design units
float  lineSpacingPixel; // line spacing converted to pixels
FontFamily fontFamily = new FontFamily("Arial");
Font font = new Font(
   fontFamily,
   16, FontStyle.Regular,
   GraphicsUnit.Pixel);
PointF pointF = new PointF(10, 10);
SolidBrush   solidBrush = new SolidBrush(Color.Black);
// Display the font size in pixels.
infoString = "font.Size returns " + font.Size + ".";
e.Graphics.DrawString(infoString, font, solidBrush, pointF);
// Move down one line.
pointF.Y += font.Height;
// Display the font family em height in design units.
infoString = "fontFamily.GetEmHeight() returns " +
   fontFamily.GetEmHeight(FontStyle.Regular) + ".";
e.Graphics.DrawString(infoString, font, solidBrush, pointF);
// Move down two lines.
pointF.Y += 2 * font.Height;
// Display the ascent in design units and pixels.
ascent = fontFamily.GetCellAscent(FontStyle.Regular);
// 14.484375 = 16.0 * 1854 / 2048
ascentPixel = 
   font.Size * ascent / fontFamily.GetEmHeight(FontStyle.Regular);
infoString =  "The ascent is " + ascent + " design units, " + ascentPixel + 
   " pixels.";
e.Graphics.DrawString(infoString, font, solidBrush, pointF);
// Move down one line.
pointF.Y += font.Height;
// Display the descent in design units and pixels.
descent = fontFamily.GetCellDescent(FontStyle.Regular);
// 3.390625 = 16.0 * 434 / 2048
descentPixel = 
   font.Size * descent / fontFamily.GetEmHeight(FontStyle.Regular);
infoString = "The descent is " + descent + " design units, " +
   descentPixel + " pixels.";
e.Graphics.DrawString(infoString, font, solidBrush, pointF);
// Move down one line.
pointF.Y += font.Height;
// Display the line spacing in design units and pixels.
lineSpacing = fontFamily.GetLineSpacing(FontStyle.Regular);
// 18.398438 = 16.0 * 2355 / 2048
lineSpacingPixel = 
font.Size * lineSpacing / fontFamily.GetEmHeight(FontStyle.Regular);
infoString = "The line spacing is " + lineSpacing + " design units, " +
   lineSpacingPixel + " pixels.";
e.Graphics.DrawString(infoString, font, solidBrush, pointF);
}

Text and Drawing Operations

This section describes how you can perform the following text and drawing operations in the .NET environment.

  • Drawing text.

  • Filling shapes.

  • Obtaining the color of the display elements.

  • Drawing a gray text at the specified location.

This section also discusses the classes and related methods that help achieve these functionalities.

Drawing Text

There are two methods of drawing text: the X Windows XDrawString() function in X Windows and the DrawString() function of Graphics class in .NET. The XDrawString() requires a context to draw on, the x and y coordinates, the string, and the string length in characters. Similarly, the DrawString() method requires an object of the Graphics class to call it, the x and y coordinates, and the string to be drawn.

The code examples provided in this section draw the "Hello World" string in the current font and colors at the specified coordinates. It is often desirable to set a particular font or color before writing the text. The following code examples show how this task is accomplished in the two systems.

A programmer can code font and text display in X Windows as follows.

X Windows example: Drawing the text

Font = XLoadQueryFont (display,"fixed");
XSetFont (display, gc, font->fid);
XSetBackground (display, gc, WhitePixel (display,screen));
XSetForeground (display, gc, BlackPixel (display, screen));
XDrawString (display, d, gc, x, y, "Hello World", 11);

The DrawString() function in the Graphics class draws a formatted text in the specified location. The following code example creates a text, creates a font (Arial 16 pt), creates a solid black brush to draw with, and draws the text at the specified location in vertical format.

.NET example: Drawing the text

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

public void DrawStringFloatFormat(PaintEventArgs e)
{
// Create string to draw.
String drawString = "Sample Text";
// Create font and brush.
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Black);
// Create point for upper-left corner of drawing.
float x = 150.0F;
float y =  50.0F;
// Set format of string.
StringFormat drawFormat = new StringFormat();
drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
// Draw string to screen.
e.Graphics.DrawString(drawString, drawFont, drawBrush
, x, y, drawFormat);
}

One drawback of using XDrawString() is that the background is not erased before drawing the text string. Continually outputting strings to the same x and y coordinates results in a jumble of unreadable text strings, one upon the other. The X Windows library provides the DrawImageString() function, which calculates a rectangle containing the string and fills it with the background pixel color before drawing the text in the foreground pixel color.

However, in .NET, this is taken care of by an overloaded version of DrawString(). The syntax of that overloaded version is as follows:

public void DrawString(
   string s,
   Font font,
   Brush brush,
   RectangleF layoutRectangle
);
Filling Shapes

The constructor of System.Drawing.SolidBrush defines a brush of a single color. Brushes are used to fill graphics shapes, such as rectangles, ellipses, pies, polygons, or paths. The following example code shows the SolidBrush constructor. Color is a structure that represents the color of the brush.

public SolidBrush(
   Color color
);
Obtaining the Color of the Display Elements

The System.Drawing.SystemColors class contains several properties; each of these properties is a Color structure that represents the color of a Windows display element. Display elements are the parts of a window and the Windows display that appear on the system display screen. Some of the properties of the SystemColors class are explained in the following table.

Table 7.7. Properties of SystemColors Class

Property Name

Use of Property

SystemColors.ActiveBorder

Gets a Color structure that is the color of the active window's border.

SystemColors.Desktop

Gets a Color structure that is the color of the desktop.

SystemColors.Menu

Gets a Color structure that is the color of a menu's background.

SystemColors.ScrollBar

Gets a Color structure that is the color of the background of a scroll bar

The SetTextColor() function sets the text color for the specified device context to the specified color, as shown in the following example:

COLORREF SetTextColor(
  HDC      hdc,           // handle to DC
  COLORREF crColor        // text color
);
Drawing a Gray Text at the Specified Location

To draw a gray string at the specified location, you must pass Drawing.Brushes.Gray as the Brushes argument in the constructor of the DrawString function. The following example code draws a gray string at the specified location.

.NET example: Drawing the text with Brushes at specified location

public void DrawGrayString(PaintEventArgs e)
{
// Create string to draw.
String drawString = "Gray Text";
// Create font and brush.
Font drawFont = new Font("Arial", 16);
// Create point for upper-left corner of drawing.
float x = 150.0F;
float y =  50.0F;
// Draw string to screen.
e.Graphics.DrawString(drawString, drawFont, Brushes.Gray, x, y);
} 

Calculating Text Metrics

The X Windows programmer can rely on XTextWidth() to get the length of a character string in pixels. The Windows Forms programmer has an equivalent method called MeasureString() available in the Graphics class. This method returns a SizeF structure that represents the size, in pixels, of the specified string drawn with the specified font. From the SizeF structure, both the width and height of the string can be obtained. SizeF.Width represents the width of the string and SizeF.Height represents the height of the string.

The MeasureString() method is as follows.

public SizeF MeasureString(
   string text,
   Font font,
   int width
);

The following example code shows the use of MeasureString. It creates a string to measure and a font object set to Arial (16 pt). It then sets the maximum width of the string, creates a size object, and then uses the font object and the maximum string width to measure the size of the string. Finally, it draws a red rectangle using the measured size of the string and draws the string within the drawn rectangle.

.NET example: Measuring the string

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

 public void MeasureStringWidth(PaintEventArgs e)
 {
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Set maximum width of string.
int stringWidth = 200;
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString,
stringFont, stringWidth);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(
new Pen(Color.Red, 1),
0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(
measureString,
stringFont,
Brushes.Black,
new PointF(0, 0));
} 

Text Widgets and Controls

A text widget or control is used to display, enter, and edit text. The exact functionality of a text widget or control depends upon how its resources are set.

In X Windows, the widget functionality is set as shown in the following example.

X Windows example: Setting widget functionality

text = XtVaCreateManagedWidget ( "myTextWidget", 
                                 asciiTextWidgetClass, 
                                 parentWidget,
                                 XtNfromHoriz, 
                                 quit, 
                                 XtNresize,
                                 XawtextResizeBoth, 
                                 XtNresizable, 
                                 True, 
                                 NULL);

In Motif, the widget functionality is set as shown in the following example.

Motif example: Setting widget functionality

main (int argc, char *argv[])
{
  Widget       mainWidget;
  Widget       textWidget;
  XtAppContext appContext;
  mainWidget = 
    XtVaOpenApplication ( &appContext, 
                          "TextExample", 
                          NULL, 
                          0, 
                          &argc, 
                          argv, 
                          NULL, 
                          sessionShellWidgetClass, 
                          NULL);
  (...)
  textWidget = 
    XmCreateText ( mainWidget,"textWidget",NULL,0);
  (...)
  XtAppMainLoop( appContext );
}

In Windows Forms, a text box is used to display, enter, and edit text. A text box can be inserted into a form using the drag and drop feature of the IDE or it can be programmatically inserted into a form. The following example code shows how a text box is programmatically added to a form and displayed to the user.

.NET example: Using text box

public class FrmText : System.Windows.Forms.Form
{
private TextBox txtDisplay;
    public Form1()
    {
        txtDisplay = new TextBox();
        txtDisplay.Location = new Point(50,50);
        txtDisplay.Text = "Default Text";
        Controls.Add(txtDisplay);
}
        static void Main() 
    {
        FrmText obFrm = new FrmText();
        Application.Run(obForm);
    }
}

Drawing

Drawing functions present graphical information on the screen. These range from primitive functions, such as turning a pixel on or off, to complex two-dimensional and three-dimensional drawing functions. The following are some notable differences in how drawing functions work on the X Windows and .NET platforms:

  • Display and color management.

  • Drawing two-dimensional lines.

  • Drawing shapes and rectangles.

You can use the information in this section to assist you in understanding the programming differences in the drawing areas between the UNIX and .NET environments and in replacing the UNIX drawing routines with the equivalent .NET classes.

Display and Color Management

X Windows and Win32-based GDI are both constrained by the physical limitations of the available display hardware. One such limitation is the number of colors a display adapter is capable of showing.

All X Windows applications use a color map. This map can be shared or private. A shared color map is used by all applications that are not using a private map. Using a private map gives an application better control over color and a greater number of colors. However, there is one problem with private maps: When the mouse moves on or off the client area using a private map, the screen colors change.

.NET-based applications typically use color with no regard for the display device. If the application uses a color that is beyond the capabilities of the display device, the system approximates that color within the limits of the hardware. On display devices that support a color palette, applications sensitive to color quality can create and manage one or more logical palettes.

The System.Drawing.Image.Palette property is used to create a logical palette in .NET. The Palette property gets or sets the color palette (object of System.Drawing.Imaging.ColorPalette) used for the Image object. The System.Drawing.Imaging.ColorPalette defines an array of colors that make up a color palette. The colors are 32-bit ARGB colors.

To determine the capabilities of the hardware and calculate the best possible behaviors of the display, an X Windows program can use such functions as DefaultColorMap(), DefaultVisual(), DisplayCells(), DisplayPlanes(), XGetVisualInfo(), and XGetWindowAttributes().

A .NET-based application can rely on System.Drawing.Graphics properties. The Graphics properties get or set device context information.

Note More information on the ColorPalette class and its members is available at https://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdrawingimagingcolorpaletteclasstopic.asp.

Drawing Two-Dimensional Lines

Two sets of line and curve drawing functions are provided in the .NET environment. System.Drawing.Graphics.DrawLine and System.Drawing.Graphics.DrawLines are used for drawing lines. System.Drawing.Graphics.DrawArc and System.Drawing.Graphics.DrawBeziers are used for drawing curves.

The following table describes the preceding functions (one of overloaded functions) and their usage.

Table 7.8. Drawing lines in .NET

Function Name

Function Signature

Usage

System.Drawing.Graphics.DrawLine

public void DrawLine(

Pen, // Object of Pen class

int, // x1 co-ordinate

int, // y1 co-ordinate

int, // x2 co-ordinate

int  // y2 co-ordinate

);

To draw a line from the current position up to, but not including, a specified point.

System.Drawing.Graphics.DrawLines

public void DrawLines(

Pen, // Objetc of Pen class

Point[] //Array of Point Structure

);

To draw a series of line segments by connecting the points in the specified array.

System.Drawing.Graphics. DrawArc

public void DrawArc(

   Pen pen,

   Rectangle rect,

   float startAngle,

   float sweepAngle

);

To draw an arc representing a portion of an ellipse specified by a Rectangle structure.

System.Drawing.Graphics.DrawBeziers

public void DrawBeziers(

   Pen pen,

   Point[] points

);

To draw a series of Bézier splines from an array of Point structures.

Note More information on drawing curves is available at https://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDrawingGraphicsMethodsTopic.asp.

The following example shows the use of XDrawLine() in X Windows.

X Windows example: Using XDrawLine() to draw a line

int main (int argc, char **argv)
{ 
  XtToolkitInitialize ();
  myApplication = XtCreateApplicationContext ();
  myDisplay     = XtOpenDisplay( myApplication, 
                                 NULL, 
                                 NULL, 
                                 "XBlaat", 
                                 NULL, 
                                 0, 
                                 &argc, 
                                 argv);
  myWindow = RootWindowOfScreen(DefaultScreenOfDisplay (mydisplay));
  //+
  // now we need a surface to draw on
  //-
  myMap = XCreatePixmap ( myDisplay,myWindow,64,64, 1 );
  values.foreground = 
    BlackPixel (myDisplay, DefaultScreen (myDisplay));
  myGC = XCreateGC (myDisplay, mySurface, GCForeground, &values);
  //+
  //  draw two diagonal lines across the 64x64 surface
  //  
  XDrawLine( myDisplay,mySurface,myGC,0,0,63,63 ); 
  XDrawLine( myDisplay,mySurface,myGC,0,63,63,0 );
  ...
}

The following example shows the use of DrawLine method in .NET to draw lines.

.NET example: Using DrawLine to draw lines

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private void DrawX()
{
System.Drawing.Pen objPen = new Pen
(System.Drawing.Color.Black);
System.Drawing.Graphics objGraph = 
this.CreateGraphics();
objGraph.DrawLine(objPen,0,0,63,63);
objGraph.DrawLine(objPen,0,63,63,0);
objPen.Dispose();
objGraph.Dispose();
}

Drawing Shapes and Rectangles

Filled shapes are geometric forms that the current pen can outline and the current brush can fill.

There are five filled shapes:

  • Ellipse

  • Chord

  • Pie

  • Polygon

  • Rectangle

The X Windows version of XDrawRectangle() uses an upper-left–corner point and the width and height.

In .NET, System.Drawing.Graphics.DrawRectangle() draws a rectangle specified by a coordinate pair: a width, and a height. System.Drawing.Graphics.FillRectangle() fills the interior of a rectangle specified by a pair of coordinates: a width, and a height.

Rectangle functions that fill the rectangle are:

  • X Windows: XFillRectangle()

  • .NET: System.Drawing.Graphics.FillRectangle()

Rectangle functions that draw the outline only are:

  • X Windows: XDrawRectangle()

  • .NET: System.Drawing.Graphics.DrawRectangle()

The following example demonstrates rectangle functions in X Windows.

X Windows example: Drawing a rectangle

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

void drawSomeRectangles()
{
  //+
  // fill the rectangle and then draw a black border around it
  //-
  XFillRectangle (myDisplay, mySurface, myWhiteGC, 0, 0, 31, 31);
  XDrawRectangle (myDisplay, mySurface, myBlackGC, 0, 0, 31, 31);
  //+
  //  draw an empty rectangle ten pixels square
  //- 
  XDrawRectangle( myDislay, mySurface, myBlackGC, 0,0, 10,10 );
}

The following example demonstrates rectangle functions in .NET.

.NET example: Drawing a rectangle

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

private void DrawRec()
{
System.Drawing.Pen objPen = new Pen(
System.Drawing.Color.Black);
System.Drawing.SolidBrush objBrush = new SolidBrush(
System.Drawing.Color.White);
System.Drawing.Graphics objGraph = this.CreateGraphics();
objGraph.FillRectangle(objBrush,0,0,31,31);
objGraph.DrawRectangle(objPen,0,0,31,31);
objGraph.DrawRectangle(objPen,0,0,10,10);
objPen.Dispose();
objBrush.Dispose();
objGraph.Dispose();
}

Timers

Timers are required to determine and act on delays in user input. The functionality and differences between X Windows timeouts and .NET timers are discussed in the following sections.

X Windows Timer

An X Windows client program can use the XtAddAppTimeOut() and XtRemoveTimeOut() functions with a callback to perform processing based on an interval specified in milliseconds. The following code shows an example of this.

X Windows example: Handling timer events

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

//+
// perform task every one second
//-
void myTimerProc( Widget    w, 
                  XEvent   *event,
                  String   *pars, 
                  Cardinal *npars)
{
    ...
    ...
}
//+
// start a 1 second timer
//-
void startTimer( XtIntervalId *timer )
{
  (*timer) = XtAppAddTimeOut( gContext, 1000, 
myTimerProc, NULL);
}
//+
// stop the timer
//-
void stopTimer( XtIntervalId * timer )
{
  if( *timer ) {
    XtRemoveTimeOut( *timer );
    (*timer) = NULL;
  }
}

.NET Timers

You can use .NET timers in two scenarios. First, as in the X Windows approach, a callback function can be identified to execute at each timer interval. Second, an event can be raised to process timer intervals.

The System.Threading.Timer class provides a mechanism for executing a method at specified intervals.

The following example shows the callback version using System.Threading.Timer.

.NET example: Handling timer events with System.Threading

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

using System;
using System.Threading;
namespace AlarmSignal
{
    /// <summary>
    /// Class to simulate the alarm
    /// </summary>
    class TimerSample
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            CallBackClass objCallBack = new CallBackClass();
//The object of the AutoResetEvent class notifies the 
//waiting thread that an event has occured.
            AutoResetEvent objState =  new
AutoResetEvent(false);
//TimerCallback delegate represents the method that 
//handles the calls from a Timer object.
TimerCallback objTimerCallBack = new TimerCallback
(objCallBack.execTimer);
            Console.WriteLine("alarm application 
starting");
//The Timer class represents a mechanism for executing
//a method at specific intervals
Timer objTimer = new Timer(objTimerCallBack,objState,
5000,0);
            Console.WriteLine("waiting for alarm");
//WaitOne method blocks the current thread until the 
//current WaitHandle receives a signal.
            objState.WaitOne(-1,false);
                        objTimer.Dispose();
            Console.WriteLine("alarm application done");
        }
    }
    /// <summary>
    /// Class that has the method for executing the alarm.
    /// </summary>
    class CallBackClass
    {
        public void execTimer(Object stateInfo)
        {
            AutoResetEvent objAutoEvt = (AutoResetEvent) stateInfo;
            Console.WriteLine("Ring...Ring!");
            //Sets the state of the specified event to signaled.
            objAutoEvt.Set();
        }
    }
}

(Source File: N_Timers-UAMV4C7.01.cs)

The System.Timers namespace provides the Timer component, which allows you to raise an event on a specified interval.

The following example shows the raising of an event to process time intervals.

.NET example: Handling timer events with System.Timers

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

using System;
using System.Timers;
public class Timer1
{
     public static void Main()
    {
        System.Timers.Timer aTimer = new 
System.Timers.Timer();
        aTimer.Elapsed+=new ElapsedEventHandler
(OnTimedEvent);
        // Set the Interval to 5 seconds.
        aTimer.Interval=5000;
        aTimer.Enabled=true;
        Console.WriteLine("Press \'q\' to quit the sample.");
        while(Console.Read()!='q');
    }
     // Specify what you want to happen when the Elapsed
event is raised.
    private static void OnTimedEvent(object source, 
ElapsedEventArgs e)
    {
        Console.WriteLine("Hello World!");
    }
}

(Source File: N_Timers-UAMV4C7.02.cs)

Migrating Character-based User Interfaces

Not all UNIX-based interfaces are graphical. Character-based interfaces were the original mainstay of UNIX computing, long before the graphical workstation was developed. The character-based UIs can be replaced with a Windows Forms–based or HTML-based UIs using .NET.

Porting OpenGL Applications

OpenGL was originally developed by Silicon Graphics as a platform-independent set of graphics APIs. This has made OpenGL an attractive option for developers who want to target multiple platforms. The interface of the OpenGL library is standardized by specifications that are available publicly. New functionalities called OpenGL Extensions can also be added without updating the entire specification.

However, OpenGL is not a set of windowing libraries. An OpenGL application with windows uses either the windowing system of the target platform (X Windows or Win32) or a cross-platform library such as the OpenGL Graphics Library Utility Kit (GLUT). Because of licensing concerns, however, most commercial applications incorporate the target platform windowing system.

When moving a UNIX application that uses OpenGL to .NET, the .NET interoperability strategies are used. While migrating the OpenGL libraries using .NET interoperability mechanism, the migrated libraries are treated as unmanaged code. Some third-party open source .NET classes are available, which wrap access to OpenGL and allow .NET to act as a container to access OpenGL. Internally, these classes have used the interoperability mechanisms such as P/Invoke only. An example of this is the C# OpenGL library.

Note   More information on this library is available at
https://csgl.sourceforge.net/.
More information on OpenGL and platform-specific examples is available at
https://www.sgi.com/software/opengl/ and
https://www.opengl.org/.

Mapping X Windows Terminology to Windows Forms

The graphical models of UNIX and Windows are very different. There are conceptual similarities, but little side-by-side mapping is possible. The following sections describe the possible mappings.  

In the headings of the following sections, the Win32 GDI term is followed by the corresponding X Windows term in the following format: X Windows term vs. .NET term.

Callback vs. Event Handlers

Windows Forms uses the Event Handler functions in the same capacity as Callback in X Windows.

Client vs. Client Window

X Windows consists of a protocol that describes how a client interacts with a server that could be running on a remote computer. How objects are drawn is the responsibility of the server. This provides device-independence for the client application because it is not responsible for knowing anything about the physical hardware.

In the Windows environment, the Windows Forms provide a layer of device-independence and are not required to access the graphics hardware directly.

A single Windows-based application can contain any number of separate windows. Each of these windows can have a window frame, caption bar, system menu, minimize and maximize buttons, and its own main display area, which is referred to as the client window.

Multiple document interface (MDI) applications have three kinds of windows: a frame window, an MDI client window, and a number of child windows. The term "iclient window" takes on a special meaning in this case. iClient is special kind of an application with visualization, input ctrl, and local models.

Note   More information about MDI and the MDI documentation is available at
https://msdn2.microsoft.com/en-us/library/ms171654.aspx.

Console Mode vs. Command Window

If X Windows or some other GUI is not running on a UNIX system, a user must work in text only or in console mode.

Windows is exactly the opposite. If a console is not running, the user must work in GUI mode. Windows text-based mode is provided by running the Cmd.exe tool. This environment is also referred to as a command window or the MS-DOS prompt. To run the Cmd.exe tool, click Start, and then click Run. Type cmd, and then click OK. Alternatively, on the keyboard, press the Windows key and then press R. The Run dialog box appears.

DPI vs. Screen Resolution

When starting an X Windows session, using the -dpi (dots per inch) option can improve appearance on displays with larger resolutions, such as 1600 × 1200. The -dpi option also helps to work around possible font issues.

A Windows-based application is usually built with no assumptions about the capabilities of the system that the application will run on. The .NET Framework API provides various classes to access system and device-specific information. The properties of System.Windows.Forms.SystemInformation are used to retrieve system metrics and configuration settings. System.Drawing.Graphics properties and System.Drawing.Printing.PrinterSettings and System.Management classes are used to retrieve device-specific information for the specified device.

Graphics Context vs. Graphics Class Object

The X Windows graphics context (GC) contains required information about how drawing functions are to be executed. In .NET, the Graphics class object provides similar information. The Graphics class here is an encapsulation of the GDI+ drawing surface, which includes the Win32 device context (DC).  Table 7.9 lists X Windows graphic context and the corresponding Win32 device context.

Table 7.9. X Windows GC and Win32 DC Comparable Functions

Xlib

.NET Framework API

XtGetGC

To retrieve a Graphics class object, use any of the following:

System.Drawing.Graphics.FromHwnd(Windows.Forms.Control.Handle)

System.Drawing.Printing.PrintPageEventArgs.Graphics

System.Windows.Forms.PaintEventArgs.Graphics

To explicitly retrieve a handle, use the following:

System.Drawing.Graphics.GetHdc

XtReleaseGC

System.Drawing.Graphics.ReleaseHdc

Resources vs. Properties

In X Windows terminology, a widget is defined by its resources. Width, height, color, and font are examples of resources. Resources can be managed by using the XtVaCreateManagedWidget() method, by using resource files, or by using XtVaGetValues() and XtVaSetValues().

In Windows Forms terminology, a control is defined by its properties. For example, a text control has the following properties: Center Vertically, No Wrap, Transparent, Right-Aligned Text, and Visible.

Resource Files vs. Configuration Files

X Windows systems use configuration files, referred to as resource files, to store information about system settings or preferences for a particular X Windows client.

In .NET, these settings and preferences for applications are generally stored in application configuration files, which are in XML format. The following is a sample configuration file, which an application reads.

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="LabelColor" Value="Yellow" />
        <add key="MaximumWeight" Value="150" />
        <add key="Title" Value="MyApplication" />
      </appSettings>
    </configuration>

The configuration file should be in the same directory as the application. The name of the configuration file should be the same as the application, with .config at the end. For example, an application called MyApplication.exe should have a configuration file called MyApplication.exe.config.

Root Window vs. Desktop Window

All X Windows windows are descendents of the root window. In the Windows environment, the desktop window is a system-defined window that is the base for all windows displayed by all applications.

/bin vs. /System32

In Windows, the /System32 directory is roughly equivalent to the /bin directory on a UNIX system. This is where the system executable files are located. The /System32 directory is located in the system root directory. To find the system root, type set at the command prompt and press ENTER. This displays a listing of the current environment. In the list, locate SYSTEMROOT. Under SYSTEMROOT, there is an entry similar to SYSTEMROOT=C:\WINNT. This is the system directory and under that directory is the /System32 directory.

/usr/bin vs. Program Files

The Program Files directory on a Windows-based system is similar to the /usr/bin directory on a UNIX system. This is the default location for user applications. In Windows, a user can create more than one such directory. Each drive, for example, might have a Program Files directory. The system environment variable, ProgramFiles, contains the path of one default location. For example, ProgramFiles=C:\ProgramFiles.

/usr/lib vs. LIB Environment Variable

In Windows, the path to user libraries can be anywhere. To manage this relationship, retrieve or set the system environment variable LIB.

/usr/include vs. INCLUDE Environment Variable

In Windows, the path to user include files can be anywhere. To manage this relationship, retrieve or set the system environment variable INCLUDE.

Pixmap or Bitmap vs. Bitmap

In X Windows, bitmap and pixmap have the same use as Windows bitmaps. For example, they can be used as pictures, fill patterns, icons, and cursors. They are, however, very different in form.

The following example represents a simple 16 × 16 "X" figure in X Windows.

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

#define simple_width 16
#define simple_height 16
static unsigned char simple_bits[] = {
    0x01, 0x80, 0x02, 0x04, 0x20, 0x08, 0x10, 0x10,
    0x08, 0x20, 0x04, 0x40, 0x02, 0x80, 0x01, 0x80,
    0x01, 0x02, 0x20, 0x04, 0x10, 0x08, 0x08, 0x10,
    0x04, 0x20, 0x02, 0x40, 0x01, 0x80 
};

The following example represents a simple 16 × 16 "X" figure in Windows.

000000

 

42

4D

7E

00

00

00

00

00

00

00

3E

00

00

00

28

00

000010

 

00

00

10

00

00

00

10

00

00

00

01

00

01

00

00

00

000020

 

00

00

40

00

00

00

CA

0E

00

00

C4

0E

00

00

00

00

000030

 

00

00

00

00

00

00

00

00

00

00

FF

FF

FF

00

7F

FE

000040

 

00

00

BF

FD

00

00

DF

FB

00

00

EF

F7

00

00

F7

EF

000050

 

00

00

FB

DF

00

00

FD

BF

00

00

FE

7F

00

00

FE

7F

000060

 

00

00

FD

BF

00

00

FB

DF

00

00

F7

EF

00

00

EF

F7

000070

 

00

00

DF

FB

00

00

BF

FD

00

00

7F

FE

00

00

 

 

Window Manager vs. Windows Server 2003 and Windows XP

A special kind of X Windows client called the Window Manager provides a consistent working environment in the root window.

In a Windows environment, the operating system itself is the window manager and provides the desktop window. When a user logs on, the system creates three desktops within the WinSta0 windows station.

Note   For additional information, search for "WinSta0" on the MSDN Web site at
https://msdn.microsoft.com/.

Widgets are usually represented as controls in Windows Forms–based applications. Like the X Windows environment, Windows Forms offers many widgets. For example, X Windows dialog boxes are widgets. In Windows Forms, however, dialog boxes are not considered controls, although objects such as dialog boxes, buttons, and scroll bars are all windows.

X Library [Xlib] [X11] vs. Drawing Namespace

The X Windows library [Xlib][X11] is the lowest level library. Like the System.Drawing namespace, it provides all the basic drawing functions.

X Toolkit [Intrinsics] [Xt] vs. Windows Forms

The X Toolkit (Xt) is a library that accesses the lower-level graphics functionality of Xlib (X Windows) and provides UI elements such as menus, buttons, and scroll bars. It is similar to Windows Forms, which provides all the UI elements in the .NET environment.

Mapping X Windows Tools to Microsoft Windows

The primary tools for .NET development are the .NET Framework SDK and Visual Studio .NET. If Visual Studio .NET is installed in the default location, tools are found in DriveLetter:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools. Help provides information on these tools.

Note   In some cases, the X Windows tool and the Windows tool have the same name but do not perform the same function. The bitmap tool is an example.

Bitmap vs. Mspaint.exe

In Visual Studio .NET, you can use the forms designer to create and edit bitmaps and icons. You can also use Mspaint.exe to edit bitmaps. This tool is found in the /System32 directory.

Manual Pages vs. Help

UNIX provides online documentation, which explains commands and procedures, in the form of manual pages. To access a particular manual page, type man command_name at the shell prompt.

Windows systems use the commands help and help CommandName. The Windows Help provides a similar look and feel to man on UNIX systems. However, most of Windows Help is found on the Start menu under Help. Additionally, most, if not all, of the components of the Microsoft development environment (MSDN, compilers, Visual Studio .NET, and Word) provide topical help and context-sensitive help.

At a command prompt, type help and press ENTER to see a list of available commands. Typing help followed by the name of the command (for example, typing help setlocal) provides information about the specified command. Windows Advanced Server installations provide ntbooks.exe in the /System32 directory. This is an excellent Help resource for all Windows server commands.

xcalc vs. Calc.exe

The Calc.exe tool is the Windows calculator program. It is located in the /System32 directory and provides number base conversion between decimal, hexadecimal, and binary.

xclipboard vs. Clipbrd.exe

The Clipbrd.exe tool is found in the /System32 directory and provides the Windows Clipboard viewing, sharing, and saving functions.

xedit vs. Notepad.exe

The Notepad.exe tool is a simple text editor such as xedit. Notepad is located in the system root directory.

xev vs. Spyxx.exe

The Spyxx.exe tool provides functionality similar to that of xev. This tool allows selection of a window and filtering of desired events and messages. The Spyxx.exe tool is provided in the .NET Framework SDK and can be located at DriveLetter:\Program Files\Microsoft Visual Studio .NET\Common7\Tools.

xfd vs. Fontview.exe

The Fontview.exe command-line tool enables viewing of fonts. For example, the following command displays the Modern fonts.

fontview modern.fon

However, the Charmap.exe tool, a GUI tool located in the /System32 directory, is a much better choice for viewing and manipulating fonts in a graphical manner.

xkill vs. Kill.exe

The Win32 Kill.exe tool provides the same functionality as the X Windows xkill command. The Kill.exe tool is located in the /System32 directory.

When a user presses CTRL+ALT+DEL on a Windows-based system, a dialog box appears. Click the Task Manager button to display the Task Manager dialog box. To display the process ID (PID) of the currently running tasks, click the Processes tab in the Task Manager dialog box. Locate the errant process in the list and use that PID in the kill command, or click the process and then click End Process.

xlsclients vs. Pview.exe

Like xlsclients, the Pview.exe tool lists the current running applications. Pview is a GUI application that can be used to select the name of a computer to view.

xlsfonts vs. Fonts Control Panel Item

The Windows Control Panel Fonts item provides all font management functionality. For more information, refer to Fonts Help in the /System/Help Fonts.chm file.

xmag vs. Magnify.exe or Zoomin.exe

The Windows Magnify.exe tool is equivalent to X Windows xmag. Magnify is located in the /System32 directory on Windows 2000 and Windows XP.

xon vs. Start.exe or Remote.exe

Like the X Windows xon command, the Windows Start.exe tool starts a new command window to run a specified program or command.

xset client vs. Control Panel Items

Windows provides a GUI interface for managing the keyboard, the mouse, and the screen. Control Panel includes an item for managing each of these devices.

The Mode, Color, and Graftabl commands can be used to perform some device management. To see a list of features for these three commands, type help mode, help color, or help graftabl at the command prompt.

If a particular application requires advanced device control, that application must provide code to perform this required functionality. Use the SystemParametersInfo() function to set or retrieve system-wide parameters.

User Interface Coding Examples

The following examples show how to port an X Windows–based application to Windows:

  • X Windows "Hello World" example (including xHello.mak)

  • .NET "Hello World" example

X Windows "Hello World" Example

The following example demonstrates the "Hello World" code for X Windows.

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

/* 
** xHello.c
** One possible “Hello World” according to X11 
*/
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
char helloString[] = "Hello World";
int main( int argc, char **argv )
{
  int           iScreen;
  unsigned long ulForeground;
  unsigned long ulBackground;  
  Display      *pDisplay;
  Window        exampleWindow;
  GC            gc;
  XSizeHints    sizeHints;
  XWMHints      wmHints;
  XTextProperty textProperty;
  XEvent        xEvent;
  pDisplay         = XOpenDisplay( NULL );
  iScreen          = DefaultScreen( pDisplay );
  ulBackground     = WhitePixel( pDisplay, iScreen );
  ulForeground     = BlackPixel( pDisplay, iScreen );
  sizeHints.x      = 0;
  sizeHints.y      = 0;
  sizeHints.width  = 250;
  sizeHints.height = 30;
  sizeHints.flags  = ( PPosition | PSize );
  wmHints.flags    = InputHint;
  wmHints.input    = True;
  exampleWindow    = XCreateSimpleWindow( 
pDisplay,
DefaultRootWindow( pDisplay ),
sizeHints.x,
sizeHints.y,
sizeHints.width,
sizeHints.height,
2,
ulForeground,
ulBackground );
  XStringListToTextProperty( &argv[0],1,&textProperty );
  XSetWMName( pDisplay, exampleWindow ,&textProperty );
  XSetWMProperties( pDisplay, 
                    exampleWindow, 
                    &textProperty, 
                    NULL, 
                    NULL, 
                    0, 
                    &sizeHints, 
                    &wmHints, 
                    NULL );
  gc = XCreateGC( pDisplay, exampleWindow, 0,0 );
  XSetBackground( pDisplay, gc, ulBackground );
  XSetForeground( pDisplay, gc, ulForeground );
  XSelectInput( pDisplay, exampleWindow, ( KeyPressMask
| ExposureMask ) );
  XMapWindow( pDisplay, exampleWindow );
  do {
    XNextEvent( pDisplay, &xEvent );
    if ( xEvent.type == Expose ) {
      if ( xEvent.xexpose.count == 0 ) {
        XClearWindow( pDisplay, exampleWindow );
        XDrawImageString( pDisplay,
                          exampleWindow,
                          gc,
                          (sizeHints.width/10),
                          (sizeHints.height/2),
                          helloString,
                          (strlen( helloString )));
      }
    }
  } while (1); 
  exit( 0 ) ;
}

(Source File: U_UIExample-UAMV4C7.01.c)

The xHello.mak File

The following example shows the X Windows xHello.mak file used with the previous "Hello World" code.

CC = cc
INSTALL = ./
INCLUDES = -I/usr/X11R6/include
LIBS = -L/usr/X11R6/lib -lX11 -lXaw -lXt -lXext
OBJS = xHello.o
xHello : ${OBJS}
    ${CC} -o xHello ${OBJS} ${INCLUDES} ${LIBS}
clean:
    rm -fr *.o xHello

.NET "Hello World" Example

The following example demonstrates the corresponding "Hello World" code in C#.

Note: Some of the lines in the following code have been displayed on multiple lines for better readability.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowAppTest
{
        public class HelloWindowsForms : 
System.Windows.Forms.Form
        {
        //Label 1 displays the text message "Hello Windows
Forms!"
            private System.Windows.Forms.Label label1;
        //The constructor is where all initialization happens.
//Forms created with the designer have an 
//InitializeComponent() 
//method.
            public HelloWindowsForms()
            {
//Initializes the label that will display the Hello World text
                this.label1 = new 
System.Windows.Forms.Label();
//Sets the background color to black and the foreground 
//color to white
                this.BackColor = Color.Black;
                this.ForeColor = Color.White;
//Specifies the location of the label in the form            
                label1.Location = new System.Drawing.Point(8, 8);
                //Specifies the text of the label
                label1.Text = "Hello Windows Forms!";
                //Specifies the width and height of the label
                label1.Size = new System.Drawing.Size(408, 48);
//Specifies the font type and style that needs to be 
//used to display the text in the label
label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 24f);
                //Specifies the tab index of the label
                label1.TabIndex = 0;
                //Specifies the alignment of text in the label
                label1.TextAlign = ContentAlignment.MiddleCenter;
                //Specifies the Form title
                this.Text = "Hello World";
                //Disables the maximize property of the form
                this.MaximizeBox = false;
//Specifies the base size used for autoscaling of the form
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                this.FormBorderStyle = FormBorderStyle.FixedDialog;
                this.MinimizeBox = false;
                this.ClientSize = new System.Drawing.Size(426, 55);
                //Adds the label to the form
                this.Controls.Add(label1);
            }
        // This main function instantiates a new form and runs it.
            public static void Main(string[] args)
            {
                Application.Run(new HelloWindowsForms());
            }
        }
    } // end of namespace

(Source File: N_UIExample-UAMV4C7.01.cs)

Download

Get the UNIX Custom Application Migration Guide

Update Notifications

Sign up to learn about updates and new releases

Feedback

Send us your comments or suggestions