Introduction
Return to Introduction
Advansys Formativ 2.0
Developer's Guide

This Guide describes how to use Formativ™ to build business solutions based on Novell® GroupWise®. This guide is the definitive resource for developers who are creating custom solutions with Formativ and GroupWise.

The Formativ language is syntactically based on Microsoft Visual Basic® Scripting Edition (VBScript). If you know how to work with VBScript, you can build on your knowledge easily to customize Novell GroupWise. If you are not familiar with VBScript, this guide will get you started. However, you will still need to access the VBScript documentation to get the most out of the product.

Who Should Use This Guide?

This guide has been written for developers. Developers form a large and diverse group. We use the term developer to include someone who wishes to do something as simple as automatically type some text into a GroupWise message, or create a new button on a toolbar, through to someone who wishes to build complex vertical market solutions for GroupWise using Formativ.

This Guide is not for everybody. In order to cover the information required adequately, we have made assumptions about your level of knowledge. You may benefit from first using one of the excellent introductory resources mentioned later in this guide. Once you are happy that you have a sound grip of the basics, you can return to this Guide.

What Does This Guide Cover?

The purpose of this document is to guide you through the many facets of developing solutions using the Formativ environment. As the Formativ Applet language is based on Microsoft Visual Basic® Scripting Edition, we assume you are comfortable with VBS, and that you understand the concept of data types, variable scoping, functions and subroutines. We also assume you have a basic knowledge of the Novell GroupWise 5.5/6.x Windows client. If you are not comfortable with these topics, please refer to the appropriate resources before returning to this guide.

Copyright © 2001-2004 Advansys Pty Limited - All Rights Reserved
Formativ is a trademark of Advansys Pty Limited.
GroupWise is a trademark of Novell Inc.
Visual Basic is a trademark of Microsoft Corporation.


Code samples and style guide
This Guide contains code samples you can use to experiment with the concepts and ideas presented. This document and the applet samples that ship with Formativ use the following coding conventions:

· In full procedures, all variables are declared locally, or are listed with an initialization procedure that declares public variables.

· An apostrophe (') introduces a comment:

' This is a comment in the source code
Dim objMessage ' This is a comment on the same line as some source

· Control-flow blocks and statements in Sub and Function procedures are indented:

Sub Main(Client, GWEvent)
   Dim Msg
   Set Msg = GroupWise.ComposingItem
   If Msg is Nothing Then
      MsgBox("No composing item available")
   Else
      ' Insert your code here
      Set Msg = Nothing
   End If
End Sub

Note: Formativ Applets are case-insensitive. Capitalization of keywords, intrinsic functions, language elements and variable names is not required. However, we recommend you adopt a standard and apply it throughout your code.


History
Traditional GroupWise Development

Early versions of Novell GroupWise provided a macro-based development environment. Macros allowed users and developers alike to build both simple and complex solutions based on the GroupWise system. The macro paradigm was widely understood, and lent itself to a broad variety of solutions. Other programming interfaces were also available, but these required a much deeper understanding of the development process, and were beyond the capabilities of many people.

The advent of GroupWise 5.x brought about a new development approach for GroupWise. The macro/scripting capabilities of GroupWise 4.x were removed and replaced by several new COM-based programming interfaces, the Object API and the C3PO API. The ability to work at a token level was still available, using either another COM-based interface or the low-level TPH API. The functionality available in macros was still available, but developers now had to use a combination of API's and third- and fourth-generation languages to access the same functionality.

While GroupWise programmability remained rich, many developers believed it was difficult to develop GroupWise solutions. This was particularly true for developers who had experience developing for other collaboration products, such as Microsoft Outlook. Outlook shipped with an integrated development environment that allowed users to use industry standard Visual Basic to develop solutions. By comparison, in GroupWise even seemingly simple tasks such as adding a button to a toolbar required a knowledge of COM programming.

GroupWise Development using Formativ

Formativ lets developers create Applets for Novell GroupWise using a single, unified development environment. The Applets you write or record use a simple, yet powerful language that is 100% compatible with Visual Basic Scripting Edition (VBScript). VBScript is a powerful, easy to learn programming language, very similar to Visual Basic.

Formativ wraps and exposes the various traditional GroupWise programming API's with VBScript. This means that the entire GroupWise Object API, Administrative Objects API and Token Commander API's are all completely accessible from within the Applets you create. In addition, the majority of the Custom Third Party Objects (C3PO) API is accessible via Applets. Developers do not require any knowledge of these API's, or how they interact with each other when using Formativ. They are all presented as simple applet commands and functions.

Write A New Applet

You write a new applet within the Formativ development environment, which is tightly integrated with the GroupWise client. You do not need to own a third party development environment, such as Visual Basic, Delphi or Visual C++. Your Applets are written using Formativ's 100% VBScript-compatible language with extensions for GroupWise support. The Formativ environment includes a fully featured applet editor. Depending on configuration, your applet is either saved locally, or to a shared area where it can be accessed by many users.

Integrate the Applet with GroupWise

Once you have written and tested an Applet, it can be integrated with the GroupWise client. This means that you specify how and when the Applet is run. You can choose to add buttons to GroupWise toolbars that run your Applet, and you can add items to both standard and context menus that activate your Applet. You can also associate your Applet with many standard GroupWise events, such as on client start-up and on message send. In this way your Applet is automatically executed when that particular event occurs.

Distribute the Applet

Depending on your installation configuration, you may now distribute your new Applet. If you are an administrator, you can simply make your Applet and its integrations available to users via eDirectory®. When your users next start GroupWise, your Applet becomes available. If you have associated integrations with an Applet, they too become active. For example, your users may see a new button appear on a toolbar that runs an Applet. Configured in an appropriate manner, users are not aware they are running Applets – the new functionality in your Applet appears to be new functionality in GroupWise.

You can also distribute Applets manually.


Formativ Capabilities
You can use Formativ to provide an incredibly wide range of GroupWise solutions. Because Formativ makes use of all the major GroupWise programming interfaces, almost anything you might otherwise have developed using C++, Visual Basic or Delphi can now be developed using simple Applets – from within the GroupWise client!

· You can use Formativ as a simple tool to automate repetitive tasks. For example, you can write Applets to automate such tasks as opening a particular view, proxying to a different account or configuring the GroupWise client in a certain way.

· You can use Formativ to record Applets. You can use the Formativ Applet recorder to create new Applets. Simply start recording, perform some actions in GroupWise, stop recording, then play back or edit the automatically created Applet.

· Use the Formativ Portals facility to embed web-based content right inside the GroupWise client.

· Use Formativ to simplify the integration of your custom application or web service with GroupWise.

· You can use Formativ to add new functionality to the GroupWise client. For example, Search and Replace is a solution that ships with the Business Solutions Pack that adds search and replace capabilities to items that are being composed. When this Applet is added to a toolbar or to context menus, it appears to be another integrated GroupWise feature.

· You can use Formativ to automate difficult or critical tasks. For example, you could create an Applet that guides users through the process of creating a vacation rule that will not create a mail storm.

· You can use Formativ to integrate GroupWise with other systems. For example, you could write an Applet to import information into GroupWise from Outlook or a corporate database.

· You can use Formativ to build complete solutions for GroupWise. Formativ Applets are surprisingly powerful, and can be used to build complex business systems. As Formativ Applets are COM-based, your Applets can take advantage of any COM service. This means you can add new functionality to the Applet language, and access almost any other modern software services, including databases, human resource systems, financial systems or sales systems.

· You can use Formativ to create new dialogs in GroupWise using the visual forms designer.

While Formativ is an extremely powerful and flexible development environment, like any tool it does have some limitations:

· Formativ is unable to add new buttons or toolbar items to the GroupWise Address Book dialog. This is an architectural restriction imposed by GroupWise.

· Formativ does not currently support an integrated debugger.

· The solution you produce with Formativ will only work with the 32-bit Windows GroupWise client. They do not currently work with WebAccess, Cross-platform or Linux clients.


The Formativ Programming Language
Formativ Applets are written using the Formativ language. The Formativ language contains both general and GroupWise-specific language constructs designed to make developing GroupWise solutions fast and easy.

The main features of the language include:

· 100% syntax-compatibility with Microsoft Visual Basic Scripting Edition
· Over 500 GroupWise-specific language extensions
· Support for event-driven visual forms, including more than 130 components
· Based on COM for easy integration with other components

The Formativ programming language is documented in the Formativ Language Guide.


Useful Resources
There are many excellent resources available for you to accelerate your proficiency with Formativ. Formativ also exposes many of the GroupWise programming API's via Applet commands, so there are many Novell and third party resources that are excellent sources of information. Some of these are listed below:

· Advansys Formativ Language Guide

This document describes the Formativ Language in detail.

· Advansys Formativ Users Guide

This document details how to use the Formativ environment. It describes installation, configuration and operation. It covers how to write a new Applet and how to integrate Applets with the GroupWise client.

· Advansys Formativ Administrators Guide

This document details how to administer Formativ using Novell eDirectory. It covers planning, installation, configuration and operation.

· Advansys Formativ Web Site

The Advansys Formativ Web site is the best source for the latest product information. You can access samples, documentation, updates and news about Formativ, including product updates and fixes.

http://www.advansyscorp.com/Formativ.htm

· Novell GroupWise Cool Solutions Web Site

The Novell GroupWise Cool Solution web site contains a wealth of information and resources for GroupWise users. It also hosts Formativ Applet Central, from where you can download free Formativ solutions.

http://www.novell.com/coolsolutions/gwmag/features/a_Formativ_applet_central_gw.html

· Advansys Formativ Business Solutions Pack

The Advansys Formativ Business Solutions Pack is a collection of complete working Applets. They represent solutions to common GroupWise enhancement requests. You can try the Business Solution Pack Applets for free for thirty days.

http://www.advansyscorp.com/Formativ_business_solutions_pack.htm

· Advansys Formativ Example Applets

This is a wide variety of example Applets, demonstrating a variety of techniques, and illustrating the type of solutions you can develop using Formativ. Some of the examples are complete solutions, while others are simple examples of specific techniques.

http://www.advansyscorp.com/Formativ_example_Applets.htm

· Microsoft Visual Basic Scripting Edition Users Guide

This is the best resource for programming with Microsoft Visual Basic Scripting Edition (VBScript). As Formativ Applets are based on an extended version of VBScript, everything you read in this Guide also applies to Formativ. The guide is installed when you install Formativ Studio or Creator, and is accessible from the Formativ IDE Help menu. You can also download the latest version from the Microsoft Scripting downloads page – see the link below.

· Novell GroupWise Object API Documentation

This online documentation, supplied and maintained by Novell, details the GroupWise Object API, which provides full access to the GroupWise message store. Advansys Formativ exposes the entire Object API, unchanged, via the Formativ Applet language. Use this reference to learn about the Object API, and how you can use it directly within your Formativ Applets.

http://developer.novell.com/ndk/doc/gwobjapi/index.html?gwobjenu/data/h7ikbsqg.html

· Novell GroupWise Tokens Documentation

This online documentation, supplied and maintained by Novell, details the GroupWise Tokens API. Tokens are generally used to manipulate the GroupWise client. Most tokens map directly to a Formativ language extension.

http://developer.novell.com/ndk/doc/gwtoken/index.html?gwtokens/data/hj8ej8g5.html

· Novell Administrative Objects API documentation

This online documentation, supplied and maintained by Novell, details the GroupWise Administrative Objects API, which provides full access to GroupWise administrative functions, such as adding new users and obtaining information about your GroupWise system. Advansys Formativ exposes the entire Administrative Objects API, unchanged, via the Formativ applet language. Use this reference to learn about the Administrative Object API, and how you can use it directly within your Formativ Applets.

http://developer.novell.com/ndk/doc/gwadmin/index.html?gwadmenu/data/h0haj3mj.html

· Microsoft Scripting Resources

The Microsoft Scripting Web site is the best resource for the latest information about Visual Basic Scripting Edition. You can access more samples, documentation, updates and news about VBS, including product updates and fixes.

http://msdn.microsoft.com/library/default.asp?url=/downloads/list/webdev.asp


Quick Start
The best way to become familiar with Formativ from a Programmer's perspective is to create a 'Hello World' Applet, then create a button on the main GroupWise toolbar that runs the Applet.

The following topics cover creating a new solution and creating a button on the main GroupWise toolbar that runs the Applet. We will also define an event that triggers the Applet when a new email message arrives in your mailbox.


Creating a New Applet
Once you have installed Formativ Studio or Creator, follow the steps shown below to create an Applet.

1. Start GroupWise
2. Locate the button for Formativ Central on the main GroupWise toolbar button

quickstart1
Formativ Central button on the main GroupWise toolbar

3. Click the button to display the Formativ IDE (also known as Formativ Central)
4. Click the New button on the Formativ toolbar. A new Applet skeleton is created and displayed in the editor
5. Enter the following line in the editor. Insert the line between the existing lines Sub Main(Client, GWEvent) and End Sub:

MsgBox "Hello World", 0, "Formativ"

Your Applet now appears as:

quickstart2
'Hello World' source code

6. Press F5, or click Run on the toolbar to run your Applet. A message box appears.

Continue with this section to define a toolbar button that runs your applet.


Defining a Toolbar Button
An Applet is not particularly useful unless you integrate it with GroupWise. An integration is a means by which you run your Applet from within GroupWise. An integration can consist of a button on a toolbar, a menu item, a popup (context) menu item or an event.

Follow the steps below to define a toolbar button to run your Applet:

1. Select the Hello World applet in the Formativ IDE
2. Click the Integrations tab
3. Locate the entry 'GroupWise Main Window' in the Context column
4. Check the Toolbar check box. This indicates you wish to define a button on the main GroupWise toolbar

quickstart3
Defining a toolbar button integration on the main GroupWise toolbar

5. Click the Properties tab
6. Enter a description and help hint for your Applet. The description and help hint will appear on toolbar buttons.
7. Click once on the icon you would like to appear on the button in the toolbar
8. Press the close button on the Formativ toolbar. This will close the Formativ IDE
9. Restart GroupWise
10. When the client restarts, you will see a new button on the GroupWise toolbar. Press the button to run your applet

Continue with this section to associate your Applet with a GroupWise event.

Note: It is possible to define custom icon images. For more information see Creating Toolbar Button Images.


Defining an Event
In some situations it makes sense to run your Applet in response to a GroupWise event. For example, you may want to perform some pre-send processing to a message, or to manage incoming messages. In this topic we will associate your Hello World Applet with the On Message Arrival event.

Follow the steps below to have your applet run automatically when a message arrives in your Mailbox:

1. Select the Applet in the Formativ IDE for which you wish to define a button. (If you have been following the Quick Start topics in order, your Hello World applet will already be selected.)
2. Click the Integrations tab
3. Locate the entry 'GroupWise Application' in the Context column
4. Click the button in the Events column. A dialog appears showing the events that are available in this context
5. Check the box next to the first entry – On Message Arrival

quickstart4
Integrating the applet with the On Message Arrival event

6. Click the Close button on the Formativ toolbar. The Formativ IDE closes down
7. Restart the GroupWise client
8. Send yourself an email message. Your Applet will be executed when the message arrives in your Mailbox

Note: GroupWise requires that you restart the client after defining integrations that affect the currently visible view.


Applet Structure
Every applet you write must contain a subroutine called Main(). This is the main entry point of every applet, and is the subroutine Formativ attempts to execute when an applet is run. You cannot run an applet that does not contain a properly formed Main subroutine.

The Main() subroutine must accept two arguments: Client and GWEvent . It does not matter what these parameters are called, but we recommend you use 'Client' and 'GWEvent'. They must be present in every Main() subroutine, or your applet will not execute. The purpose and use of the mandatory parameters are discussed in the following section.

The minimum applet code that will run in the Formativ environment is:

Sub Main(Client, GWEvent)
End Sub

Client and GWEvent Arguments

These two arguments pass useful contextual information regarding the state of the GroupWise client to your applet. You can use the values contained in these two arguments to determine the currently selected message or messages in GroupWise, and to modify the behavior of your applet depending on the event (if any) that was fired when your applet was executed.

Client: This argument represents the state of the GroupWise client at the time your applet was executed. It is the same as the GroupWise C3PO ClientState Object. Your applet should not assume a specific Client object is in a particular state. Rather, the ClientName, MajorVersion, and MinorVersion properties should be checked to identify the appropriate state of the object. Full documentation of the Client argument can be found at: ClientState and ClientState (Implementation) on the Novell Web site.

GWEvent: This argument contains a string representing the GroupWise event that caused the applet to be executed. You can use the value of this argument to dynamically change the behaviour of your applet based on the event that caused it to run.

Possible values are:

GW#C#ACCEPT | An item is being accepted.
GW#C#ARCHIVE | An item is being archived.
GW#C#COMPLETE | An item is being marked complete.
GW#C#COMPOSE | An item is being composed.
GW#C#DECLINE | A message is being declined.
GW#C#DELEGATE | A message is being delegated.
GW#C#DELETE | A message is being deleted.
GW#C#DOC_CHECKIN | A document is being checked-in.
GW#C#DOC_CHECKOUT | A document is being checked-out.
GW#C#DOC_RESETINUSE | A document is being reset.
GW#C#FORWARD | A message is being forwarded.
GW#C#INFO | The information dialog of a message is being accessed.
GW#C#OPEN | A message is being opened.
GW#C#PRINT | A message is being printed.
GW#C#PROPERTIES | A message's properties are being accessed.
GW#C#REPLY | A message is being replied to.
GW#C#RESEND | A message is being resent.
GW#C#SAVE | A message is being saved.
GW#C#SAVEAS | A message is being saved with a new name.
GW#C#SETALARMS | A message is having alarm data set.
GW#C#UNDELETE | A message is being undeleted.
GW#C#VIEW | A message is being viewed.
GW#C#SEND | A message is being sent.
GW#C#TKN#n | A low-level token has just been triggered, where n is the token ID.
GW#E#0 | GroupWise has just started.
GW#E#1 | A new message just arrived in the mailbox.
GW#E#3 | More than one message has arrived in the mailbox at the same time.


Client Argument Examples
Example One

In the following code, the ClientState property of the Client argument is used to access the command message from GroupWise. The command message is the currently active, saved message in GroupWise.

Sub Main(Client, GWEvent)
   Dim Msg
   On Error resume Next
   Set Msg = GroupWise.ComposingItem
   If Msg is Nothing Then
      On Error resume Next
      Set Msg = Client.ClientState.CommandMessage
      ComposeMode = False
      If Msg is Nothing Then
         MsgBox("Sorry, the message type could not be identified")
         Exit Sub
      End If
   End If
End Sub

Example Two

In the following code, the ClientState.SelectedMessages property of the Client argument is used to access the list of currently selected items in GroupWise. If there are no items selected, an attempt is made to access the command message.

Sub Main(Context, GWEvent)
   Dim Msg
   iCount = Context.ClientState.SelectedMessages.Count
   If iCount > 0 Then
      For x = 1 To iCount
         Set Msg = Context.ClientState.SelectedMessages.Item(x)
         ' Do something with the msg object
         Set Msg = Nothing
      Next
   Else
      Set Msg = Context.ClientState.CommandMessage
      ' Do something with the msg object
      Set Msg = Nothing
   End If
End Sub

Example Three

In the following code, the ClientState version methods are called to display the major and minor version numbers of the GroupWise client in a message box.

Sub Main(Client, GWEvent)
   MsgBox(Client.ClientState.MajorVersion & " " & Client.ClientState.MinorVersion)
End Sub


Working with the GroupWise Message Store
Formativ gives you full access to items in the GroupWise message store: Mail, Appointments, Tasks, Notes, Address Book entries and Documents. Using Applets you can create new items, and you can create, delete and modify existing items.

Formativ also lets you access an item that is being composed – though it does not yet exist in the message store. For example, you can access an email message that is still being composed and modify most of its properties, including the body and subject. You could write an Applet that automatically inserts disclaimer text each time you create a new message.

The following topics show how to create new items in the message store, how to access items that are being composed, and how to access items that already exist in the message store. Since accessing GroupWise Address Book/Contact information is slightly different from the generic message types, it is described in its own topics, Accessing Address Book Information via the Account and Accessing Address Book Information via the AddressBooks Object.


What is the Message Store?
The GroupWise message store is a proprietary database, usually residing on a server. A message store is contained inside a GroupWise Post Office. Unless you are writing an Applet that uses the Trusted Application API, or using multi-login, you can assume only one message store is available, from which all messages can be accessed and that the message store belongs to the account of the logged-in GroupWise user.

All items in GroupWise, other than Address Book data, are known as messages. A message represents a discrete item in the GroupWise message store.

All messages share some common properties, such as a unique ID, which uniquely identifies the item in the message store. Distinct kinds of message, such as Mail and Appointment, have unique properties that set them apart from other kinds. For example, an Appointment will have a start time property, whereas a Mail message will not.

In the message store, every kind of item belongs to a specific class. The different classes of item are based on a hierarchical structure, in which one class is a specialization of another class. Every item belongs to the class "GW.MESSAGE". Each distinct kind of item belongs to a class whose name is an extension of this base item class.

For example, the class of a Mail message is "GW.MESSAGE.MAIL". An Appointment has the class "GW.MESSAGE.APPOINTMENT". A complete list of the basic classes is shown below:

· GW.MESSAGE – The base message class
· GW.MESSAGE.MAIL – Mail Message
· GW.MESSAGE.APPOINTMENT – Appointment
· GW.MESSAGE.TASK – Task
· GW.MESSAGE.NOTE – Note
· GW.MESSAGE.PHONE – Phone Message
· GW.MESSAGE.DOCUMENTREFERENCE – Document

Third parties are free to create new message classes, based on one of the above classes. For example, you may come across a message in the message store, with class "GW.MESSAGE.MAIL.PROJECTX", which indicates a new class of Mail message. It will expose all the same properties and events of "GW.MESSAGE.MAIL", but may include additional properties only found in "GW.MESSAGE.MAIL.PROJECTX".

From the programmer's point of view, a message in the message store is represented by an object. An object is a variable that has a set of properties for getting and setting information about the entity it represents, and a set of methods for performing operations on the message. For example, all message objects have the property MessageID that can be used to determine the unique ID for that message, and the Delete method which deletes the item from the message store.

Note: Every message in the GroupWise message store has a MessageID property. This is a string property that is guaranteed to be remain unique for the life of the message in the message store.

Accessing the Message Store

The GroupWise message store is accessed via the Account property of the GroupWise object:

Dim objAccount
Set objAccount = GroupWise.Account

objAccount now holds an instance of the GroupWise Account object. The entire GroupWise message store can be accessed via the Account object.

The GroupWise.Account object is actually a reference to the GroupWise Object API Account object for the currently logged in GroupWise user. This is a very important point. The GroupWise Object API Account object and all the methods and objects it supports are documented on Novell's web site. Any Object API code you may have written previously can be used almost unchanged within an Applet.

The following sections discuss how to use the Account object to create new items in the message store, how to access items already in the message store and how to access an item that is being composed and is not yet in the message store.


Accessing Messages
In many cases you may need to access GroupWise items programmatically. For example, you may need to extract all appointments for a given day, or access the currently selected messages. There are a number of different techniques available, depending on what you need to achieve.

GroupWise items in the message store are accessed in two main ways. If you know the MessageID of the item you are seeking, you can access the message directly. If you are interested in all messages of a particular type, you can use various message extraction techniques to query for those messages.

In either case you use methods of the GroupWise.Account property. The GroupWise.Account property provides full access to the GroupWise message store. See Novell's Object API documentation for complete details of the properties and methods available.

If you have the MessageID of a particular message, you can easily extract it from the message store using the object GroupWise.Account.MailBox.Messages. For example, the following Applet attempts to access a message and display the subject in a message box:

Sub Main(Client, GWEvent)

   ' Hard coded MessageID
   Const MSG_ID = "35FE9AD8.GWHQ.MOSMAN.100.1636E61.1.4A.1"

   Dim objMessages
   Dim objMsg

   ' Set a variable to the MailBox.Messages object
   Set objMessages = GroupWise.Account.MailBox.Messages

   ' Get the message using its ID and set it to objMsg
   Set objMsg = objMessages.Item(MSG_ID)

   ' Display the message subject text
   MsgBox(objMsg.Subject)

   ' Release the objects
   Set objMsg = Nothing
   Set objMessages = Nothing

End Sub

In other situations you may wish to extract any number of messages from GroupWise and process them. For example, you may wish to process all tasks from your account. Use the methods of the GroupWise.Account object to access the appropriate messages.

You may wish to process all the tasks in your account . To extract each task, we can use the collection GroupWise.Account.Calendar.Messages. In the following Applet, the subject of each task is displayed.

Sub Main(Client, GWEvent)

   Dim objMessages
   Dim objTasks
   Dim objTask

   ' Set a variable to the Calendar object
   Set objMessages = GroupWise.Account.Calendar

   ' Use a filter to locate personal, accepted tasks
   Set objTasks = objMessages.FindMessages("(TASK) AND (ACCEPTED) AND (BOX_TYPE = INCOMING OR BOX_TYPE = PERSONAL)")

   ' Display the subject and MessageID of each task located
   For Each objTask In objTasks
      MsgBox(objTask.Subject & " - " & objTask.MessageID)
   Next

   ' Release the objects
   Set objTasks = Nothing
   Set objTask = Nothing
   Set objMessages = Nothing

End Sub


Creating new Messages
There are two main techniques you can use to create a new item:

· Directly inside the message store with no user interface
· Automating the GroupWise client user interface

The following topics discuss these approaches.


Directly in the Message Store
You can create any kind of message without a user interface. You would normally use this approach when you have all the information required to create a new item, and there is no need for user interaction. For example, you may write an Applet to read email addresses from a database, then create and send a customized email message to each address. In this case there is no need for a user to see the actual messages being composed.

Although there are several variations, the most common way to create a new message is this: Call the Add method of the Messages collection owned by the folder in which you wish to store the message. For example, the following Applet creates a new personal GroupWise Appointment in your own calendar:

Sub Main(Client, GWEvent)

     Dim objMessage

     ' Create the new message
     Set objMessage = GroupWise.Account.Calendar.Messages.Add("GW.MESSAGE.APPOINTMENT", 3)

     ' Set some properties
     objMessage.OnCalendar = True
     objMessage.FromText = GroupWise.Account.Owner.DisplayName
     objMessage.Subject = "This was created using Formativ"

     ' Display the MessageID of the new message
     MsgBox(objMessage.MessageID)

End Sub

The Calendar and Messages objects and the Add method are all documented in the GroupWise Object API documentation, which is freely available from Novell's web site. (Remember that the Account property of the GroupWise object gives you complete access to the entire GroupWise Object API.)

In the next example, we create a new personal Task in your own calendar:

Sub Main(Client, GWEvent)

     Dim objTask

     ' Create the new task
     Set objTask = GroupWise.Account.Calendar.Messages.Add("GW.MESSAGE.TASK", 3)

     ' Set some properties
     objTask.OnCalendar = True
     objTask.FromText = GroupWise.Account.Owner.DisplayName
     objTask.TaskCategory = "A"
     objTask.TaskPriority = 1
     objTask.Subject = "This was created using Formativ"

     ' Display the MessageID
     MsgBox(objTask.MessageID)

End Sub

Finally, a slightly more complex example, creating a new email message to oneself. The only user interface element is the popup dialog at the end of the process, which displays the unique MessageID of the message. All objects and properties used in this example are documented in the GroupWise Object API documentation.

Sub Main(Client, GWEvent)

     Dim objDraft
     Dim objEmail
     Dim objRecipient

     ' Create a draft email message
     Set objDraft = GroupWise.Account.MailBox.Messages.Add(4)

     ' Add a single recipient - ourself
     objRecipient = objDraft.Recipients.Add(objDraft.Sender.EmailAddress,,0)

     ' Add some properties
     objDraft.Subject = "This was created using Formativ"
     objDraft.BodyText.PlainText = "This is the body text of the email message"

     ' Send the email by calling the send method
     Set objEmail = objDraft.Send

     ' Display the MessageID
     MsgBox(objEmail.MessageID)

End Sub

If you have the Formativ development environment open in GroupWise when a new message arrives, you may notice a slight delay in notification of the message's arrival. We recommend that you close the Formativ development environment when not editing Applets.

Naturally, VBScript constructs may be used in your code. Here is the same example slightly modified to send the same message to your own Mailbox three times. Each message is given a slightly different subject:

Sub Main(Client, GWEvent)

     Dim objDraft
     Dim objEmail
     Dim objRecipient

     ' Create three new messages
     For x = 1 To 3

           ' Create a draft email message
           Set objDraft = GroupWise.Account.MailBox.Messages.Add(4)

           ' Add a single recipient - ourself
           objRecipient = objDraft.Recipients.Add(objDraft.Sender.EmailAddress,,0)

           ' Add some properties
           objDraft.Subject = "This is message no. " & x
           objDraft.BodyText.PlainText = "This is the body text of the email message"

           ' Send the email by calling the send method
           Set objEmail = objDraft.Send
     Next

     MsgBox("Done!")

End Sub


Via the GroupWise Client Interface
You may wish to create a new message in the GroupWise client itself. Using a Formativ Applet, you can create a new message by displaying the new message dialog for the type of message you wish to create. You can leave it to the user to complete the rest of the details, or you may fill out some or all of the details before making the item available to the user.

For example, the following code creates a new Mail message, and leaves it to the user to complete and send the message manually. When the Applet is executed, the standard GroupWise new Mail message dialog is displayed:

Sub Main(Client, GWEvent)

     GroupWise.NewMail

End Sub

In some cases you may wish to fill out some of the message properties before making the item available to the user. You may wish to complete the subject and body text, as shown in the following example, using the ComposingItem property of the GroupWise object. Notice this example uses error checking to ensure that a valid composing item is accessible:

Sub Main(Client, GWEvent)

     Dim Msg

     ' Create a new visible email message
     GroupWise.NewMail

     ' Attempt to access the composing item
     ' If available, set its subject and body text
     Set Msg = GroupWise.ComposingItem
     If Msg is Nothing Then
           MsgBox("No composing item available")
     Else
           Msg.Subject = "This is the new subject"
           Msg.BodyText = "This is the body text"
           Set Msg = Nothing
     End If

End Sub

Refer to the Language Guide for full details of the ComposingItem property.

Formativ is only able to access the ComposingItem if the dialog displaying the new message has the focus at the time you access it. This is a limitation of the underlying GroupWise architecture rather than Formativ, and is not usually an issue as long as you attempt to access the item soon after it is created.


Accessing Messages via the Client
In many cases, you may wish to write an Applet which operates on the currently selected GroupWise items. For example, you may wish to perform an operation on a list of selected items in GroupWise, or you may wish to access the current open saved item, such as an email message that arrived in your Mailbox.

In order to determine if any messages are selected in the GroupWise client when your script is run, you should use the Client parameter passed into the Main procedure of your applet. The Client parameter is an object which represents the state of the client when your Applet was executed. See the earlier section Applet Structure for full details on the definition of the Client parameter.

The following topics discuss how to access the currently selected messages and folders in the GroupWise client.


Accessing a Saved Message
If you wish to act upon a single saved item, either selected or opened , you can use the Client.ClientState.CommandMessage object. The CommandMessage object gives you access to the current saved GroupWise item. For example, the following applet checks if the CommandMessage object is valid. If so, the message subject is displayed.

Sub Main(Client, GWEvent)

     Dim objMsg

     On Error Resume Next
     Set objMsg = Client.ClientState.CommandMessage
     If Not objMsg is Nothing Then
           MsgBox(objMsg.Subject)
           Set objMsg = Nothing
     End If

End Sub


Accessing Multiple Selected Messages
If you wish to act upon all selected messages in the GroupWise client, you should check the Client.ClientState.SelectedMessages object. If any messages are selected, you can then use this object to access each one. For example, the following code displays the subject of each selected item in GroupWise. Before running the Applet, display a list of items in the GroupWise client and select them:

Sub Main(Client, GWEvent)

     Dim objMsg

     ' Find out how many items are selected in GroupWise
     iCount = Client.ClientState.SelectedMessages.Count

     ' If any are selected, access each one
     If iCount > 0 Then
           For x = 1 To iCount

                 ' Get the message and display its subject
                 Set objMsg = Client.ClientState.SelectedMessages.Item(x)
                 MsgBox(objMsg.Subject)
                 Set objMsg = Nothing
           Next
     Else
           MsgBox("No messages were selected")
     End If

End Sub


Accessing the Message Being Composed
In some situations you may wish to access data in a new GroupWise message that is still being composed.

Note: An item is still being composed when it has not been sent, or saved to Work in Progress.

For example, when you create a new Mail message, the message is not saved until you click the Send button. Likewise, when you reply to an existing email message, your reply is not saved until you click the Send button.

The distinction between a saved and an unsaved message is very important from a programmer's perspective. Until a GroupWise message has been saved, it does not have a unique MessageID, and it does not exist in the message store. This means you cannot use any of the GroupWise.Account methods to access the message. The only way you can read and write an item that has not yet been saved is to:

· Use the ComposingItem property of the GroupWise Object

or

· Use the ItemSetText and ItemGetText methods of the GroupWise Object, using the special message ID "X00" to identify the message.

Every message in the GroupWise message store is allocated a unique ID that never changes during the life of the message. Items that have not been saved, and therefore have not yet been allocated an ID, can be accessed using the special ID "X00". This ID can usually be used in place of a permanent ID to access the current composing item.

Note: The only caveat is that the item being composed needs to have the focus in Windows (i.e. the active window).

The ComposingItem property of the GroupWise object provides a convenient method to access items that are currently being composed. ComposingItem lets you read and write data in items being composed, including Subject and body text. ComposingItem exposes the following properties:

· BoxType: Integer (Read Only)
· ClassName: String (Read Only)
· ConvertAttachments: Boolean
· CreationDate: Date (Read Only)
· Deleted: Boolean (Read Only)
· FromText: String
· Hidden: Boolean
· MessageID: String (Read Only)
· NotifyWhenDeleted: Integer
· NotifyWhenOpened: Integer
· Opened: Boolean
· Parent: Variant (Read Only)
· Priority: Integer
· Read: Boolean
· ReplyDaysRequested: Integer
· ReplyRequested: Integer
· Routed: Boolean
· RoutingEndOfLine: Boolean (Read Only)
· Sender: String (Read Only)
· ViewName: String
· IsPrivate: Boolean
· Subject: String
· BodyText: String
· CC: String
· BC: String
· To_: String
· StartDate: Date
· EndDate: Date
· DueDate: Date
· CallerCompany: String
· CallerName: String
· CameToSee: Boolean
· PleaseCall: Boolean
· ReturnedCall: Boolean
· Telephoned: Boolean
· Urgent: Boolean
· WantsToSee: Boolean
· WillCall: Boolean
· AssignedDate: Date
· TaskCategory: String
· TaskPriority: String

In the following example, the ComposingItem property is used to insert a simple disclaimer at the top of the body text of a message being composed. To be useful, this Applet would be associated with the On Send event for email messages so that it would be automatically executed each time a new Mail message is sent:

Sub Main(Client, GWEvent)

     ' This is the disclaimer text to insert
     Const DISCLAIMER = "This is some disclaimer text"
     Dim NewLine
     Dim Msg

     NewLine = Chr(13) & Chr(10)

     ' Attempt to access the composing item
     Set Msg = GroupWise.ComposingItem

     ' If we have the composing item, insert the disclaimer into the body text
     If Not Msg is Nothing Then
           Msg.BodyText = DISCLAIMER & NewLine & NewLine & Msg.BodyText
           Set Msg = Nothing
     Else
           MsgBox("No GroupWise items were available for disclaimer insertion.")
     End If

End Sub


Accessing Address Book Data
Formativ gives you complete access to the GroupWise address books. With Formativ, you can write Applets to create new address books, add, edit and delete address book entries, and quickly extract contact details.

There are two main techniques you can use to access address book information. You may use the standard GroupWise.Account object which provides low-level access to the complex structure, or the GroupWise.AddressBooks object which provides simpler, slightly higher-level access. The technique you use will ultimately depend on the problem you are trying to solve.

Address book entries in GroupWise do not have accessible persistent ID's as do other item types such as Mail. This means you cannot obtain an address book entry's ID, then access the entry directly (using the ID) at a later time. This is due to architectural issues in GroupWise. To get around this, you can add your own custom fields to address book entries, and assign them a unique value, such as a GUID, and use the value as a unique ID during later sessions.


Address Book Access via the Account Object
The GroupWise.Account object provides low-level access to address book data. You can access data down to FieldDef level and work with custom fields. Access via the GroupWise.Account object is the same as with the Object API. See Novell's Object API documentation for complete details.

For example, the following code displays the name of every address book available in the current account:

Sub Main(Client, GWEvent)

     Dim objAddressBooks
     Dim objAddressBook

     ' Get the AddressBooks object
     Set objAddressBooks = GroupWise.Account.AddressBooks

     ' Display the name of each address book
     For Each objAddressBook In objAddressBooks
           MsgBox(objAddressBook.name)
     Next

     Set objAddressBooks = Nothing

End Sub

You may access an individual address book either by its name or index value within its collection. For example, the following Applet lists the email address for each contact in the address book 'Frequent Contacts':

Sub Main(Client, GWEvent)

     Dim objAddressBooks
     Dim objAddessBook
     Dim objAddressBookEntry

     ' Get the AddressBooks object
     Set objAddressBooks = GroupWise.Account.AddressBooks

     ' Locate the address book called 'Frequent Contacts'
     Set objAddressBook = objAddressBooks.Item("Frequent Contacts")

     ' Display the email address of each entry in the book
     For Each objAddressBookEntry In objAddressBook.AddressBookEntries
           MsgBox(objAddressBookEntry.EmailAddress)
     Next

     Set objAddressBook = Nothing
     Set objAddressBooks = Nothing

End Sub

Essentially, this technique uses 'raw' GroupWise Object API calls. Our experience is that the GroupWise Object API can be a little unstable when accessing certain address books, particularly the Novell LDAP address book. Using the GroupWise.AddressBooks object avoids this instability since Formativ shields you from it.


Address Book Access via the AddressBooks Object
The GroupWise.AddressBooks object provides a clean, simple object model with which you can access GroupWise address books. This technique shields you from much instability inherent in some native GroupWise address book calls. More importantly, it encapsulates the GroupWise address book FieldDef paradigm, making it very simple to access address book fields by name without having to worry about Field Definitions or the version and language of the GroupWise client.

See the Object Model documentation for full details of the GroupWise.AddressBooks object model.

Semantically, using the GroupWise.AddressBooks object is similar to using the GroupWise.Account model. For example, the Applet to list the names of all the address books available in an account is:

Sub Main(Client, GWEvent)

     Dim objAddressBooks
     Dim objAddressBook

     Set objAddressBooks = GroupWise.AddressBooks
     For Each objAddressBook In objAddressBooks
           MsgBox(objAddressBook.Name)
     Next

     Set objAddressBooks = Nothing

End Sub

Likewise, the code to access a single address book by name is:

Sub Main(Client, GWEvent)

     Dim objAddressBooks
     Dim objAddressBook
     Set objAddressBooks = GroupWise.AddressBooks

     ' Locate the address book called 'Frequent Contacts'
     Set objAddressBook = objAddressBooks.Item("Frequent Contacts")

     ' Display the email address of each entry in the book
     For Each objAddressBookEntry In objAddressBook
           MsgBox(objAddressBookEntry.EmailAddress)
     Next

     Set objAddressBooks = Nothing

End Sub

Note: You do not have to use the AddressBookEntries property as you do when using the GroupWise.Account access technique.

The real benefit to using GroupWise.AddressBooks becomes apparent when you have to access address book entry fields. Unlike the GroupWise.Account technique, you can access all standard fields directly using properties of the AddressBookEntry object. There is no need to be concerned with FieldDefs, the version or language of the GroupWise client being used as is the case when accessing most fields using the GroupWise.Account technique.

GroupWise's underlying architecture dictates that address book fields traditionally had to be accessed using field names. These textual field names varied between versions of the client and the language of the client. For example, if you wanted to write a program that accessed the 'Title' field of an address book, it was necessary to know the local variation of that name. If the user had an English client, the field called 'Title' was located. If the user had a French client, your program had to be aware of this and search for the French for 'Title' instead.

Formativ alleviates this problem through its implementation of the GroupWise.AddressBooks object. For example, if you wanted to extract the 'Title' field value of every contact in a particular address book, you could do so by using the Title property of the AddressBookEntry object as shown here:

Sub Main(Client, GWEvent)

     Dim objAddressBooks
     Dim objAddressBook

     Set objAddressBooks = GroupWise.AddressBooks

     ' Locate the address book called 'Frequent Contacts'
     Set objAddressBook = objAddressBooks.Item("Frequent Contacts")

     ' Display the email address of each entry in the book
     For Each objAddressBookEntry In objAddressBook
           MsgBox(objAddressBookEntry.Title)
     Next

     Set objAddressBook = Nothing
     Set objAddressBooks = Nothing

End Sub

This technique also makes adding new address book entries very simple. For example, to add a new contact to a personal address book called "Test Book", you could use the following Applet:

Sub Main(Client, GWEvent)

     Dim AddressBooks
     Dim AddressBook
     Dim oAddressBookEntries
     Dim oAddressBookEntry

     Set AddressBooks = GroupWise.AddressBooks

     On Error Resume Next
     Set AddressBook = Nothing
     Set AddressBook = AddressBooks.Item("Test Book")

     If AddressBook Is Nothing Then
           MsgBox("Could not locate that address book")
     Else
           MsgBox(AddressBook.Name)
           Set oAddressBookEntry = AddressBook.AddContact("Bill Smith")
           With oAddressBookEntry
                 .FirstName = "Bill"
                 .LastName = "Smith"
                 .Organization = "Smith Inc"
                 .EmailAddress = "bill@Smith.com"
                 .EmailType = "NGW"
                 .Address = "This is the address"
                 .City = "The city"
                 .State = "The state"
                 .ZipCode = "The zip"
                 .Country = "The country"
                 .Department = "The dept"
                 .Title = "The title"
                 .MailStop = "The mailstop"
                 .Greeting = "The greeting"
                 .OfficePhone = "1111111"
                 .HomePhone = "22222"
                 .CellPhone = "333333"
                 .FaxPhone = "444444"
                 .Comments = "This is the comments field"
           End With
     End If

     Set AddressBookEntry = Nothing
     Set AddressBook = Nothing
     Set AddressBooks = Nothing

     MsgBox("Done")

End Sub

Note: Despite the convenience of the GroupWise.AddressBooks object model, there may be times when you need access to the lower-lever native Object API representation of an Address Book or Address Book Entry. You may access the native objects via the AddressBookEntry.Objects and AddressBook.Objects properties.


Customizing the GroupWise Client
Formativ provides many methods in the GroupWise object to manipulate the GroupWise client user interface. These methods range from displaying dialogs to opening and closing various views.

You can add buttons to toolbars, create menu items, create popup menu items and run Applets in response to GroupWise events. The following topics deal with these issues.


Automating Client Features
Formativ provides methods within the GroupWise object to manipulate the GroupWise client user interface. These range from displaying dialogs to opening and closing various views. Check the Formativ Language Guide for full details.

For example, to display the GroupWise About dialog, simply call the method GroupWise.AboutDlg:

Sub Main(Client, GWEvent)
     GroupWise.AboutDlg
End Sub

Note: Take care not to close down GroupWise programmatically using an Applet. Closing GroupWise while an applet is executing may cause unpredictable results, which may even result in a system crash. Always check if a window is open before using one of the window close/cancel commands.


Adding Buttons, Menus and Event Integrations
One of the most powerful features of Formativ is the ease with which you can add buttons to toolbars, items to menus and hook into the GroupWise event system. Traditionally, this has been one of the most difficult aspects of GroupWise development. Formativ lets you add these elements by simply indicating which GroupWise context you wish to link to these elements.

A GroupWise context maps to either a message type or to an aspect of the GroupWise client. For example, each message type (Mail, Appointment, Note etc.) has its own context. A context is represented by a descriptive name, such as 'Email' or 'Appointments'. Each context is divided into categories, such as 'Toolbars', 'Menus' and 'Events' and each category is further divided into options. For example, the 'Events' category of the 'GroupWise Email' context consists of all the events you can assign scripts to, such as 'OnSend' and 'OnOpen'.

Note: You can see all the contexts and context categories you can use on the Integrations tab in the Formativ IDE for each Applet you have written.

When you assign integrations to an Applet, the information about that integration is saved with the Applet itself. This means that if you distribute the Applet to other users, its integrations will also appear automatically within their GroupWise clients. For example, if you write an Applet that proxies to another user, and you decide to integrate a button on the main GroupWise toolbar that executes the Applet, any user to whom you distribute that Applet will have the same button appear on their toolbar automatically the next time they start GroupWise.

At GroupWise start-up, Formativ has to register its interest with any context it wishes to integrate into. In some cases, Formativ is unable to register interest in a particular context in time for it to take effect; this is due to the underlying GroupWise architecture. For example, if you write an Applet, and integrate a button for the Applet on the main toolbar, the button will not appear until you restart the client. Formativ will attempt to identify these situations and advise the user that a client restart is required. If any new integrations you design do not appear, or the events you subscribe to do not fire, you should restart the GroupWise client and try again.

Before defining any client integrations, you should define the Applet description, help hint and image. Select the appropriate Applet in Formativ Central, then activate the Properties tab. This tab lets you specify the Applet description, help hint and image. The description is the text that appears on the button face if you have selected the property Picture and text for the GroupWise toolbar. The description also appears in any menu with which the applet is integrated. The help hint is the text that appears when the mouse pointer is held over a button or menu integration in the GroupWise client.

You should keep the description text short if you intend to use the GroupWise Picture and text option for toolbars. With this option set, GroupWise widens all toolbar buttons to be the width of the longest button description. If you have long descriptions, this can make the GroupWise buttons very untidy.

The Properties tab also lets you specify an image, from the selection of images, to display on the button. Formativ ships with a wide selection of general images.

You may edit the description, help hint and image associated with an Applet at any time. However, you may have to restart the GroupWise client to see the changes take effect.


Adding Toolbar Buttons
Formativ lets you add any number of buttons to most toolbars in the GroupWise client. For each button you define, Formativ lets you supply the text that appears on the button, the hint text that appears when holding the mouse pointer over the button, and an image for the button.

As with all integrations, defining a button is context-based. This means you can assign a button to appear with one or more GroupWise contexts. To define where the button should appear, select the Integrations tab within Formativ Central and select the context in which the button should appear. For example, if you would like to add the button to the GroupWise main toolbar, find the context 'GroupWise Main Window', then check the corresponding box in the Toolbar column. The next time you start the GroupWise client, a button will appear on the main toolbar with the image, caption and help hint you defined. Clicking the button will execute the applet.

integrations1
Defining a toolbar button on the Mail view dialog

You can define any number of buttons that execute a single Applet. For example, if you would like to have the button described above appear on the Mail view toolbar, find the 'Mail' context and check the corresponding box in the Toolbar column. The GroupWise client will now have two new buttons that execute the same Applet. One will appear on the main window, another will appear on the Mail view dialog.


Adding Menu Items
Formativ lets you add any number of menu items to most top-level menus in the GroupWise client. For each menu item you define, Formativ lets you supply the text that appears on the menu and the hint text that appears when you hold the mouse pointer over the menu item.

As with all integrations, menu integrations are context-based. This means you can assign a menu item to appear within one or more GroupWise contexts. To define where the menu item should appear, select the Integrations tab within Formativ Central.

For example, if you would like to add the menu item to the GroupWise main menu under the 'File' menu, complete the following steps. Each step corresponds to the numbers in the figure below.

1. Find the 'GroupWise Main Window' context, then click the button in the Menus column. This will open the Menus dialog, which displays all menu items within the context. Menu items are displayed in groups, where each group corresponds to the menu these items belong to. For each item there are two check boxes, representing before and after the item.
2. First locate the 'File' menu group, then find a menu item (e.g. 'New') that will act as an 'anchor' for your new item. Check the lower box so that your new item will appear immediately after 'New' on the 'File' menu. Click the cross button at the bottom of the dialog to save this integration.

The next time you start the GroupWise client, the new menu item will appear on the GroupWise 'File' menu. When you click the item, your Applet will be executed.

integrations4
Adding a menu integration to the email dialog File menu

You can define any number of menu items that execute a single Applet. For example, if you would like to have the same menu item as described above appear on the Mail view, find the 'Mail' context, then follow the steps above. The GroupWise client will now have two new menu items that execute the same Applet. One appears on the main window menu, the other appears on the Mail view menu.

Note: Formativ identifies existing menu items by the menu caption text. By default, Formativ only recognizes the captions used by the US English GroupWise client. Users of other language clients can add support for those clients by editing the # entries in the appropriate msgclass?_?.txt files. You can find these files in the folder where you installed Formativ.


Adding Popup Menu Items
Formativ lets you add context menu (also known as floating or popup menu) items to the GroupWise client. These items appear when you click the right mouse button (or left mouse button if left-handed) over a particular item or area in the GroupWise client. For example, if you select a Mail message in a folder and click this button, a context menu appears with options specific to Mail items.

As with all integrations, defining a context menu item is context-based. To define the context menu an item should be added to, select the Integrations tab within Formativ Central.

For example, if you would like to add an item to the context menu that appears for a Mail message, find the 'Email' context, then check the box in the Popup column, as shown below. The next time you click for a context menu on a Mail message, the context menu that appears will contain a new item whose caption is the description you defined for the applet. Clicking the context menu item will execute the applet.

integrations5
Defining a pop up menu to the email context menu

The context GroupWise uses can change depending where the mouse is when you click for a context menu. Be aware of this when defining context menu integrations. You may have to define several context menu integrations to have your applet accessible from all the menus where you require your new item to appear.


Working with GroupWise Events
Formativ lets you execute an applet when particular GroupWise events occur, such as when the GroupWise client starts up, a new message appears in your mailbox, or when you send a new item.

There is a wide range of events you may associate with Applets. Most of the events of interest are those associated with the GroupWise message contexts, such as Mail and Appointments. For example, Formativ lets you associate an Applet with the 'OnSend' event of all message types, giving you the capability to write Applets that perform some action prior to a message being sent.

Events are given names starting with 'On', such as 'OnSend', 'OnPrint' and 'OnOpen'.

Standard events available for most message types include:

· OnAccept
· OnArchive
· OnComplete
· OnCompose
· OnDecline
· OnDelegate
· OnDelete
· OnDocCheckIn
· OnDocCheckOut
· OnDocResetInUse
· OnForward
· OnInfo
· OnOpen
· OnPrint
· OnProperties
· OnReply
· OnResend
· OnSave
· OnSaveAs
· OnSetAlarms
· OnUndelete
· OnView
· OnSend

When you have your Applet subscribe to a particular event, the GroupWise processing that would normally occur is executed first, then your Applet is executed. The only exception is the OnSend event, where your Applet is executed before the item is sent by GroupWise. You can choose to override this behavior and specify the order in which the GroupWise event should occur in relation to your applet. You can choose to run your Applet:

· Before the GroupWise event
· After the GroupWise event
· In place of the GroupWise event

Notice how the final option above lets you choose to discard the original processing completely and replace the functionality with that contained in your Applet.

As with all integrations, associating an applet with a GroupWise event is context-based. To associate your Applet with an event, select the Integrations tab within Formativ Central.

For example, if you would like to run an Applet when the user opens a saved Mail message, complete the following steps. Each step corresponds to the numbers in the figure below.

1. Find the 'Email' context, then click the button in the Events column. This will open the Events dialog, shown below.
2. In the Events dialog, check the box next to OnOpen. Notice how the arrow changes from gray to blue. Click the triangle button next to the arrow to select the way your Applet changes the normal processing of the event.

The next time a Mail message is opened, the Applet will be executed.

integrations3
Integrating the applet with the Mail OnOpen event

You can associate a single Applet with multiple events in a single context, or with multiple events in different contexts. For example, you might associate an Applet with the 'OnCompose' and 'OnReply' events of all message types.

Take care when associating Applets with events. While it is technically possible to associate an applet with any supported events, try to limit the intrusion of your Applet onto events as much as possible. Some Applets lend themselves to association with events more than others. For example, while it makes good sense to associate a Signature or Disclaimer applet with the 'OnSend' event, other Applets may not lend themselves as favorably.


Creating User Interfaces
User interfaces form a key component of many Formativ solutions. Formativ offers four ways to create user interfaces:

· Code-based Dialogs
· Visual Forms Designer Dialogs
· HTML Dialogs
· Portals

Each approach has its own strengths and weaknesses. The following introduction provides an overview of the four approaches.

Code-based Dialogs

· Are constructed entirely in code (cannot be visualized at design-time)
· Offer compatibility with all versions of Formativ
· Are static – the content cannot be updated without re-displaying the dialog
· Have a limited number of controls available
· Offer limited control over layout

Visual Forms Designer Dialogs

· Are constructed using a visual drag-and-drop Forms Designer
· Offer the capability to create extremely rich forms
· Are compatible with Formativ 2.0 and above
· Can be updated in real time without having to re-display the dialog
· Are event driven – your code can respond to events on the dialog
· Maximize control over layout

HTML Dialogs

· Are constructed using HTML
· Offer compatibility with all versions of Formativ
· Can be updated with dynamic HTML/Javascript
· Some degree of event handling is possible via JavaScript™

Portals

· Are constructed using HTML
· Are displayed inside the GroupWise client
· Offer high-level visual GroupWise client integration
· Offer compatibility with all versions of Formativ
· Can be updated with dynamic HTML/Javascript
· Some degree of event handling is possible via JavaScript™

Note: If you are targeting Formativ 2.x users, we recommend Visual Forms Designer Dialogs for general dialogs/forms, and Portals for embedded visual interfaces.


Code-based Dialogs
Formativ provides a number of language extensions that allow you to design simple, yet flexible dialogs in Applets. You can build dialogs that display information, collect information from the user (using forms), or both.

codedialog
Code-based Dialog

Note: Unless you need to target versions of Formativ prior to version 2.0, we recommend using Visual Forms Designer Dialogs rather than code-based dialogs. Forms created with the visual forms designer are far richer and more flexible than code-based dialogs.


Creating Code-based Dialogs
Code-based dialogs are created entirely in code. You cannot design a code-based dialog visually. (To create dialogs using a visual, drag-and-drop approach, use the Formativ Visual Forms Designer.)

To create a code-based dialog, you must first obtain an instance of a new Control Box Dialog object. Then you add controls to this object, setting their properties in turn.

Create a new Control Box Dialog Object

To create a new Control Box dialog object, call the Utilities.NewControlBoxDialog method. This method returns a new fcControlDlg object.

Dim RuleDlg
Set RuleDlg = Utilities.NewControlBoxDialog

The fcControlDlg object has a number of properties you can read and write to control the way the dialog appears and behaves. You can use properties (among others) to specify:

· the base buttons that appear on the dialog
· whether the form auto sizes
· the Height and Width of the dialog
· the Wizard image (if any) to display
· the Title and Caption of the dialog

Once the properties have been set, you may add visual controls to the dialog.

Adding Controls

Controls are added to a fcControlDlg object by calling methods exposed by the object. There are methods for adding controls such as buttons, list boxes, group boxes, combo boxes, images, radio buttons, check boxes, etc. Each of these methods returns an object representing the appropriate control, which in turn exposes control-specific properties and methods.

You may call the following methods to add controls to fcControlDlg objects:

· AddCheckBoxControl
· AddCheckListControl
· AddComboBoxControl
· AddDateTimeControl
· AddEditControl
· AddImageControl
· AddListBoxControl
· AddMemoControl
· AddMultiLineLabelControl
· AddPanelControl
· AddRadioButtonControl
· AddRadioGroupControl
· AddSpinEditControl
· AddStringGridControl
· AddTabListBoxControl

For example, the following code creates a new fcControlDlg object and adds a checked list box control. Three items are added to the list box, and the first item is checked:

Dim RuleDlg
Dim ListBoxCtl

Set RuleDlg = Utilities.NewControlBoxDialog
Set ListBoxCtl = RuleDlg.AddCheckListControl
ListBoxCtl.AddItem("Mail - Reply to Sender", True)
ListBoxCtl.AddItem("Appointment - Decline", False)
ListBoxCtl.AddItem("Task - Decline", False)

See the Language Guide for details of the objects returned and the properties/methods they expose.


Displaying Code-Based Dialogs
A code-based dialog is displayed by calling the Execute method of the fcControlDlg object. This forces the dialog to be displayed modally; meaning the user must dismiss the dialog by clicking a button in order to continue.

The Execute method returns an integer indicating which button the user pressed to dismiss the dialog. Possible values are:

· Btn1 = 1
· Btn2 = 2
· Btn3 = 3
· Btn4 = 4
· Btn5 = 5
· Btn6 = 6

Note: Btn1 is the right-most button. Btn1 through Btn6 can be used directly in your code.


Visual Forms Designer
Formativ 2.0 introduces an integrated Visual Forms Designer. The forms designer makes it easy to design event driven, interactive forms and use them in your Applets.

The Visual Forms Designer

The visual forms designer includes:

· Fully Visual Form Design - You use the visual forms designer to create dialog forms. Using a familiar visual drag and drop approach, forms are designed by dropping components onto forms and defining their properties and events.

· Fully Event Driven Operation - You may link Formativ code easily to events exposed by forms and form components. This makes it possible to perform certain actions dynamically in response to events that occur on a form. For example, you can associate code with a button click event which adds an item dynamically to a list box control located on the same form.

· A Rich Component Set - When designing your Formativ forms you can choose from a collection of 125 components within 11 categories. Component categories include standard, Additional, Windows, System, Dialogs, GroupWise, Enhanced 1 & II, Netware, LDAP and NDAP.

The visual forms designer consists of four main components:

· Component Palette
· Object Inspector
· Alignment Palette
· Designed Form


Creating Forms
Creating a New Form

1. Select the Applet which requires the new form.
2. From the Formativ editor toolbar, press the Forms button.

Forms button on the editor toolbar

3. The forms dialog appears. Select New.
4. Provide a name for the new form. Press OK.
5. The Forms designer is activated.

Visual Forms Designer

A new, empty form is displayed, along with the Object Inspector, Component Palette, and Alignment Palette. Select the appropriate controls from the component palette and drop them on the form. Use the Object Inspector to give components meaningful names, to specify other component properties and define events. Press the Save Changes button to save your changes and return the editor. Press the Cancel button to discard any changes and return the editor. You can toggle between Design View and the Code View by pressing F11 or the toggle view button on the component palette.


Managing Forms
To Edit an Existing Form

1. Select the Applet.
2. From the Formativ editor toolbar, press the Forms button.
3. Double click the appropriate form in the forms dialog list.
4. The Forms designer is activated.

Note: From the Formativ editor toolbar, press the drop down sectiont of the Forms button and select the name of the pre-defined form from the drop down list.

To Delete an Existing Form

1. Select the Applet.
2. From the Formativ editor toolbar, press the Forms button.
3. Select the appropriate form in the Forms list dialog.
4. Press the 'Delete' button.
5. Confirm the deletion process.

To Rename an Existing Form

1. Select the Applet.
2. From the Formativ editor toolbar, press the Forms button.
3. Select the appropriate form in the Forms list dialog.
4. Press the 'Rename' button.
5. Provide a new name. The name you provide must be unique in the current Applet.

To Export an Existing Form

Formativ enables you to export an existing form as a .FRM file. Exported FRM files may be imported into other Applets. Use this technique to build a library of commonly used forms which can be imported into your Applets.

1. Select the Applet.
2. From the Formativ editor toolbar, press the Forms button.
3. Select the appropriate form in the Forms list dialog.
4. Press the 'Export' button.
5. Supply a location and name for the exported form and press OK.

To Import a Form

You can import FRM form files into an Applet. Existing Applet forms, which have the same name as those being imported from the FRM file, may be optionally replaced.

1. Select the Applet.
2. From the Formativ editor toolbar, press the Forms button.
3. Select the appropriate form in the Forms list dialog.
4. Press the 'Import' button.
5. Select the FRM file you wish to import and press OK.


Form Events
Most components (and forms) expose events for which you can write event handlers. An event handler is a Formativ subroutine which is called automatically when the related component or form event is triggered.

Events are triggered in response to an operation which involves a form or control. For example, an 'OnClick' event occurs when a user clicks a button on a form. By associating a Formativ subroutine with a button's 'OnClick' event, the subroutine is executed automatically whenever the button is pressed.

To Create an Event Handler

1. Select the control for which you wish to define an event handler.
2. Select the Events tab in the Object Inspector.
3. Double click the event for which you will write an event handler.
4. Formativ creates a stub subroutine in your Applet. Write the code which will execute in response to the event.

Defining an OnClick event for a button

To Associate an Existing Subroutine with an Event Handler

You can associate an existing subroutine with a component's event handler if the subroutine has the same argument list expected by the handler. The mechanism makes it possible to write a single event handler subroutine that can be used by many different component events.

1. Select the control for with you wish to define an event handler.
2. Select the Events tab of the Object Inspector.
3. Locate the event you wish to associate and press the drop down control to the right of the event name. Select a compatible, pre-existing subroutine from the list.

Assign existing subroutines to events


Displaying Forms
There are two ways to display a form from an Applet at runtime: as a Modal or non-modal form. A form shown modally needs to be closed by the user before the Applet will continue processing. A form shown non-modally does not block Applet execution. Unless you wish to display a form that is used to display status information, you would normally display forms modally.

Regardless of how a form is shown, the form event system continues to be active for the duration of the form's appearance. This means that, even though Applet processing may be paused because the form is being shown modally, event handler subroutines will continue to be called in response to triggered form events.

Note: You do not need to explicitly create or destroy Formativ forms in your Applet code. In fact, trying to destroy or create form within Applet code is likely to result in unpredictable behavior. When an Applet containing forms is executed, Formativ creates all its forms automatically. This means an Applet is guaranteed to have its forms available at all times. Likewise, when the Applet stops executing, Formativ destroys all Applet forms automatically.

Displaying a Form Modally

To display a form modally, you call the form .ShowModal() function. This function causes the form to be displayed and pauses Applet execution until the user performs an action which closes the form. When the form is closed, the .ShowModal() function returns a value indicating how the form was closed. This value is known as the modal result and will be one of the following constant values:

· mrNone
· mrOK
· mrCancel
· mrAbort
· mrRetry
· mrIgnore
· mrYes
· mrNo
· mtAll
· mrNoToAll
· mrYesToAll

In order specify the modal result value, normally you specify the modal result property of the control which will close the form. For example, you might create a form with two buttons - Button1 and Button2. Button1 will close the form and accept any user input changes. Button2 will close the form, canceling any changes made by the user.

To implement this functionality, you set the Button1.ModalResult property to mrOK, and the Button2.ModalResult property to mrCancel. When this form is displayed modally using a call to ShowModal(), if the user presses Button1 the ShowModal() function will return the constant value mrOK or, if the user presses Button2, it will return mrCancel . Assuming the form is called test, you could write the following code to display the form and if the user presses Button1, perform a specific action:

If test.ShowModal = mrOK Then
   MsgBox "You pressed Button1"
Else
   MsgBox "You pressed Button2"
End If

The form will be displayed by the line test.ShowModal(). At this point the Applet will pause until the form is closed, then display the appropriate message box.

Displaying Forms Non-Modally

To display a form non-modally, simply call the form .Show() method. To close the form, call the .Hide() method. Calling the .Show() method does not pause Applet execution. However, the form may move out of view as GroupWise or other processes display new windows. For this reason, when you wish to use a form to display real time information about a process which is occurring in the background (like process progress status), forms are normally shown non-modally .

Note: It may be necessary to ensure the Windows message queue is cleared after calling the Show() method to ensure all the controls on your form are rendered correctly. You may ensure the message queue is cleared by calling Utilities.DoEvents.

For example, assuming your Applet contains a form called test, you can write the following code:

Test.show
Utilities.DoEvents
' Perform some process here and update components on form test
' to indicate progress

Test.hide


Accessing Forms and Components at Runtime
Using Applet code, you can access and modify any form and component property at runtime. To access a specific component, in the code you need to provide the fully qualified name of the component, starting from the name of the component's parent form.

A fully qualified component name consists of:

· the component name prefixed by a period; and
· the component's parent component name (i.e. the parent component is the one which the component is sitting on).

This naming procedure is repeated until the parent form is reached.

For example, a button component has a caption property, which contains the text that appears on the face of the button. Assuming a form called 'test' contains a button called 'button1', the fully qualified name of the button would be

test.button1

You could use the following code to update the button's caption property:

test.button1.Caption = "This is the new caption"


Component Palette
The component palette appears at the top of the screen when in form design mode. The component palette contains the components you may use when designing forms. The component palette also contains controls that allow you to:

· save the current form and return the Formativ editor;
· cancel any form changes and return the Formativ editor; and
· toggle between the form and code view.

The Component Palette

Note: See the Formativ Readme.txt for information regarding component documentation.

To Use a Component

Click the component you wish to use from the palette, then click once on the form being designed. An instance of the component appears on the form. You may now use the Object Inspector to specify component properties and to define events.

To Save Changes

The Stop Designing button saves changes made to the current form and returns to the Formativ code editor.

Stop designing

To Cancel Changes

The Cancel Changes button discards changes made to the current form and returns to the Formativ code editor.

Cancel Changes

To Toggle Form Design/Code View

The Toggle Form/Source View button toggles between the form design and code editor views. You may also press F11 to toggle between the form design and code editor views.

Toggle View


Object Inspector
The Object Inspector shows the properties and events exposed by the selected component. Properties specify the appearance and behaviors of a component. Events specify the Formativ subroutine/function executed in response to a component event. You can specify properties at both design time and at runtime.

Object Inspector


Alignment Palette
The alignment palette is used to align groups of selected controls. You may align controls to the left, right, centre, etc.. Select the components you wish to align (select multiple components by Shift-Left mouse button clicking), then press the appropriate alignment option on the alignment palette.

Alignment Palette


Designed Form
The designed form is the canvas you use to create the form. You drop controls from the component palette onto the designed form. You can also specify designed form properties and events by selecting the designed form and using the Object Inspector.

Blank Designed Form


HTML Dialogs
Formativ HTML Dialogs are a powerful feature: You can create dialogs using industry-standard HTML. An HTML dialog may be used to display information to end users, as well as collecting data from users that can then be used by your Applets.

htmldialog
HTML Dialog

Note: Unless you need to target versions of Formativ prior to version 2.0, we recommend using the Visual Forms Designer Dialogs instead of HTML dialogs. Forms created with the visual forms designer are far richer and more flexible than HTML dialogs.


What are HTML Dialogs?
HTML dialogs are modal dialogs whose content consists purely of HTML and related content, such as JavaScript. HTML dialogs make it possible to build dialogs that contain interactive content.

HTML Dialog Characteristics

· HTML Dialogs are modal. This means the dialog must be closed before the Applet that created it (and GroupWise) can continue executing.

· HTML Dialogs can be displayed as standard floating windows, or they can be embedded into the GroupWise client. A floating dialog can be moved around the screen just like a normal window. Floating dialogs can also be resized. An embedded HTML dialog is displayed in the message/calendar list area of the GroupWise client. Embedded dialogs give the appearance that they are tightly integrated with the GroupWise client.

· HTML Dialogs display standard HTML content. They can also contain other Internet content, such as JavaScript.

· HTML Dialogs can be made to behave in an interactive manner through the use of Java, JavaScript, etc.

· Data entered into an HTML dialog is accessible from within the Formativ applet that created and displayed it via the FormVariables object.

· It is the developer's responsibility to add buttons that close the dialog. However, standard OK and Cancel toolbar buttons can be made to appear on the dialog.


Creating HTML Dialogs
HTML dialogs are created using the Utilities.NewHTMLDialog method. This method returns an instance of a new HTMLDialog object.

Utilities.NewHTMLDialog

The Utilities.NewHTMLDialog method returns an instance of a new HTMLDialog object. Once an instance of a HTMLDialog has been created, you set up its properties and finally, call its Execute method to display the dialog. For example:

Dim aDlg

Set aDlg = Utilities.NewHTMLDialog
aDlg.WindowState = fbsEmbedded
aDlg.Caption = "Publish Address Books to MS Word"
aDlg.HTMLCode = <supply HTML code here>
aDlg.Execute

This code snippet:

· defines a new HTMLDialog,
· sets its style to fbsEmbedded so that it will appear to be embedded into the GroupWise client,
· sets its caption and illustrates where the raw HTML containing the dialog controls would be assigned,
· finally, the .Execute method is called to display the dialog modally to the user.

You can assign any valid HTML code to the HTMLCode property.


HTML Dialog Content
HTML Dialogs can contain any valid HTML code. They can also contain HTML related content, such as Java and JavaScript in order to add functionality.

HTML Dialog Content

Most HTML dialog content will consist of an HTML <FORM> element with a number of form elements, such as text edit areas, list boxes and combo boxes. The <FORM> will also have at least one <INPUT TYPE="SUBMIT"> element representing a button used to dismiss the dialog. Formativ uses specially formatted <INPUT TYPE="SUBMIT"> elements in order to determine which button the user clicked in dismissing the dialog. For more information see Adding Buttons.

For example, to create a very simple HTML dialog that displays a message and an OK button, the following HTML could be used:

<HTML>
<BODY>
<FORM METHOD="POST" NAME="DlgForm">
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0">
<TR>
<TD VALIGN="MIDDLE">HTML Dialog Test</TD>
</TR>
</TABLE><P></P>
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0">
<TR>
<TD WIDTH="10"></TD>
<TD></TD>
<TD WIDTH="10" VALIGN="TOP" ALIGN="RIGHT"></TD>
<TD WIDTH="10" VALIGN="TOP" ALIGN="RIGHT"></TD>
<TD WIDTH="75%" VALIGN="TOP" ALIGN="RIGHT"><INPUT TYPE="SUBMIT"
NAME="MROK" VALUE="OK">&nbsp;&nbsp;<INPUT TYPE="SUBMIT"
NAME="MRCANCEL" VALUE="Cancel">&nbsp;</TD>
</TR>
</TABLE></FORM> </BODY>
</HTML>

The important things to note about this HTML are:

· Most of the code is within a <FORM> element. This is required in order to use form elements, such as edit controls, list boxes and buttons.

· The <FORM> element has its METHOD attribute set to POST. This is required in order for the act of clicking buttons to be recognized by Formativ.

· The two buttons have been defined as <INPUT TYPE="SUBMIT"> controls. This is required in order for the act of clicking buttons to be recognized by Formativ.

· The two buttons have special names assigned to their NAME attributes ("MROK" and "MRCANCEL"). These special names are used by Formativ to determine how the dialog was dismissed. For detailed information, see Adding Buttons.

When creating HTML dialog content, you can:

· Load an existing, external HTML file into an HTML dialog

· Dynamically build HTML content within your applet and assign it to the HTML dialog

· Load an existing, external HTML file into memory, modify its contents, then assign it to the HTML dialog.

Displaying Existing Data in a HTML Dialog

In some instances you may wish to to define your HTML content as separate, external files. This approach is particularly useful when you wish to maintain a central copy of the HTML, or the HTML is going to change on a regular basis.

In order to load an external HTML file into a HTML dialog, the simplest approach is to use the Utilities.LoadStringFromFile method to load the HTML file directly into the HTMLCode property of the HTMLDialog object. For example, the following code snippet creates a new dialog and uses the contents of the file 'HTML Dialog.htm' (located in the Formativ Data Directory) as the contents of the dialog:

Dim aDlg
Set aDlg = Utilities.NewHTMLDialog
aDlg.Caption = "Example HTML Dialog"
aDlg.HTMLCode = Utilities.LoadStringFromFile(Utilities.GetDataDirectory & "HTML Dialog.htm")
aDlg.Execute

Displaying Dynamically Built Data in a HTML Dialog

In many instances you will need to modify or generate HTML just prior to displaying a HTML dialog. For example, you may wish to dynamically add items to list box controls, or change text in the dialog, dependent on some external factor. In some instances an Applet will insert dynamic JavaScript that initializes the dialog controls, based on the state of some GroupWise data you have just extracted.

The simplest way to create dynamic content is to build markers into your base HTML, load the HTML into a Formativ Applet string variable, then manipulate the string in memory to make the appropriate changes. Once the changes are complete, assign the new HTML string variable to the .HTMLCode property and call the Execute method to display the dialog.

Interactive HTML Dialog Content

Because HTML Dialogs use industry-standard HTML and associated technologies, it is easy to build interactive, dynamic dialogs. You can use Java Applets, ActiveX controls and JavaScript to enrich the functionality of a HTML dialog. For example, using JavaScript, you can easily present different options to users when the user selects a new entry from a combo box.

Details on how to use JavaScript (and other technologies) to provide dynamic HTML content are beyond the scope of this document. There are many excellent resources available that document in great detail how to achieve a rich user experience.

Note: Local machine security policies may preclude certain content types from being used.


Adding Buttons
It is the developer's responsibility to provide users with buttons in HTML dialogs that allow for dismissing the dialog. Formativ can provide two toolbar buttons that act as OK and Cancel buttons, but this facility does not allow for data to be extracted from the dialogs. These buttons are provided only as an emergency exit for users to dismiss the HTML dialog.

Buttons are added to HTML dialogs using HTML <INPUT> elements. An example of a properly formed <INPUT> element is:

<INPUT TYPE="SUBMIT" NAME="[ID]" VALUE="[CAPTION]">

where:

· [ID] is a specially-coded button identification string (see below), and
· [CAPTION] is the string to appear on the button.

As with all HTML form controls, this code must appear within a <FORM></FORM> pair.

For example, a button that acts as an OK button when pressed might be defined as:

<INPUT TYPE="SUBMIT" NAME="MROK" VALUE="OK">

Button Identification

When a user presses an HTML dialog button, Formativ looks to see if it contains a specially-coded NAME attribute. A specially-coded NAME attribute indicates to Formativ that the dialog should be dismissed, and an appropriate return value handed back to your Applet, indicating which button the user clicked.

For example, to define a button that dismisses the dialog and indicates to the applet that the OK button was pressed, the following HTML code snippet might be used:

<INPUT TYPE="SUBMIT" NAME="MROK" VALUE="OK">

Note that the NAME attribute has been assigned the string value "MROK". "MROK" is recognized by Formativ as a button that is to dismiss the dialog and indicate to the calling Applet that the OK button was pressed.

Valid values for the NAME attribute are:

MROK
MRCANCEL
MRABORT
MRRETRY
MRIGNORE
MRYES
MRNO

Any other values assigned to the NAME attribute are ignored by Formativ. Pressing buttons without one of the above NAME values will not dismiss the dialog. Of course, such a button may initiate some other valid action, such as executing JavaScript in the dialog.

When a button containing one of the above NAME attributes is clicked, the dialog is dismissed and control returns to the calling Applet. A value indicating which button dismissed the dialog is returned by the HTMLDialog.Execute method.


HTML Dialog Properties
The Formativ HTML Dialog facility provides only the most rudimentary user interface by default. It is the responsibility of the developer to use HTML elements to provide the appropriate user interface elements, including buttons to dismiss the dialog. Formativ does provide a number of properties that can be used to customize the overall appearance and behavior of your HTML dialogs.

WindowState

The HTMLDialog.WindowState property is a read/write property that lets you control the overall appearance of your dialog. It can take one of three values:

· fbsDesigned – The dialog is displayed in the center of the screen.
· fbsMaximized – The dialog is displayed maximized.
· fbsEmbedded – The dialog is embedded in the GroupWise client.

Width and Height

The HTMLDialog.Width and HTMLDialog.Height properties control the overall width and height of a dialog in pixels. These settings only have an effect if the WindowState property is set to fbsDesigned.

BorderStyle

The HTMLDialog.BorderStyle property is a read/write property that lets you control the type of border for your dialog. It can take one of four values:

· fbsNone – The dialog has no visible border.
· fbsSingle – The dialog has a single line border.
· fbsSizeable – The dialog has a border that allows resizing of the dialog.
· fbsDialog – The dialog has a standard dialog border with no control buttons visible.

Note: BorderStyle has no effect if the WindowState property is set to fbsEmbedded.

Caption

The HTMLDialog.Caption property is a write-only string property that sets the caption text of the dialog. It has no effect if the WindowState property is set to fbsEmbedded.

ContextMenuEnabled

The HTMLDialog.ContextMenuEnabled property is a write-only Boolean property that controls whether the Internet Explorer mouse content menu is enabled when displaying HTML dialogs.

ToolbarVisible

The HTMLDialog.ToolbarVisible property is a read/write property that controls the visibility of the dialog toolbar. The dialog toolbar contains an OK and Cancel button. These buttons return OK and CANCEL values from the HTMLDialog.Execute method. These buttons do not activate the variable extraction routines normally available when using HTML <INPUT> elements to close the dialog.


Displaying HTML Dialogs
An HTML dialog is displayed by calling the HTMLDialog.Execute method. The Execute method displays the dialog modally, which means the user must dismiss it in order for processing to continue. An Applet pauses at the Execute method until a return value is obtained, indicating which button was used to dismiss the dialog.

The Execute Method

The Execute method returns an integer value indicating which button was used to dismiss the dialog. The possible return values are:

1 - MROK
2 - MRCANCEL
3 - MRABORT
4 - MRRETRY
5 - MRIGNORE
6 - MRYES
7 - MRNO

The labels MROK, MRCANCEL map directly to the names given to the button controls within your HTML. For full details see Adding Buttons.


Extracting Data from HTML Dialogs
As with Formativ Portals, you are able to extract the values of HTML form controls from your HTML dialogs. You access dialog data via the HTMLDialog.Variables property.

HTMLDialog.Variables

The HTMLDialog.Variables property is a read-only property that returns a FormVariables object. FormVariables is a collection of FormVariable objects. A FormVariable object represents a single HTML element and its value.

Once a dialog has been displayed via its Execute method, you query its Variables property to determine the value of the HTML form elements in the dialog. For more information see The FormVariables Object.


HTML Dialog Object Model
Utilities.NewHTMLDialog

Returns an instance of a new HTMLDialog object.

HTMLDialog

You may create any number of HTMLDialog objects in an applet.

HTMLDialog.Execute

Causes the dialog to be displayed modally. Returns an integer value indicating which button dismissed the dialog.

HTMLDialog.OpenGroupWiseMsgs

Read/write Boolean property. Specifies whether GroupWise MessageIDs embedded in HTML will cause the message to be opened when clicked. More information can be found here.

HTMLDialog.Navigate

Loads the HTML code at the given URL.

HTMLDialog.HTMLCode

Read/write string property. Lets you specify the HTML code to be displayed.

HTMLDialog.WindowState

Read/write property. Specifies how the dialog is to be displayed. Possible values are:

· fbsDesigned – The dialog is displayed in the center of the screen
· fbsMaximized – The dialog is displayed maximized
· fbsEmbedded – The dialog is embedded in the GroupWise client

HTMLDialog.Width

Read/write integer property. Specifies a width for the dialog in pixels. Only applicable if WindowState is fbsDesigned.

HTMLDialog.Height

Read/write integer property. Specifies a height for the dialog in pixels. Only applicable if WindowState is fbsDesigned.

HTMLDialog.BorderStyle

Read/write property. Specifies the border style of the dialog. Possible values are:

· fbsNone – The dialog has no visible border.
· fbsSingle – The dialog has a single line border.
· fbsSizeable – The dialog has a border that allows resizing of the dialog.
· fbsDialog – The dialog has a standard dialog border with no control buttons visible.

Note: The BorderStyle property has no effect if the WindowState property is set to fbsEmbedded.

HTMLDialog.Variables

Read-only property. Returns any variables and their values set by HTML form controls in the dialog. Variables are returned in a FormVariables collection.

HTMLDialog.Caption

Write-only string property. Specifies the caption displayed on the dialog. It has no effect if the WindowState property is set to fbsEmbedded.

HTMLDialog.ContextMenuEnabled

Write-only Boolean property. Specifies whether the mouse context menu should be accessible via the dialog.

HTMLDialog.ToolBarVisible

Read/write Boolean property. Specifies whether the dialog toolbar, containing OK and Cancel buttons, is visible.


Portals
The Formativ Portal Manager is a powerful feature that lets you create and embed portals into the GroupWise client. A portal is a window that can display many different types of data. The types of data you can display depends on the software you have installed on your computer, but at a minimum you can display web sites, XML, HTML and images. The Formativ Portal Manager lets you create and display any number of portals directly in the GroupWise client. You can also programmatically access the information being displayed in a portal.

The Portal Manager requires Novell GroupWise 6.01 or greater. Novell have also released a beta FTF file for the GroupWise 5.5.7.1 Enhancement Pack client which enables the use of Formativ Portal Manager™ based solutions with the GroupWise 5.5 EP client. See Novell TID 2963458 for details on the update and information on how to download the GroupWise 5.5.7.2 Beta FTF file (f32eppp1.exe).

portal
The Today View portal embedded in GroupWise


What is a Portal?
A portal is a custom window that appears embedded in the GroupWise client. It can be used to display any information that Microsoft Internet Explorer can display, such as HTML, XML, images, web sites, etc.

You can display pre-existing content in a portal (such as a web site or XML file), or you can display content built dynamically by a Formativ Applet. For example, you could write an Applet that extracts all of today's appointments from your GroupWise calendar, builds HTML representing the appointments, then displays the HTML inside a portal.

Portal Characteristics

· Portals are custom windows that appear in the GroupWise client

· Portals appear in the calendar/message list area of the GroupWise client

· Portals use Microsoft Internet Explorer to display content (you need to have Microsoft Internet Explorer 5.5 or later installed to use the portal manager)

· You can build dynamic content and display it in a portal, or you can display existing content, such as a web page

· You can extract information from a portal and use it an applet

· You can use a portal to open GroupWise items by clicking on specially formatted HTML links

· You can customize the appearance of a portal window to include standard browser buttons, captions, etc.

· Portals are persistent. This means that a portal and its contents remain active during a GroupWise session, even if hidden. This means you can display live content in a portal (such as a web site), hide the portal then open it again in the same session – with its content unchanged.

· Portals use Microsoft's Internet Explorer security settings. This means the settings defined in IE's Internet Options will also affect any portals you create.

· You can create any number of portals. If more than one portal exists and they are visible, each portal appears on its own tab within the GroupWise client. Users can click a tab to activate a portal, or an Applet can programmatically activate a particular portal.


Creating a Portal
Portals are created and managed using the Formativ Portal Manager. The Formativ Portal Manager is accessed via the Formativ Portal Object Model.

The Portal Manager

The Formativ Portal Manager is accessed via the GroupWise.PortalManager object. For example, the following code sets the variable iPortals to the portal manager's Portals collection.

' Get an instance of the Portals collection
Set iPortals = GroupWise.PortalManager.Portals

To create a new portal, simply call the .Add method of the PortalManager.Portals object. The .Add method returns a new portal object. The following code creates a new portal object and sets some properties. Note that this does not display the portal in the client.

Set iPortal1 = iPortals.Add
iPortal1.Caption = "Advansys Home"
iPortal1.TabCaption = "Advansys"
iPortal1.ID = "PORTAL1"
iPortal1.NavigationControlsEnabled = True
iPortal1.URLInputEnabled = True
iPortal1.Url = PORTAL_URL1

Portal IDs

Each portal has a unique ID which is accessible via the .ID property of the Portal object. A portal ID is a string that uniquely identifies a portal. Portal ID's are used to locate portals within the Portals collection. You can manually allocate a portal ID (as is done in the example above), or you can let Formativ automatically allocate an ID for you. The Portal Manager will allocate an ID of "Portal1" to the first portal you create, "Portal2" to the second and so on. It is often useful to override the default portal ID with something more meaningful so that you can programmatically access the portal later in the session.

Note: Remember that portals are persistent within a GroupWise session. Even after an Applet that created a portal has finished running, the portal will persist until the user explicitly destroys the portal, the portal is destroyed by an Applet, or GroupWise is shut down.

Checking if a Portal Exists

There are many instances where your Applets need to check if a particular portal already exists. For example, you may have an Applet that creates a portal to display a particular web site. You want your users to be able to keep the portal active for the current GroupWise session, even if the portal is hidden during the session. Each time the Applet is executed, it should first check to see if the portal has been previously created. If it has, the portal simply needs to be displayed. If it has not been previously created, it needs to be created then displayed.

This functionality can be achieved by checking for the portal via the Portals.Item property:

Set iPortal1 = iPortals.Item("PORTAL1")

' If the above code did not return a portal, create it (this will happen the
' first time the applet is executed during a session).
If iPortal1 is Nothing Then
    Set iPortal1 = iPortals.Add
    iPortal1.Caption = "Advansys Home"
    iPortal1.TabCaption = "Advansys"
    iPortal1.ID = "PORTAL1"
    iPortal1.NavigationControlsEnabled = True
    iPortal1.URLInputEnabled = True
    iPortal1.Url = PORTAL_URL1
End If

In this example, we try to set iPortal1 to be the portal with the unique ID "PORTAL1" by passing the portal ID to the Portals.Item property. If a portal with this ID exists, it is assigned to the iPortal1 variable, and can then be shown. We check for an object by comparing the return variable (iPortal1) against the nothing data type:

If iPortal1 is Nothing Then
    ...
End If


Displaying a Portal
To display a portal, call its .Show method. This has the effect of displaying all portals that have their Visible property set to TRUE.

Portals are displayed in the calendar/message list area of the GroupWise client. If messages were being displayed when the portal was shown, you need to hide the portal in order to see the messages again. You can still view calendar data by selecting a calendar view in GroupWise. Reselecting a message view in the client causes the portal(s) to reappear. The opposite effect is seen if the user has a calendar view open when a portal is shown.

Note: Portals are asynchronous in nature. This means that when a portal is shown, your Applet continues to run. This means you cannot pause your applet and wait for certain conditions to be met before continuing. You can achieve the same result by using the portal Applet execution feature.

To Display a Portal

To display a portal, call its .Show method. For example

iPortal1.Show

To Select a Portal

If more than one portal exists, each portal is shown on a single tab. Calling a portal's .Show method is not sufficient in order for that portal to be the one that is ultimately shown. To ensure a particular portal is visible, you need to set the Portals.ActivePortal property. The ActivePortal property is a string representing the unique ID of the portal that is currently visible. For example:

iPortals.ActivePortal = "PORTAL1"

makes the portal with the ID "PORTAL1" the frontmost portal in the GroupWise client.


Portal User Interface
Portals appear within the GroupWise client. They appear in the message list/calendar area of the client. The portal interface consists of a toolbar, the portal itself, and a number of tabs if more than one portal has been defined. The user can select which portal to view by clicking on the tabs, or you can programmatically define which portal should be frontmost.

You can customize the controls that appear on individual portal toolbars by using the properties exposed by the portal object. For example, you can make a URL edit control appear on one portal but not another.

Customizing the portal toolbar

You customize the portal toolbar for an individual portal by using the properties exposed by the Portal object. The appropriate properties are:

.Caption = [String value]

The .Caption property specifies the text that appears at the top of the portal page within the toolbar area. This property is optional, and an empty value results in no caption being displayed.

.TabCaption = [String value]

The .TabCaption property specifies the text that appears on the tab holding this portal. The tab is only visible if more than one portal has been created.

.NavigationControlsEnabled = True|False

The .NavigationControlsEnabled property specifies whether the HTML navigation buttons (back, forward, refresh and stop) appear on the portal toolbar.

.URLInputEnabled = True|False

The .URLInputEnabled property specifies whether the URL edit control appears on the toolbar.

.CanClose = True|False

Setting .CanClose to FALSE will hide the Close Portal button and prevent the user from manually closing the Portal. A value of TRUE will display the Close Portal button.

.HideCloseControlsEnabled = True|False

Setting .HideCloseControlsEnabled to FALSE hides the Hide all Portals, Hide this Portal and Close this Portal buttons. A value of TRUE will display all close and hide buttons, unless the CanClose property is FALSE, in which case the Close this Portal button will not be displayed.


Portal Content
There are two main ways to get content into a portal for display:

· Use existing data (such as a web site or local HTML), or
· Have your Applet dynamically create content and load it into a portal for display.

Using Existing Data

The primary means of loading existing data into a portal is to use the portal.URL property. The .URL property is a string that accepts any properly formed URL. A URL can be the address of a web site, or the full path to a file. (Assuming you have an appropriate browser plug-in installed, you can view documents other than HTML directly inside the portal.)

For example, to browse to the Advansys web site, use the following syntax (assuming iPortal1 represents a Portal object):

iPortal1.Url = "www.advansyscorp.com"

To load the contents of a file into a portal, use:

iPortal1.Url = "C:\FileList.txt"

Creating Content

Portal objects expose a .HTML property. This string property lets you both read and write the HTML contents of a portal.

Writing a value to the .HTML property clears the portal of any existing data and loads it with the given HTML content. The HTML string supplied must represent a valid HTML document.

This technique makes it possible to dynamically build content based on GroupWise data, or any other accessible data. For example, you could write an Applet that extracts calendar information from your GroupWise account, then builds an HTML representation of the data. This HTML is finally loaded into a portal and displayed.

For example, here is a simple Applet that builds dynamic HTML content and displays it to the user in a portal:

Dim iPortal1
Dim iPortals

Set iPortals = GroupWise.PortalManager.Portals
Set iPortal1 = iPortals.Item("Example")

If iPortal1 is Nothing Then
    Set iPortal1 = iPortals.add
    iPortal1.ID = "Example"
    iPortal1.NavigationControlsEnabled = True
    iPortal1.HTML = "<html><body>Hello " & GroupWise.Account.Owner.DisplayName & ", welcome to Formativ!</body></html>"
End If

iPortal1.Show
iPortals.ActivePortal = iPortal1.ID


The FormVariables Object
The FormVariables object is used to access values from a HTML form. FormVariables is a collection of FormVariable objects. A FormVariable object represents the name and value of an HTML form element. The FormVariables object is updated whenever a POST operation is performed within a portal that contains a HTML form.

The FormVariables Object

The FormVariables object is available for use automatically within an applet. It does not have to be instantiated from any other objects. FormVariables is a collection of FormVariable objects (see below), and exposes the following properties and methods:

FormVariables.Count

FormVariables.Count is a read-only integer property. It returns the number of FormVariable objects currently in the collection.

FormVariables.Item(Index Integer)

FormVariables.Item is a read-only property. It returns the FormVariable object that has the given index value.

FormVariables.ItemByName(Name String)

FormVariables.ItemByName is a method. It returns the FormVariable object that has the name given in Name. The .ItemByName method is a convenient means to determine if a FormVariable with a given name exists in the collection.

FormVariable

FormVariable represents a single HTML form variable. All FormVariable objects are managed by the FormVariables object. FormVariable exposes the following properties:

FormVariable.Name

FormVariable.Name is a read-only string property. It contains the name of the HTML form variable.

FormVariable.Value

FormVariable.Value is a read-only string property. It contains the value of the HTML form variable.

Mapping HTML to FormVariable Objects

Formativ automatically maps HTML form elements to FormVariable objects when the POST operation is called on a form:

<FORM METHOD="POST">
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0">
<TR VALIGN="MIDDLE">
<TD VALIGN="MIDDLE" ALIGN="LEFT" CLASS="headingdate"></TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT" WIDTH="50%" COLSPAN="2">[TODAY_DATE]</TD>
<TD VALIGN="MIDDLE" ALIGN="RIGHT" WIDTH="50%" COLSPAN="2" HEIGHT="35">
<INPUT TYPE="HIDDEN" NAME="formativapplet" VALUE="today view_flexlock.vbf"><INPUT TYPE="SUBMIT" NAME="DisplaySettings" VALUE="Settings..."></TD>
</TR>
</TABLE>
</FORM>


Extracting Portal Information
Not only do Formativ portals let you define content, they also expose the contents of a portal to your Applets. This powerful feature enables you to:

· Extract and process the raw HTML a portal may be displaying
· Extract data from HTML forms being displayed in a portal
· Execute a Formativ applet from a portal

Extracting HTML from a portal

The portal object exposes a property called .HTML. The .HTML property is a read/write string property that lets you access the raw HTML code currently being displayed in a portal. This feature lets you create Applets that can visit a web site and analyze its content.

To access a portal's raw HTML, simply read the .HTML property into a string variable. For example, the following Applet creates a portal, navigates to a web site and counts the number of "bold on" attributes ("<B>") found:

Const BOLDATTR = "<B>"
Dim iPortal1
Dim iPortals
Dim iHTML

Set iPortals = GroupWise.PortalManager.Portals
Set iPortal1 = iPortals.Item("Example")

If iPortal1 is Nothing Then
   Set iPortal1 = iPortals.Add
   iPortal1.ID = "Example"
   iPortal1.NavigationControlsEnabled = True
   iPortal1.URL = "www.advansyscorp.com"
End If

iPortal1.Show

' Wait for the portal to load
While ((iPortal1.ReadyState <> READYSTATE_COMPLETE) And (iPortal1.ReadyState <> READYSTATE_INTERACTIVE))
   Utilities.DoEvents
Wend

iHTML = iPortal1.HTML

iFound = 0
iPos = 0
iPos = InStr(1, iHTML, BOLDATTR, vbTextCompare)
While iPos > 0
   iFound = iFound + 1
   iPos = InStr(iPos + Len(BOLDATTR), iHTML, BOLDATTR, vbTextCompare)
Wend

MsgBox iFound & " instances of <B> were found."

It is important to note that the Portal.HTML property will not return the portal's source code until the entire document has been loaded. You can check this by querying the Portal.ReadyState property, documented in the Language Guide. A peculiarity of the Microsoft Internet Explorer window used by the portals is that it does not return the appropriate ready state unless it is visible. This means that you need to display a portal via its .Show method to ensure it has completely loaded before you can reliably query the .ReadyState and .HTML properties.

Extracting Data from HTML Forms

It is easy to extract data from portals displaying HTML forms. The ability to extract data from a portal, coupled with the ability to execute an applet from a portal (see below), makes it easy to build very powerful and flexible data collection systems in GroupWise. For example, you could create a portal that displays an HTML form to the user. When the user completes the form and presses a button on the form, the data entered on the form can then be used by another Applet to perform further processing. The Today View Applet that ships with Formativ is a complete working example of such a system.

The FormVariables object is used to access data from a HTML form. This object lets you access the names and values of every named HTML form element contained in a portal.

For example, the following Applet creates a portal that displays a simple HTML form. The form consists of two text edit controls and a button. When the button is pressed, the applet is automatically re-executed via a portal trigger. The Applet determines that it has been executed as a result of a portal trigger, then uses the FormVariables object to access and display the values of the two text edit controls.

Dim iDlg

'-------------------------------------------------------------------------------
' Main line processing
'-------------------------------------------------------------------------------
Sub Main(Client, GWEvent)

ExecutePortal

' If the Ok button was clicked
If GWEvent = "HTML_TRIGGER" Then
   ReadUserData
End If

End Sub

'-------------------------------------------------------------------------------
' Execute the portal
'-------------------------------------------------------------------------------
Sub ExecutePortal

   Dim iPortal
   Dim iPortals

   iPortalID = "Test"

   Set iPortals = GroupWise.PortalManager.Portals
   Set iPortal = iPortals.Item(iPortalID)

   If iPortal is Nothing Then
      Set iPortal = iPortals.Add
      With iPortal
         .Caption = "Formativ Business Solutions"
         .TabCaption = "Test"
         .ID = iPortalID
         .OpenMessages = True
         .RunApplets = True
         .HTML = Utilities.LoadStringFromFile(Utilities.GetDataDirectory + "testPortal.htm")
      End With
   End If

   iPortal.Show
   iPortals.ActivePortal = iPortalID

End Sub

'-------------------------------------------------------------------------------
' Read the dialog value if 'Ok' button pressed
'-------------------------------------------------------------------------------
Function ReadUserData

   Dim iProcess
   Dim iNameCTL
   Dim iAddressCTL

   Set iProcess = FormVariables.ItemByName("MROK")
   If Not iProcess is Nothing Then
      ' Get the text inside the name field
      Set iNameCTL = FormVariables.ItemByName("nameCTL")
      If Not iNameCTL is Nothing Then
         Call MsgBox(iNameCTL.Value, vbInformation, "Name")
      End If

      ' Get the text inside the address field
      Set iAddressCTL = FormVariables.ItemByName("addressCTL")
      If Not iAddressCTL is Nothing Then
         Call MsgBox(iAddressCTL.Value, vbInformation, "Address")
      End If
   End If

   Set iProcess = Nothing

End Function

The HTML used by this example is shown below; note the hidden input element named "formativapplet". This is a specially coded <INPUT> type that tells Formativ it needs to execute the Applet named in the VALUE element when the button is pressed. Notice also that the two edit box controls have been named 'nameCTL' and 'addressCTL'. These names map directly to the FormVariables object in Formativ, and are used to name the instances of the FormVariable objects returned by the FormVariables collection. You can see how to access these objects in the Applet example above.

For example, to obtain the value of the text entered in the INPUT control called 'nameCTL', we could use the following applet code:

Set iNameCTL = FormVariables.ItemByName("nameCTL")
If Not iNameCTL is Nothing Then
   Call MsgBox(iNameCTL.Value, vbInformation, "Name")
End If

<HTML>
<HEAD>
<TITLE></TITLE>
</HEAD>
<BODY>
<FORM METHOD="POST">
<TABLE WIDTH="100%">
<TR>
<TD></TD>
<TD HEIGHT="50">Enter text and click 'Ok'.</TD>
</TR>
<TR>
<TD>Name: </TD>
<TD> <INPUT TYPE="TEXT" NAME="nameCTL" SIZE="60"></TD>
</TR>
<TR>
<TD>Address:</TD>
<TD> <INPUT TYPE="TEXT" NAME="addressCTL" SIZE="60"></TD>
</TR>
<TR>
<TD></TD>
<TD></TD>
</TR>
<TR>
<TD></TD>
<TD ALIGN="RIGHT"><INPUT TYPE="HIDDEN" NAME="formativapplet" VALUE="Test.vbf">
<INPUT TYPE="SUBMIT" NAME="MROK" VALUE="Ok">&nbsp;&nbsp;</TD>
</TR>
</TABLE></FORM> </BODY>
</HTML>


Opening GroupWise Messages from a Portal
Formativ portals recognize specially formatted links within HTML as links to messages in the GroupWise message store. Using this technique, you can dynamically build HTML that lets users click on a link that automatically opens any GroupWise message. For example, the Today View Applet that ships with Formativ dynamically builds HTML representing calendar information. When any item in the portal is clicked by the user, the original GroupWise message represented by that item is opened automatically.

Creating a Portal that supports automatic opening of GroupWise messages

In order for this feature to work, you need to set the Portal.OpenMessages property to TRUE. Portal.OpenMessages is a read/write Boolean property. Portal.OpenMessages is FALSE by default.

For example, the following code snippet shows how to create a portal that supports automatic opening of GroupWise messages:

Set iPortal1 = iPortals.Add
iPortal1.OpenMessages = True

Encoding GroupWise MessageIDs

In order to build HTML that automatically opens a GroupWise message, you need to build a specially formatted HREF attribute containing the MessageID of the message to be opened (a MessageID is the unique ID of a message). A properly-formed MessageID HREF element is shown below:

<A HREF="UID:[MessageID]">[Description]</A>

where:

· [MessageID] is the unique MessageID of the message to be displayed when the link is clicked, and
· [Description] is the text that describes the link.

An example of such a link is:

<A HREF="UID:3C8467EB.GWDEVDOM.GWDEVPO.100.16D676D.1.68B.1"><B>Sales Meeting</B></A>

This HTML code will result in a link being displayed with the label "Sales Meeting". When the link is clicked, the original GroupWise message (in this case an Appointment) will be automatically opened for the user.

For example, the following Applet extracts the subjects of the currently selected messages from your GroupWise account and displays each subject in a portal. When a subject entry is clicked, the original GroupWise item is opened:

Sub Main(Client, GWEvent)

   Dim iHRT
   Dim iMsg
   Dim iPortal
   Dim iPortals
   Dim iHTML
   Dim x

   iHRT = Chr(13) & Chr(10)

   Set iPortals = GroupWise.PortalManager.Portals
   Set iPortal = iPortals.Item("Example")

   If iPortal is Nothing Then
      Set iPortal = iPortals.Add
      iPortal.ID = "Example"
      iPortal.OpenMessages = True
      iPortal.NavigationControlsEnabled = False
   End If

   iCount = Client.ClientState.SelectedMessages.Count
   For x = 1 To iCount
      Set iMsg = Client.ClientState.SelectedMessages.Item(x)
      iHTML = iHTML & iHRT & "<A HREF=""UID:"& iMsg.MessageID &"""><B>" & iMsg.Subject & "</B></A><BR>"
   next

   iPortal.HTML = "<HTML><BODY>" & iHTML & "</BODY></HTML>"
   iPortal.Show
   iPortals.ActivePortal = iPortal.ID

End Sub


Executing Applets from a Portal
Formativ portals let you optionally execute an Applet when a portal HTML button is clicked. This is useful for when you need to perform further processing based on the content of a portal. For example, the Today View Applet has a Settings button. When this button is clicked, another HTML page is loaded into the same portal that allows users to specify user interface settings. When the OK button on this portal is clicked, the settings entered are used to redisplay the Today View portal. All this functionality is achieved by automatically executing the same Applet from within the portal and using data obtained via the FormVariables object.

Executing an Applet from a Portal

You can execute a Formativ applet by defining a hidden HTML <INPUT> element within an HTML form. When a SUBMIT action is sent (as a result of pressing a button, for example), Formativ looks for any hidden <INPUT> elements that are formatted to execute Applets. If it finds one, Formativ executes the Applet defined in the tag.

A properly formatted <INPUT> element is shown below:

<INPUT TYPE="HIDDEN" NAME="formativapplet" VALUE="[appletname]">

where:

[appletname] is the name of the applet to execute, including the .VBF extension.

For example, the following HTML code snippet defines an HTML form that contains a SUBMIT button with the caption "Settings...". When this button is clicked, Formativ locates the tag

<INPUT TYPE="HIDDEN" NAME="formativapplet" VALUE="today view_flexalock.vbf">

and executes the Applet called "today view_flexalock.vbf".

<FORM METHOD="POST">
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0">
<TR VALIGN="MIDDLE">
<TD VALIGN="MIDDLE" ALIGN="LEFT" CLASS="headingdate"></TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT" WIDTH="50%">Date</TD>
<TD VALIGN="MIDDLE" ALIGN="RIGHT" WIDTH="50%>
<INPUT TYPE="HIDDEN" NAME="formativapplet" VALUE="today view_flexalock.vbf"><INPUT
TYPE="SUBMIT" NAME="DisplaySettings" VALUE="Settings..."></TD>
</TR>
</TABLE>
</FORM>

Note: This technique can only be used to execute local Applets.

Determining if an Applet is being executed via a Portal

In many cases your Applet needs to know if it is being executed as a result of a portal input tag as described above. For example, the above code causes the "today view_flexalock.vbf" Applet to be executed. This is the same Applet that dynamically built the original portal. When this Applet is executed as a result of the "Settings..." buttons being clicked, instead of redisplaying the Today View portal, we need it to display the Settings portal content instead.

An Applet can detect if it is being executed as a result of a portal by checking the GWEvent parameter of the Main subroutine in every Applet. If the GWEvent parameter equals the string "HTML_TRIGGER", the Applet is being executed as a result of a portal trigger.

For example, the following code snippet illustrates how it is possible for an Applet to perform different processing if it was executed as a result of a portal trigger:

Sub Main(Client, GWEvent)
   If GWEvent = "HTML_TRIGGER" Then
      DetermineAction
   Else
      DisplayView
   End If
End Sub

In this example, the Applet will call the DetermineAction subroutine if the Applet is being called as a result of a portal trigger. Otherwise, the Applet will call the DisplayView subroutine.

If the DetermineAction subroutine was called, it would probably use the FormVariables collection to access the data that was entered into the form at run time.


Portal Object Model
GroupWise.PortalManager

Returns the single instance object of the PortalManager.

PortalManager

There is only one instance of the PortalManager available at any time. The PortalManager persists for the duration of the GroupWise session.

PortalManager.Portals

Returns a reference to the single instance Portals object.

PortalManager.ShowAll

Shows all portals.

PortalManager.HideAll

Hides all portals.

Portals

Portals is a collection of individual Portal objects. It is returned by the PortalManager.Portals property.

Portals.Count

Returns the number of Portals which have been created.

Portals.Item(Index)

Returns the Portal object identified by the Index parameter. The index parameter can be an integer or a string portal ID.

Portals.Delete(Index)

Deletes and destroys the Portal identified by the Index parameter. The index parameter can be an integer or a string portal ID.

Portals.Clear

Clears and destroys all Portals.

Portals.Add

Creates and returns a new Portal. A unique Portal ID is assigned automatically. The string ID can be set to another value by using the Portal.ID parameter. See the Portal object for details.

Portals.ActivePortal

Gets or returns the active Portal ID by using the Portal.ID parameter string value.

Portal

Portal represents a single portal object. A portal will persist for the duration of a GroupWise session unless it is explicitly destroyed by the user or by an Applet.

Portal.ID

The unique string ID associated with a Portal. A portal ID is automatically assigned when you create a new portal, or you can define your own.

Portal.Caption

Sets or returns the text located at the top left of the Portal toolbar.

Portal.TabCaption

Sets or returns the Portal tab caption text.

Portal.TabVisible

Sets or returns whether the Portal tab is visible or hidden.

Portal.HTML

Sets or returns the HTML source for each Portal. Setting the HTML property will render the page within the Portal. Reading the HTML property will return the HTML source displayed in the Portal.

Portal.CanClose

Setting CanClose to FALSE will hide the Close Portal button and prevent the user from manually closing the Portal. A value of TRUE will display the Close Portal button.

Portal.RunApplets

A value of TRUE instructs Formativ to parse and run an Applet which is referenced in an HTML form SUBMIT function. This feature enables Applets to be executed from HTML pages. A value of FALSE will cause Formativ to process the SUBMIT function as a normal HTML form process and will ignore any embedded Applet references.

Portal.OpenMessages

A value of TRUE will instruct Formativ to parse the user-selected URL and extract any embedded GroupWise MessageID. If a valid MessageID is found, Formativ will automatically open the associated message and display it using the standard GroupWise client view. A value of FALSE will activate user-selected URL's using standard browser operation and will not look for embedded GroupWise MessageID's.

Portal.URL

Setting the URL property will cause the Portal to display the content at the location specified by the URL. Reading the URL property will return the URL for the content currently displayed in the Portal.

Portal.Visible

Setting this property to TRUE will make the Portal visible. Setting the value to FALSE will hide the Portal. Reading the property will return the current visibility of the Portal. See also the Show and Hide methods.

Portal.Delete

The Delete method destroys the Portal and removes the Portal ID from the list of available Portals.

Portal.Show

The Show method makes the Portal visible and sets it as the topmost, active Portal.

Portal.Hide

The Hide method hides the Portal from view.

Portal.URLInputEnabled

Set to TRUE to display the URL navigation edit control. A value of FALSE will hide the URL navigation edit control.

Portal.NavigationControlsEnabled

TRUE displays the Forward, Back, Refresh and Stop Activity browser controls. FALSE hides these browser navigation controls.

Portal.HideCloseControlsEnabled

FALSE hides the Hide all Portals, Hide this Portal and Close this Portal buttons. A value of TRUE will display all close and hide buttons, unless the CanClose property is FALSE, in which case the Close this Portal button will not be displayed.

Portal.ReadyState

Indicates the state of the Web browser control. Read ReadyState to obtain state information specific to the Web browser control. Use this information to avoid attempting to use the Web browser control when it is not ready to perform an action. The portal must be visible in order to obtain an accurate result from this property. The following table lists the possible values:

READYSTATE_UNINITIALIZED | Default initialization state. The control has not begun loading any properties.
READYSTATE_LOADING | The control is loading its properties.
READYSTATE_LOADED | The control has initialized its properties but is not yet interactive.
READYSTATE_INTERACTIVE | The control is interactive, but not all of its data is available. (It is downloading a document or frame).
READYSTATE_COMPLETE | The control is interactive and all of its data is available. (The current document is fully downloaded.)

Portal.Document

Provides access to the Automation interface of the portal's HTML document. Use Document to access an IDispatch interface for manipulating the contents of the HTML document through the COM object model. If there is no active document, Document is empty. That is, you must first load a document using the HTML or URL properties before you can manipulate it using the Document interface. For more information about the Document interface, see the document object section of Microsoft's Dynamic HTML reference.


Applet Chaining
Formativ 2.0 allows you to specify an Applet that should be executed when the current Applet has finished executing. Applet Chaining makes it possible to build interactive solutions based on two or more discrete Applets.

Formativ 2.0 also introduces the concept of Applet Data Exchange, which makes it easy for one Applet to pass data to another via a global 'scratch pad'. This feature can be used to pass data between Applets during chaining.

Specifying an Applet to Chain

Specify the Applet you wish to chain by providing its name to the Utilities.ChainApplet property. Only the Applet name needs to be supplied, though the full path may optionally be supplied. When the Applet containing this line finishes executing, the Applet indicated by Utilities.ChainApplet will be automatically executed (assuming the Applet is available).

You can only specify one chain Applet at a time. If your Applet makes two calls to ChainApplet, only the most recent call will take effect.

Note: The Applet you specify in the Utilities.ChainApplet property does not get executed until the current Applet finishes.

For example, suppose you wish to chain an Applet called 'test.vbf'. You would simply need to enter the following line in your chaining Applet:

Utilities.ChainApplet = "test.vbf"

Checking an Applet is Available to be Chained

It is good practice to first check that an Applet you wish to chain is actually available on the user's computer. The easiest way to check that a particular Applet exists is to use the Utilities.AppletInstalled() method. This method takes as its only argument the name of the Applet you wish to chain. It returns a Boolean indicating if the Applet is actually installed on the current computer.

For example, if you wished to chain an Applet called 'test.vbf', you could confirm it first existed by using the following code:

If Not Utilities.AppletInstalled(IDR_APPLET_TO_CHAIN) Then
   MsgBox "Sorry - this applet is not installed.", 0, IDS_TITLE
Else
   Utilities.ChainApplet = IDR_APPLET_TO_CHAIN
End If


Applet Data Exchange
In some situations you may wish to pass data between two or more Applets. This is particularly useful when used with Applet Chaining. Formativ 2.0 introduces a global property, accessible to all Applets in the system.

Passing Data Between Applets

To pass data between two or more Applets, assign the data to the Utilities.TransferData property. Utilities.TransferData is a read/write property that accepts string data. As long as you can coerce your data into a string you may assign it to the Utilities.TransferData property.

Consider the following scenario. You have two Applets, A and B. You want to pass the subject of a message from Applet A to Applet B. You want Applet B to automatically run once Applet A is done.

Applet A:

Sub Main(Client, GWEvent)
   Utilities.ChainApplet = "B.vbf"
   Utilities.TransferData = "This is the data we want to transfer to Applet B"
End Sub

Applet B:

Sub Main(Client, GWEvent)
   MsgBox Utilities.TransferData, 0, "This is the transferred data"
End Sub

When Applet A finishes executing, Applet B will automatically start and display a message box containing the string "This is the data we want to transfer to applet B".

Security Considerations

· The Utilities.TransferData property is a global property, available to all Applets running on the computer. This means any Applet is free to modify or delete the contents of the property at any time. Your Applets should never assume the contents of Utilities.TransferData are the expected contents. Ideally, you should check the format of the contents of Utilities.TransferData before using it.

· Because the Utilities.TransferData is global, you should not use it to transfer sensitive information using plain text. Encrypt sensitive data before placing it in the Utilities.TransferData property.


Working with XML
The Formativ Applet language makes it easier to work with XML data. The native Microsoft XML Document Object Model is exposed via the Utilities.XMLDom method. The Utilities.XMLDom method returns an instance of the Formativ XMLDom object.

The XMLDom Object

An instance of the XMLDom object can be obtained by calling the Utilities.XMLDom method. A XMLDom object has the following methods and properties:

LoadFromDisk(const XMLFile: String)

This method loads an existing XML file into the DOM. Returns a Boolean indicating success.

LoadFromString(const XMLString: String)

This method loads the DOM with a string containing XML data. Returns a Boolean indicating success.

SaveToDisk(const Filename: String)

This method saves the contents of the DOM to disk using the supplied filename.

Document

This property returns an instance of a IXMLDOMDocument2 interface. This interface gives you native access to the XML DOM. The IXMLDOMDocument2 interface is defined by Microsoft.


Working with HTML
The Formativ Applet language makes it easier to work with HTML data. The native Microsoft HTML Document Object Model is exposed via the Utilities.HTMLDom method. The Utilities.HTMLDom method returns an instance of the Formativ HTMLDom object.

The HTMLDom Object

An instance of the HTMLDom object can be obtained by calling the Utilities.HTMLDom method. A HTMLDom object has the following methods and properties:

LoadFromDisk(const Filename: String)

Method. Loads an existing HTML file into the DOM. Returns a Boolean indicating success.

SaveToDisk(const Filename: String)

Method. Saves the contents of the DOM to disk using the supplied filename.

LoadFromURL(const SourceURL: String)

Method. Loads the HTML at the given URL into the DOM. Returns a Boolean indicating success.

DosPathToUnixPath(const DosPath: String)

Helper method to convert a DOS-compatible path specification to a UNIX-compatible path specification as used on the Web. Use DosPathToUnixPath to convert a path name on the local machine to a path name that can be sent in an HTTP message, or that will be used by a UNIX-based application. DosPathToUnixPath converts all backslash characters (\) to forward slash characters (/).

HTMLDecode(const HTMLIn: String)

Helper method to decode an HTML entity reference, e.g. from "&amp;" to "&". Returns a string.

HTMLEncode(const HTMLIn: String)

Helper method to encode an HTML entity reference, e.g. from "&" to "&amp;". Returns a string.

HTTPDecode(const HTMLIn: String)

Helper method to decode a string that includes HTTP escape characters. Decodes the escape characters (+ and %) in a string that comes from an HTTP message header. Plus characters (+) are converted into spaces. Percent signs (%) indicate that the next two characters are the hex representation of a character. If a percent sign is followed by another percent sign (%%), it is converted into a single percent sign. Returns a string.

HTTPEncode(const HTMLIn: String)

Helper method to convert a string into a form that contains no characters that are illegal in an HTTP message header. Converts all characters except for the letters A through Z (and a through z), numerals 0 through 9, the asterisk (*), dollar sign ($), exclamation point (!), at sign (@), period (.), underscore (_), single quote ('), comma (,) parentheses, and hyphen (-). Spaces are converted to plus characters (+), and every other character is converted into a hex value prefixed by the percent sign (%). Returns a string.

UnixPathToDosPath(const UnixPath: String)

Helper method that performs the reverse of DosPathToUnixPath (see above). Returns a string.

Document

Property. Returns an instance of Microsoft's IHTMLDocument2 interface for the given document. IHTMLDocument2 gives you full access the HTML DOM.

Note: Formativ includes several helper methods designed to make working with the HTML DOM easier. See Utilities.IHTMLDocumentSaveToFile(), Utilities.IHTMLDocumentAsString() and Utilities.IHTMLDocumentFromViewHandle() for more information.


Accessing the HTML of a GroupWise Message
Formativ 2.0 introduces the ability to access the native HTML code behind an HTML message view. If the message is a received message, you may access the HTML in read-only mode. If the message is being composed, you may both read and write the native HTML code.

This facility means you are able to programmatically assign HTML content to composing messages. For example, you could use this facility to personalize the content of a HTML message via an Applet.

Accessing a Message View's IHTMLDocument2 Interface

You access the raw HTML in a message view using the IHTMLDocument2 interface. IHTMLDocument2 gives you full access to the HTML via an extensive document object model, or DOM.

You can only access the IHTMLDocument2 interface for the currently open message view. You cannot use this technique to access HTML content in a message that is being created directly in the message store without a user interface. To access the IHTMLDocument2 interface, first ensure a HTML message is open and has the focus, then call the Formativ method Utilities.IHTMLDocumentFromView(). (You may also call Utilities.IHTMLDocumentFromViewHandle() if you have the handle of the view window).

Utilities.IHTMLDocumentFromView() has one parameter. This variable must have already been dimensioned in your Applet. If the call to Utilities.IHTMLDocumentFromView() is successful, this parameter is initialized with an instance of the IHTMLDocument2 interface for the current message view.

For example, the following Applet attempts to access the IHTMLDocument2 interface for the currently active message view.

Sub Main(Client, GWEvent)

   Dim iDocument

   If Utilities.IHTMLDocumentFromView(iDocument) = 0 Then
     MsgBox iDocument.Body.OuterHTML,0,"Message HTML"
     Set iDocument = Nothing
   Else
     MsgBox "Could not access the HTML in this message"
   End If

End Sub

Test the Applet by integrating it with the Mail view toolbar, then open a received Mail message that has the HTML view available. When the Applet is run from an open HTML Mail view, the HTML is extracted and displayed in a message box as shown here:

htmlextraction
Message Box showing HTML content of the open HTML Mail message

See the Formativ Language Guide for full details of IHTMLDocumentFromView() and IHTMLDocumentFromViewHandle().


Error Handling
There are essentially two main types of Applet errors: syntax errors and runtime errors.

Syntax errors are fundamental problems in your Applet that cause the Applet not to run.

Runtime errors are problems with your Applet that only appear under particular circumstances. For example, if your Applet attempts to access the services of a COM server (such as Microsoft Word) that is not installed on a particular PC, a runtime error will occur when your Applet attempts to start the service. Runtime errors are often more difficult to detect as they are often environment-sensitive.

Syntax Errors

Syntax errors are usually detected while developing Applets. When you attempt to execute your Applet, a message box appears stating that the Applet cannot be executed, and the reason why. This error dialog will also indicate the line number in the source code where the error was found.

To fix a syntax error, locate the offending line of code and examine the syntax used. You may have to refer to the language documentation to determine the correct syntax.

Some things to be aware of when debugging syntax errors:

· If the error is not obvious in the row indicated by the error message, look at the lines just above or below the indicated row. An error reported to be at a particular location is sometimes caused by a syntax error just above or below the given location.
· Be careful in your use of parentheses when calling a procedure. See the Visual Basic Scripting Edition language documentation for more details.
· If a procedure call syntax fails, try calling the procedure with the Call keyword.

Runtime Errors

Runtime errors might occur at some point while an Applet is running. Runtime errors occur when a syntactically correct piece of code fails for some reason. These errors can often be more difficult to solve because they might only occur on certain machines or under certain circumstances.

The key to debugging runtime errors is to replicate the steps taken to induce the failure. If reproducing the steps taken to run the Applet does not force the error, you may need to check if the Applet is attempting to use any resources that are not installed on the target machine, such as COM services or other resources.

Defensive Programming

The best way to avoid runtime errors in your Applets is to employ defensive programming strategies. Never assume a particular service will be available, and never assume that every call you make will succeed.

For example, if your Applet uses third party COM services such as Microsoft Word or Excel, you should check that you are able to create an instance of the COM object before actually using its services. This usually means using the On Error statement followed by checks to confirm your request for a particular service was successful. In the example below, a defensive attempt is made to use services in Microsoft Word. This code will not cause a runtime error if Word does not exist on the target PC, or if some other error occurred:

    CheckWord = True

    ' Resume with the next line following the error.
    On Error Resume Next

    ' Attempt to reference Word, which is already running.
    Set Word = Nothing
    Set Word = GetObject(, "Word.Application")

    If Word Is Nothing Then

        ' Word is not running. Create a new instance of the Word application.
        Set Word = CreateObject("Word.Application")

        ' If true, MS Word 8.0 is not installed.
        If Word Is Nothing Then
            MsgBox "MS Word is not installed on your computer."
        End If

    End If


Debugging
Unfortunately, the current version of Formativ doesn't include a runtime debugger. However, there are techniques you can use to simulate real time debugging. Perhaps the most useful is to include trace output commands in your Applet, then use any debug output viewer capable of intercepting calls to the Win32 OutputDebugString() function.

Note: We use and recommend the free DebugView utility from SysInternals.

Using Trace Commands with DebugView

Through the use of strategically-placed trace commands, you can get a real-time picture of the execution of your Applet. Trace commands are created through the use of the Utilities.Trace() method. Utilities.Trace() takes a single string argument. The string value you supply is output to any attached debugger in real time as the Applet executes.

Note: Utilities.Trace() ultimately uses the Win32 function OutputDebugString() to output the string value. This function sends a string to the debugger for display. If GroupWise has no debugger attached, the system debugger displays the string. If GroupWise has no debugger and the system debugger is not active, OutputDebugString() does nothing. If you use the SysInternals DebugView utility, you only need to run DebugView prior to starting GroupWise – you do not need to attach it to the GroupWise process.

The data you pass to Utilities.Trace() can be as simple or as complex as you choose. You can simply trace execution points, or include the values of local and system variables. For example, the following code snippet traces out properties of the VBScript error object which is instantiated whenever a runtime error is raised.

Utilities.Trace(aErr.Number & vbtab & aErr.Description & vbtab & aText)

For example, consider the following Applet. This code simply runs through a loop five times, tracing the value of the variable x.

Sub Main(Client, GWEvent)
    For x = 1 To 5
        Utilities.Trace("Formativ Trace Output: x=" & CStr(x))
    Next
End Sub

If you execute this Applet while DebugView is running, the trace commands are output in real time, as shown below:

traceoutput
An Applet containing trace output being run with DebugView


Creating Toolbar Button Images
Formativ ships with a large number of images you can choose to assign to your Applets. However, there may be times when you would like to use an image that is not included with the product.

Creating a new image to use with Formativ is a three-step process:

1. Create a 16 by 16 pixel bitmap and draw your image
2. Add the image to a library in Formativ
3. Distribute the library to all users who require the new image

Note that adding a new image to Formativ is a technical process and requires developer tools. You should only attempt to create new images if you are familiar with using developer tools. Please consult your IT department if you are in doubt.

Step 1 – Create a new bitmap

Create a new bitmap file. The bitmap must be 16 pixels high by 16 pixels wide. It must use the 16-color Windows palette. Fill the entire bitmap with green, i.e. RGB(0, 255, 0). This color is used by GroupWise to represent transparent areas. Any green area will be transparent when the image is drawn on a button in GroupWise. Once you have filled the bitmap with green you may start drawing your image using the standard 16-color Windows palette.

Save your bitmap file when you are satisfied with the results.

Step 2 – Add the image to a Formativ Library

In order to make your bitmap available, you must add it to a Formativ image library. An image library is a resource DLL that contains nothing other than bitmap images. Formativ ships with a number of different image library files. They are named using the category of image they represent, and all have the extension .DLI. Technically, adding a new image to an image library involves adding a new bitmap resource to a DLL.

The exact steps you take to add a new bitmap to an image library varies based on the tool you will use. The following steps are based on using Microsoft Visual Studio 6.0, but you can use most modern Windows development tools.

1. Start Microsoft Visual Studio 6
2. Select File | Open. When the Open dialog appears, change the Open As combo box selection to Resources
3. Browse to the location of the .DLI into which you wish to add the new image. This is the same location where Formativ was installed
4. Select the appropriate .DLI and select Open
5. When the file opens, select the Bitmap node of the display, click for a context menu and select Import...
6. When the Import Resource dialog appears, browse to the location of your new bitmap file. You may have to change the file type selection to *.bmp in order to see bitmaps. Select the bitmap and click Import
7. The bitmap has now been added to the .DLI file. Press CTRL+S to save your work, then exit Visual Studio.

The image is now available to Formativ. Simply restart GroupWise if running and the image should appear in the list of available images.

Step 3 – Distribute the new Library

Should you wish other Formativ users to have access to your updated image library, you must make it available to them. To make the image library available, simply copy the appropriate .DLI file into each user's Formativ folder. Each user will have to re-start GroupWise in order to see the new image in Formativ Central.


System Requirements
Windows

· Microsoft Windows XP, or
· Microsoft Windows 2000, or
· Microsoft Windows NT4 with Service Pack 6, or
· Microsoft Windows Millennium Edition, or
· Microsoft Windows 98

GroupWise

· Novell GroupWise 6.5, 32-bit Windows client, or
· Novell GroupWise 6.0, 32-bit Windows client, or
· Novell GroupWise 5.5, 32-bit Windows client

Other Components

· Microsoft Internet Explorer 5.5 or above, and
· Microsoft Windows Scripting 5.5 or above
· Novell ConsoleOne or NWAdmin (Formativ Studio Administrators Only)

Notes

1. The GroupWise client and Microsoft Internet Explorer must be installed prior to installing Formativ.
2. Windows 95 is not supported.
3. The Formativ Portal Manager requires GroupWise 6.01 or above. Novell have released a beta FTF file for the GroupWise 5.5.7.1 Enhancement Pack client, which enables the use of Formativ Portal Manager based solutions with the GroupWise 5.5 EP client. See Novell TID 2963458 to download the GroupWise 5.5.7.2 Beta FTF file (f32eppp1.exe). http://support.novell.com/cgi-bin/search/searchtid.cgi?/2963458.htm.
4. Applets that make use of the standard GroupWise HTML features require GroupWise 5.5 Enhancement Pack or higher. They will not work with the GroupWise HTML plug-in.
5. Novell NetWare Client is required for the Schema Wizard administration tool (Formativ administrators only).
6. Some Applets have minimum GroupWise client version requirements. See the Applet documentation for details.
7. Some Applets have minumum Formativ version requirements. See the Applet documention for details.
8. The GroupWise C3PO architecture requires users have read and write access to the HKEY_LOCAL_MACHINE hive of the Windows registry. While Formativ will still operate without these rights being available, Applets will need to be installed by an Administrator. This is particularly relevant in Windows Terminal Services environments, such as Citrix.


Support

Formativ Support
Should you require Formativ technical support, there are three main resources available. We recommend you use these resources in the order listed below.

Note: Advansys does not provide telephone support.

Formativ Support Page

The Formativ Support page contains links to various support resources. Here you will find current information regarding:

· Last minute documentation changes.
· Product updates and patches.
· Frequently Asked Questions.
· Links to other support resources.

Moderated Support Forums

Advansys provides Formativ technical support through online moderated forums. These Web-based forums are moderated by Advansys technical staff and represent the primary source of Formativ support. Feel free to log in and post a question or search the forums to check if a similar question has been answered already.

Support forums are available for the following topics:

· Developing Solutions with Formativ.
· Formativ Solution Packs.
· Formativ Runtime.
· Formativ Creator (Developer).
· Formativ Studio (Admin).
· eDirectory management.
· Free GroupWise CoolSolutions Applets.

You can access the Formativ support forums on the Web at:

http://advansys.atinfopop.com/4/OpenTopic?a=cfrm&s=7534089931&f=3634089931


On the Web
Advansys Home Page

www.advansyscorp.com

Formativ Home Page

www.advansyscorp.com/formativ.htm

Sales

www.advansyscorp.com/formativ_buy.htm

Formativ Resellers

www.advansyscorp.com/resellers_formativ.htm

Support Forums

http://advansys.atinfopop.com/4/OpenTopic?a=cfrm&s=7534089931&f=3634089931


Via Email
General Formativ Enquiries

formativ@advansyscorp.com

Sales Enquiries

sales@advansyscorp.com

Note: Please note that technical support is available via our Online Support Forums.


Telephone and Fax
Telephone

+61 2 9968 2991

Facsimile

+61 2 9969 7551

Note: Advansys is located in Sydney, Australia.

Note: Advansys does not provide technical support by telephone. Please use our online support forum if you require technical support.


.topic 1 Advansys Formativ 2.0 Developer's Guide This Guide describes how to use Formativ™ to build business solutions based on Novell® GroupWise®. This guide is the definitive resource for developers who are creating custom solutions with Formativ and GroupWise. The Formativ language is syntactically based on Microsoft Visual Basic® Scripting Edition (VBScript). If you know how to work with VBScript, you can build on your knowledge easily to customize Novell GroupWise. If you are not familiar with VBScript, this guide will get you started. However, you will still need to access the VBScript documentation to get the most out of the product. Who Should Use This Guide? This guide has been written for developers. Developers form a large and diverse group. We use the term developer to include someone who wishes to do something as simple as automatically type some text into a GroupWise message, or create a new button on a toolbar, through to someone who wishes to build complex vertical market solutions for GroupWise using Formativ. This Guide is not for everybody. In order to cover the information required adequately, we have made assumptions about your level of knowledge. You may benefit from first using one of the excellent introductory resources mentioned later in this guide. Once you are happy that you have a sound grip of the basics, you can return to this Guide. What Does This Guide Cover? The purpose of this document is to guide you through the many facets of developing solutions using the Formativ environment. As the Formativ Applet language is based on Microsoft Visual Basic® Scripting Edition, we assume you are comfortable with VBS, and that you understand the concept of data types, variable scoping, functions and subroutines. We also assume you have a basic knowledge of the Novell GroupWise 5.5/6.x Windows client. If you are not comfortable with these topics, please refer to the appropriate resources before returning to this guide. Copyright © 2001-2004 Advansys Pty Limited - All Rights Reserved Formativ is a trademark of Advansys Pty Limited. GroupWise is a trademark of Novell Inc. Visual Basic is a trademark of Microsoft Corporation. .topic 21 Traditional GroupWise Development Early versions of Novell GroupWise provided a macro-based development environment. Macros allowed users and developers alike to build both simple and complex solutions based on the GroupWise system. The macro paradigm was widely understood, and lent itself to a broad variety of solutions. Other programming interfaces were also available, but these required a much deeper understanding of the development process, and were beyond the capabilities of many people. The advent of GroupWise 5.x brought about a new development approach for GroupWise. The macro/scripting capabilities of GroupWise 4.x were removed and replaced by several new COM-based programming interfaces, the Object API and the C3PO API. The ability to work at a token level was still available, using either another COM-based interface or the low-level TPH API. The functionality available in macros was still available, but developers now had to use a combination of API's and third- and fourth-generation languages to access the same functionality. While GroupWise programmability remained rich, many developers believed it was difficult to develop GroupWise solutions. This was particularly true for developers who had experience developing for other collaboration products, such as Microsoft Outlook. Outlook shipped with an integrated development environment that allowed users to use industry standard Visual Basic to develop solutions. By comparison, in GroupWise even seemingly simple tasks such as adding a button to a toolbar required a knowledge of COM programming. GroupWise Development using Formativ Formativ lets developers create Applets for Novell GroupWise using a single, unified development environment. The Applets you write or record use a simple, yet powerful language that is 100% compatible with Visual Basic Scripting Edition (VBScript). VBScript is a powerful, easy to learn programming language, very similar to Visual Basic. Formativ wraps and exposes the various traditional GroupWise programming API's with VBScript. This means that the entire GroupWise Object API, Administrative Objects API and Token Commander API's are all completely accessible from within the Applets you create. In addition, the majority of the Custom Third Party Objects (C3PO) API is accessible via Applets. Developers do not require any knowledge of these API's, or how they interact with each other when using Formativ. They are all presented as simple applet commands and functions. Write A New Applet You write a new applet within the Formativ development environment, which is tightly integrated with the GroupWise client. You do not need to own a third party development environment, such as Visual Basic, Delphi or Visual C++. Your Applets are written using Formativ's 100% VBScript-compatible language with extensions for GroupWise support. The Formativ environment includes a fully featured applet editor. Depending on configuration, your applet is either saved locally, or to a shared area where it can be accessed by many users. Integrate the Applet with GroupWise Once you have written and tested an Applet, it can be integrated with the GroupWise client. This means that you specify how and when the Applet is run. You can choose to add buttons to GroupWise toolbars that run your Applet, and you can add items to both standard and context menus that activate your Applet. You can also associate your Applet with many standard GroupWise events, such as on client start-up and on message send. In this way your Applet is automatically executed when that particular event occurs. Distribute the Applet Depending on your installation configuration, you may now distribute your new Applet. If you are an administrator, you can simply make your Applet and its integrations available to users via eDirectory®. When your users next start GroupWise, your Applet becomes available. If you have associated integrations with an Applet, they too become active. For example, your users may see a new button appear on a toolbar that runs an Applet. Configured in an appropriate manner, users are not aware they are running Applets – the new functionality in your Applet appears to be new functionality in GroupWise. You can also distribute Applets manually. .topic 31 You can use Formativ to provide an incredibly wide range of GroupWise solutions. Because Formativ makes use of all the major GroupWise programming interfaces, almost anything you might otherwise have developed using C++, Visual Basic or Delphi can now be developed using simple Applets – from within the GroupWise client! You can use Formativ as a simple tool to automate repetitive tasks. For example, you can write Applets to automate such tasks as opening a particular view, proxying to a different account or configuring the GroupWise client in a certain way. You can use Formativ to record Applets. You can use the Formativ Applet recorder to create new Applets. Simply start recording, perform some actions in GroupWise, stop recording, then play back or edit the automatically created Applet. Use the Formativ Portals facility to embed web-based content right inside the GroupWise client. Use Formativ to simplify the integration of your custom application or web service with GroupWise. You can use Formativ to add new functionality to the GroupWise client. For example, Search and Replace is a solution that ships with the Business Solutions Pack that adds search and replace capabilities to items that are being composed. When this Applet is added to a toolbar or to context menus, it appears to be another integrated GroupWise feature. You can use Formativ to automate difficult or critical tasks. For example, you could create an Applet that guides users through the process of creating a vacation rule that will not create a mail storm. You can use Formativ to integrate GroupWise with other systems. For example, you could write an Applet to import information into GroupWise from Outlook or a corporate database. You can use Formativ to build complete solutions for GroupWise. Formativ Applets are surprisingly powerful, and can be used to build complex business systems. As Formativ Applets are COM-based, your Applets can take advantage of any COM service. This means you can add new functionality to the Applet language, and access almost any other modern software services, including databases, human resource systems, financial systems or sales systems. You can use Formativ to create new dialogs in GroupWise using the visual forms designer. While Formativ is an extremely powerful and flexible development environment, like any tool it does have some limitations: Formativ is unable to add new buttons or toolbar items to the GroupWise Address Book dialog. This is an architectural restriction imposed by GroupWise. Formativ does not currently support an integrated debugger. The solution you produce with Formativ will only work with the 32-bit Windows GroupWise client. They do not currently work with WebAccess, Cross-platform or Linux clients. .topic 561 Formativ Applets are written using the Formativ language. The Formativ language contains both general and GroupWise-specific language constructs designed to make developing GroupWise solutions fast and easy. The main features of the language include: 100% syntax-compatibility with Microsoft Visual Basic Scripting Edition Over 500 GroupWise-specific language extensions Support for event-driven visual forms, including more than 130 components Based on COM for easy integration with other components The Formativ programming language is documented in the Formativ Language Guide. .topic 11 There are many excellent resources available for you to accelerate your proficiency with Formativ. Formativ also exposes many of the GroupWise programming API's via Applet commands, so there are many Novell and third party resources that are excellent sources of information. Some of these are listed below: Advansys Formativ Language Guide This document describes the Formativ Language in detail. Advansys Formativ Users Guide This document details how to use the Formativ environment. It describes installation, configuration and operation. It covers how to write a new Applet and how to integrate Applets with the GroupWise client. Advansys Formativ Administrators Guide This document details how to administer Formativ using Novell eDirectory. It covers planning, installation, configuration and operation. Advansys Formativ Web Site The Advansys Formativ Web site is the best source for the latest product information. You can access samples, documentation, updates and news about Formativ, including product updates and fixes. http://www.advansyscorp.com/Formativ.htm Novell GroupWise Cool Solutions Web Site The Novell GroupWise Cool Solution web site contains a wealth of information and resources for GroupWise users. It also hosts Formativ Applet Central, from where you can download free Formativ solutions. http://www.novell.com/coolsolutions/gwmag/features/a_Formativ_applet_central_gw.html Advansys Formativ Business Solutions Pack The Advansys Formativ Business Solutions Pack is a collection of complete working Applets. They represent solutions to common GroupWise enhancement requests. You can try the Business Solution Pack Applets for free for thirty days. http://www.advansyscorp.com/Formativ_business_solutions_pack.htm Advansys Formativ Example Applets This is a wide variety of example Applets, demonstrating a variety of techniques, and illustrating the type of solutions you can develop using Formativ. Some of the examples are complete solutions, while others are simple examples of specific techniques. http://www.advansyscorp.com/Formativ_example_Applets.htm Microsoft Visual Basic Scripting Edition Users Guide This is the best resource for programming with Microsoft Visual Basic Scripting Edition (VBScript). As Formativ Applets are based on an extended version of VBScript, everything you read in this Guide also applies to Formativ. The guide is installed when you install Formativ Studio or Creator, and is accessible from the Formativ IDE Help menu. You can also download the latest version from the Microsoft Scripting downloads page – see the link below. Novell GroupWise Object API Documentation This online documentation, supplied and maintained by Novell, details the GroupWise Object API, which provides full access to the GroupWise message store. Advansys Formativ exposes the entire Object API, unchanged, via the Formativ Applet language. Use this reference to learn about the Object API, and how you can use it directly within your Formativ Applets. http://developer.novell.com/ndk/doc/gwobjapi/index.html?gwobjenu/data/h7ikbsqg.html Novell GroupWise Tokens Documentation This online documentation, supplied and maintained by Novell, details the GroupWise Tokens API. Tokens are generally used to manipulate the GroupWise client. Most tokens map directly to a Formativ language extension. http://developer.novell.com/ndk/doc/gwtoken/index.html?gwtokens/data/hj8ej8g5.html Novell Administrative Objects API documentation This online documentation, supplied and maintained by Novell, details the GroupWise Administrative Objects API, which provides full access to GroupWise administrative functions, such as adding new users and obtaining information about your GroupWise system. Advansys Formativ exposes the entire Administrative Objects API, unchanged, via the Formativ applet language. Use this reference to learn about the Administrative Object API, and how you can use it directly within your Formativ Applets. http://developer.novell.com/ndk/doc/gwadmin/index.html?gwadmenu/data/h0haj3mj.html Microsoft Scripting Resources The Microsoft Scripting Web site is the best resource for the latest information about Visual Basic Scripting Edition. You can access more samples, documentation, updates and news about VBS, including product updates and fixes. http://msdn.microsoft.com/library/default.asp?url=/downloads/list/webdev.asp .topic 41 The best way to become familiar with Formativ from a Programmer's perspective is to create a 'Hello World' Applet, then create a button on the main GroupWise toolbar that runs the Applet. The following topics cover creating a new solution and creating a button on the main GroupWise toolbar that runs the Applet. We will also define an event that triggers the Applet when a new email message arrives in your mailbox. .topic 531 Once you have installed Formativ Studio or Creator, follow the steps shown below to create an Applet. 1. Start GroupWise 2. Locate the button for Formativ Central on the main GroupWise toolbar button 3. Click the button to display the Formativ IDE (also known as Formativ Central) 4. Click the New button on the Formativ toolbar. A new Applet skeleton is created and displayed in the editor 5. Enter the following line in the editor. Insert the line between the existing lines Sub Main(Client, GWEvent) and End Sub: MsgBox "Hello World", 0, "Formativ" Your Applet now appears as: 6. Press F5, or click Run on the toolbar to run your Applet. A message box appears. Continue with this section to define a toolbar button that runs your applet. .topic 541 An Applet is not particularly useful unless you integrate it with GroupWise. An integration is a means by which you run your Applet from within GroupWise. An integration can consist of a button on a toolbar, a menu item, a popup (context) menu item or an event. Follow the steps below to define a toolbar button to run your Applet: 1. Select the Hello World applet in the Formativ IDE 2. Click the Integrations tab 3. Locate the entry 'GroupWise Main Window' in the Context column 4. Check the Toolbar check box. This indicates you wish to define a button on the main GroupWise toolbar 5. Click the Properties tab 6. Enter a description and help hint for your Applet. The description and help hint will appear on toolbar buttons. 7. Click once on the icon you would like to appear on the button in the toolbar 8. Press the close button on the Formativ toolbar. This will close the Formativ IDE 9. Restart GroupWise 10. When the client restarts, you will see a new button on the GroupWise toolbar. Press the button to run your applet Continue with this section to associate your Applet with a GroupWise event. Note: It is possible to define custom icon images. For more information see Creating Toolbar Button Images. .topic 551 In some situations it makes sense to run your Applet in response to a GroupWise event. For example, you may want to perform some pre-send processing to a message, or to manage incoming messages. In this topic we will associate your Hello World Applet with the On Message Arrival event. Follow the steps below to have your applet run automatically when a message arrives in your Mailbox: 1. Select the Applet in the Formativ IDE for which you wish to define a button. (If you have been following the Quick Start topics in order, your Hello World applet will already be selected.) 2. Click the Integrations tab 3. Locate the entry 'GroupWise Application' in the Context column 4. Click the button in the Events column. A dialog appears showing the events that are available in this context 5. Check the box next to the first entry – On Message Arrival 6. Click the Close button on the Formativ toolbar. The Formativ IDE closes down 7. Restart the GroupWise client 8. Send yourself an email message. Your Applet will be executed when the message arrives in your Mailbox Note: GroupWise requires that you restart the client after defining integrations that affect the currently visible view. .topic 651 Every applet you write must contain a subroutine called Main(). This is the main entry point of every applet, and is the subroutine Formativ attempts to execute when an applet is run. You cannot run an applet that does not contain a properly formed Main subroutine. The Main() subroutine must accept two arguments: Client and GWEvent . It does not matter what these parameters are called, but we recommend you use 'Client' and 'GWEvent'. They must be present in every Main() subroutine, or your applet will not execute. The purpose and use of the mandatory parameters are discussed in the following section. The minimum applet code that will run in the Formativ environment is: Sub Main(Client, GWEvent) End Sub Client and GWEvent Arguments These two arguments pass useful contextual information regarding the state of the GroupWise client to your applet. You can use the values contained in these two arguments to determine the currently selected message or messages in GroupWise, and to modify the behavior of your applet depending on the event (if any) that was fired when your applet was executed. Client: This argument represents the state of the GroupWise client at the time your applet was executed. It is the same as the GroupWise C3PO ClientState Object. Your applet should not assume a specific Client object is in a particular state. Rather, the ClientName, MajorVersion, and MinorVersion properties should be checked to identify the appropriate state of the object. Full documentation of the Client argument can be found at: ClientState and ClientState (Implementation) on the Novell Web site. GWEvent: This argument contains a string representing the GroupWise event that caused the applet to be executed. You can use the value of this argument to dynamically change the behaviour of your applet based on the event that caused it to run. Possible values are: .topic 661 Example One In the following code, the ClientState property of the Client argument is used to access the command message from GroupWise. The command message is the currently active, saved message in GroupWise. Sub Main(Client, GWEvent) Dim Msg On Error resume Next Set Msg = GroupWise.ComposingItem If Msg is Nothing Then On Error resume Next Set Msg = Client.ClientState.CommandMessage ComposeMode = False If Msg is Nothing Then MsgBox("Sorry, the message type could not be identified") Exit Sub End If End If End Sub Example Two In the following code, the ClientState.SelectedMessages property of the Client argument is used to access the list of currently selected items in GroupWise. If there are no items selected, an attempt is made to access the command message. Sub Main(Context, GWEvent) Dim Msg iCount = Context.ClientState.SelectedMessages.Count If iCount > 0 Then For x = 1 To iCount Set Msg = Context.ClientState.SelectedMessages.Item(x) ' Do something with the msg object Set Msg = Nothing Next Else Set Msg = Context.ClientState.CommandMessage ' Do something with the msg object Set Msg = Nothing End If End Sub Example Three In the following code, the ClientState version methods are called to display the major and minor version numbers of the GroupWise client in a message box. Sub Main(Client, GWEvent) MsgBox(Client.ClientState.MajorVersion & " " & Client.ClientState.MinorVersion) End Sub .topic 61 Formativ gives you full access to items in the GroupWise message store: Mail, Appointments, Tasks, Notes, Address Book entries and Documents. Using Applets you can create new items, and you can create, delete and modify existing items. Formativ also lets you access an item that is being composed – though it does not yet exist in the message store. For example, you can access an email message that is still being composed and modify most of its properties, including the body and subject. You could write an Applet that automatically inserts disclaimer text each time you create a new message. The following topics show how to create new items in the message store, how to access items that are being composed, and how to access items that already exist in the message store. Since accessing GroupWise Address Book/Contact information is slightly different from the generic message types, it is described in its own topics, Accessing Address Book Information via the Account and Accessing Address Book Information via the AddressBooks Object. .topic 121 The GroupWise message store is a proprietary database, usually residing on a server. A message store is contained inside a GroupWise Post Office. Unless you are writing an Applet that uses the Trusted Application API, or using multi-login, you can assume only one message store is available, from which all messages can be accessed and that the message store belongs to the account of the logged-in GroupWise user. All items in GroupWise, other than Address Book data, are known as messages. A message represents a discrete item in the GroupWise message store. All messages share some common properties, such as a unique ID, which uniquely identifies the item in the message store. Distinct kinds of message, such as Mail and Appointment, have unique properties that set them apart from other kinds. For example, an Appointment will have a start time property, whereas a Mail message will not. In the message store, every kind of item belongs to a specific class. The different classes of item are based on a hierarchical structure, in which one class is a specialization of another class. Every item belongs to the class "GW.MESSAGE". Each distinct kind of item belongs to a class whose name is an extension of this base item class. For example, the class of a Mail message is "GW.MESSAGE.MAIL". An Appointment has the class "GW.MESSAGE.APPOINTMENT". A complete list of the basic classes is shown below: GW.MESSAGE – The base message class GW.MESSAGE.MAIL – Mail Message GW.MESSAGE.APPOINTMENT – Appointment GW.MESSAGE.TASK – Task GW.MESSAGE.NOTE – Note GW.MESSAGE.PHONE – Phone Message GW.MESSAGE.DOCUMENTREFERENCE – Document Third parties are free to create new message classes, based on one of the above classes. For example, you may come across a message in the message store, with class "GW.MESSAGE.MAIL.PROJECTX", which indicates a new class of Mail message. It will expose all the same properties and events of "GW.MESSAGE.MAIL", but may include additional properties only found in "GW.MESSAGE.MAIL.PROJECTX". From the programmer's point of view, a message in the message store is represented by an object. An object is a variable that has a set of properties for getting and setting information about the entity it represents, and a set of methods for performing operations on the message. For example, all message objects have the property MessageID that can be used to determine the unique ID for that message, and the Delete method which deletes the item from the message store. Note: Every message in the GroupWise message store has a MessageID property. This is a string property that is guaranteed to be remain unique for the life of the message in the message store. Accessing the Message Store The GroupWise message store is accessed via the Account property of the GroupWise object: Dim objAccount Set objAccount = GroupWise.Account objAccount now holds an instance of the GroupWise Account object. The entire GroupWise message store can be accessed via the Account object. The GroupWise.Account object is actually a reference to the GroupWise Object API Account object for the currently logged in GroupWise user. This is a very important point. The GroupWise Object API Account object and all the methods and objects it supports are documented on Novell's web site. Any Object API code you may have written previously can be used almost unchanged within an Applet. The following sections discuss how to use the Account object to create new items in the message store, how to access items already in the message store and how to access an item that is being composed and is not yet in the message store. .topic 131 In many cases you may need to access GroupWise items programmatically. For example, you may need to extract all appointments for a given day, or access the currently selected messages. There are a number of different techniques available, depending on what you need to achieve. GroupWise items in the message store are accessed in two main ways. If you know the MessageID of the item you are seeking, you can access the message directly. If you are interested in all messages of a particular type, you can use various message extraction techniques to query for those messages. In either case you use methods of the GroupWise.Account property. The GroupWise.Account property provides full access to the GroupWise message store. See Novell's Object API documentation for complete details of the properties and methods available. If you have the MessageID of a particular message, you can easily extract it from the message store using the object GroupWise.Account.MailBox.Messages. For example, the following Applet attempts to access a message and display the subject in a message box: Sub Main(Client, GWEvent) ' Hard coded MessageID Const MSG_ID = "35FE9AD8.GWHQ.MOSMAN.100.1636E61.1.4A.1" Dim objMessages Dim objMsg ' Set a variable to the MailBox.Messages object Set objMessages = GroupWise.Account.MailBox.Messages ' Get the message using its ID and set it to objMsg Set objMsg = objMessages.Item(MSG_ID) ' Display the message subject text MsgBox(objMsg.Subject) ' Release the objects Set objMsg = Nothing Set objMessages = Nothing End Sub In other situations you may wish to extract any number of messages from GroupWise and process them. For example, you may wish to process all tasks from your account. Use the methods of the GroupWise.Account object to access the appropriate messages. You may wish to process all the tasks in your account . To extract each task, we can use the collection GroupWise.Account.Calendar.Messages. In the following Applet, the subject of each task is displayed. Sub Main(Client, GWEvent) Dim objMessages Dim objTasks Dim objTask ' Set a variable to the Calendar object Set objMessages = GroupWise.Account.Calendar ' Use a filter to locate personal, accepted tasks Set objTasks = objMessages.FindMessages("(TASK) AND (ACCEPTED) AND (BOX_TYPE = INCOMING OR BOX_TYPE = PERSONAL)") ' Display the subject and MessageID of each task located For Each objTask In objTasks MsgBox(objTask.Subject & " - " & objTask.MessageID) Next ' Release the objects Set objTasks = Nothing Set objTask = Nothing Set objMessages = Nothing End Sub .topic 141 There are two main techniques you can use to create a new item: Directly inside the message store with no user interface Automating the GroupWise client user interface The following topics discuss these approaches. .topic 151 You can create any kind of message without a user interface. You would normally use this approach when you have all the information required to create a new item, and there is no need for user interaction. For example, you may write an Applet to read email addresses from a database, then create and send a customized email message to each address. In this case there is no need for a user to see the actual messages being composed. Although there are several variations, the most common way to create a new message is this: Call the Add method of the Messages collection owned by the folder in which you wish to store the message. For example, the following Applet creates a new personal GroupWise Appointment in your own calendar: Sub Main(Client, GWEvent) Dim objMessage ' Create the new message Set objMessage = GroupWise.Account.Calendar.Messages.Add("GW.MESSAGE.APPOINTMENT", 3) ' Set some properties objMessage.OnCalendar = True objMessage.FromText = GroupWise.Account.Owner.DisplayName objMessage.Subject = "This was created using Formativ" ' Display the MessageID of the new message MsgBox(objMessage.MessageID) End Sub The Calendar and Messages objects and the Add method are all documented in the GroupWise Object API documentation, which is freely available from Novell's web site. (Remember that the Account property of the GroupWise object gives you complete access to the entire GroupWise Object API.) In the next example, we create a new personal Task in your own calendar: Sub Main(Client, GWEvent) Dim objTask ' Create the new task Set objTask = GroupWise.Account.Calendar.Messages.Add("GW.MESSAGE.TASK", 3) ' Set some properties objTask.OnCalendar = True objTask.FromText = GroupWise.Account.Owner.DisplayName objTask.TaskCategory = "A" objTask.TaskPriority = 1 objTask.Subject = "This was created using Formativ" ' Display the MessageID MsgBox(objTask.MessageID) End Sub Finally, a slightly more complex example, creating a new email message to oneself. The only user interface element is the popup dialog at the end of the process, which displays the unique MessageID of the message. All objects and properties used in this example are documented in the GroupWise Object API documentation. Sub Main(Client, GWEvent) Dim objDraft Dim objEmail Dim objRecipient ' Create a draft email message Set objDraft = GroupWise.Account.MailBox.Messages.Add(4) ' Add a single recipient - ourself objRecipient = objDraft.Recipients.Add(objDraft.Sender.EmailAddress,,0) ' Add some properties objDraft.Subject = "This was created using Formativ" objDraft.BodyText.PlainText = "This is the body text of the email message" ' Send the email by calling the send method Set objEmail = objDraft.Send ' Display the MessageID MsgBox(objEmail.MessageID) End Sub If you have the Formativ development environment open in GroupWise when a new message arrives, you may notice a slight delay in notification of the message's arrival. We recommend that you close the Formativ development environment when not editing Applets. Naturally, VBScript constructs may be used in your code. Here is the same example slightly modified to send the same message to your own Mailbox three times. Each message is given a slightly different subject: Sub Main(Client, GWEvent) Dim objDraft Dim objEmail Dim objRecipient ' Create three new messages For x = 1 To 3 ' Create a draft email message Set objDraft = GroupWise.Account.MailBox.Messages.Add(4) ' Add a single recipient - ourself objRecipient = objDraft.Recipients.Add(objDraft.Sender.EmailAddress,,0) ' Add some properties objDraft.Subject = "This is message no. " & x objDraft.BodyText.PlainText = "This is the body text of the email message" ' Send the email by calling the send method Set objEmail = objDraft.Send Next MsgBox("Done!") End Sub .topic 161 You may wish to create a new message in the GroupWise client itself. Using a Formativ Applet, you can create a new message by displaying the new message dialog for the type of message you wish to create. You can leave it to the user to complete the rest of the details, or you may fill out some or all of the details before making the item available to the user. For example, the following code creates a new Mail message, and leaves it to the user to complete and send the message manually. When the Applet is executed, the standard GroupWise new Mail message dialog is displayed: Sub Main(Client, GWEvent) GroupWise.NewMail End Sub In some cases you may wish to fill out some of the message properties before making the item available to the user. You may wish to complete the subject and body text, as shown in the following example, using the ComposingItem property of the GroupWise object. Notice this example uses error checking to ensure that a valid composing item is accessible: Sub Main(Client, GWEvent) Dim Msg ' Create a new visible email message GroupWise.NewMail ' Attempt to access the composing item ' If available, set its subject and body text Set Msg = GroupWise.ComposingItem If Msg is Nothing Then MsgBox("No composing item available") Else Msg.Subject = "This is the new subject" Msg.BodyText = "This is the body text" Set Msg = Nothing End If End Sub Refer to the Language Guide for full details of the ComposingItem property. Formativ is only able to access the ComposingItem if the dialog displaying the new message has the focus at the time you access it. This is a limitation of the underlying GroupWise architecture rather than Formativ, and is not usually an issue as long as you attempt to access the item soon after it is created. .topic 171 In many cases, you may wish to write an Applet which operates on the currently selected GroupWise items. For example, you may wish to perform an operation on a list of selected items in GroupWise, or you may wish to access the current open saved item, such as an email message that arrived in your Mailbox. In order to determine if any messages are selected in the GroupWise client when your script is run, you should use the Client parameter passed into the Main procedure of your applet. The Client parameter is an object which represents the state of the client when your Applet was executed. See the earlier section Applet Structure for full details on the definition of the Client parameter. The following topics discuss how to access the currently selected messages and folders in the GroupWise client. .topic 181 If you wish to act upon a single saved item, either selected or opened , you can use the Client.ClientState.CommandMessage object. The CommandMessage object gives you access to the current saved GroupWise item. For example, the following applet checks if the CommandMessage object is valid. If so, the message subject is displayed. Sub Main(Client, GWEvent) Dim objMsg On Error Resume Next Set objMsg = Client.ClientState.CommandMessage If Not objMsg is Nothing Then MsgBox(objMsg.Subject) Set objMsg = Nothing End If End Sub .topic 191 If you wish to act upon all selected messages in the GroupWise client, you should check the Client.ClientState.SelectedMessages object. If any messages are selected, you can then use this object to access each one. For example, the following code displays the subject of each selected item in GroupWise. Before running the Applet, display a list of items in the GroupWise client and select them: Sub Main(Client, GWEvent) Dim objMsg ' Find out how many items are selected in GroupWise iCount = Client.ClientState.SelectedMessages.Count ' If any are selected, access each one If iCount > 0 Then For x = 1 To iCount ' Get the message and display its subject Set objMsg = Client.ClientState.SelectedMessages.Item(x) MsgBox(objMsg.Subject) Set objMsg = Nothing Next Else MsgBox("No messages were selected") End If End Sub .topic 201 In some situations you may wish to access data in a new GroupWise message that is still being composed. Note: An item is still being composed when it has not been sent, or saved to Work in Progress. For example, when you create a new Mail message, the message is not saved until you click the Send button. Likewise, when you reply to an existing email message, your reply is not saved until you click the Send button. The distinction between a saved and an unsaved message is very important from a programmer's perspective. Until a GroupWise message has been saved, it does not have a unique MessageID, and it does not exist in the message store. This means you cannot use any of the GroupWise.Account methods to access the message. The only way you can read and write an item that has not yet been saved is to: Use the ComposingItem property of the GroupWise Object or Use the ItemSetText and ItemGetText methods of the GroupWise Object, using the special message ID "X00" to identify the message. Every message in the GroupWise message store is allocated a unique ID that never changes during the life of the message. Items that have not been saved, and therefore have not yet been allocated an ID, can be accessed using the special ID "X00". This ID can usually be used in place of a permanent ID to access the current composing item. Note: The only caveat is that the item being composed needs to have the focus in Windows (i.e. the active window). The ComposingItem property of the GroupWise object provides a convenient method to access items that are currently being composed. ComposingItem lets you read and write data in items being composed, including Subject and body text. ComposingItem exposes the following properties: BoxType: Integer (Read Only) ClassName: String (Read Only) ConvertAttachments: Boolean CreationDate: Date (Read Only) Deleted: Boolean (Read Only) FromText: String Hidden: Boolean MessageID: String (Read Only) NotifyWhenDeleted: Integer NotifyWhenOpened: Integer Opened: Boolean Parent: Variant (Read Only) Priority: Integer Read: Boolean ReplyDaysRequested: Integer ReplyRequested: Integer Routed: Boolean RoutingEndOfLine: Boolean (Read Only) Sender: String (Read Only) ViewName: String IsPrivate: Boolean Subject: String BodyText: String CC: String BC: String To_: String StartDate: Date EndDate: Date DueDate: Date CallerCompany: String CallerName: String CameToSee: Boolean PleaseCall: Boolean ReturnedCall: Boolean Telephoned: Boolean Urgent: Boolean WantsToSee: Boolean WillCall: Boolean AssignedDate: Date TaskCategory: String TaskPriority: String In the following example, the ComposingItem property is used to insert a simple disclaimer at the top of the body text of a message being composed. To be useful, this Applet would be associated with the On Send event for email messages so that it would be automatically executed each time a new Mail message is sent: Sub Main(Client, GWEvent) ' This is the disclaimer text to insert Const DISCLAIMER = "This is some disclaimer text" Dim NewLine Dim Msg NewLine = Chr(13) & Chr(10) ' Attempt to access the composing item Set Msg = GroupWise.ComposingItem ' If we have the composing item, insert the disclaimer into the body text If Not Msg is Nothing Then Msg.BodyText = DISCLAIMER & NewLine & NewLine & Msg.BodyText Set Msg = Nothing Else MsgBox("No GroupWise items were available for disclaimer insertion.") End If End Sub .topic 211 Formativ gives you complete access to the GroupWise address books. With Formativ, you can write Applets to create new address books, add, edit and delete address book entries, and quickly extract contact details. There are two main techniques you can use to access address book information. You may use the standard GroupWise.Account object which provides low-level access to the complex structure, or the GroupWise.AddressBooks object which provides simpler, slightly higher-level access. The technique you use will ultimately depend on the problem you are trying to solve. Address book entries in GroupWise do not have accessible persistent ID's as do other item types such as Mail. This means you cannot obtain an address book entry's ID, then access the entry directly (using the ID) at a later time. This is due to architectural issues in GroupWise. To get around this, you can add your own custom fields to address book entries, and assign them a unique value, such as a GUID, and use the value as a unique ID during later sessions. .topic 221 The GroupWise.Account object provides low-level access to address book data. You can access data down to FieldDef level and work with custom fields. Access via the GroupWise.Account object is the same as with the Object API. See Novell's Object API documentation for complete details. For example, the following code displays the name of every address book available in the current account: Sub Main(Client, GWEvent) Dim objAddressBooks Dim objAddressBook ' Get the AddressBooks object Set objAddressBooks = GroupWise.Account.AddressBooks ' Display the name of each address book For Each objAddressBook In objAddressBooks MsgBox(objAddressBook.name) Next Set objAddressBooks = Nothing End Sub You may access an individual address book either by its name or index value within its collection. For example, the following Applet lists the email address for each contact in the address book 'Frequent Contacts': Sub Main(Client, GWEvent) Dim objAddressBooks Dim objAddessBook Dim objAddressBookEntry ' Get the AddressBooks object Set objAddressBooks = GroupWise.Account.AddressBooks ' Locate the address book called 'Frequent Contacts' Set objAddressBook = objAddressBooks.Item("Frequent Contacts") ' Display the email address of each entry in the book For Each objAddressBookEntry In objAddressBook.AddressBookEntries MsgBox(objAddressBookEntry.EmailAddress) Next Set objAddressBook = Nothing Set objAddressBooks = Nothing End Sub Essentially, this technique uses 'raw' GroupWise Object API calls. Our experience is that the GroupWise Object API can be a little unstable when accessing certain address books, particularly the Novell LDAP address book. Using the GroupWise.AddressBooks object avoids this instability since Formativ shields you from it. .topic 231 The GroupWise.AddressBooks object provides a clean, simple object model with which you can access GroupWise address books. This technique shields you from much instability inherent in some native GroupWise address book calls. More importantly, it encapsulates the GroupWise address book FieldDef paradigm, making it very simple to access address book fields by name without having to worry about Field Definitions or the version and language of the GroupWise client. See the Object Model documentation for full details of the GroupWise.AddressBooks object model. Semantically, using the GroupWise.AddressBooks object is similar to using the GroupWise.Account model. For example, the Applet to list the names of all the address books available in an account is: Sub Main(Client, GWEvent) Dim objAddressBooks Dim objAddressBook Set objAddressBooks = GroupWise.AddressBooks For Each objAddressBook In objAddressBooks MsgBox(objAddressBook.Name) Next Set objAddressBooks = Nothing End Sub Likewise, the code to access a single address book by name is: Sub Main(Client, GWEvent) Dim objAddressBooks Dim objAddressBook Set objAddressBooks = GroupWise.AddressBooks ' Locate the address book called 'Frequent Contacts' Set objAddressBook = objAddressBooks.Item("Frequent Contacts") ' Display the email address of each entry in the book For Each objAddressBookEntry In objAddressBook MsgBox(objAddressBookEntry.EmailAddress) Next Set objAddressBooks = Nothing End Sub Note: You do not have to use the AddressBookEntries property as you do when using the GroupWise.Account access technique. The real benefit to using GroupWise.AddressBooks becomes apparent when you have to access address book entry fields. Unlike the GroupWise.Account technique, you can access all standard fields directly using properties of the AddressBookEntry object. There is no need to be concerned with FieldDefs, the version or language of the GroupWise client being used as is the case when accessing most fields using the GroupWise.Account technique. GroupWise's underlying architecture dictates that address book fields traditionally had to be accessed using field names. These textual field names varied between versions of the client and the language of the client. For example, if you wanted to write a program that accessed the 'Title' field of an address book, it was necessary to know the local variation of that name. If the user had an English client, the field called 'Title' was located. If the user had a French client, your program had to be aware of this and search for the French for 'Title' instead. Formativ alleviates this problem through its implementation of the GroupWise.AddressBooks object. For example, if you wanted to extract the 'Title' field value of every contact in a particular address book, you could do so by using the Title property of the AddressBookEntry object as shown here: Sub Main(Client, GWEvent) Dim objAddressBooks Dim objAddressBook Set objAddressBooks = GroupWise.AddressBooks ' Locate the address book called 'Frequent Contacts' Set objAddressBook = objAddressBooks.Item("Frequent Contacts") ' Display the email address of each entry in the book For Each objAddressBookEntry In objAddressBook MsgBox(objAddressBookEntry.Title) Next Set objAddressBook = Nothing Set objAddressBooks = Nothing End Sub This technique also makes adding new address book entries very simple. For example, to add a new contact to a personal address book called "Test Book", you could use the following Applet: Sub Main(Client, GWEvent) Dim AddressBooks Dim AddressBook Dim oAddressBookEntries Dim oAddressBookEntry Set AddressBooks = GroupWise.AddressBooks On Error Resume Next Set AddressBook = Nothing Set AddressBook = AddressBooks.Item("Test Book") If AddressBook Is Nothing Then MsgBox("Could not locate that address book") Else MsgBox(AddressBook.Name) Set oAddressBookEntry = AddressBook.AddContact("Bill Smith") With oAddressBookEntry .FirstName = "Bill" .LastName = "Smith" .Organization = "Smith Inc" .EmailAddress = "bill@Smith.com" .EmailType = "NGW" .Address = "This is the address" .City = "The city" .State = "The state" .ZipCode = "The zip" .Country = "The country" .Department = "The dept" .Title = "The title" .MailStop = "The mailstop" .Greeting = "The greeting" .OfficePhone = "1111111" .HomePhone = "22222" .CellPhone = "333333" .FaxPhone = "444444" .Comments = "This is the comments field" End With End If Set AddressBookEntry = Nothing Set AddressBook = Nothing Set AddressBooks = Nothing MsgBox("Done") End Sub Note: Despite the convenience of the GroupWise.AddressBooks object model, there may be times when you need access to the lower-lever native Object API representation of an Address Book or Address Book Entry. You may access the native objects via the AddressBookEntry.Objects and AddressBook.Objects properties. .topic 71 Formativ provides many methods in the GroupWise object to manipulate the GroupWise client user interface. These methods range from displaying dialogs to opening and closing various views. You can add buttons to toolbars, create menu items, create popup menu items and run Applets in response to GroupWise events. The following topics deal with these issues. .topic 241 Formativ provides methods within the GroupWise object to manipulate the GroupWise client user interface. These range from displaying dialogs to opening and closing various views. Check the Formativ Language Guide for full details. For example, to display the GroupWise About dialog, simply call the method GroupWise.AboutDlg: Sub Main(Client, GWEvent) GroupWise.AboutDlg End Sub Note: Take care not to close down GroupWise programmatically using an Applet. Closing GroupWise while an applet is executing may cause unpredictable results, which may even result in a system crash. Always check if a window is open before using one of the window close/cancel commands. .topic 251 One of the most powerful features of Formativ is the ease with which you can add buttons to toolbars, items to menus and hook into the GroupWise event system. Traditionally, this has been one of the most difficult aspects of GroupWise development. Formativ lets you add these elements by simply indicating which GroupWise context you wish to link to these elements. A GroupWise context maps to either a message type or to an aspect of the GroupWise client. For example, each message type (Mail, Appointment, Note etc.) has its own context. A context is represented by a descriptive name, such as 'Email' or 'Appointments'. Each context is divided into categories, such as 'Toolbars', 'Menus' and 'Events' and each category is further divided into options. For example, the 'Events' category of the 'GroupWise Email' context consists of all the events you can assign scripts to, such as 'OnSend' and 'OnOpen'. Note: You can see all the contexts and context categories you can use on the Integrations tab in the Formativ IDE for each Applet you have written. When you assign integrations to an Applet, the information about that integration is saved with the Applet itself. This means that if you distribute the Applet to other users, its integrations will also appear automatically within their GroupWise clients. For example, if you write an Applet that proxies to another user, and you decide to integrate a button on the main GroupWise toolbar that executes the Applet, any user to whom you distribute that Applet will have the same button appear on their toolbar automatically the next time they start GroupWise. At GroupWise start-up, Formativ has to register its interest with any context it wishes to integrate into. In some cases, Formativ is unable to register interest in a particular context in time for it to take effect; this is due to the underlying GroupWise architecture. For example, if you write an Applet, and integrate a button for the Applet on the main toolbar, the button will not appear until you restart the client. Formativ will attempt to identify these situations and advise the user that a client restart is required. If any new integrations you design do not appear, or the events you subscribe to do not fire, you should restart the GroupWise client and try again. Before defining any client integrations, you should define the Applet description, help hint and image. Select the appropriate Applet in Formativ Central, then activate the Properties tab. This tab lets you specify the Applet description, help hint and image. The description is the text that appears on the button face if you have selected the property Picture and text for the GroupWise toolbar. The description also appears in any menu with which the applet is integrated. The help hint is the text that appears when the mouse pointer is held over a button or menu integration in the GroupWise client. You should keep the description text short if you intend to use the GroupWise Picture and text option for toolbars. With this option set, GroupWise widens all toolbar buttons to be the width of the longest button description. If you have long descriptions, this can make the GroupWise buttons very untidy. The Properties tab also lets you specify an image, from the selection of images, to display on the button. Formativ ships with a wide selection of general images. You may edit the description, help hint and image associated with an Applet at any time. However, you may have to restart the GroupWise client to see the changes take effect. .topic 261 Formativ lets you add any number of buttons to most toolbars in the GroupWise client. For each button you define, Formativ lets you supply the text that appears on the button, the hint text that appears when holding the mouse pointer over the button, and an image for the button. As with all integrations, defining a button is context-based. This means you can assign a button to appear with one or more GroupWise contexts. To define where the button should appear, select the Integrations tab within Formativ Central and select the context in which the button should appear. For example, if you would like to add the button to the GroupWise main toolbar, find the context 'GroupWise Main Window', then check the corresponding box in the Toolbar column. The next time you start the GroupWise client, a button will appear on the main toolbar with the image, caption and help hint you defined. Clicking the button will execute the applet. You can define any number of buttons that execute a single Applet. For example, if you would like to have the button described above appear on the Mail view toolbar, find the 'Mail' context and check the corresponding box in the Toolbar column. The GroupWise client will now have two new buttons that execute the same Applet. One will appear on the main window, another will appear on the Mail view dialog. .topic 271 Formativ lets you add any number of menu items to most top-level menus in the GroupWise client. For each menu item you define, Formativ lets you supply the text that appears on the menu and the hint text that appears when you hold the mouse pointer over the menu item. As with all integrations, menu integrations are context-based. This means you can assign a menu item to appear within one or more GroupWise contexts. To define where the menu item should appear, select the Integrations tab within Formativ Central. For example, if you would like to add the menu item to the GroupWise main menu under the 'File' menu, complete the following steps. Each step corresponds to the numbers in the figure below. 1. Find the 'GroupWise Main Window' context, then click the button in the Menus column. This will open the Menus dialog, which displays all menu items within the context. Menu items are displayed in groups, where each group corresponds to the menu these items belong to. For each item there are two check boxes, representing before and after the item. 2. First locate the 'File' menu group, then find a menu item (e.g. 'New') that will act as an 'anchor' for your new item. Check the lower box so that your new item will appear immediately after 'New' on the 'File' menu. Click the cross button at the bottom of the dialog to save this integration. The next time you start the GroupWise client, the new menu item will appear on the GroupWise 'File' menu. When you click the item, your Applet will be executed. You can define any number of menu items that execute a single Applet. For example, if you would like to have the same menu item as described above appear on the Mail view, find the 'Mail' context, then follow the steps above. The GroupWise client will now have two new menu items that execute the same Applet. One appears on the main window menu, the other appears on the Mail view menu. Note: Formativ identifies existing menu items by the menu caption text. By default, Formativ only recognizes the captions used by the US English GroupWise client. Users of other language clients can add support for those clients by editing the # entries in the appropriate msgclass?_?.txt files. You can find these files in the folder where you installed Formativ. .topic 281 Formativ lets you add context menu (also known as floating or popup menu) items to the GroupWise client. These items appear when you click the right mouse button (or left mouse button if left-handed) over a particular item or area in the GroupWise client. For example, if you select a Mail message in a folder and click this button, a context menu appears with options specific to Mail items. As with all integrations, defining a context menu item is context-based. To define the context menu an item should be added to, select the Integrations tab within Formativ Central. For example, if you would like to add an item to the context menu that appears for a Mail message, find the 'Email' context, then check the box in the Popup column, as shown below. The next time you click for a context menu on a Mail message, the context menu that appears will contain a new item whose caption is the description you defined for the applet. Clicking the context menu item will execute the applet. The context GroupWise uses can change depending where the mouse is when you click for a context menu. Be aware of this when defining context menu integrations. You may have to define several context menu integrations to have your applet accessible from all the menus where you require your new item to appear. .topic 291 Formativ lets you execute an applet when particular GroupWise events occur, such as when the GroupWise client starts up, a new message appears in your mailbox, or when you send a new item. There is a wide range of events you may associate with Applets. Most of the events of interest are those associated with the GroupWise message contexts, such as Mail and Appointments. For example, Formativ lets you associate an Applet with the 'OnSend' event of all message types, giving you the capability to write Applets that perform some action prior to a message being sent. Events are given names starting with 'On', such as 'OnSend', 'OnPrint' and 'OnOpen'. Standard events available for most message types include: OnAccept OnArchive OnComplete OnCompose OnDecline OnDelegate OnDelete OnDocCheckIn OnDocCheckOut OnDocResetInUse OnForward OnInfo OnOpen OnPrint OnProperties OnReply OnResend OnSave OnSaveAs OnSetAlarms OnUndelete OnView OnSend When you have your Applet subscribe to a particular event, the GroupWise processing that would normally occur is executed first, then your Applet is executed. The only exception is the OnSend event, where your Applet is executed before the item is sent by GroupWise. You can choose to override this behavior and specify the order in which the GroupWise event should occur in relation to your applet. You can choose to run your Applet: Before the GroupWise event After the GroupWise event In place of the GroupWise event Notice how the final option above lets you choose to discard the original processing completely and replace the functionality with that contained in your Applet. As with all integrations, associating an applet with a GroupWise event is context-based. To associate your Applet with an event, select the Integrations tab within Formativ Central. For example, if you would like to run an Applet when the user opens a saved Mail message, complete the following steps. Each step corresponds to the numbers in the figure below. 1. Find the 'Email' context, then click the button in the Events column. This will open the Events dialog, shown below. 2. In the Events dialog, check the box next to OnOpen. Notice how the arrow changes from gray to blue. Click the triangle button next to the arrow to select the way your Applet changes the normal processing of the event. The next time a Mail message is opened, the Applet will be executed. You can associate a single Applet with multiple events in a single context, or with multiple events in different contexts. For example, you might associate an Applet with the 'OnCompose' and 'OnReply' events of all message types. Take care when associating Applets with events. While it is technically possible to associate an applet with any supported events, try to limit the intrusion of your Applet onto events as much as possible. Some Applets lend themselves to association with events more than others. For example, while it makes good sense to associate a Signature or Disclaimer applet with the 'OnSend' event, other Applets may not lend themselves as favorably. .topic 81 User interfaces form a key component of many Formativ solutions. Formativ offers four ways to create user interfaces: Code-based Dialogs Visual Forms Designer Dialogs HTML Dialogs Portals Each approach has its own strengths and weaknesses. The following introduction provides an overview of the four approaches. Code-based Dialogs Are constructed entirely in code (cannot be visualized at design-time) Offer compatibility with all versions of Formativ Are static – the content cannot be updated without re-displaying the dialog Have a limited number of controls available Offer limited control over layout Visual Forms Designer Dialogs Are constructed using a visual drag-and-drop Forms Designer Offer the capability to create extremely rich forms Are compatible with Formativ 2.0 and above Can be updated in real time without having to re-display the dialog Are event driven – your code can respond to events on the dialog Maximize control over layout HTML Dialogs Are constructed using HTML Offer compatibility with all versions of Formativ Can be updated with dynamic HTML/Javascript Some degree of event handling is possible via JavaScript™ Portals Are constructed using HTML Are displayed inside the GroupWise client Offer high-level visual GroupWise client integration Offer compatibility with all versions of Formativ Can be updated with dynamic HTML/Javascript Some degree of event handling is possible via JavaScript™ Note: If you are targeting Formativ 2.x users, we recommend Visual Forms Designer Dialogs for general dialogs/forms, and Portals for embedded visual interfaces. .topic 301 Formativ provides a number of language extensions that allow you to design simple, yet flexible dialogs in Applets. You can build dialogs that display information, collect information from the user (using forms), or both. Note: Unless you need to target versions of Formativ prior to version 2.0, we recommend using Visual Forms Designer Dialogs rather than code-based dialogs. Forms created with the visual forms designer are far richer and more flexible than code-based dialogs. .topic 571 Code-based dialogs are created entirely in code. You cannot design a code-based dialog visually. (To create dialogs using a visual, drag-and-drop approach, use the Formativ Visual Forms Designer.) To create a code-based dialog, you must first obtain an instance of a new Control Box Dialog object. Then you add controls to this object, setting their properties in turn. Create a new Control Box Dialog Object To create a new Control Box dialog object, call the Utilities.NewControlBoxDialog method. This method returns a new fcControlDlg object. Dim RuleDlg Set RuleDlg = Utilities.NewControlBoxDialog The fcControlDlg object has a number of properties you can read and write to control the way the dialog appears and behaves. You can use properties (among others) to specify: the base buttons that appear on the dialog whether the form auto sizes the Height and Width of the dialog the Wizard image (if any) to display the Title and Caption of the dialog Once the properties have been set, you may add visual controls to the dialog. Adding Controls Controls are added to a fcControlDlg object by calling methods exposed by the object. There are methods for adding controls such as buttons, list boxes, group boxes, combo boxes, images, radio buttons, check boxes, etc. Each of these methods returns an object representing the appropriate control, which in turn exposes control-specific properties and methods. You may call the following methods to add controls to fcControlDlg objects: AddCheckBoxControl AddCheckListControl AddComboBoxControl AddDateTimeControl AddEditControl AddImageControl AddListBoxControl AddMemoControl AddMultiLineLabelControl AddPanelControl AddRadioButtonControl AddRadioGroupControl AddSpinEditControl AddStringGridControl AddTabListBoxControl For example, the following code creates a new fcControlDlg object and adds a checked list box control. Three items are added to the list box, and the first item is checked: Dim RuleDlg Dim ListBoxCtl Set RuleDlg = Utilities.NewControlBoxDialog Set ListBoxCtl = RuleDlg.AddCheckListControl ListBoxCtl.AddItem("Mail - Reply to Sender", True) ListBoxCtl.AddItem("Appointment - Decline", False) ListBoxCtl.AddItem("Task - Decline", False) See the Language Guide for details of the objects returned and the properties/methods they expose. .topic 581 A code-based dialog is displayed by calling the Execute method of the fcControlDlg object. This forces the dialog to be displayed modally; meaning the user must dismiss the dialog by clicking a button in order to continue. The Execute method returns an integer indicating which button the user pressed to dismiss the dialog. Possible values are: Btn1 = 1 Btn2 = 2 Btn3 = 3 Btn4 = 4 Btn5 = 5 Btn6 = 6 Note: Btn1 is the right-most button. Btn1 through Btn6 can be used directly in your code. .topic 1 Formativ 2.0 introduces an integrated Visual Forms Designer. The forms designer makes it easy to design event driven, interactive forms and use them in your Applets. The visual forms designer includes: Fully Visual Form Design - You use the visual forms designer to create dialog forms. Using a familiar visual drag and drop approach, forms are designed by dropping components onto forms and defining their properties and events. Fully Event Driven Operation - You may link Formativ code easily to events exposed by forms and form components. This makes it possible to perform certain actions dynamically in response to events that occur on a form. For example, you can associate code with a button click event which adds an item dynamically to a list box control located on the same form. A Rich Component Set - When designing your Formativ forms you can choose from a collection of 125 components within 11 categories. Component categories include standard, Additional, Windows, System, Dialogs, GroupWise, Enhanced 1 & II, Netware, LDAP and NDAP. The visual forms designer consists of four main components: Component Palette Object Inspector Alignment Palette Designed Form .topic 61 Creating a New Form 1. Select the Applet which requires the new form. 2. From the Formativ editor toolbar, press the Forms button. 3. The forms dialog appears. Select New. 4. Provide a name for the new form. Press OK. 5. The Forms designer is activated. A new, empty form is displayed, along with the Object Inspector, Component Palette, and Alignment Palette. Select the appropriate controls from the component palette and drop them on the form. Use the Object Inspector to give components meaningful names, to specify other component properties and define events. Press the Save Changes button to save your changes and return the editor. Press the Cancel button to discard any changes and return the editor. You can toggle between Design View and the Code View by pressing F11 or the toggle view button on the component palette. .topic 131 To Edit an Existing Form 1. Select the Applet. 2. From the Formativ editor toolbar, press the Forms button. 3. Double click the appropriate form in the forms dialog list. 4. The Forms designer is activated. Note: From the Formativ editor toolbar, press the drop down sectiont of the Forms button and select the name of the pre-defined form from the drop down list. To Delete an Existing Form 1. Select the Applet. 2. From the Formativ editor toolbar, press the Forms button. 3. Select the appropriate form in the Forms list dialog. 4. Press the 'Delete' button. 5. Confirm the deletion process. To Rename an Existing Form 1. Select the Applet. 2. From the Formativ editor toolbar, press the Forms button. 3. Select the appropriate form in the Forms list dialog. 4. Press the 'Rename' button. 5. Provide a new name. The name you provide must be unique in the current Applet. To Export an Existing Form Formativ enables you to export an existing form as a .FRM file. Exported FRM files may be imported into other Applets. Use this technique to build a library of commonly used forms which can be imported into your Applets. 1. Select the Applet. 2. From the Formativ editor toolbar, press the Forms button. 3. Select the appropriate form in the Forms list dialog. 4. Press the 'Export' button. 5. Supply a location and name for the exported form and press OK. To Import a Form You can import FRM form files into an Applet. Existing Applet forms, which have the same name as those being imported from the FRM file, may be optionally replaced. 1. Select the Applet. 2. From the Formativ editor toolbar, press the Forms button. 3. Select the appropriate form in the Forms list dialog. 4. Press the 'Import' button. 5. Select the FRM file you wish to import and press OK. .topic 71 Most components (and forms) expose events for which you can write event handlers. An event handler is a Formativ subroutine which is called automatically when the related component or form event is triggered. Events are triggered in response to an operation which involves a form or control. For example, an 'OnClick' event occurs when a user clicks a button on a form. By associating a Formativ subroutine with a button's 'OnClick' event, the subroutine is executed automatically whenever the button is pressed. To Create an Event Handler 1. Select the control for which you wish to define an event handler. 2. Select the Events tab in the Object Inspector. 3. Double click the event for which you will write an event handler. 4. Formativ creates a stub subroutine in your Applet. Write the code which will execute in response to the event. To Associate an Existing Subroutine with an Event Handler You can associate an existing subroutine with a component's event handler if the subroutine has the same argument list expected by the handler. The mechanism makes it possible to write a single event handler subroutine that can be used by many different component events. 1. Select the control for with you wish to define an event handler. 2. Select the Events tab of the Object Inspector. 3. Locate the event you wish to associate and press the drop down control to the right of the event name. Select a compatible, pre-existing subroutine from the list. .topic 91 There are two ways to display a form from an Applet at runtime: as a Modal or non-modal form. A form shown modally needs to be closed by the user before the Applet will continue processing. A form shown non-modally does not block Applet execution. Unless you wish to display a form that is used to display status information, you would normally display forms modally. Regardless of how a form is shown, the form event system continues to be active for the duration of the form's appearance. This means that, even though Applet processing may be paused because the form is being shown modally, event handler subroutines will continue to be called in response to triggered form events. Note: You do not need to explicitly create or destroy Formativ forms in your Applet code. In fact, trying to destroy or create form within Applet code is likely to result in unpredictable behavior. When an Applet containing forms is executed, Formativ creates all its forms automatically. This means an Applet is guaranteed to have its forms available at all times. Likewise, when the Applet stops executing, Formativ destroys all Applet forms automatically. Displaying a Form Modally To display a form modally, you call the form .ShowModal() function. This function causes the form to be displayed and pauses Applet execution until the user performs an action which closes the form. When the form is closed, the .ShowModal() function returns a value indicating how the form was closed. This value is known as the modal result and will be one of the following constant values: mrNone mrOK mrCancel mrAbort mrRetry mrIgnore mrYes mrNo mtAll mrNoToAll mrYesToAll In order specify the modal result value, normally you specify the modal result property of the control which will close the form. For example, you might create a form with two buttons - Button1 and Button2. Button1 will close the form and accept any user input changes. Button2 will close the form, canceling any changes made by the user. To implement this functionality, you set the Button1.ModalResult property to mrOK, and the Button2.ModalResult property to mrCancel. When this form is displayed modally using a call to ShowModal(), if the user presses Button1 the ShowModal() function will return the constant value mrOK or, if the user presses Button2, it will return mrCancel . Assuming the form is called test, you could write the following code to display the form and if the user presses Button1, perform a specific action: If test.ShowModal = mrOK Then MsgBox "You pressed Button1" Else MsgBox "You pressed Button2" End If The form will be displayed by the line test.ShowModal(). At this point the Applet will pause until the form is closed, then display the appropriate message box. Displaying Forms Non-Modally To display a form non-modally, simply call the form .Show() method. To close the form, call the .Hide() method. Calling the .Show() method does not pause Applet execution. However, the form may move out of view as GroupWise or other processes display new windows. For this reason, when you wish to use a form to display real time information about a process which is occurring in the background (like process progress status), forms are normally shown non-modally . Note: It may be necessary to ensure the Windows message queue is cleared after calling the Show() method to ensure all the controls on your form are rendered correctly. You may ensure the message queue is cleared by calling Utilities.DoEvents. For example, assuming your Applet contains a form called test, you can write the following code: Test.show Utilities.DoEvents ' Perform some process here and update components on form test ' to indicate progress Test.hide .topic 101 Using Applet code, you can access and modify any form and component property at runtime. To access a specific component, in the code you need to provide the fully qualified name of the component, starting from the name of the component's parent form. A fully qualified component name consists of: the component name prefixed by a period; and the component's parent component name (i.e. the parent component is the one which the component is sitting on). This naming procedure is repeated until the parent form is reached. For example, a button component has a caption property, which contains the text that appears on the face of the button. Assuming a form called 'test' contains a button called 'button1', the fully qualified name of the button would be test.button1 You could use the following code to update the button's caption property: test.button1.Caption = "This is the new caption" .topic 21 The component palette appears at the top of the screen when in form design mode. The component palette contains the components you may use when designing forms. The component palette also contains controls that allow you to: save the current form and return the Formativ editor; cancel any form changes and return the Formativ editor; and toggle between the form and code view. Note: See the Formativ Readme.txt for information regarding component documentation. To Use a Component Click the component you wish to use from the palette, then click once on the form being designed. An instance of the component appears on the form. You may now use the Object Inspector to specify component properties and to define events. To Save Changes The Stop Designing button saves changes made to the current form and returns to the Formativ code editor. To Cancel Changes The Cancel Changes button discards changes made to the current form and returns to the Formativ code editor. To Toggle Form Design/Code View The Toggle Form/Source View button toggles between the form design and code editor views. You may also press F11 to toggle between the form design and code editor views. .topic 31 The Object Inspector shows the properties and events exposed by the selected component. Properties specify the appearance and behaviors of a component. Events specify the Formativ subroutine/function executed in response to a component event. You can specify properties at both design time and at runtime. .topic 41 The alignment palette is used to align groups of selected controls. You may align controls to the left, right, centre, etc.. Select the components you wish to align (select multiple components by Shift-Left mouse button clicking), then press the appropriate alignment option on the alignment palette. .topic 51 The designed form is the canvas you use to create the form. You drop controls from the component palette onto the designed form. You can also specify designed form properties and events by selecting the designed form and using the Object Inspector. .topic 311 Formativ HTML Dialogs are a powerful feature: You can create dialogs using industry-standard HTML. An HTML dialog may be used to display information to end users, as well as collecting data from users that can then be used by your Applets. Note: Unless you need to target versions of Formativ prior to version 2.0, we recommend using the Visual Forms Designer Dialogs instead of HTML dialogs. Forms created with the visual forms designer are far richer and more flexible than HTML dialogs. .topic 321 HTML dialogs are modal dialogs whose content consists purely of HTML and related content, such as JavaScript. HTML dialogs make it possible to build dialogs that contain interactive content. HTML Dialog Characteristics HTML Dialogs are modal. This means the dialog must be closed before the Applet that created it (and GroupWise) can continue executing. HTML Dialogs can be displayed as standard floating windows, or they can be embedded into the GroupWise client. A floating dialog can be moved around the screen just like a normal window. Floating dialogs can also be resized. An embedded HTML dialog is displayed in the message/calendar list area of the GroupWise client. Embedded dialogs give the appearance that they are tightly integrated with the GroupWise client. HTML Dialogs display standard HTML content. They can also contain other Internet content, such as JavaScript. HTML Dialogs can be made to behave in an interactive manner through the use of Java, JavaScript, etc. Data entered into an HTML dialog is accessible from within the Formativ applet that created and displayed it via the FormVariables object. It is the developer's responsibility to add buttons that close the dialog. However, standard OK and Cancel toolbar buttons can be made to appear on the dialog. .topic 331 HTML dialogs are created using the Utilities.NewHTMLDialog method. This method returns an instance of a new HTMLDialog object. Utilities.NewHTMLDialog The Utilities.NewHTMLDialog method returns an instance of a new HTMLDialog object. Once an instance of a HTMLDialog has been created, you set up its properties and finally, call its Execute method to display the dialog. For example: Dim aDlg Set aDlg = Utilities.NewHTMLDialog aDlg.WindowState = fbsEmbedded aDlg.Caption = "Publish Address Books to MS Word" aDlg.HTMLCode = aDlg.Execute This code snippet: defines a new HTMLDialog, sets its style to fbsEmbedded so that it will appear to be embedded into the GroupWise client, sets its caption and illustrates where the raw HTML containing the dialog controls would be assigned, finally, the .Execute method is called to display the dialog modally to the user. You can assign any valid HTML code to the HTMLCode property. .topic 341 HTML Dialogs can contain any valid HTML code. They can also contain HTML related content, such as Java and JavaScript in order to add functionality. HTML Dialog Content Most HTML dialog content will consist of an HTML
element with a number of form elements, such as text edit areas, list boxes and combo boxes. The will also have at least one element representing a button used to dismiss the dialog. Formativ uses specially formatted elements in order to determine which button the user clicked in dismissing the dialog. For more information see Adding Buttons. For example, to create a very simple HTML dialog that displays a message and an OK button, the following HTML could be used:
HTML Dialog Test

The important things to note about this HTML are: Most of the code is within a
element. This is required in order to use form elements, such as edit controls, list boxes and buttons. The element has its METHOD attribute set to POST. This is required in order for the act of clicking buttons to be recognized by Formativ. The two buttons have been defined as controls. This is required in order for the act of clicking buttons to be recognized by Formativ. The two buttons have special names assigned to their NAME attributes ("MROK" and "MRCANCEL"). These special names are used by Formativ to determine how the dialog was dismissed. For detailed information, see Adding Buttons. When creating HTML dialog content, you can: Load an existing, external HTML file into an HTML dialog Dynamically build HTML content within your applet and assign it to the HTML dialog Load an existing, external HTML file into memory, modify its contents, then assign it to the HTML dialog. Displaying Existing Data in a HTML Dialog In some instances you may wish to to define your HTML content as separate, external files. This approach is particularly useful when you wish to maintain a central copy of the HTML, or the HTML is going to change on a regular basis. In order to load an external HTML file into a HTML dialog, the simplest approach is to use the Utilities.LoadStringFromFile method to load the HTML file directly into the HTMLCode property of the HTMLDialog object. For example, the following code snippet creates a new dialog and uses the contents of the file 'HTML Dialog.htm' (located in the Formativ Data Directory) as the contents of the dialog: Dim aDlg Set aDlg = Utilities.NewHTMLDialog aDlg.Caption = "Example HTML Dialog" aDlg.HTMLCode = Utilities.LoadStringFromFile(Utilities.GetDataDirectory & "HTML Dialog.htm") aDlg.Execute Displaying Dynamically Built Data in a HTML Dialog In many instances you will need to modify or generate HTML just prior to displaying a HTML dialog. For example, you may wish to dynamically add items to list box controls, or change text in the dialog, dependent on some external factor. In some instances an Applet will insert dynamic JavaScript that initializes the dialog controls, based on the state of some GroupWise data you have just extracted. The simplest way to create dynamic content is to build markers into your base HTML, load the HTML into a Formativ Applet string variable, then manipulate the string in memory to make the appropriate changes. Once the changes are complete, assign the new HTML string variable to the .HTMLCode property and call the Execute method to display the dialog. Interactive HTML Dialog Content Because HTML Dialogs use industry-standard HTML and associated technologies, it is easy to build interactive, dynamic dialogs. You can use Java Applets, ActiveX controls and JavaScript to enrich the functionality of a HTML dialog. For example, using JavaScript, you can easily present different options to users when the user selects a new entry from a combo box. Details on how to use JavaScript (and other technologies) to provide dynamic HTML content are beyond the scope of this document. There are many excellent resources available that document in great detail how to achieve a rich user experience. Note: Local machine security policies may preclude certain content types from being used. .topic 351 It is the developer's responsibility to provide users with buttons in HTML dialogs that allow for dismissing the dialog. Formativ can provide two toolbar buttons that act as OK and Cancel buttons, but this facility does not allow for data to be extracted from the dialogs. These buttons are provided only as an emergency exit for users to dismiss the HTML dialog. Buttons are added to HTML dialogs using HTML elements. An example of a properly formed element is: where: [ID] is a specially-coded button identification string (see below), and [CAPTION] is the string to appear on the button. As with all HTML form controls, this code must appear within a
pair. For example, a button that acts as an OK button when pressed might be defined as: Button Identification When a user presses an HTML dialog button, Formativ looks to see if it contains a specially-coded NAME attribute. A specially-coded NAME attribute indicates to Formativ that the dialog should be dismissed, and an appropriate return value handed back to your Applet, indicating which button the user clicked. For example, to define a button that dismisses the dialog and indicates to the applet that the OK button was pressed, the following HTML code snippet might be used: Note that the NAME attribute has been assigned the string value "MROK". "MROK" is recognized by Formativ as a button that is to dismiss the dialog and indicate to the calling Applet that the OK button was pressed. Valid values for the NAME attribute are: MROK MRCANCEL MRABORT MRRETRY MRIGNORE MRYES MRNO Any other values assigned to the NAME attribute are ignored by Formativ. Pressing buttons without one of the above NAME values will not dismiss the dialog. Of course, such a button may initiate some other valid action, such as executing JavaScript in the dialog. When a button containing one of the above NAME attributes is clicked, the dialog is dismissed and control returns to the calling Applet. A value indicating which button dismissed the dialog is returned by the HTMLDialog.Execute method. .topic 361 The Formativ HTML Dialog facility provides only the most rudimentary user interface by default. It is the responsibility of the developer to use HTML elements to provide the appropriate user interface elements, including buttons to dismiss the dialog. Formativ does provide a number of properties that can be used to customize the overall appearance and behavior of your HTML dialogs. WindowState The HTMLDialog.WindowState property is a read/write property that lets you control the overall appearance of your dialog. It can take one of three values: fbsDesigned – The dialog is displayed in the center of the screen. fbsMaximized – The dialog is displayed maximized. fbsEmbedded – The dialog is embedded in the GroupWise client. Width and Height The HTMLDialog.Width and HTMLDialog.Height properties control the overall width and height of a dialog in pixels. These settings only have an effect if the WindowState property is set to fbsDesigned. BorderStyle The HTMLDialog.BorderStyle property is a read/write property that lets you control the type of border for your dialog. It can take one of four values: fbsNone – The dialog has no visible border. fbsSingle – The dialog has a single line border. fbsSizeable – The dialog has a border that allows resizing of the dialog. fbsDialog – The dialog has a standard dialog border with no control buttons visible. Note: BorderStyle has no effect if the WindowState property is set to fbsEmbedded. Caption The HTMLDialog.Caption property is a write-only string property that sets the caption text of the dialog. It has no effect if the WindowState property is set to fbsEmbedded. ContextMenuEnabled The HTMLDialog.ContextMenuEnabled property is a write-only Boolean property that controls whether the Internet Explorer mouse content menu is enabled when displaying HTML dialogs. ToolbarVisible The HTMLDialog.ToolbarVisible property is a read/write property that controls the visibility of the dialog toolbar. The dialog toolbar contains an OK and Cancel button. These buttons return OK and CANCEL values from the HTMLDialog.Execute method. These buttons do not activate the variable extraction routines normally available when using HTML elements to close the dialog. .topic 371 An HTML dialog is displayed by calling the HTMLDialog.Execute method. The Execute method displays the dialog modally, which means the user must dismiss it in order for processing to continue. An Applet pauses at the Execute method until a return value is obtained, indicating which button was used to dismiss the dialog. The Execute Method The Execute method returns an integer value indicating which button was used to dismiss the dialog. The possible return values are: 1 - MROK 2 - MRCANCEL 3 - MRABORT 4 - MRRETRY 5 - MRIGNORE 6 - MRYES 7 - MRNO The labels MROK, MRCANCEL map directly to the names given to the button controls within your HTML. For full details see Adding Buttons. .topic 381 As with Formativ Portals, you are able to extract the values of HTML form controls from your HTML dialogs. You access dialog data via the HTMLDialog.Variables property. HTMLDialog.Variables The HTMLDialog.Variables property is a read-only property that returns a FormVariables object. FormVariables is a collection of FormVariable objects. A FormVariable object represents a single HTML element and its value. Once a dialog has been displayed via its Execute method, you query its Variables property to determine the value of the HTML form elements in the dialog. For more information see The FormVariables Object. .topic 391 Utilities.NewHTMLDialog Returns an instance of a new HTMLDialog object. HTMLDialog You may create any number of HTMLDialog objects in an applet. HTMLDialog.Execute Causes the dialog to be displayed modally. Returns an integer value indicating which button dismissed the dialog. HTMLDialog.OpenGroupWiseMsgs Read/write Boolean property. Specifies whether GroupWise MessageIDs embedded in HTML will cause the message to be opened when clicked. More information can be found here. HTMLDialog.Navigate Loads the HTML code at the given URL. HTMLDialog.HTMLCode Read/write string property. Lets you specify the HTML code to be displayed. HTMLDialog.WindowState Read/write property. Specifies how the dialog is to be displayed. Possible values are: fbsDesigned – The dialog is displayed in the center of the screen fbsMaximized – The dialog is displayed maximized fbsEmbedded – The dialog is embedded in the GroupWise client HTMLDialog.Width Read/write integer property. Specifies a width for the dialog in pixels. Only applicable if WindowState is fbsDesigned. HTMLDialog.Height Read/write integer property. Specifies a height for the dialog in pixels. Only applicable if WindowState is fbsDesigned. HTMLDialog.BorderStyle Read/write property. Specifies the border style of the dialog. Possible values are: fbsNone – The dialog has no visible border. fbsSingle – The dialog has a single line border. fbsSizeable – The dialog has a border that allows resizing of the dialog. fbsDialog – The dialog has a standard dialog border with no control buttons visible. Note: The BorderStyle property has no effect if the WindowState property is set to fbsEmbedded. HTMLDialog.Variables Read-only property. Returns any variables and their values set by HTML form controls in the dialog. Variables are returned in a FormVariables collection. HTMLDialog.Caption Write-only string property. Specifies the caption displayed on the dialog. It has no effect if the WindowState property is set to fbsEmbedded. HTMLDialog.ContextMenuEnabled Write-only Boolean property. Specifies whether the mouse context menu should be accessible via the dialog. HTMLDialog.ToolBarVisible Read/write Boolean property. Specifies whether the dialog toolbar, containing OK and Cancel buttons, is visible. .topic 401 The Formativ Portal Manager is a powerful feature that lets you create and embed portals into the GroupWise client. A portal is a window that can display many different types of data. The types of data you can display depends on the software you have installed on your computer, but at a minimum you can display web sites, XML, HTML and images. The Formativ Portal Manager lets you create and display any number of portals directly in the GroupWise client. You can also programmatically access the information being displayed in a portal. The Portal Manager requires Novell GroupWise 6.01 or greater. Novell have also released a beta FTF file for the GroupWise 5.5.7.1 Enhancement Pack client which enables the use of Formativ Portal Manager™ based solutions with the GroupWise 5.5 EP client. See Novell TID 2963458 for details on the update and information on how to download the GroupWise 5.5.7.2 Beta FTF file (f32eppp1.exe). .topic 411 A portal is a custom window that appears embedded in the GroupWise client. It can be used to display any information that Microsoft Internet Explorer can display, such as HTML, XML, images, web sites, etc. You can display pre-existing content in a portal (such as a web site or XML file), or you can display content built dynamically by a Formativ Applet. For example, you could write an Applet that extracts all of today's appointments from your GroupWise calendar, builds HTML representing the appointments, then displays the HTML inside a portal. Portal Characteristics Portals are custom windows that appear in the GroupWise client Portals appear in the calendar/message list area of the GroupWise client Portals use Microsoft Internet Explorer to display content (you need to have Microsoft Internet Explorer 5.5 or later installed to use the portal manager) You can build dynamic content and display it in a portal, or you can display existing content, such as a web page You can extract information from a portal and use it an applet You can use a portal to open GroupWise items by clicking on specially formatted HTML links You can customize the appearance of a portal window to include standard browser buttons, captions, etc. Portals are persistent. This means that a portal and its contents remain active during a GroupWise session, even if hidden. This means you can display live content in a portal (such as a web site), hide the portal then open it again in the same session – with its content unchanged. Portals use Microsoft's Internet Explorer security settings. This means the settings defined in IE's Internet Options will also affect any portals you create. You can create any number of portals. If more than one portal exists and they are visible, each portal appears on its own tab within the GroupWise client. Users can click a tab to activate a portal, or an Applet can programmatically activate a particular portal. .topic 421 Portals are created and managed using the Formativ Portal Manager. The Formativ Portal Manager is accessed via the Formativ Portal Object Model. The Portal Manager The Formativ Portal Manager is accessed via the GroupWise.PortalManager object. For example, the following code sets the variable iPortals to the portal manager's Portals collection. ' Get an instance of the Portals collection Set iPortals = GroupWise.PortalManager.Portals To create a new portal, simply call the .Add method of the PortalManager.Portals object. The .Add method returns a new portal object. The following code creates a new portal object and sets some properties. Note that this does not display the portal in the client. Set iPortal1 = iPortals.Add iPortal1.Caption = "Advansys Home" iPortal1.TabCaption = "Advansys" iPortal1.ID = "PORTAL1" iPortal1.NavigationControlsEnabled = True iPortal1.URLInputEnabled = True iPortal1.Url = PORTAL_URL1 Portal IDs Each portal has a unique ID which is accessible via the .ID property of the Portal object. A portal ID is a string that uniquely identifies a portal. Portal ID's are used to locate portals within the Portals collection. You can manually allocate a portal ID (as is done in the example above), or you can let Formativ automatically allocate an ID for you. The Portal Manager will allocate an ID of "Portal1" to the first portal you create, "Portal2" to the second and so on. It is often useful to override the default portal ID with something more meaningful so that you can programmatically access the portal later in the session. Note: Remember that portals are persistent within a GroupWise session. Even after an Applet that created a portal has finished running, the portal will persist until the user explicitly destroys the portal, the portal is destroyed by an Applet, or GroupWise is shut down. Checking if a Portal Exists There are many instances where your Applets need to check if a particular portal already exists. For example, you may have an Applet that creates a portal to display a particular web site. You want your users to be able to keep the portal active for the current GroupWise session, even if the portal is hidden during the session. Each time the Applet is executed, it should first check to see if the portal has been previously created. If it has, the portal simply needs to be displayed. If it has not been previously created, it needs to be created then displayed. This functionality can be achieved by checking for the portal via the Portals.Item property: Set iPortal1 = iPortals.Item("PORTAL1") ' If the above code did not return a portal, create it (this will happen the ' first time the applet is executed during a session). If iPortal1 is Nothing Then Set iPortal1 = iPortals.Add iPortal1.Caption = "Advansys Home" iPortal1.TabCaption = "Advansys" iPortal1.ID = "PORTAL1" iPortal1.NavigationControlsEnabled = True iPortal1.URLInputEnabled = True iPortal1.Url = PORTAL_URL1 End If In this example, we try to set iPortal1 to be the portal with the unique ID "PORTAL1" by passing the portal ID to the Portals.Item property. If a portal with this ID exists, it is assigned to the iPortal1 variable, and can then be shown. We check for an object by comparing the return variable (iPortal1) against the nothing data type: If iPortal1 is Nothing Then ... End If .topic 431 To display a portal, call its .Show method. This has the effect of displaying all portals that have their Visible property set to TRUE. Portals are displayed in the calendar/message list area of the GroupWise client. If messages were being displayed when the portal was shown, you need to hide the portal in order to see the messages again. You can still view calendar data by selecting a calendar view in GroupWise. Reselecting a message view in the client causes the portal(s) to reappear. The opposite effect is seen if the user has a calendar view open when a portal is shown. Note: Portals are asynchronous in nature. This means that when a portal is shown, your Applet continues to run. This means you cannot pause your applet and wait for certain conditions to be met before continuing. You can achieve the same result by using the portal Applet execution feature. To Display a Portal To display a portal, call its .Show method. For example iPortal1.Show To Select a Portal If more than one portal exists, each portal is shown on a single tab. Calling a portal's .Show method is not sufficient in order for that portal to be the one that is ultimately shown. To ensure a particular portal is visible, you need to set the Portals.ActivePortal property. The ActivePortal property is a string representing the unique ID of the portal that is currently visible. For example: iPortals.ActivePortal = "PORTAL1" makes the portal with the ID "PORTAL1" the frontmost portal in the GroupWise client. .topic 441 Portals appear within the GroupWise client. They appear in the message list/calendar area of the client. The portal interface consists of a toolbar, the portal itself, and a number of tabs if more than one portal has been defined. The user can select which portal to view by clicking on the tabs, or you can programmatically define which portal should be frontmost. You can customize the controls that appear on individual portal toolbars by using the properties exposed by the portal object. For example, you can make a URL edit control appear on one portal but not another. Customizing the portal toolbar You customize the portal toolbar for an individual portal by using the properties exposed by the Portal object. The appropriate properties are: .Caption = [String value] The .Caption property specifies the text that appears at the top of the portal page within the toolbar area. This property is optional, and an empty value results in no caption being displayed. .TabCaption = [String value] The .TabCaption property specifies the text that appears on the tab holding this portal. The tab is only visible if more than one portal has been created. .NavigationControlsEnabled = True|False The .NavigationControlsEnabled property specifies whether the HTML navigation buttons (back, forward, refresh and stop) appear on the portal toolbar. .URLInputEnabled = True|False The .URLInputEnabled property specifies whether the URL edit control appears on the toolbar. .CanClose = True|False Setting .CanClose to FALSE will hide the Close Portal button and prevent the user from manually closing the Portal. A value of TRUE will display the Close Portal button. .HideCloseControlsEnabled = True|False Setting .HideCloseControlsEnabled to FALSE hides the Hide all Portals, Hide this Portal and Close this Portal buttons. A value of TRUE will display all close and hide buttons, unless the CanClose property is FALSE, in which case the Close this Portal button will not be displayed. .topic 451 There are two main ways to get content into a portal for display: Use existing data (such as a web site or local HTML), or Have your Applet dynamically create content and load it into a portal for display. Using Existing Data The primary means of loading existing data into a portal is to use the portal.URL property. The .URL property is a string that accepts any properly formed URL. A URL can be the address of a web site, or the full path to a file. (Assuming you have an appropriate browser plug-in installed, you can view documents other than HTML directly inside the portal.) For example, to browse to the Advansys web site, use the following syntax (assuming iPortal1 represents a Portal object): iPortal1.Url = "www.advansyscorp.com" To load the contents of a file into a portal, use: iPortal1.Url = "C:\FileList.txt" Creating Content Portal objects expose a .HTML property. This string property lets you both read and write the HTML contents of a portal. Writing a value to the .HTML property clears the portal of any existing data and loads it with the given HTML content. The HTML string supplied must represent a valid HTML document. This technique makes it possible to dynamically build content based on GroupWise data, or any other accessible data. For example, you could write an Applet that extracts calendar information from your GroupWise account, then builds an HTML representation of the data. This HTML is finally loaded into a portal and displayed. For example, here is a simple Applet that builds dynamic HTML content and displays it to the user in a portal: Dim iPortal1 Dim iPortals Set iPortals = GroupWise.PortalManager.Portals Set iPortal1 = iPortals.Item("Example") If iPortal1 is Nothing Then Set iPortal1 = iPortals.add iPortal1.ID = "Example" iPortal1.NavigationControlsEnabled = True iPortal1.HTML = "Hello " & GroupWise.Account.Owner.DisplayName & ", welcome to Formativ!" End If iPortal1.Show iPortals.ActivePortal = iPortal1.ID .topic 461 The FormVariables object is used to access values from a HTML form. FormVariables is a collection of FormVariable objects. A FormVariable object represents the name and value of an HTML form element. The FormVariables object is updated whenever a POST operation is performed within a portal that contains a HTML form. The FormVariables Object The FormVariables object is available for use automatically within an applet. It does not have to be instantiated from any other objects. FormVariables is a collection of FormVariable objects (see below), and exposes the following properties and methods: FormVariables.Count FormVariables.Count is a read-only integer property. It returns the number of FormVariable objects currently in the collection. FormVariables.Item(Index Integer) FormVariables.Item is a read-only property. It returns the FormVariable object that has the given index value. FormVariables.ItemByName(Name String) FormVariables.ItemByName is a method. It returns the FormVariable object that has the name given in Name. The .ItemByName method is a convenient means to determine if a FormVariable with a given name exists in the collection. FormVariable FormVariable represents a single HTML form variable. All FormVariable objects are managed by the FormVariables object. FormVariable exposes the following properties: FormVariable.Name FormVariable.Name is a read-only string property. It contains the name of the HTML form variable. FormVariable.Value FormVariable.Value is a read-only string property. It contains the value of the HTML form variable. Mapping HTML to FormVariable Objects Formativ automatically maps HTML form elements to FormVariable objects when the POST operation is called on a form:
[TODAY_DATE]
.topic 471 Not only do Formativ portals let you define content, they also expose the contents of a portal to your Applets. This powerful feature enables you to: Extract and process the raw HTML a portal may be displaying Extract data from HTML forms being displayed in a portal Execute a Formativ applet from a portal Extracting HTML from a portal The portal object exposes a property called .HTML. The .HTML property is a read/write string property that lets you access the raw HTML code currently being displayed in a portal. This feature lets you create Applets that can visit a web site and analyze its content. To access a portal's raw HTML, simply read the .HTML property into a string variable. For example, the following Applet creates a portal, navigates to a web site and counts the number of "bold on" attributes ("") found: Const BOLDATTR = "" Dim iPortal1 Dim iPortals Dim iHTML Set iPortals = GroupWise.PortalManager.Portals Set iPortal1 = iPortals.Item("Example") If iPortal1 is Nothing Then Set iPortal1 = iPortals.Add iPortal1.ID = "Example" iPortal1.NavigationControlsEnabled = True iPortal1.URL = "www.advansyscorp.com" End If iPortal1.Show ' Wait for the portal to load While ((iPortal1.ReadyState <> READYSTATE_COMPLETE) And (iPortal1.ReadyState <> READYSTATE_INTERACTIVE)) Utilities.DoEvents Wend iHTML = iPortal1.HTML iFound = 0 iPos = 0 iPos = InStr(1, iHTML, BOLDATTR, vbTextCompare) While iPos > 0 iFound = iFound + 1 iPos = InStr(iPos + Len(BOLDATTR), iHTML, BOLDATTR, vbTextCompare) Wend MsgBox iFound & " instances of were found." It is important to note that the Portal.HTML property will not return the portal's source code until the entire document has been loaded. You can check this by querying the Portal.ReadyState property, documented in the Language Guide. A peculiarity of the Microsoft Internet Explorer window used by the portals is that it does not return the appropriate ready state unless it is visible. This means that you need to display a portal via its .Show method to ensure it has completely loaded before you can reliably query the .ReadyState and .HTML properties. Extracting Data from HTML Forms It is easy to extract data from portals displaying HTML forms. The ability to extract data from a portal, coupled with the ability to execute an applet from a portal (see below), makes it easy to build very powerful and flexible data collection systems in GroupWise. For example, you could create a portal that displays an HTML form to the user. When the user completes the form and presses a button on the form, the data entered on the form can then be used by another Applet to perform further processing. The Today View Applet that ships with Formativ is a complete working example of such a system. The FormVariables object is used to access data from a HTML form. This object lets you access the names and values of every named HTML form element contained in a portal. For example, the following Applet creates a portal that displays a simple HTML form. The form consists of two text edit controls and a button. When the button is pressed, the applet is automatically re-executed via a portal trigger. The Applet determines that it has been executed as a result of a portal trigger, then uses the FormVariables object to access and display the values of the two text edit controls. Dim iDlg '------------------------------------------------------------------------------- ' Main line processing '------------------------------------------------------------------------------- Sub Main(Client, GWEvent) ExecutePortal ' If the Ok button was clicked If GWEvent = "HTML_TRIGGER" Then ReadUserData End If End Sub '------------------------------------------------------------------------------- ' Execute the portal '------------------------------------------------------------------------------- Sub ExecutePortal Dim iPortal Dim iPortals iPortalID = "Test" Set iPortals = GroupWise.PortalManager.Portals Set iPortal = iPortals.Item(iPortalID) If iPortal is Nothing Then Set iPortal = iPortals.Add With iPortal .Caption = "Formativ Business Solutions" .TabCaption = "Test" .ID = iPortalID .OpenMessages = True .RunApplets = True .HTML = Utilities.LoadStringFromFile(Utilities.GetDataDirectory + "testPortal.htm") End With End If iPortal.Show iPortals.ActivePortal = iPortalID End Sub '------------------------------------------------------------------------------- ' Read the dialog value if 'Ok' button pressed '------------------------------------------------------------------------------- Function ReadUserData Dim iProcess Dim iNameCTL Dim iAddressCTL Set iProcess = FormVariables.ItemByName("MROK") If Not iProcess is Nothing Then ' Get the text inside the name field Set iNameCTL = FormVariables.ItemByName("nameCTL") If Not iNameCTL is Nothing Then Call MsgBox(iNameCTL.Value, vbInformation, "Name") End If ' Get the text inside the address field Set iAddressCTL = FormVariables.ItemByName("addressCTL") If Not iAddressCTL is Nothing Then Call MsgBox(iAddressCTL.Value, vbInformation, "Address") End If End If Set iProcess = Nothing End Function The HTML used by this example is shown below; note the hidden input element named "formativapplet". This is a specially coded type that tells Formativ it needs to execute the Applet named in the VALUE element when the button is pressed. Notice also that the two edit box controls have been named 'nameCTL' and 'addressCTL'. These names map directly to the FormVariables object in Formativ, and are used to name the instances of the FormVariable objects returned by the FormVariables collection. You can see how to access these objects in the Applet example above. For example, to obtain the value of the text entered in the INPUT control called 'nameCTL', we could use the following applet code: Set iNameCTL = FormVariables.ItemByName("nameCTL") If Not iNameCTL is Nothing Then Call MsgBox(iNameCTL.Value, vbInformation, "Name") End If
 | Enter text and click 'Ok'.
Name: |
Address: |
.topic 481 Formativ portals recognize specially formatted links within HTML as links to messages in the GroupWise message store. Using this technique, you can dynamically build HTML that lets users click on a link that automatically opens any GroupWise message. For example, the Today View Applet that ships with Formativ dynamically builds HTML representing calendar information. When any item in the portal is clicked by the user, the original GroupWise message represented by that item is opened automatically. Creating a Portal that supports automatic opening of GroupWise messages In order for this feature to work, you need to set the Portal.OpenMessages property to TRUE. Portal.OpenMessages is a read/write Boolean property. Portal.OpenMessages is FALSE by default. For example, the following code snippet shows how to create a portal that supports automatic opening of GroupWise messages: Set iPortal1 = iPortals.Add iPortal1.OpenMessages = True Encoding GroupWise MessageIDs In order to build HTML that automatically opens a GroupWise message, you need to build a specially formatted HREF attribute containing the MessageID of the message to be opened (a MessageID is the unique ID of a message). A properly-formed MessageID HREF element is shown below: [Description] where: [MessageID] is the unique MessageID of the message to be displayed when the link is clicked, and [Description] is the text that describes the link. An example of such a link is: Sales Meeting This HTML code will result in a link being displayed with the label "Sales Meeting". When the link is clicked, the original GroupWise message (in this case an Appointment) will be automatically opened for the user. For example, the following Applet extracts the subjects of the currently selected messages from your GroupWise account and displays each subject in a portal. When a subject entry is clicked, the original GroupWise item is opened: Sub Main(Client, GWEvent) Dim iHRT Dim iMsg Dim iPortal Dim iPortals Dim iHTML Dim x iHRT = Chr(13) & Chr(10) Set iPortals = GroupWise.PortalManager.Portals Set iPortal = iPortals.Item("Example") If iPortal is Nothing Then Set iPortal = iPortals.Add iPortal.ID = "Example" iPortal.OpenMessages = True iPortal.NavigationControlsEnabled = False End If iCount = Client.ClientState.SelectedMessages.Count For x = 1 To iCount Set iMsg = Client.ClientState.SelectedMessages.Item(x) iHTML = iHTML & iHRT & "" & iMsg.Subject & "
" next iPortal.HTML = "" & iHTML & "" iPortal.Show iPortals.ActivePortal = iPortal.ID End Sub .topic 491 Formativ portals let you optionally execute an Applet when a portal HTML button is clicked. This is useful for when you need to perform further processing based on the content of a portal. For example, the Today View Applet has a Settings button. When this button is clicked, another HTML page is loaded into the same portal that allows users to specify user interface settings. When the OK button on this portal is clicked, the settings entered are used to redisplay the Today View portal. All this functionality is achieved by automatically executing the same Applet from within the portal and using data obtained via the FormVariables object. Executing an Applet from a Portal You can execute a Formativ applet by defining a hidden HTML element within an HTML form. When a SUBMIT action is sent (as a result of pressing a button, for example), Formativ looks for any hidden elements that are formatted to execute Applets. If it finds one, Formativ executes the Applet defined in the tag. A properly formatted element is shown below: where: [appletname] is the name of the applet to execute, including the .VBF extension. For example, the following HTML code snippet defines an HTML form that contains a SUBMIT button with the caption "Settings...". When this button is clicked, Formativ locates the tag and executes the Applet called "today view_flexalock.vbf".
Date
Note: This technique can only be used to execute local Applets. Determining if an Applet is being executed via a Portal In many cases your Applet needs to know if it is being executed as a result of a portal input tag as described above. For example, the above code causes the "today view_flexalock.vbf" Applet to be executed. This is the same Applet that dynamically built the original portal. When this Applet is executed as a result of the "Settings..." buttons being clicked, instead of redisplaying the Today View portal, we need it to display the Settings portal content instead. An Applet can detect if it is being executed as a result of a portal by checking the GWEvent parameter of the Main subroutine in every Applet. If the GWEvent parameter equals the string "HTML_TRIGGER", the Applet is being executed as a result of a portal trigger. For example, the following code snippet illustrates how it is possible for an Applet to perform different processing if it was executed as a result of a portal trigger: Sub Main(Client, GWEvent) If GWEvent = "HTML_TRIGGER" Then DetermineAction Else DisplayView End If End Sub In this example, the Applet will call the DetermineAction subroutine if the Applet is being called as a result of a portal trigger. Otherwise, the Applet will call the DisplayView subroutine. If the DetermineAction subroutine was called, it would probably use the FormVariables collection to access the data that was entered into the form at run time. .topic 501 GroupWise.PortalManager Returns the single instance object of the PortalManager. PortalManager There is only one instance of the PortalManager available at any time. The PortalManager persists for the duration of the GroupWise session. PortalManager.Portals Returns a reference to the single instance Portals object. PortalManager.ShowAll Shows all portals. PortalManager.HideAll Hides all portals. Portals Portals is a collection of individual Portal objects. It is returned by the PortalManager.Portals property. Portals.Count Returns the number of Portals which have been created. Portals.Item(Index) Returns the Portal object identified by the Index parameter. The index parameter can be an integer or a string portal ID. Portals.Delete(Index) Deletes and destroys the Portal identified by the Index parameter. The index parameter can be an integer or a string portal ID. Portals.Clear Clears and destroys all Portals. Portals.Add Creates and returns a new Portal. A unique Portal ID is assigned automatically. The string ID can be set to another value by using the Portal.ID parameter. See the Portal object for details. Portals.ActivePortal Gets or returns the active Portal ID by using the Portal.ID parameter string value. Portal Portal represents a single portal object. A portal will persist for the duration of a GroupWise session unless it is explicitly destroyed by the user or by an Applet. Portal.ID The unique string ID associated with a Portal. A portal ID is automatically assigned when you create a new portal, or you can define your own. Portal.Caption Sets or returns the text located at the top left of the Portal toolbar. Portal.TabCaption Sets or returns the Portal tab caption text. Portal.TabVisible Sets or returns whether the Portal tab is visible or hidden. Portal.HTML Sets or returns the HTML source for each Portal. Setting the HTML property will render the page within the Portal. Reading the HTML property will return the HTML source displayed in the Portal. Portal.CanClose Setting CanClose to FALSE will hide the Close Portal button and prevent the user from manually closing the Portal. A value of TRUE will display the Close Portal button. Portal.RunApplets A value of TRUE instructs Formativ to parse and run an Applet which is referenced in an HTML form SUBMIT function. This feature enables Applets to be executed from HTML pages. A value of FALSE will cause Formativ to process the SUBMIT function as a normal HTML form process and will ignore any embedded Applet references. Portal.OpenMessages A value of TRUE will instruct Formativ to parse the user-selected URL and extract any embedded GroupWise MessageID. If a valid MessageID is found, Formativ will automatically open the associated message and display it using the standard GroupWise client view. A value of FALSE will activate user-selected URL's using standard browser operation and will not look for embedded GroupWise MessageID's. Portal.URL Setting the URL property will cause the Portal to display the content at the location specified by the URL. Reading the URL property will return the URL for the content currently displayed in the Portal. Portal.Visible Setting this property to TRUE will make the Portal visible. Setting the value to FALSE will hide the Portal. Reading the property will return the current visibility of the Portal. See also the Show and Hide methods. Portal.Delete The Delete method destroys the Portal and removes the Portal ID from the list of available Portals. Portal.Show The Show method makes the Portal visible and sets it as the topmost, active Portal. Portal.Hide The Hide method hides the Portal from view. Portal.URLInputEnabled Set to TRUE to display the URL navigation edit control. A value of FALSE will hide the URL navigation edit control. Portal.NavigationControlsEnabled TRUE displays the Forward, Back, Refresh and Stop Activity browser controls. FALSE hides these browser navigation controls. Portal.HideCloseControlsEnabled FALSE hides the Hide all Portals, Hide this Portal and Close this Portal buttons. A value of TRUE will display all close and hide buttons, unless the CanClose property is FALSE, in which case the Close this Portal button will not be displayed. Portal.ReadyState Indicates the state of the Web browser control. Read ReadyState to obtain state information specific to the Web browser control. Use this information to avoid attempting to use the Web browser control when it is not ready to perform an action. The portal must be visible in order to obtain an accurate result from this property. The following table lists the possible values: Portal.Document Provides access to the Automation interface of the portal's HTML document. Use Document to access an IDispatch interface for manipulating the contents of the HTML document through the COM object model. If there is no active document, Document is empty. That is, you must first load a document using the HTML or URL properties before you can manipulate it using the Document interface. For more information about the Document interface, see the document object section of Microsoft's Dynamic HTML reference. .topic 601 Formativ 2.0 allows you to specify an Applet that should be executed when the current Applet has finished executing. Applet Chaining makes it possible to build interactive solutions based on two or more discrete Applets. Formativ 2.0 also introduces the concept of Applet Data Exchange, which makes it easy for one Applet to pass data to another via a global 'scratch pad'. This feature can be used to pass data between Applets during chaining. Specifying an Applet to Chain Specify the Applet you wish to chain by providing its name to the Utilities.ChainApplet property. Only the Applet name needs to be supplied, though the full path may optionally be supplied. When the Applet containing this line finishes executing, the Applet indicated by Utilities.ChainApplet will be automatically executed (assuming the Applet is available). You can only specify one chain Applet at a time. If your Applet makes two calls to ChainApplet, only the most recent call will take effect. Note: The Applet you specify in the Utilities.ChainApplet property does not get executed until the current Applet finishes. For example, suppose you wish to chain an Applet called 'test.vbf'. You would simply need to enter the following line in your chaining Applet: Utilities.ChainApplet = "test.vbf" Checking an Applet is Available to be Chained It is good practice to first check that an Applet you wish to chain is actually available on the user's computer. The easiest way to check that a particular Applet exists is to use the Utilities.AppletInstalled() method. This method takes as its only argument the name of the Applet you wish to chain. It returns a Boolean indicating if the Applet is actually installed on the current computer. For example, if you wished to chain an Applet called 'test.vbf', you could confirm it first existed by using the following code: If Not Utilities.AppletInstalled(IDR_APPLET_TO_CHAIN) Then MsgBox "Sorry - this applet is not installed.", 0, IDS_TITLE Else Utilities.ChainApplet = IDR_APPLET_TO_CHAIN End If .topic 611 In some situations you may wish to pass data between two or more Applets. This is particularly useful when used with Applet Chaining. Formativ 2.0 introduces a global property, accessible to all Applets in the system. Passing Data Between Applets To pass data between two or more Applets, assign the data to the Utilities.TransferData property. Utilities.TransferData is a read/write property that accepts string data. As long as you can coerce your data into a string you may assign it to the Utilities.TransferData property. Consider the following scenario. You have two Applets, A and B. You want to pass the subject of a message from Applet A to Applet B. You want Applet B to automatically run once Applet A is done. Applet A: Sub Main(Client, GWEvent) Utilities.ChainApplet = "B.vbf" Utilities.TransferData = "This is the data we want to transfer to Applet B" End Sub Applet B: Sub Main(Client, GWEvent) MsgBox Utilities.TransferData, 0, "This is the transferred data" End Sub When Applet A finishes executing, Applet B will automatically start and display a message box containing the string "This is the data we want to transfer to applet B". Security Considerations The Utilities.TransferData property is a global property, available to all Applets running on the computer. This means any Applet is free to modify or delete the contents of the property at any time. Your Applets should never assume the contents of Utilities.TransferData are the expected contents. Ideally, you should check the format of the contents of Utilities.TransferData before using it. Because the Utilities.TransferData is global, you should not use it to transfer sensitive information using plain text. Encrypt sensitive data before placing it in the Utilities.TransferData property. .topic 621 The Formativ Applet language makes it easier to work with XML data. The native Microsoft XML Document Object Model is exposed via the Utilities.XMLDom method. The Utilities.XMLDom method returns an instance of the Formativ XMLDom object. The XMLDom Object An instance of the XMLDom object can be obtained by calling the Utilities.XMLDom method. A XMLDom object has the following methods and properties: LoadFromDisk(const XMLFile: String) This method loads an existing XML file into the DOM. Returns a Boolean indicating success. LoadFromString(const XMLString: String) This method loads the DOM with a string containing XML data. Returns a Boolean indicating success. SaveToDisk(const Filename: String) This method saves the contents of the DOM to disk using the supplied filename. Document This property returns an instance of a IXMLDOMDocument2 interface. This interface gives you native access to the XML DOM. The IXMLDOMDocument2 interface is defined by Microsoft. .topic 631 The Formativ Applet language makes it easier to work with HTML data. The native Microsoft HTML Document Object Model is exposed via the Utilities.HTMLDom method. The Utilities.HTMLDom method returns an instance of the Formativ HTMLDom object. The HTMLDom Object An instance of the HTMLDom object can be obtained by calling the Utilities.HTMLDom method. A HTMLDom object has the following methods and properties: LoadFromDisk(const Filename: String) Method. Loads an existing HTML file into the DOM. Returns a Boolean indicating success. SaveToDisk(const Filename: String) Method. Saves the contents of the DOM to disk using the supplied filename. LoadFromURL(const SourceURL: String) Method. Loads the HTML at the given URL into the DOM. Returns a Boolean indicating success. DosPathToUnixPath(const DosPath: String) Helper method to convert a DOS-compatible path specification to a UNIX-compatible path specification as used on the Web. Use DosPathToUnixPath to convert a path name on the local machine to a path name that can be sent in an HTTP message, or that will be used by a UNIX-based application. DosPathToUnixPath converts all backslash characters (\) to forward slash characters (/). HTMLDecode(const HTMLIn: String) Helper method to decode an HTML entity reference, e.g. from "&" to "&". Returns a string. HTMLEncode(const HTMLIn: String) Helper method to encode an HTML entity reference, e.g. from "&" to "&". Returns a string. HTTPDecode(const HTMLIn: String) Helper method to decode a string that includes HTTP escape characters. Decodes the escape characters (+ and %) in a string that comes from an HTTP message header. Plus characters (+) are converted into spaces. Percent signs (%) indicate that the next two characters are the hex representation of a character. If a percent sign is followed by another percent sign (%%), it is converted into a single percent sign. Returns a string. HTTPEncode(const HTMLIn: String) Helper method to convert a string into a form that contains no characters that are illegal in an HTTP message header. Converts all characters except for the letters A through Z (and a through z), numerals 0 through 9, the asterisk (*), dollar sign ($), exclamation point (!), at sign (@), period (.), underscore (_), single quote ('), comma (,) parentheses, and hyphen (-). Spaces are converted to plus characters (+), and every other character is converted into a hex value prefixed by the percent sign (%). Returns a string. UnixPathToDosPath(const UnixPath: String) Helper method that performs the reverse of DosPathToUnixPath (see above). Returns a string. Document Property. Returns an instance of Microsoft's IHTMLDocument2 interface for the given document. IHTMLDocument2 gives you full access the HTML DOM. Note: Formativ includes several helper methods designed to make working with the HTML DOM easier. See Utilities.IHTMLDocumentSaveToFile(), Utilities.IHTMLDocumentAsString() and Utilities.IHTMLDocumentFromViewHandle() for more information. .topic 641 Formativ 2.0 introduces the ability to access the native HTML code behind an HTML message view. If the message is a received message, you may access the HTML in read-only mode. If the message is being composed, you may both read and write the native HTML code. This facility means you are able to programmatically assign HTML content to composing messages. For example, you could use this facility to personalize the content of a HTML message via an Applet. Accessing a Message View's IHTMLDocument2 Interface You access the raw HTML in a message view using the IHTMLDocument2 interface. IHTMLDocument2 gives you full access to the HTML via an extensive document object model, or DOM. You can only access the IHTMLDocument2 interface for the currently open message view. You cannot use this technique to access HTML content in a message that is being created directly in the message store without a user interface. To access the IHTMLDocument2 interface, first ensure a HTML message is open and has the focus, then call the Formativ method Utilities.IHTMLDocumentFromView(). (You may also call Utilities.IHTMLDocumentFromViewHandle() if you have the handle of the view window). Utilities.IHTMLDocumentFromView() has one parameter. This variable must have already been dimensioned in your Applet. If the call to Utilities.IHTMLDocumentFromView() is successful, this parameter is initialized with an instance of the IHTMLDocument2 interface for the current message view. For example, the following Applet attempts to access the IHTMLDocument2 interface for the currently active message view. Sub Main(Client, GWEvent) Dim iDocument If Utilities.IHTMLDocumentFromView(iDocument) = 0 Then MsgBox iDocument.Body.OuterHTML,0,"Message HTML" Set iDocument = Nothing Else MsgBox "Could not access the HTML in this message" End If End Sub Test the Applet by integrating it with the Mail view toolbar, then open a received Mail message that has the HTML view available. When the Applet is run from an open HTML Mail view, the HTML is extracted and displayed in a message box as shown here: See the Formativ Language Guide for full details of IHTMLDocumentFromView() and IHTMLDocumentFromViewHandle(). .topic 511 There are essentially two main types of Applet errors: syntax errors and runtime errors. Syntax errors are fundamental problems in your Applet that cause the Applet not to run. Runtime errors are problems with your Applet that only appear under particular circumstances. For example, if your Applet attempts to access the services of a COM server (such as Microsoft Word) that is not installed on a particular PC, a runtime error will occur when your Applet attempts to start the service. Runtime errors are often more difficult to detect as they are often environment-sensitive. Syntax Errors Syntax errors are usually detected while developing Applets. When you attempt to execute your Applet, a message box appears stating that the Applet cannot be executed, and the reason why. This error dialog will also indicate the line number in the source code where the error was found. To fix a syntax error, locate the offending line of code and examine the syntax used. You may have to refer to the language documentation to determine the correct syntax. Some things to be aware of when debugging syntax errors: If the error is not obvious in the row indicated by the error message, look at the lines just above or below the indicated row. An error reported to be at a particular location is sometimes caused by a syntax error just above or below the given location. Be careful in your use of parentheses when calling a procedure. See the Visual Basic Scripting Edition language documentation for more details. If a procedure call syntax fails, try calling the procedure with the Call keyword. Runtime Errors Runtime errors might occur at some point while an Applet is running. Runtime errors occur when a syntactically correct piece of code fails for some reason. These errors can often be more difficult to solve because they might only occur on certain machines or under certain circumstances. The key to debugging runtime errors is to replicate the steps taken to induce the failure. If reproducing the steps taken to run the Applet does not force the error, you may need to check if the Applet is attempting to use any resources that are not installed on the target machine, such as COM services or other resources. Defensive Programming The best way to avoid runtime errors in your Applets is to employ defensive programming strategies. Never assume a particular service will be available, and never assume that every call you make will succeed. For example, if your Applet uses third party COM services such as Microsoft Word or Excel, you should check that you are able to create an instance of the COM object before actually using its services. This usually means using the On Error statement followed by checks to confirm your request for a particular service was successful. In the example below, a defensive attempt is made to use services in Microsoft Word. This code will not cause a runtime error if Word does not exist on the target PC, or if some other error occurred: CheckWord = True ' Resume with the next line following the error. On Error Resume Next ' Attempt to reference Word, which is already running. Set Word = Nothing Set Word = GetObject(, "Word.Application") If Word Is Nothing Then ' Word is not running. Create a new instance of the Word application. Set Word = CreateObject("Word.Application") ' If true, MS Word 8.0 is not installed. If Word Is Nothing Then MsgBox "MS Word is not installed on your computer." End If End If .topic 521 Unfortunately, the current version of Formativ doesn't include a runtime debugger. However, there are techniques you can use to simulate real time debugging. Perhaps the most useful is to include trace output commands in your Applet, then use any debug output viewer capable of intercepting calls to the Win32 OutputDebugString() function. Note: We use and recommend the free DebugView utility from SysInternals. Using Trace Commands with DebugView Through the use of strategically-placed trace commands, you can get a real-time picture of the execution of your Applet. Trace commands are created through the use of the Utilities.Trace() method. Utilities.Trace() takes a single string argument. The string value you supply is output to any attached debugger in real time as the Applet executes. Note: Utilities.Trace() ultimately uses the Win32 function OutputDebugString() to output the string value. This function sends a string to the debugger for display. If GroupWise has no debugger attached, the system debugger displays the string. If GroupWise has no debugger and the system debugger is not active, OutputDebugString() does nothing. If you use the SysInternals DebugView utility, you only need to run DebugView prior to starting GroupWise – you do not need to attach it to the GroupWise process. The data you pass to Utilities.Trace() can be as simple or as complex as you choose. You can simply trace execution points, or include the values of local and system variables. For example, the following code snippet traces out properties of the VBScript error object which is instantiated whenever a runtime error is raised. Utilities.Trace(aErr.Number & vbtab & aErr.Description & vbtab & aText) For example, consider the following Applet. This code simply runs through a loop five times, tracing the value of the variable x. Sub Main(Client, GWEvent) For x = 1 To 5 Utilities.Trace("Formativ Trace Output: x=" & CStr(x)) Next End Sub If you execute this Applet while DebugView is running, the trace commands are output in real time, as shown below: .topic 101 Formativ ships with a large number of images you can choose to assign to your Applets. However, there may be times when you would like to use an image that is not included with the product. Creating a new image to use with Formativ is a three-step process: 1. Create a 16 by 16 pixel bitmap and draw your image 2. Add the image to a library in Formativ 3. Distribute the library to all users who require the new image Note that adding a new image to Formativ is a technical process and requires developer tools. You should only attempt to create new images if you are familiar with using developer tools. Please consult your IT department if you are in doubt. Step 1 – Create a new bitmap Create a new bitmap file. The bitmap must be 16 pixels high by 16 pixels wide. It must use the 16-color Windows palette. Fill the entire bitmap with green, i.e. RGB(0, 255, 0). This color is used by GroupWise to represent transparent areas. Any green area will be transparent when the image is drawn on a button in GroupWise. Once you have filled the bitmap with green you may start drawing your image using the standard 16-color Windows palette. Save your bitmap file when you are satisfied with the results. Step 2 – Add the image to a Formativ Library In order to make your bitmap available, you must add it to a Formativ image library. An image library is a resource DLL that contains nothing other than bitmap images. Formativ ships with a number of different image library files. They are named using the category of image they represent, and all have the extension .DLI. Technically, adding a new image to an image library involves adding a new bitmap resource to a DLL. The exact steps you take to add a new bitmap to an image library varies based on the tool you will use. The following steps are based on using Microsoft Visual Studio 6.0, but you can use most modern Windows development tools. 1. Start Microsoft Visual Studio 6 2. Select File | Open. When the Open dialog appears, change the Open As combo box selection to Resources 3. Browse to the location of the .DLI into which you wish to add the new image. This is the same location where Formativ was installed 4. Select the appropriate .DLI and select Open 5. When the file opens, select the Bitmap node of the display, click for a context menu and select Import... 6. When the Import Resource dialog appears, browse to the location of your new bitmap file. You may have to change the file type selection to *.bmp in order to see bitmaps. Select the bitmap and click Import 7. The bitmap has now been added to the .DLI file. Press CTRL+S to save your work, then exit Visual Studio. The image is now available to Formativ. Simply restart GroupWise if running and the image should appear in the list of available images. Step 3 – Distribute the new Library Should you wish other Formativ users to have access to your updated image library, you must make it available to them. To make the image library available, simply copy the appropriate .DLI file into each user's Formativ folder. Each user will have to re-start GroupWise in order to see the new image in Formativ Central. .topic 1 Windows Microsoft Windows XP, or Microsoft Windows 2000, or Microsoft Windows NT4 with Service Pack 6, or Microsoft Windows Millennium Edition, or Microsoft Windows 98 GroupWise Novell GroupWise 6.5, 32-bit Windows client, or Novell GroupWise 6.0, 32-bit Windows client, or Novell GroupWise 5.5, 32-bit Windows client Other Components Microsoft Internet Explorer 5.5 or above, and Microsoft Windows Scripting 5.5 or above Novell ConsoleOne or NWAdmin (Formativ Studio Administrators Only) Notes 1. The GroupWise client and Microsoft Internet Explorer must be installed prior to installing Formativ. 2. Windows 95 is not supported. 3. The Formativ Portal Manager requires GroupWise 6.01 or above. Novell have released a beta FTF file for the GroupWise 5.5.7.1 Enhancement Pack client, which enables the use of Formativ Portal Manager based solutions with the GroupWise 5.5 EP client. See Novell TID 2963458 to download the GroupWise 5.5.7.2 Beta FTF file (f32eppp1.exe). http://support.novell.com/cgi-bin/search/searchtid.cgi?/2963458.htm. 4. Applets that make use of the standard GroupWise HTML features require GroupWise 5.5 Enhancement Pack or higher. They will not work with the GroupWise HTML plug-in. 5. Novell NetWare Client is required for the Schema Wizard administration tool (Formativ administrators only). 6. Some Applets have minimum GroupWise client version requirements. See the Applet documentation for details. 7. Some Applets have minumum Formativ version requirements. See the Applet documention for details. 8. The GroupWise C3PO architecture requires users have read and write access to the HKEY_LOCAL_MACHINE hive of the Windows registry. While Formativ will still operate without these rights being available, Applets will need to be installed by an Administrator. This is particularly relevant in Windows Terminal Services environments, such as Citrix. .topic 11 Should you require Formativ technical support, there are three main resources available. We recommend you use these resources in the order listed below. Note: Advansys does not provide telephone support. Formativ Support Page The Formativ Support page contains links to various support resources. Here you will find current information regarding: Last minute documentation changes. Product updates and patches. Frequently Asked Questions. Links to other support resources. Moderated Support Forums Advansys provides Formativ technical support through online moderated forums. These Web-based forums are moderated by Advansys technical staff and represent the primary source of Formativ support. Feel free to log in and post a question or search the forums to check if a similar question has been answered already. Support forums are available for the following topics: Developing Solutions with Formativ. Formativ Solution Packs. Formativ Runtime. Formativ Creator (Developer). Formativ Studio (Admin). eDirectory management. Free GroupWise CoolSolutions Applets. You can access the Formativ support forums on the Web at: http://advansys.atinfopop.com/4/OpenTopic?a=cfrm&s=7534089931&f=3634089931 .topic 1 Advansys Home Page www.advansyscorp.com Formativ Home Page www.advansyscorp.com/formativ.htm Sales www.advansyscorp.com/formativ_buy.htm Formativ Resellers www.advansyscorp.com/resellers_formativ.htm Support Forums http://advansys.atinfopop.com/4/OpenTopic?a=cfrm&s=7534089931&f=3634089931 .topic 11 General Formativ Enquiries formativ@advansyscorp.com Sales Enquiries sales@advansyscorp.com Note: Please note that technical support is available via our Online Support Forums. .topic 21 Telephone +61 2 9968 2991 Facsimile +61 2 9969 7551 Note: Advansys is located in Sydney, Australia. Note: Advansys does not provide technical support by telephone. Please use our online support forum if you require technical support. .topic 100001 No Help topic is associated with this item. .topic 100002 OK Button Applies changes you have made and then closes this dialog box. .topic 100003 Cancel Button Closes this dialog box without saving the changes you have made. .topic 100004 Close Closes the current window. .topic 100005 Help Displays a help topic that gives you an overview of this dialog. .topic 100006 Apply Button Saves all changes you have made without closing the dialog box. .topic 100010 What's This? Button Click to start up a temporary, context-sensitive help mode. In this mode you can left-click any object to display a context-sensitive help window for that object. The help window provides a brief explanation about the object and how to use it. Note Press ESC to cancel context sensitive help. .topic 100011 What's This? (Help Menu) Starts up a temporary, context-sensitive help mode. In this help mode you can left-click any object to display a context-sensitive help window for that object. The help window provides a brief explanation about the object and how to use it. Note Press ESC to cancel the context sensitive help mode.