Example of Using an IObjectWindow as a Part
4/3/96

This example shows how to use IObjectWindow and to create a part out of it.
It shows how to receive messages off of the message queue and to process them,
and if necessary send out part notifications.

The example is composed of two parts, MyPart and TestMyPart. MyPart is the
actual IObjectWindow subclass part. TestMyPart is the driver to show how 
MyPart works.

*********************************************************************************

Here is the list of files in this package:

- IObjectWindow definition (since not in standard VBBase.vbb)
 IObjWin.vbb            - VBB for IObjectWindow
 IObjWin.vbe            - VBE to create the VBB

- MyPart files - The example of a subclass of IObjectWindow
 MyPart.cpp   
 MyPart.cpv   
 MyPart.h     
 MyPart.hpp   
 MyPart.hpv   
 MyPart.obj   
 MyPart.rc    
 MyPart.rci   
 MyPart.rcx   
 MyPart.vbb   

 NewMyPrt.Vbe           - This VBE is used to create your own MyPart

- TestMyPart files
 TstMyPrt.app 
 TstMyPrt.cpp 
 TstMyPrt.exe 
 TstMyPrt.h   
 TstMyPrt.hpp 
 TstMyPrt.mak 
 TstMyPrt.map 
 TstMyPrt.o   
 TstMyPrt.obj 
 TstMyPrt.rc  
 TstMyPrt.rci 
 TstMyPrt.rcx 
 TstMyPrt.RES 
 TstMyPrt.vbb 

*********************************************************************************

What MyPart does:

  What MyPart does is subclass IObjectWindow and processes message queue messages.
For demonstration purposes, there are only two messages, MyMsg1 and MyMsg2. They
both have the important information in parameter1. When these messages are
received, MyPart will send out a notification of the events msg1 and msg2 respectively.
The event parm for each of these events will be the integer in parameter1 of the
respective message.

  The actions sendMessage1 and sendMessage2 both take an integer as a parameter,
Each causes MyMsg1 and MyMsg2 to be posted to the message queue for MyPart respectively.
The integer is sent in as parameter1 of the message.
  
  To get this to work with OpenClass, we need to create an imbedded handler, called
MyPart::MyHandler. This handler is attached to MyPart at the creation of MyPart and
handles the messages coming from the message queue for MyPart. It is created as a
private imbedded class of MyPart because it really doesn't have any general purpose
outside of MyPart.

  The handler demonstrates two different ways of processing the messages for MyPart.
The processing of MyMsg1 demonstrates letting MyPart handle the message. When MyMsg1
is received, MyHandler asks for the window pointer for the event (which will be the
MyPart that the message was sent to) and then calls a private method within MyPart
to process the message. The method in MyPart will then send out a notification of
the msg1 event. This type of processing should be used if there is extensive processing
required.

  The handler also demonstrated how it can handle the message itself. MyMsg2 is this
kind of processing. When MyMsg2 is received, MyHandler asks for the window pointer,
as previously, but it sends out the notification of msg2 event on behalf of MyPart.
This type of processing should be used for very simple processing, such as a simple
notification being sent, rather than coding up a whole new method in MyPart for it.

  An important point to be noted about MyHandler is that there is only one instance
of it in the process. It would be shared by all instances of MyPart. This can be done
as long as the handler can get all of the information it needs from the controlWindow()
pointer returned by the event. This means it must be assured that this handler is
only attached to MyPart objects. This is why it is a private imbedded class, so no
one else can use it.

*********************************************************************************

What TestMyPart does:

  TestMyPart is the test driver for MyPart. It displays a window with two sections.
The first section is for sending MyMsg1, and the second is for MyMsg2. When the
button "Send Message 1" is clicked, the value in the field "From Value" is sent to
the action sendMessage1. This then causes MyMsg1 to be posted. The handler then
receives this message and the value is put into the value of the msg1 event and this
event is then notified. "Result Value" is watching for this event, and puts the value
from the event into the field.

  The second section does the same thing, except for MyMsg2.

*********************************************************************************

How do you create you own MyPart:

  The first step is to copy NewMyPrt.vbe to a directory and call it what you want
your new part to be called. Edit this new vbe, and change MyPart to your new part.
NOTE: !!! Erase this VBE after you import. It is only used to prime the pump because
          the current implementation will not let you inherit from IObjectWindow as
          a non-visual part, which is what you would want. Using the VBE to start it
          off gets around this problem. However, once you start making changes, this
          VBE is obsolete and should be destroyed.

  Then open the Visual Builder, load IObjWin.VBB, import your new part vbe. Now 
bring up your new part in composition editor. Now do the following:

  - Options->Add Part...
  - Add the IObjectWindow* (part) to your freeform surface.
  - Add any other parts and make connections between that you may need.

  - Switch to the Class Editor page and fill in the following fields:
    - User Constructor Code: myHandler.handleEventsFor(this);
    - User Destructor Code:  myHandler.stopHandlingEventsFor(this);
        Note: If below, you change the name of myHandler, you will need to change
              it in the above two statements also.
    - User .hpv File: yourpart.hpv
    - User .cpv File: yourpart.cpv
    - Required Include Files:
         <ihandler.hpp> _IHANDLER_
         <inotifev.hpp> _INOTIFEV_

  - Switch to the Part Interface Editor
    - Create the Attributes/Actions/Events that you require and generate the
      feature source code for them.

  You now have to fine tune your hpv and cpv. Edit the hpv file:

  - Put the following code at the top, changing MyPart and MyHandler to your more
    descriptive names.

     /* MyPart's user include code */
     private:
     /* Define MyHandler as imbedded class because no one else needs it */
     class MyHandler : public IHandler
      {
       protected:
       Boolean dispatchHandlerEvent(IEvent& event);
      };
     
     static MyHandler myHandler;     // Only one copy needed.
     friend MyHandler;       // So that it can get to private stuff

  - Add the following, but change the names to more descriptive names, and the
    values should be set to the ones that you are using as message numbers.

     private:
       enum MyMsgNumbers {MyMsg1=16000, MyMsg2};

  Now edit the cpv file:

  - Put the following code at the top, changing myhandler and mypart to what you
    have changed them to:

    MyPart::MyHandler MyPart::myHandler;  // Only one instance needed because MyHandler
                                          // written such that it can get all the information
                                          // it needs from the event.

  - Put the following at the bottom. This code is just a template. You will have
    to completely rewrite the cases to what you need. You may need to go back into
    the hpv and add some new private methods to do message processing and put their
    code in this cpv. An example of this is the method "receivedMsg1()". The 
    important thing is that you should be returning false to allow other handlers
    to process.

     Boolean MyPart::MyHandler::dispatchHandlerEvent(IEvent& event)
      {
       switch (event.eventId())
        {
         // First case is you want the mypart to actually process the msg:
         case MyPart::MyMsg1:
           ((MyPart*)event.controlWindow())->receivedMsg1(event.parameter1());
           break;
     
         // Second case is you want this handler to actually process the msg:
         case MyPart::MyMsg2:
           ((MyPart*)event.controlWindow())->notifyObservers(INotificationEvent(
             MyPart::msg2Id,
             *event.controlWindow(),
             false,
             IEventData(event.parameter1())));
           break;
     
         default:
           break;
        }
       return false;
      }

  You now have to Generate the Part Source in the Visual Builder. If you have
CTV304 installed (which is not available as of May 3, but RSN), then the code
generated is fine. However, previous to CTV304, you may get a slight error in
the generated code, because it thinks it may be a visual part. You may need to 
go into the HPP and CPP and remove the references to partWindowId and any lines
that partWindowId is on. This will need to be done on each regen until CTV304
is installed. If the code compiles clean, then you won't be needing to make this
change. 

  That's it. You can now drop and use this part as you would any other part that 
you have created.

--- End of README
