![]() |
Automating an OWL applicationCreating OLE Automation servers with OCF and OWL. In order to automate an OWL application without linking in support for linking and embedding you need to take the following steps: 1) Convert the Application objects definition so that it includes any necessary Automation macro definitions: class molmassApp : public TApplication
{
public:
TDialog FAR* Dlg;
molmassApp();
virtual ~molmassApp ();
virtual void InitMainWindow();
protected:
void CmHelpAbout ();
//the following functions will be exposed by OLE:
void SetShow(bool visible);
bool GetShow();
const char far* GetPathName();
const char far* GetPath();
void SetLeft(int);
int GetLeft();
void SetTop(int);
int GetTop();
const char far* GetFormula();
void SetFormula(LPCSTR);
void Configure(int wd);
double GetMass(){return ((mainwindow*)Dlg)->Calc.RelativeMass;}
BOOL GetStatus(){return ((mainwindow*)Dlg)->Calc.Status;}
LPCSTR GetPString(){return ((mainwindow*)Dlg)->Calc.GetPString();}
Formula* GetFormulaObject(){return (&((mainwindow*)Dlg)->Calc);}
DECLARE_RESPONSE_TABLE(molmassApp);
//the following macros declare the functions to OLE:
DECLARE_AUTOCLASS(molmassApp)
AUTOPROP (Visible, GetShow, SetShow, TBool, )
AUTOPROPRO(AppName, GetName, TAutoString, )
AUTOPROPRO(FullName,GetPathName, TAutoString, )
AUTOPROP (Interactive, GetShow, SetShow, TBool, )
AUTOPROP (Left, GetLeft, SetLeft, int, )
AUTOPROP (Top, GetTop, SetTop, int, )
AUTOPROPRO(Path, GetPath, TAutoString, )
AUTOPROP (Formula, GetFormula, SetFormula, TAutoString, )
AUTOFUNC1V(Config, Configure, int, )
AUTOPROPRO(FMass, GetMass, double, )
AUTOPROPRO(FStatus, GetStatus, TBool, )
AUTOPROPRO(FPersent, GetPString, TAutoString, )
AUTOPROPRO(AtomCollection, GetFormulaObject, TAutoObjectByVal<AtomCollection>,)
};
2) In the applications cpp file include the Automation macros necessary to define your applications OLE interface, for example the following definition table matches the declarations given above: DEFINE_AUTOCLASS(molmassApp)
EXPOSE_PROPRW(Visible, TAutoBool, "Visible", "Main window shown", 0)
EXPOSE_PROPRW(Interactive, TAutoBool, "Interactive", "Main window interactive", 0)
EXPOSE_PROPRW(Left, TAutoInt, "Left", "Main window left position", 0)
EXPOSE_PROPRW(Top, TAutoInt, "Top", "Main window top postion", 0)
EXPOSE_PROPRO(AppName, TAutoString, "Name", "Application name", 0)
EXPOSE_PROPRO(FullName,TAutoString, "FullName", "Complete path to application", 0)
EXPOSE_PROPRO(Path, TAutoString, "Path", "Application path", 0)
EXPOSE_PROPRW(Formula, TAutoString, "Formula", "Chemical Formula", 0)
EXPOSE_METHOD(Config, TAutoVoid, "Configure", "Configure Abbreviations", 0)
REQUIRED_ARG(TAutoInt, "hwnd")
EXPOSE_APPLICATION(molmassApp, "Application", "Application object", 0)
#if !defined(__DLL__)
EXPOSE_QUIT("Quit", "Shutdown application", 0)
#endif
EXPOSE_PROPRO(FMass, TAutoDouble, "RMM", "Relative Molecular Mass", 0)
EXPOSE_PROPRO(FStatus, TAutoBool, "Status", "Calculator Status", 0)
EXPOSE_PROPRO(FPersent, TAutoString, "Persentages", "Percentages of each element", 0)
EXPOSE_PROPRO(AtomCollection, AtomCollection, "Atoms", "Collection of atomic information", 0)
END_AUTOCLASS(molmassApp, tfAppObject|tfCanCreate, "Molmass", "Molmass Application Object", Molmass_Automation_Object)
3) If the application is likely to be built as a dll then include a declaration for an application dictionary: #if defined(__DLL__) DEFINE_APP_DICTIONARY(AppDictionary); #endif 4) Declare a pointer to the Registrar object: TPointer<TRegistrar> Registrar; 5) Create a Registration table: REGISTRATION_FORMAT_BUFFER(150)
BEGIN_REGISTRATION(AppReg)
#if !defined(__WIN32__)
REGDATA(clsid, "{34212EC0-473F-101C-A27A-040224007802}")
REGDATA(progid, "Molmass.Application.16")
#else
REGDATA(clsid, "{612DCC00-F516-11CE-96A5-FE8A5E5B0C16}")
REGDATA(progid, "Molmass.Application.32")
#endif
#if defined(__DLL__)
REGDATA(serverctx, "Inproc")
#endif
REGDATA(description, "Molecular mass calculator 1.0")
REGDATA(appname, "Molecular Mass Calculator")
REGDATA(cmdline, "/Auto")
REGDATA(version, "1.5")
END_REGISTRATION
6) Modify your OWL main to create a TRegistrar object using TAutoObject as the factory callback, TAutoObject "knows" how to initialise an OWL application but does not include linking and embedding support or load bocof.dll: OwlMain(int /*argc*/, char* /*argv*/ [])
{
try {
::Registrar = new TRegistrar(AppReg, TAutoFactory<molmassApp>(),
TApplication::GetCmdLine());
if (Registrar->IsOptionSet(amAnyRegOption))
return 0;
return Registrar->Run();
}
catch (xmsg& x) {
::MessageBox(0, x.why().c_str(), "Exception", MB_OK);
}
return -1;
}
Using the above procedure will create a single use exe or dll - each time a client application asks for your Automation interface a separate instance of your dll or exe will be loaded into memory. But what if you want all instances of client applications to bind to the same (single) instance of your server - in this case some editing of the OCF source is necessary - just follow the steps shown below: 1) Add the following entry to your registration table: REGDATA(usage, ocrMultipleUse) 2) Make a copy of appdesc.cpp in your project source directory and add it to your project node. Make the following changes to appdesc.cpp: In TAppDescriptor::Init(IMalloc*) change: if (Options & amExeModule) {
const char* usage = RegInfo.Lookup("usage");
char su[] = ocrSingleUse;
if (usage && *usage == *su)
Options |= amSingleUse;
}
To: if (Options & amExeModule) {
const char* usage = RegInfo.Lookup("usage");
char su[] = ocrSingleUse;
if (usage && *usage == *su)
Options |= amSingleUse;
else if(Options &amExeMode)
Options |= amAutomation;
}
In TAppDescriptor::ProcessCmdLine(string& cmdLine) comment out the two lines that read: if ((Options & (amAutomation | amExeModule)) == (amAutomation | amExeModule))
Options |= amSingleUse;
From now on, no matter how many client applications connect to your server, they will all connect to the same instance regardless of whether it was started with the /Automation switch or not. Of course this presupposes that your application can correctly deal with multiple concurrent clients!
Copyright Dr J. Maddock. Last Updated: 23 May 1997 |