An OLE automation server exposes functionality to other applications
in the form of properties and methods. A property is analogous to a C++ data
member; a method is analogous to a C++ member function. An application that uses
the properties and methods of an OLE automation server is called an OLE automation
controller.
In this step, you'll expose some of the functionality of the drawing
application, making it possible for OLE automation controllers to open new drawing
documents, set pen attributes, and add lines.
It's a relatively simple task to turn a regular OLE server into an
OLE automation server. You just make small changes to the application, document, and view
classes.
Changing the application class
To change the application class, follow these steps.
- Include the automation and Step 16 header files.
- Add the /automation command-line switch to the application registration table.
- Declare and implement member functions that can be exposed as properties and methods.
- Expose member functions as properties and methods.
Including the automation and Step 16 header files
Take the #include listing from the step15.cpp file and
make the following changes:
- Add the ocf/automacr.h header file.
- Add the Step 16 resource (.RC), source (.CPP), and header (.H) files.
- Remove the Step 15 header files.
Note: In Step 16, the header file (step16.h) is separate from
the source file (step16.cpp) for the application class.
Add the /automation command-line switch to the application
registration table
An OLE automation server must register itself with the /automation
command-line switch. Therefore, you must add the /automation switch to the
application registration table using the cmdline keyword.
For the drawing application, you should also modify the description
so it says ``..Automation Server'' instead of ``...Server.''
Your new registration table should look something like this:
BEGIN_REGISTRATION(AppReg)
REGDATA(clsid, "{5E4BD320-8ABC-101B-A23B-CE4E85D07ED2}")
REGDATA(description,"OWL Drawing Pad Automation Server")
REGDATA(cmdline, "/automation")
END_REGISTRATION
Note: Remember, never use a GUID or
program identifier that another application uses.
Declaring and implementing member functions that can be exposed
as properties and methods
Although you can expose the data members of the application class
directly, you may want to implement one member function (for read-only or write-only
properties) or two member functions (for read/write properties) that handle the tasks of
getting and setting values. In this way, you can validate the data being transferred,
preventing possible errors.
In addition, for each member function that has parameters with one
or more complex data types, you should create a new member function that has parameters
with only basic data types. The new function should perform the necessary conversions
between data types and then call the original function. By exposing member functions that
take only basic data types, you make it easier for an automation controller to use them.
Finally, most OLE automation servers expose a set of standard
properties and methods, including the following:
- Visible (read/write property)
- Name (read-only property)
- FullName (read-only property)
- NewDocument (method)
- OpenDocument (method)
- Quit (method)
You should declare and
implement member functions for each of the standard properties and methods.
For example, the step16.h file contains declarations for the
standard properties and methods in the private section of the TDrawApp class:
void SetShow(bool visible); // Sets the Visible property value.
bool GetShow(); // Gets the Visible property value.
TDrawDocument* OpenDoc; // Opens or creates a document.
Note: You don't need to declare or
implement a member function for the Quit method since these tasks are handled
automatically by ObjectComponents if you use the EXPOSE_QUIT macro, as shown in the next
section.
The step16.cpp file contains the implementations of these functions:
// Get the Visible property value.
TDrawApp::SetShow(bool visible)
{
TFrameWindow* frame = GetMainWindow();
if (frame && frame->IsWindow()) {
unsigned flags = visible ? SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|
SWP_SHOWWINDOW : SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|
SWP_HIDEWINDOW;
frame->SetWindowPos(HWND_TOP, 0,0,0,0, flags);
}
// Set the Visible property value.
bool TDrawApp::GetShow()
{
TFrameWindow* frame = GetMainWindow();
return (frame && frame->IsWindow() && frame->IsWindowVisible());
}
// Get the Fullname property value.
const char far* TDrawApp::GetPath()
{
static char buf[_MAX_PATH];
GetModuleFileName(buf, sizeof(buf)-1);
return buf;
}
// Open or create a document.
extern TDocTemplate drawTpl;
TDrawDocument* TDrawApp::OpenDoc(const char far* name)
{
long flags = name ? 0 : dtNewDoc;
TDocManager* docManager = GetDocManager();
if (!docManager)
return 0;
HWND hWnd = ::GetFocus();
TDocument* doc = GetDocManager()->CreateDoc(&drawTpl, name, 0, flags);
::SetFocus(hWnd);
return dynamic_cast<TDrawDocument*>(doc);
}
Exposing properties and methods to other applications
You expose properties and methods by declaring and defining them.
Declaring properties and methods
To declare properties and methods for the application class, add
the DECLARE_AUTOAGGREGATE macro to the end of the application class declaration.
The step16.h file contains declarations of the properties and
methods for the application class of the drawing application:
DECLARE_AUTOAGGREGATE(TDrarwApp)
AUTOPROP (Visible, GetShow, SetShow, TBool)
AUTOFUNC0 (NewDoc, OpenDoc, TAutoObject<TDrawDocument>,)
AUTOFUNC1 (OpenDoc, OpenDoc, TAutoObject<TDrawDocument>, TAutoString,)
AUTOPROPRO (AppName, GetName, TAutoString,)
AUTOPROPRO (FullName, GetPath, TAutoString,)
Defining properties and methods
To define properties and methods, use the DEFINE_AUTOAGGREGATE
macro.
The step16.cpp file contains definitions of the properties and
methods for the application class of the drawing application:
DEFINE_AUTOAGGREGATE(TDrawApp, OcApp->Aggregate)
EXPOSE_PROPRW(Visible, TAutoBool, "Visible", "Main window shown", 0)
EXPOSE_METHOD(NewDoc, TDrawDocument, "NewDocument", "Create new document", 0)
EXPOSE_METHOD(OpenDoc TDrawDocument, "OpenDocument", "Open existing document", 0)
REQUIRED_ARG( TAutoString, "Name")
EXPOSE_PROPRO(AppName, TAutoString, "Name", "Application name", 0)
EXPOSE_PROPRO(FullName,TAutoString, "FullName", "Complete path to application", 0)
EXPOSE_APPLICATION(TDrawApp, "Application", "Application object", 0)
EXPOSE_QUIT( "Quit", "Shutdown application", 0)
END_AUTOAGGREGATE(TDrawApp,tfAppObject|tfCanCreate,"T DrawApp","Application class", 0)
Changing the document class
The changes you make to the document class are very similar to the
changes you make to the application class:
- Include the automation and Step 16 header files.
- Update the document registration table.
- Declare and implement member functions that can be exposed as properties and methods.
- Update the constructor and destructor of the document class.
- Expose member functions as properties and methods.
Including the automation and Step 16 header files
Take the #include listing from the step15dv.cpp file
and make the following changes:
- Add the ocf/automacr.h header file.
- Add the Step 16 resource (.RC), source (.CPP), and header (.H) files.
- Remove the Step 15 header files.
Note: In Step 16, the header file (step16dv.h) is separate from
the source file (step16dv.cpp) for the document class.
Update the document registration table
To update the document registration table, change the description
to ``...Automation Server...'' from ...``Server...''
Declaring and implementing member functions that can be exposed
as properties and methods
Although you can expose the data members of the document class
directly, you may want to implement one member function (for read-only or write-only
properties) or two member functions (for read/write properties) that handle the tasks of
getting and setting values. In this way, you can validate the data being transferred,
preventing errors.
In addition, for each member function that has parameters with one
or more complex data types, you should create a new member function that has parameters
with only basic data types. The new function should perform the necessary conversions
between data types and then call the original function. By exposing member functions that
take only basic data types, you make it easier for an automation controller to use them.
When you create new member functions, you may find that you need
new data members as well.
For example, the step16dv.h file contains the declarations and
implementations of eight new member functions of the document class:
long GetPenColor() // PenColor property.
{
return AutoPenColor;
}
void SetPenColor(long color) // PenColor property.
{
AutoPenColor = color;
AutoLine->SetPen(TColor(color));
}
short GetPenSize() // PenSize property.
{
return AutoPenSize;
}
void SetPenSize(short penSize) // PenSize property.
{
AutoPenSize = penSize;
AutoLine->SetPen(penSize);
}
void AddPoint(short x, short y) // AddPoint method.
{
AutoLine->Add(TPoint(x,y));
}
void AddLine()
{
AddLine(*AutoLine);
ClearLine();
}
void ClearLine() // ClearLine method.
{
delete AutoLine;
AutoLine = new TLine(AutoPenColor, AutoPenSize);
}
In addition, the step16dv.h file contains
the declarations of three new data members of the document class:
TLine* AutoLine;
long AutoPenColor;
short AutoPenSize;
Updating the constructor and destructor of the document class
When you create new data members and member functions of the
document class, you may need to update the document class constructor and destructor.
For example, the step16dv.h file contains new lines of code in the
constructor and destructor that initialize and destroy the new data members:
TDrawDocument::TDrawDocument(TDocument* parent)
: TOleDocument(parent), UndoLine(0), UndoState(UndoNone)
{
Lines = new TLines(100, 0, 5);
AutoPenSize = 1;
AutoPenColor = RGB(0, 0, 0);
AutoLine = new TLine(AutoPenColor, AutoPenSize);
}
TDrawDocument::~TDrawDocument()
{
delete AutoLine;
delete Lines;
delete UndoLine;
}
Exposing properties and methods to other applications
You expose properties and methods by declaring and defining them.
Declaring properties and methods
To declare properties and methods for the document class, add the
DECLARE_AUTOCLASS macro to the end of the document class declaration.
The step16dv.h file contains declarations of the properties and
methods for the document class of the drawing application:
DECLARE_AUTOCLASS(TDrawDocument)
AUTOPROP(PenSize, GetPenSize, SetPenSize, short, )
AUTOPROP(PenColor, GetPenColor, SetPenColor, long, )
AUTOFUNC2V(AddPoint, AddPoint, short, short, )
AUTOFUNC0V(AddLine, AddLine, )
AUTOFUNC0V(ClearLine,ClearLine, )
To define properties and methods for the
document class, use the DEFINE_AUTOCLASS macro.
Defining properties and methods
The step16.cpp file contains definitions of the properties and
methods for the document class of the drawing application:
DEFINE_AUTOCLASS(TDrawDocument)
EXPOSE_PROPRW(PenSize, TAutoShort, "PenSize", "Current pen size", 0)
EXPOSE_PROPRW(PenColor, TAutoLong, "PenColor", "Current pen color", 0)
EXPOSE_METHOD(AddPoint, TAutoVoid, "AddPoint", "Add a point to the current line", 0)
REQUIRED_ARG( TAutoShort, "X")
REQUIRED_ARG( TAutoShort, "Y")
EXPOSE_METHOD(AddLine, TAutoVoid, "AddLine", "Add current line into drawing", 0)
EXPOSE_METHOD(ClearLine, TAutoVoid, "ClearLine", "Erases current line", 0)
EXPOSE_APPLICATION( TDrawApp, "Application","Application object", 0)
END_AUTOCLASS(TDrawDocument, tfNormal, "TDrawDoc", "Draw document class", 0)
Prev
Up
Next
|