Introduction to WFC Programming

 

Microsoft Corporation

July 13, 1998

Introduction

Windows Foundation Classes for Java (WFC) is a set of class libraries that works seamlessly with the Rapid Application Development (RAD) tool Visual J++™. The combination of this class framework and RAD tool make it easy to build fast and powerful applications and components for the Microsoft platform using the Java language. WFC brings the Java language to the Win32 platform and the Dynamic HTML (DHTML) object model, which is a W3C standard supported by Internet Explorer 4.0. This means you can use Java to solve real problems today and know that you have a smooth migration path into the future.

A goal of WFC is to provide complete and compelling component and programming models for Java. Because Java provides a unique set of advantages in terms of language features, it is the language of choice for developing Windows® and DHTML applications using this new programming model.

WFC enables developers to quickly build rich Win32 applications and ActiveX® controls in Java by using the Visual J++ Forms Designer to drag and drop controls onto a form, set properties, and generate event handlers. Developers can also easily access data on a server from their applications and deploy their applications as Windows .exe files or Internet URLs. Moreover, they can build their own WFC components by using the designer or writing code directly in the editor. Finally, developers can access the DHTML object model using Java classes.

The rich application model takes advantage of the J/Direct™ technology to access the Win32 API. However, this model makes it much easier to program by taking care of details like Window message-handling procedures, message pumps, messages, window handles, and so forth. The application model is open, so experienced Win32 programmers can intermix J/Direct calls with WFC classes to add any functionality available on the Win32 platform.

If you are looking for a quick "hands-on" introduction to using Visual J++ to develop a WFC application, take a few minutes to walk through Creating a Windows Application with WFC, which steps you through building and running a simple WFC application.

Getting Started with Controls and Templates

One of the strengths of the WFC component model is that the Visual J++ development environment provides most of the components, forms, menus, and dialog boxes that you typically need. These components can either be extended for your own needs or you can author your own controls. Because Visual J++ provides controls typically used in the Win32 environment, you'll feel at home with the visual components available from the Visual J++ design environment.

The Visual J++ development environment is tightly integrated with the WFC classes, so most of what you need to know to get started using controls, forms, and menus can be found in Using Visual J++.

Starting with a Form

Most application windows are represented in WFC programming as forms. A form is used wherever you want a separate overlapping, graphical component, such as a main application window or dialog box. Forms act as containers for controls, allowing you to visually compose applications. Forms have their own properties, which can be set in the Properties window. Syntactically, a form is a Java class derived from the com.ms.wfc.ui.Form class. The Form class extends the com.ms.wfc.ui.Control class, as do the controls that you place on a form. Control encapsulates a Win32 window.

When you create a new project and choose Windows Application from the New Projects dialog box, a form is automatically created for you. You can add other forms by choosing either Add Item or Add Form from the Project menu.

Once a form is added to your project, the form can be viewed either in design mode or in the Text editor. You can use the Forms Designer to size it and set properties by choosing View Designer from the shortcut menu of the form in Project Explorer. Each form belongs to a nonvisual Application object that contains the main thread of the application. Forms and controls represent the visual Windows components. The integration of the visual and nonvisual aspects of the window is handled completely by WFC framework.

When you open the Text editor on a new form, you'll see the template-based class created for you that contains the necessary syntax of the Form class, including a constructor and a main() method with code that instantiates your form. When you work in design mode, adding controls, setting properties, and so forth, the Forms Designer inserts and modifies a section of this class.

Adding Controls

Controls are added by dragging them from the Toolbox onto the form, sizing them, and setting their properties in the Properties window. You can drag and drop both ActiveX and WFC controls onto your forms in Visual J++.

WFC controls can be grouped into three categories, although there is no distinction between categories in the way you use them:

  • Intrinsic controls. The basic Windows controls such as buttons, check boxes, edit boxes, list boxes, and so on.
  • Common controls. The Win32 common controls found in comctl32.dll. These include controls such as animations, toolbars, tabs, status bars, and Tree view controls.
  • WFC controls. Custom controls written specifically for the WFC framework.

All existing WFC controls are Java classes found in the com.ms.wfc.ui package.

If you want, you can create your own controls using the WFC packages, either by extending existing controls or writing your own from scratch, and adding them to the Toolbox. The WFC component model makes it easy to expose information about your control's properties and events, enabling your control to work seamlessly with the Visual J++ Forms Designer.

Adding Menus

Menus are added in a manner similar to controls and appear in the Toolbox as simply another control. To add a menu, you drag the MainMenu control from the Toolbox onto the form. Once the menu is enabled on the form, the Forms Designer lets you add submenus and menu items by simply typing them in. Each menu item has an event handler that can be hooked up in the coding phase of development. And, as with controls, all implementation code for the menus and menu items is created automatically for you as you visually create the menu.

Adding Code

The Forms Designer helps you to create your initial form class and even provides much of the skeleton code for things like event handlers. However, at some point you need to actually write code to make your application do what you want it to.

Event handler methods are called when an event is triggered from a user-interface element on the form, such as a mouse click on a control. The Forms Designer creates skeleton code for these, so it's mostly a matter of filling in the code you want run when the event occurs. The WFC component model employs a new delegate keyword in the Visual J++ compiler that is the basis of all event handling. While delegates are transparent when using the Forms Designer to hook up handlers for events, they can be used directly for more advanced scenarios, such as sourcing your own events. Since they are essentially the same as a function pointer in other languages, they are useful in a number of ways.

In addition to controls and event handlers, there are many other parts of the WFC library that you will find useful.

  • Graphics support. Several classes in the com.ms.wfc.ui package, including the Graphics class, provide support for accessing Windows graphical services.
  • Dynamic HTML support. The com.ms.wfc.html package provides an extensive set of classes that provide access to the DHTML object model implemented by Internet Explorer (versions 4.0 and later).
  • Data binding support. WFC is designed to use the ActiveX Data Objects (ADO) components to support both simple and complex data binding. Using the DataBinder component, you can bind a field from a recordset to the property of any WFC component. WFC also provides other complex-bound components that interact directly with a recordset.
  • Localization support. WFC provides support for localizing your code more easily by letting you store resource elements, such as strings, fonts, and bitmaps, in a resource file matching a specific international locale. This simplifies the job of translating user interfaces for multiple languages.
  • Direct Win32 API support. The J/Direct technology provided with Visual J++ enables you to call any dynamic-link library (DLL) from your Java code. WFC is built upon a layer of J/Direct calls to Win32 libraries (implemented in the com.ms.wfc.Win32 and com.ms.wfc.OLE32 packages). Consequently, if you are comfortable with standard Windows programming and want to access those libraries directly, WFC provides the underlying elements (such as device contexts and window handles) to give you ultimate control. While this may be desirable for some specialized applications, most programmers will find the basic services of WFC sufficient.

A Sample Walkthrough

This section contains a brief overview of a simple Visual J++ application called MyNotepad, which is based on the Windows Notepad application. MyNotepad is a Text editor with a File menu containing New, Open, Save, Save As, and Exit menu items. It covers the most primitive functions of an editor, allowing the user to open a file, edit it, and save it to the same file or to a different file.

**Note   **this application is similar to the JPad application generated using the Visual J++ Application Wizard. However, MyNotepad was not constructed using the Application Wizard; it was written specifically to demonstrate a few basic concepts as clearly as possible. After walking through MyNotepad, the code generated by the Application wizard should be much easier to understand, since it uses most of the same principles.

MyNotepad is essentially a single form (MyNotepad.java) with an edit control and a menu. A second form (NewDialog.java) represents the modal dialog box that prompts the user to save when opening a new file or closing the current file. You can find a complete listing of the codevjconCodeListings for both these files at the end of this article.

This application was designed and coded using the Visual J++ Forms Designer and Text editor. Much of the code was automatically generated by the designer. This walkthrough describes what the Forms Designer does for you, the code automatically generated by the designer to create this application, and a few basic concepts for programming a WFC application. Specifically, it describes:

  • Using the Forms Designer to create the applications

    formsvjconCreatingApplicationUsingVisualJ

  • How to start and stop an application

    vjconStartingStoppingApplication

  • The anatomy of a Visual J++ Form template

    vjconAnatomyOfVisualJFormTemplate

  • How to handle events

    vjconHandlingEvents

  • How to open a modal dialog box and retrieve user results

    vjconImplementingModalDialogBox

  • How to use OpenFileDialog and SaveFileDialog classes to work with files

    vjconImplementingFileDialogBoxesFileIO

  • How to use the File stream class for file input/output (I/O)

    vjconImplementingFileDialogBoxesFileIO

The Sample Walkthrough ends with:

  • Sample Walkthrough Summary

    vjconSampleWalkthroughSummary

  • Code Listings

Creating the Application Using Visual J++

This section walks through the steps required to create the MyNotepad application in Visual J++. It's helpful to look at the steps in the design environment before jumping into the code generated by the designer for those steps.

  1. Create the main form.

    To create the main form, use the New Project dialog box that appears when you first open Visual J++ or select New Project from the File menu. Select the Windows Application icon, type in the name of your application form (MyNotepad in this case), and choose Open, and Visual J++ creates a project with that name.

    The project contains a form called Form1.java by default, which will be renamed to MyNotepad.java in a later step.

  2. Add controls and menus to the form.

    The Visual J++ Forms Designer makes it easy to layout the form. To open the form in design mode, select Form1.java in the Project Explorer and then choose Designer from the View menu (or choose View Designer from the shortcut menu). With the form displayed, you can add controls from the toolbox. To access the WFC controls in the toolbox, click on the Toolbox tab or choose Toolbox from the View menu, and click the WFC Controls button in the toolbox to display those controls.

    For this sample, an edit control was added to the form from the toolbox.

    Adding a menu is just as easy: Drag the MainMenu control from the toolbox onto the form and place it anywhere; then begin typing in the first box and continue adding menu items in the boxes below or to the right.

    Note that you can create an accelerator key on the menu by entering an ampersand (&) before the desired character. This becomes underlined on the menu.

  3. Set properties on the form and controls.

    To set properties, use the Properties window. In this case, most properties were left with default values for the sake of simplicity. The following properties on the edit control were changed: the multiline property was set to true, the doc property to was set to Fill, the scrollBars property was set to Vertical, and the font name property was set to Fixedsys to better emulate Notepad. There may be other properties you'll want to set as well on the form and controls.

    You'll probably want to rename some of the components to make more sense programmatically. Renaming is done by selecting the form or control and setting the name property. In the case of MyNotepad, the following name changes were made:

Default Name New Name
Edit1 EditBox
MainMenu1 Menu
MenuItem1 FileMenu
MenuItem2 FileMenuNew
MenuItem3 FileMenuOpen
MenuItem4 FileMenuSave
MenuItem5 FileMenuSaveAs
MenuItem6 FileMenuExit
MenuItem7 HelpMenu
MenuItem8 HelpMenuAbout
  1. Change the name of Form1.java.

    You may want the main form to have a different name than Form1.java. To do this, select Form1.java in the Project Explorer, right-click and choose Rename from the shortcut menu, and type the new name (in this case, MyNotepad.java).

    If you do change the name, remember that you must change all occurrences of Form1 in the source code. To do this, first close the Forms Designer. Then open the source by choosing View Code from the shortcut menu. Choose Find and Replace from the Edit menu, and replace all instances of Form1 with the new name (for example, replace Form1 with MyNotepad).

  2. Create a dialog box.

    The NewDialog dialog box is just another form in the project. To create additional forms, choose Add Form from the Project menu, select Form in the Add Item dialog box, type the name of the new form (NewDialog.java, in this case) and click Open.

    In this case, three buttons were added and named YesButton, NoButton, and CancelButton, with appropriate labels (&Yes, &No, and &Cancel). The button control has a dialogResult property, which is useful when the buttons are used on a modal dialog. For example, if the YesButton control's dialogResult property is set to Yes and the user clicks this button, the dialog box closes and returns DialogResults.Yes. In this case, the dialogResult properties were set as follows:

Control dialogResult Property
YesButton Yes
NoButton No
CancelButton Cancel

One note of interest here is that the Form class has an acceptButton property that determines which button is clicked when the user presses ENTER. In this case the acceptButton property was set to the YesButton control. The Form class also has a cancelButton property that determines which button to click when the ESC key is pressed; this was set to the CancelButton control.

Likewise, the accelerator (&) characters in the button labels were used to map a specific key to each button (for example, because the label for the YesButton button is "&Yes", pressing Y clicks that button).

Two additional label controls were then added to display the message text of the dialog box. Finally, the PictureBox control was added to the form and that control's image property was set to a bitmap containing an exclamation graphic.

Because an image was added to the form, Visual J++ automatically created a resource file (called NewDialog.resources) and serialized the image to this file when the form was saved. The resource file provides a mechanism for localizing the form to different languages, although in this case it is mostly used for packaging. You can also set the localizable property of a form to true to cause a resource file to be added to your project, in which case all resources, including strings, are added to the resource file.

Starting and Stopping an Application

The com.ms.wfc.app package includes the static Application class, which takes care of all the Win32 window processing, such as registration, instantiation, handling the message loop, and so on. The main application window is created by calling the Application.run method and passing it your Form-derived object that makes up the visual aspect of the window. This call occurs in the main() method in the Form-based template class generated by Visual J++. The following code was generated for the MyNotepad application:

public static void main(String args[])
{
Application.run(new MyNotepad());
}

By default, the basic application created by a Visual J++ template is closed using the Window's exit (X) button in the top-right corner of the application. However, you can programmatically quit the application anywhere in the code by calling the Application.exit method. For example, this application is closed when Exit on the File menu is clicked:

private void FileMenuExit_click(Object sender, Event e)
{
// Call the new file handler to invoke NewDialog
// to ask if user wants to save current data. 
this.FileMenuNew_click(sender, e); 
Application.exit();
}

Having described the code that is invoked when an application is run, it is worth mentioning how a user runs your application. Visual J++ has rich deployment features, one of which is to create a Windows executable (.exe) file enabling users to run your WFC applications in a similar manner to other Windows application, assuming the WFC classes are installed on the user's computer. WFC classes are included with the latest Virtual Machine for Java which can be redistributed.

Anatomy of a Visual J++ Form Template

A basic WFC form is a public class extending the Form class with a default constructor and an initForm method. When the Form class is instantiated, the class constructor calls the initForm method, which is where the Forms Designer puts all the code used to initialize the form and control properties. Other code specific to your application follows the call to initForm in the constructor. In the MyNotepad application, the title for the application is set here (although it could have just as well been set in the form's Properties window). The constructor for the MyNotepad application is:

public MyNotepad()
{
// Required for Visual J++ Form Designer support.
initForm(); 
this.setBounds(100, 100, 300, 300);
this.setText("Untitled - MyNotepad");
}

The Visual J++ Forms Designer adds declarations for any added controls in the main body of the class just before the initForm method. For example, here are the declarations for the objects that make up the MyNotepad.java form:

/**
* NOTE: The following code is required by the Visual J++ Forms
* Designer. It can be modified using the Form editor. Do not
* modify it using the Text editor.
*/
Container components = new Container();
MainMenu Menu = new MainMenu();
MenuItem FileMenu = new MenuItem();
MenuItem FileMenuNew = new MenuItem();
MenuItem FileMenuOpen = new MenuItem();
MenuItem FileMenuSave = new MenuItem();
MenuItem FileMenuSaveAs = new MenuItem();
MenuItem FileMenuExit = new MenuItem();
MenuItem HelpMenu = new MenuItem();
MenuItem HelpMenuAbout = new MenuItem();
Edit editbox = new Edit();
private void initForm()
{
. . .

The Visual J++ Forms Designer creates this declaration code as well as the code in the initForm method that sets properties of the form and the controls placed on the form. The infrastructure for handling events is also tightly integrated with the Forms Designer, which can generate event handler mappings in the initForm method.

The first two statements in the initForm method demonstrate how the Forms Designer sets properties on an object (in this case setting the menu item Text property to "&New") and uses the object's addOnClick method to establish a click event handler for the object.

private void initForm()
{
FileMenuNew.setText("&New");
FileMenuNew.addOnClick(new EventHandler(this.FileMenuNew_click));

Handling Events

Most of the code in the MyNotepad application occurs in the event handler methods that are called when menu items are clicked. The Forms Designer makes it easy to create the skeleton event handlers for events generated by controls on the form. For example, to add a handler method for menu click events, you just double-click the menu item on the form. (While double-clicking directly on a button or a menu item produces the click event handlers, you can just as easily create handler skeleton code for other events by using the Events tab in the Properties window).

The Forms Designer then adds a skeleton event handler method, in which you can add code to your form's class, and inserts a MenuItem.addOnClick call for the appropriate MenuItem class in initForm.

For example, when you click on a menu item named FileMenuNew, the following line is added to initForm and a method called FileMenuNew_click is added to your class:

FileMenuNew.addOnClick(new EventHandler(this.FileMenuNew_click));

The MenuItem.addOnClick method takes an EventHandler object. The EventHandler object is created with a reference to the method to call when that menu item is clicked. Essentially, the MenuItem object monitors mouse clicks and calls each event handler added to it, using the delegate, when the event occurs.

All event handler objects are delegates; the difference between them is the event object they pass to the handler. An EventHandler delegate passes an Event object, which contains information about the event. But a KeyEventHandler, for example, passes a KeyEvent object that extends Event for keydown and keyup events. (KeyEvent contains an extra field specifying the UNICODE character and whether it was combined with a CTRL, SHIFT, or ALT key.)

Most WFC programmers need to know little about delegates because event handlers already exist in the WFC packages for the events they care about and the code to add them is generated by the Forms Designer for the most part.

The following is the event handler in the MyNotepad application that handles the selection of this particular menu item:

private void FileMenuNew_click(Object sender, Event e)
{
// If edit control contains text, check if it should be saved.
if (editbox.getText().length() != 0) { 
// Open NewDialog class as a modal dialog.
int result = new NewDialog().showDialog(this); 
// Retrieve result. 
// If Yes button was clicked open Save As dialog box.
if (result == DialogResult.YES)
this.FileMenuSaveAs_click(sender, e);
// If No button was clicked clear edit control and set title.
else if (result == DialogResult.NO) {
editbox.setText("");
this.setText("Untitled - MyNotepad");
}
} 
}

Of course, the Forms Designer creates just the skeleton event handler. The code that opens the custom modal dialog box was added manually.

Implementing a Modal Dialog Box

In the MyNotepad application, when a user clicks New on the File menu, the code in this event handler determines if there is text in the edit control. If so, it opens a modal dialog box that displays a message asking the user if they want to save the text. If the user clicks the Yes button, the MyNotepad.FileMenuSaveAs_click method is called, which allows the user to choose a file and save the current text. If the user clicks No, the edit control is cleared, and the title displayed on the main form becomes "Untitled – MyNotepad."

In the FileMenuNew_click method, the invocation of this dialog box and retrieval of the dialog result is done in one line as follows:

int result = new NewDialog().showDialog(this); 

While the modal dialog box is open, the dialog result value can be set from within the dialog form. The DialogResult class contains integer constants used for this purpose, but any integer can be returned. The button's dialogResult properties were used in this case, which accomplishes the same purpose of setting the DialogResult value.

As an example, clicking the yesButton control sets DialogResult.Yes. This result is then returned from the showDialog method in the owner class when the dialog box is closed. The integer result returned by showDialog is then used to determine what action to take.

The NewDialog.java form was created as a new form using the same Form template used by the main application form. Note the main() method is not required for modal dialog boxes and was removed from this example (leaving it in does not cause errors, but is not considered good practice). Also, extraneous template comments for this method were removed.

Using a Message Box as a Modal Dialog Box

You can also use a message box instead of a custom modal dialog box for simple cases. The click event handler for the About MyNotepad menu item on the Help menu uses a MessageBox object as follows:

private void HelpMenuAbout_click(Object sender, Event e)
{
MessageBox.show("Version: Visual J++ 6.0", "MyNotepad");
}

Implementing File Dialog Boxes and File I/O

The remaining code of interest in this application has to do with file I/O and using File Open and File Save dialog boxes. It demonstrates how the WFC classes simplify the job of locating, opening, reading from, and writing to files. The following is a brief summary of the WFC classes used for doing this.

In the WFC class hierarchy, both the com.ms.wfc.ui.OpenFileDialog and com.ms.wfc.ui.SaveFileDialog classes extend com.ms.wfc.ui.FileDialog. FileDialog extends CommonDialog, which is a wrapper for the Win32 common dialog API. All common dialogs are set up with properties such as setTitle and setFilter, and are run by calling the showDialog method. These dialog boxes enable users to choose a file name for opening or saving a file.

The com.ms.wfc.io package contains stream-based I/O classes. The File class, which extends DataStream, contains methods for file I/O. In the case of the MyNotepad application, all that is needed is to open a file, read all of it into the edit control (or write the contents of the edit control to the file), and then close the file.

In the MyNotepad application, all I/O and file dialog code is in the event handler methods for the Open, Save, and Save As items on the File menu. We'll look at just one of these, the Open menu event handler, because it encapsulates the common dialog and File I/O functionality. The code for FileMenuOpen_click is:

private void FileMenuOpen_click(Object sender, Event e)
{
// Create an Open File dialog box. 
OpenFileDialog ofd = new OpenFileDialog();
// Set up filters and options.
ofd.setFilter("Text Docs (*.txt)|*.txt|All Files (*.*)|*.*");
ofd.setDefaultExt("txt");
// Run the Open File dialog box.
int OK = ofd.showDialog();
// Check result of dialog box after it closes.
if (OK == DialogResult.OK) {
// Retrieve the filename entered. 
fileName = ofd.getFileName();
// Open a File stream on that filename. 
currentDoc = File.open(fileName); 
// Retrieve the length of the file.
int ilength = (int)currentDoc.getLength();
// Read in ANSI characters to edit buffer.
editbox.setText(currentDoc.readStringCharsAnsi(ilength)); 
// Close the file handle.
currentDoc.close();
fileOpen=true;
// Set the application's caption. 
this.setText(File.getName(fileName) + " - MyNotepad");
}
}

When a user clicks Open on the File menu, the FileMenuOpen_click event handler method is called. The first three lines of code in this method create an OpenFileDialog object and set the filters and extensions used by the dialog box. While these lines are manually coded here, you can do the same thing using the Forms Designer by adding an OpenFileDialog object to the form and setting its properties (the initialization code is then placed in the initForm method).

Finally, the OpenFileDialog.showDialog method is called to open the dialog box. When the dialog box closes, this method returns an integer equivalent to DialogResult.OK if the user clicks the OK button, and DialogResult.Cancel if the user clicks the Cancel button. If OK was clicked, the file name is retrieved from the OpenFileDialog object and passed to the File.open method, which returns a File stream opened on the file as read/write access to the file. File.open is a utility function that does the same thing as creating a File object with the following constructor:

File(fileName, File.OPEN, FileAccess.READWRITE, FileShare.NONE);

Sample Walkthrough Summary

A brief tutorial such as this cannot hope to cover every concept of a useful application, even one as simple as the MyNotepad application. However, the concepts of event handling, working with dialog boxes, and simple file I/O are common to most applications, and have been the main focus.

In this walkthrough we haven't touched on the code in the event handlers for the Save and Save As menu items. However, this code uses the same principals discussed elsewhere, so there should be no surprises when you look at the listings.

It's noteworthy that besides java.lang, none of the other standard Java packages were used in this application. Instead, packages such as com.ms.wfc.io and com.ms.wfc.ui were used to access the underlying power of the Windows API. This provides immense performance and usability gains when you know that your target environment will be a Win32 operating system.

Keep in mind the MyNotepad application was written as a demonstration vehicle. To keep it short and to the point, it doesn't provide much error checking or many of the features of Notepad or even JPad. However, with this quick tour completed you should be well on your way to creating your own Windows applications using Visual J++ and WFC.

Code Listings

The following code listings are provided for the two form-based classes in the MyNotepad application:

  • MyNotepad.java

    vjconMyNotepadjava

  • NewDialog.java

MyNotepad.java

/*******************************************************************
MyNotepad.java
This sample is provided as a companion to the Introduction to WFC 
Programming topic in the Visual J++ documentation. Read the section 
titled MyNotepad Sample Walkthrough in conjunction with this sample.
********************************************************************/ 
import com.ms.wfc.app.*;
import com.ms.wfc.core.*;
import com.ms.wfc.ui.*;
import com.ms.wfc.io.*;
public class MyNotepad extends Form
{
private File currentDoc; // the I/O file stream 
private String fileName; // the most recently-used file name
private boolean fileOpen = false; // set true after file opened
public MyNotepad()
{
// Required for Visual J++ Forms Designer support.
initForm(); 
this.setBounds(100, 100, 300, 300);
this.setText("Untitled - MyNotepad");
}
private void HelpMenuAbout_click(Object sender, Event e)
{
MessageBox.show("Version: Visual J++ 6.0", "MyNotepad");
}
private void FileMenuNew_click(Object sender, Event e)
{
// If edit control contains text, check if it should be saved.
if (editbox.getText().length() != 0) { 
// Open NewDialog class as a modal dialog.
int result = new NewDialog().showDialog(this); 
// Retrieve result. 
// If Yes button was clicked open Save As dialog box.
if (result == DialogResult.YES)
this.FileMenuSaveAs_click(sender, e);
// If No button was clicked clear edit control and set title.
else if (result == DialogResult.NO) {
editbox.setText("");
this.setText("Untitled - MyNotepad");
}
} 
}
private void FileMenuOpen_click(Object sender, Event e)
{
// Create an Open File dialog box. 
OpenFileDialog ofd = new OpenFileDialog();
// Set up filters and options.
ofd.setFilter("Text Docs (*.txt)|*.txt|All Files (*.*)|*.*");
ofd.setDefaultExt("txt");
// Run the Open File dialog box.
int OK = ofd.showDialog();
// Check result of dialog box after it closes.
if (OK == DialogResult.OK) {
// Retrieve the filename entered. 
fileName = ofd.getFileName();
// Open a File stream on that filename. 
currentDoc = File.open(fileName); 
// Retrieve length of file.
int ilength = (int)currentDoc.getLength();
// Read in ANSI characters to edit buffer.
editbox.setText(currentDoc.readStringCharsAnsi(ilength)); 
// Close the file handle.
currentDoc.close();
fileOpen=true;
// Set the application's caption. 
this.setText(File.getName(fileName) + " - MyNotepad");
}
}
private void FileMenuSave_click(Object sender, Event e)
{
// If there has been a file opened or saved
if (fileOpen){
// Open the current file again.
currentDoc = File.open(fileName); 
// Write edit control contents to file.
currentDoc.writeStringCharsAnsi(editbox.getText());
// Close file handle.
currentDoc.close();
}
else
this.FileMenuSaveAs_click(sender, e);
}
private void FileMenuSaveAs_click(Object sender, Event e)
{
SaveFileDialog sfd = new SaveFileDialog();
// Set the options. 
sfd.setFileName (fileName);
sfd.setTitle("Save Text File");
sfd.setFilter("Text Docs (*.txt)|*.txt|All Files (*.*)|*.*");
sfd.setDefaultExt("txt");
// Run the dialog box. 
int result = sfd.showDialog();
if (result == DialogResult.OK ) {
// Retrieve the filename entered in the dialog box.
fileName = sfd.getFileName();
// Open a File stream with ability to create a file if needed.
currentDoc = new File(fileName, FileMode.OPEN_OR_CREATE);
// Write the contents of the edit control to the file.
currentDoc.writeStringCharsAnsi(editbox.getText());
// Close the file handle.
currentDoc.close(); 
fileOpen = true;
// Set the app's caption using the filename minus its path. 
this.setText(File.getName(fileName) + " - MyNotepad"); 
}
}
private void FileMenuExit_click(Object sender, Event e)
{
// Call the new file handler to invoke NewDialog
// to ask if user wants to save current data. 
this.FileMenuNew_click(sender, e); 
Application.exit();
}
/**
* NOTE: The following code is required by the Visual J++ Forms
* Designer. It can be modified using the Form editor. Do not
* modify it using the Text editor.
*/
Container components = new Container();
MainMenu Menu = new MainMenu();
MenuItem FileMenu = new MenuItem();
MenuItem FileMenuNew = new MenuItem();
MenuItem FileMenuOpen = new MenuItem();
MenuItem FileMenuSave = new MenuItem();
MenuItem FileMenuSaveAs = new MenuItem();
MenuItem FileMenuExit = new MenuItem();
MenuItem HelpMenu = new MenuItem();
MenuItem HelpMenuAbout = new MenuItem();
Edit editbox = new Edit();
private void initForm()
{
FileMenuNew.setText("&New");
FileMenuNew.addOnClick(new EventHandler(this.FileMenuNew_click));
FileMenuOpen.setText("&Open");
FileMenuOpen.addOnClick(new EventHandler(this.FileMenuOpen_click));
FileMenuSave.setText("&Save");
FileMenuSave.addOnClick(new EventHandler(this.FileMenuSave_click));
FileMenuSaveAs.setText("Save &As");
FileMenuSaveAs.addOnClick(new 
EventHandler(this.FileMenuSaveAs_click));
FileMenuExit.setText("E&xit");
FileMenuExit.addOnClick(new EventHandler(this.FileMenuExit_click));
FileMenu.setMenuItems(new MenuItem[] {
FileMenuNew, 
FileMenuOpen, 
FileMenuSave, 
FileMenuSaveAs, 
FileMenuExit});
FileMenu.setText("&File");
HelpMenuAbout.setText("&About MyNotepad...");
HelpMenuAbout.addOnClick(new 
EventHandler(this.HelpMenuAbout_click));
HelpMenu.setMenuItems(new MenuItem[] {
HelpMenuAbout});
HelpMenu.setText("&Help");
Menu.setMenuItems(new MenuItem[] {
FileMenu, 
HelpMenu});
this.setText("MyNotepad");
this.setVisible(false);
this.setAutoScaleBaseSize(13);
this.setClientSize(new Point(302, 314));
this.setMenu(Menu);
editbox.setDock(ControlDock.FILL);
editbox.setFont(new Font("Fixedsys", 8.0f, 
FontSize.POINTS, FontWeight.NORMAL, false, false, false,
CharacterSet.DEFAULT, 0));
editbox.setSize(new Point(302, 314));
editbox.setTabIndex(1);
editbox.setText("");
editbox.setMultiline(true);
editbox.setScrollBars(ScrollBars.VERTICAL);
this.setNewControls(new Control[] {
editbox});
}
/**
* The main entry point for the application. 
* @param args Array of parameters passed to the application
* via the command line.
*/
public static void main(String args[])
{
Application.run(new MyNotepad());
}
}

NewDialog.java

/*******************************************************************
NewDialog.java
This sample is provided as a companion to the Introduction to WFC 
Programming topic in the Visual J++ documentation. Read the section 
titled MyNotepad Sample Walkthrough in conjunction with this sample.
This form represents a simple modal dialog box.
********************************************************************/ 
import com.ms.wfc.app.*;
import com.ms.wfc.core.*;
import com.ms.wfc.ui.*;
public class NewDialog extends Form
{
public NewDialog()
{
// Required for Visual J++ Forms Designer support.
initForm(); 
}
/**
* NOTE: The following code is required by the Visual J++ Forms
* Designer. It can be modified using the Form editor. Do not
* modify it using the Text editor.
*/
Container components = new Container();
Label label1 = new Label();
Label label2 = new Label();
Button yesButton = new Button();
Button noButton = new Button();
Button cancelButton = new Button();
PictureBox pictureBox1 = new PictureBox();
private void initForm()
{
// NOTE: This form is storing resource information in an
// external file. Do not modify the string parameter to any
// resources.getObject() function call. For example, do not
// modify "foo1_location" in the following line of code
// even if the name of the Foo object changes: 
// foo1.setLocation((Point)resources.getObject("foo1_location"));
IResourceManager resources = new 
ResourceManager(this, "NewDialog");
label1.setLocation(new Point(90, 20));
label1.setSize(new Point(210, 20));
label1.setTabIndex(0);
label1.setTabStop(false);
label1.setText("The text in the file may have changed.");
label2.setLocation(new Point(90, 40));
label2.setSize(new Point(190, 20));
label2.setTabIndex(1);
label2.setTabStop(false);
label2.setText("Do you want to save the changes?");
yesButton.setLocation(new Point(20, 90));
yesButton.setSize(new Point(80, 30));
yesButton.setTabIndex(2);
yesButton.setText("&Yes");
yesButton.setDialogResult(DialogResult.YES);
noButton.setLocation(new Point(110, 90));
noButton.setSize(new Point(80, 30));
noButton.setTabIndex(3);
noButton.setText("&No");
noButton.setDialogResult(DialogResult.NO);
cancelButton.setLocation(new Point(200, 90));
cancelButton.setSize(new Point(80, 30));
cancelButton.setTabIndex(4);
cancelButton.setText("&Cancel");
cancelButton.setDialogResult(DialogResult.CANCEL);
this.setText("MyNotepad");
this.setAcceptButton(yesButton);
this.setAutoScaleBaseSize(13);
this.setCancelButton(cancelButton);
this.setClientSize(new Point(297, 136));
pictureBox1.setLocation(new Point(20, 20));
pictureBox1.setSize(new Point(50, 50));
pictureBox1.setTabIndex(5);
pictureBox1.setTabStop(false);
pictureBox1.setText("");
pictureBox1.setImage((Bitmap)resources.getObject
("pictureBox1_image"));
this.setNewControls(new Control[] {
pictureBox1, 
cancelButton, 
noButton, 
yesButton, 
label2, 
label1});
}
}