text: Creating Your Own Windows Applications Using Visual J++ and WFC
  Microsoft Corporation
  Updated March 11, 1998
  Introduction
  This article contains a brief overview of a simple Microsoft® 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 that 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, because 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 code for both these files at the end of this article.
  This application was designed and coded using the Visual J++ Designer and code editor. Much of the code was automatically generated by the Designer. This walkthrough demonstrates what the Designer does for you, the code that was added to the Designer-created code to create this application, and a few basic concepts for programming a Windows Foundation Classes for Java (WFC) application. Specifically, it describes:
  - Using the Visual J++ Designer to create the applications forms.
  - How to start and stop an application.
  - The anatomy of a Visual J++ form template.
  - How to handle events.
  - How to create a modal dialog box and retrieve user results.
  - How to use OpenFileDialog and SaveFileDialog classes to work with files.
  - How to use the File stream class for file input/output (I/O).
  Creating the Application Using Visual J++
  To begin, let's walk through the steps required to create this 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.
  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. Visual J++ creates a project with that name.
  The project contains a form called Form1.java by default, which we will rename to MyNotepad.java in a later step.
  Add Controls and Menus to the Form
  The Visual J++ Designer makes it easy to lay out 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 context menu). With the form displayed, you can add controls from the toolbox. To access the WFC controls in the toolbox, click the toolbox tab or choose Toolbox from the View menu. Click the WFC Controls button in the toolbox to display those controls. To set properties, use the Properties window.
  In this case, we added an edit control to the form from the toolbox, set the multi-line property in the Properties window to true, and resized the control to fill the form.
  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.
  Set Properties 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, we made the following changes to the default names:
  You may want to set other properties on the form and controls (these are too numerous to describe at this point). In MyNotepad, we left most with default values for the sake of simplicity. However, we did set the scrollBars property to Vertical and the font name property to Fixedsys in the editbox control to emulate Notepad.
  Change the Name of Form1.java
  In this application, we wanted the main form to have the same name as the project instead of the name Form1.java. To do this, you select Form1.java in the Project Explorer, choose Rename from the context menu, and type the new name (in this case MyNotepad.java).
  If you do change the name of Form1.java for your projects, remember that you must change all occurrences of Form1 in the source code. To do this, open the source by choosing View Code from the context menu. Then choose Find and Replace from the Edit menu and replace all instances of Form1 with the new name (for example, replace Form1 with MyNotepad).
  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, we added three buttons and named them YesButton, NoButton, and CancelButton, with appropriate labels (&Yes, &No, and &Cancel).
  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, we set the acceptButton property to YesButton. The Form class also has a cancelButton property that determines which button to click when the ESC key is pressed; we set this to cancelButton.
  Likewise, we used accelerator (&) characters in the button labels to map a specific key to each button (for example, because the label for the YesButton button is "&Yes", pressing Y clicks this button).
  We then added the two label controls and set the text properties to display the message text. Finally, we added the PictureBox control and set the image property to a bitmap that contained an exclamation graphic.
  Because we added an image to the form, a resource file (called NewDialog.resources) is created when we save the form. All resources are serialized to this file. This also occurs if you set the localizable property of a form to true. This provides a mechanism for localizing the form to different languages. Essentially, you lay out the form in the language you want to localize in and then rename the resource file (such as Form1_jpn_jpn.resources for Japanese) when you are finished.
  Starting and Stopping an Application
  The wfc.app package includes the static Application class, which handles all the window's registration and instantiation, message looping, and so on. A window is created by calling the Application.run() method and passing it the Form object that makes up the visual aspect of the window. This call occurs in the main() method in the Form class generated by Visual J++. Here is what was generated for the MyNotepad application:
  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 (handling menu click events is discussed a little later):
  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 you to run your WFC applications the same as any Windows application.
  Anatomy of a Visual J++ Form Template
  A basic WFC form is a public class extending the Form class with a default constructor, a main() method, and an initForm() method. When the Form class is instantiated, the class constructor calls the initForm() method. This is where the Designer puts all the code used to initialize the form and control properties. Other constructor code specific to your application follows this. 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). Here is the constructor for the MyNotepad application:
  The Visual J++ 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:
  /** *() { . . .
  The Visual J++ 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 Designer, which can generate event handler mappings in the initForm() method.
  The first two statements in the initForm() method demonstrate how the Designer sets properties on an object (in this case setting the menu item Text property to "&New") and establishes an event handler for the object using the object's addOnClick() method.
  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 Designer makes it easy to create the skeleton event handlers for events and hook these up to the controls. For example, to add a handler method for menu click events, you just double-click the menu item on the form. The Designer then adds a skeleton event handler method to your form's class and inserts an addOnClick() call for the appropriate MenuItem class in initForm().
  For example, when you click a menu item named FileMenuNew, the following line is added to initForm(), and a method called FileMenuNew_click() is added to your class.
  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 EventHandler object monitors mouse clicks on the MenuItem object and calls the appropriate handler when they occur. This is the model for all event handling in WFC and is based on a new object called a Delegate. All EventHandler objects are Delegates; most WFC programmers need know little or nothing about Delegates because event handlers already exist in the WFC packages for the events they care about.
  Here is the event handler in MyNotepad that handles button clicks for this particular menu item:"); } } }
  Of course, the Designer creates just the skeleton event handler. The code, which opens a custom modal dialog box, was added by hand. In the next section, we'll look at the process of creating a modal dialog box demonstrated by this code.
  While double-clicking a button or a menu item directly produces the OnClick event handlers, you can just as easily create handler skeleton code for other events by using the Events tab (the lightning symbol) in the Properties window.
  For example, in MyNotepad we wanted to make sure the edit control was resized whenever the form was resized. To create the event handler for the form's resize event, we located the resize event in the Properties window, double-clicked it, and the MyNotepad_resize method was automatically added to the source:
  Also, this line of code was added to the initForm() method.
  Using a Modal Dialog Box
  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 asks the user if they want to save the text. If the user clicks the Yes button, the FileMenuSaveAs_click method is called, which contains code that 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 is changed.
  In the FileMenuNew_click() method listed previously, the invocation of this dialog box and retrieval of the dialog result is done in one line as follows:
  While the modal dialog box is open, the dialog result value can be set from within the dialog form by calling the setDialogResult() method with an integer value. The DialogResult class contains integer constants used for this purpose.
  For example, in the NewDialog class, each button click event handler (such as YesButton_click) sets the dialog result by calling the setDialogResult() method with an appropriate DialogResult constant (such as 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 compared to DialogResult constants.
  Here is the button click event handler for the Yes button in NewDialog:
  You can also use a message box instead of a custom modal dialog box for simple cases. The About MyNotepad menu item on the Help menu uses a MessageBox object as follows:
  Using 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. First, here's a brief summary of the WFC classes used for doing all of this.
  In the WFC class hierarchy, both the wfc.ui.OpenFileDialog and wfc.ui.SaveFileDialog classes extend 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 run() method. These dialog boxes enable users to choose a file name for opening or saving a file.
  The 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 MyNotepad, 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 presented below."); } }
  When a user clicks Open on the File menu, the FileMenuOpen_click() event handler method is called. First, an OpenFileDialog object is created, and then the filters, options, and extensions used by the Open File dialog box are set. Finally, the OpenFileDialog.run() method is called to open the dialog box. When the dialog box closes, this method returns true if the user clicks the OK button and false if the user clicks the Cancel button. If OK is 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 File (filename, options) constructor and passing it file access options of File.OPEN | File.READ| File.WRITE.
  In Conclusion
  A brief tutorial such as this cannot hope to cover every concept of a useful application, even one as simple as Notepad. However, the concepts of event handling, working with dialog boxes, and simple file I/O are common to most applications, and so have been the main focus of this article.
  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 principles 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 wfc.io and 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 that MyNotepad 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 complete, you should be well on your way to creating your own Windows applications using Visual J++ and WFC.
  Code Listings
  The code for the two form-based classes in MyNotepad is listed below.
  - MyNotepad.java
  - NewDialog.java
  MyNotepad.java
  /******************************************************************* MyNotepad.java This sample is provided as a companion to the tutorial on the web site. Read the MyNotepad Sample Walkthrough in conjunction with this sample. ********************************************************************/ import wfc.app.*; import wfc.core.*; import wfc.ui.*; import wfc.io.*; public class MyNotepad extends Form { private File m_CurrentDoc; // the I/O File stream private String m_Filename; // the most recently-used filename private boolean m_FileOpen = false; // set true after first file is opened. private void HelpMenuAbout_click(Object sender, Event e) { MessageBox mBox = new MessageBox(); mBox.show("Version: Visual J++ Technology Preview 1 ", "MyNotepad"); }"); } } private void FileMenuSave_click(Object sender, Event e) { // If there has been a file opened or saved if (m_FileOpen){ // Open the current file again m_CurrentDoc = File.open(m_Filename); // Write edit control contents to file m_CurrentDoc.writeStringCharsAnsi(editbox.getText()); // Close file handle m_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 (m_Filename); sfd.setTitle("Save Text File"); sfd.setFilter("Text Documents (*.txt)|*.txt|All Files (*.*)|*.*"); sfd.setOptions(sfd.getOptions() | FileDialog.HIDEREADONLY); sfd.setDefaultExt("txt"); // Run the dialog box boolean m_OK = sfd.run(); if (m_OK) { // Retrieve the filename entered in the dialog box m_Filename = sfd.getFilename(); // Open a File stream with the ability to create a file if needed m_CurrentDoc = new File(m_Filename, File.OPEN_OR_CREATE | File.WRITE); // Write the contents of the edit control to the file m_CurrentDoc.writeStringCharsAnsi(editbox.getText()); // Close the file handle m_CurrentDoc.close(); m_FileOpen = true; // Set the app's caption using the filename minus its path this.setText(File.getName(m_Filename) + " - MyNotepad"); } } private void FileMenuExit_click(Object sender, Event e) { this.FileMenuNew_click(sender, e); Application.exit(); } private void MyNotepad_resize(Object sender, Event e) { editbox.setSize (this.getClientSize ()); } public MyNotepad() { // Required for Visual J++ Form Designer support initForm(); // TODO: Add any constructor code after initForm call this.setBounds(100, 100, 300, 300); this.setText("Untitled - MyNotepad"); } /** * 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()); } /** *() { 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}); /* @designTimeOnly Menu.setLocation(new Point(0, 0)); */ this.setBackColor(Color.CONTROL); this.setLocation(new Point(0, 0)); this.setSize(new Point(310, 361)); this.setTabIndex(-1); this.setTabStop(true); this.setText("MyNotepad"); this.setAutoScaleBaseSize(13); this.setClientSize(new Point(302, 314)); this.setMenu(Menu); this.addOnResize(new EventHandler(this.MyNotepad_resize)); editbox.setBackColor(Color.WINDOW); editbox.setCursor(Cursor.IBEAM); editbox.setFont(new Font("Fixedsys", -11, 400, false, false, false, 0, 0)); editbox.setLocation(new Point(0, 0)); editbox.setSize(new Point(300, 310)); editbox.setTabIndex(1); editbox.setTabStop(true); editbox.setText(""); editbox.setMultiline(true); editbox.setScrollBars(ScrollBars.VERTICAL); this.setNewControls(new Control[] { editbox}); } // NOTE: End of form designer support code public static class ClassInfo extends Form.ClassInfo { // TODO: Add your property and event infos here } }
  NewDialog.java
  // NewDialog.java import wfc.app.*; import wfc.core.*; import wfc.ui.*; /** * This class can take a variable number of parameters on the command * line. Program execution begins with the main() method. The class * constructor is not invoked unless an object of type 'NewDialog' * created in the main() method. */ public class NewDialog extends Form { private void CancelButton_click(Object sender, Event e) { // Set the dialog result appropriately this.setDialogResult(DialogResult.CANCEL); // Remove the dialog window this.dispose(); } private void NoButton_click(Object sender, Event e) { // Set the dialog result appropriately this.setDialogResult(DialogResult.NO); // Remove the dialog window this.dispose(); } private void YesButton_click(Object sender, Event e) { // Set the dialog result appropriately this.setDialogResult(DialogResult.YES); // Remove the dialog window this.dispose(); } public NewDialog() { // Required for Visual J++ Form Designer support initForm(); // TODO: Add any constructor code after initForm call } /** * 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.runDialog(new NewDialog()); } /** * NOTE: The following code is required by the Visual J++ form * designer. It can be modified using the form editor. Do not * modify it using the code 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() { ResourceManager resources = new ResourceManager(this, "NewDialog"); label1.setLocation(new Point(90, 20)); label1.setSize(new Point(210, 20)); label1.setText("The text in the file may have changed."); label1.setTabIndex(0); label2.setLocation(new Point(90, 40)); label2.setSize(new Point(190, 20)); label2.setText("Do you want to save the changes?"); label2.setTabIndex(1); YesButton.setLocation(new Point(20, 90)); YesButton.setSize(new Point(80, 30)); YesButton.setTabIndex(2); YesButton.setTabStop(true); YesButton.setText("&Yes"); YesButton.addOnClick(new EventHandler(this.YesButton_click)); NoButton.setLocation(new Point(110, 90)); NoButton.setSize(new Point(80, 30)); NoButton.setTabIndex(3); NoButton.setTabStop(true); NoButton.setText("&No"); NoButton.addOnClick(new EventHandler(this.NoButton_click)); CancelButton.setLocation(new Point(200, 90)); CancelButton.setSize(new Point(80, 30)); CancelButton.setTabIndex(4); CancelButton.setTabStop(true); CancelButton.setText("&Cancel"); CancelButton.addOnClick(new EventHandler(this.CancelButton_click)); this.setBackColor(Color.CONTROL); this.setLocation(new Point(0, 0)); this.setSize(new Point(305, 163)); this.setTabIndex(-1); this.setTabStop(true); 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.setImage((Bitmap)resources.getObject("pictureBox1_image")); this.setNewControls(new Control[] { pictureBox1, CancelButton, NoButton, YesButton, label2, label1}); } // NOTE: End of form designer support code public static class ClassInfo extends Form.ClassInfo { // TODO: Add your property and event infos here } }