C++Builder 5 Developers Guide

   

Creating and Using Creators

The Tools API also provides a way to create common IDE objects such as a file (unit), a module, or a project by creating a class that's derived from one its Creator interfaces. Suppose, in our example, we want our Wizard to dump out some text, viewable in the IDE, that displays the memory information for each run of the loaded application. We would need to create a file that's included with the project associated to the application we want to test.

Let's take a look at the various types of creator interfaces provided by the Tools API.

Table 23.6. Tools API Creator Interfaces

Creator Interface

Description

IOTACreator

This is the base class for all creators.

IOTAAdditionalFilesModuleCreator

Used to create additional files such as documentation, a Web page, or other text files associated with a unit.

IOTAModuleCreator

Used to create a module such as a new unit, form, or text file for a project, or to supply custom file contents or filenames.

IOTAProjectCreator50

Used to create a default application, library, or package, or to supply custom file contents or filenames.

IOTAProjectGroupCreator

Used to create a project group, or a new module for opening up an existing project group .

In addition to this list, one other Tools API interface that is typically used to support a creator interface is IOTAFile . IOTAFile is used to supply custom file content, such as source code for a new file, for a creator.

Defining a Custom Creator Class

For our wizard, IOTAModuleCreator provides the interface we need to generate a text file. To use it, we need to create a custom class representing this interface to the wizard_memstatus.h file as shown in Listing 23.15.

Listing 23.15 Creator Class Declaration

class Creator: public IOTAModuleCreator { public: __fastcall Creator(const AnsiString creator_type, const MemStatusWizard* wizard); virtual __fastcall ~Creator(); // IOTAModuleCreator methods virtual AnsiString __fastcall GetAncestorName(); virtual AnsiString __fastcall GetImplFileName(); virtual AnsiString __fastcall GetIntfFileName(); virtual AnsiString __fastcall GetFormName(); virtual bool __fastcall GetMainForm(); virtual bool __fastcall GetShowForm(); virtual bool __fastcall GetShowSource(); virtual _di_IOTAFile __fastcall NewFormFile( const AnsiString FormIdent, const AnsiString AncestorIdent); virtual _di_IOTAFile __fastcall NewImplSource( const AnsiString ModuleIdent, const AnsiString FormIdent, const AnsiString AncestorIdent); virtual _di_IOTAFile __fastcall NewIntfSource( const AnsiString ModuleIdent, const AnsiString FormIdent, const AnsiString AncestorIdent); virtual void __fastcall FormCreated( const _di_IOTAFormEditor FormEditor); // IOTACreator methods virtual AnsiString __fastcall GetCreatorType(); virtual bool __fastcall GetExisting(); virtual AnsiString __fastcall GetFileSystem(); virtual _di_IOTAModule __fastcall GetOwner(); virtual bool __fastcall GetUnnamed(); protected: // override IInterface methods virtual HRESULT __stdcall QueryInterface(const GUID&, void**); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); private: long ref_count; const AnsiString creator_type; const MemStatusWizard* wizard; // keep track of the wizard // that owns this notifier };

Although there are a lot of methods, the key methods we are most interested in are the Creator constructor and the NewImplSource() method. For all the other methods we simply return the default values. Now, let's look at the implementation for these methods that have been added to the wizard_memstatus.cpp file as shown in Listing 23.16.

Listing 23.16 Creator Class ”Constructor Method

__fastcall Creator::Creator(const AnsiString creator_type, const MemStatusWizard* wizard) : ref_count(0), creator_type(creator_type), wizard(wizard) { #ifdef DebugMessages char value[MAX_PATH]; sprintf(value," - [Debug] - Creator has been created. Index = %d",index); wizard->MessageServices->AddTitleMessage( AnsiString(wizard->GetName() + value),wizard->MessageGroup); #endif }

In our constructor, we pass in the type of module we are going to create, and also a pointer to our wizard so that we can access some of the data we want to display. It's important to identify the proper type of module to be created. Table 23.7 identifies the various creator types.

Table 23.7. Tools API Creator Types

Creator Type

Description

sApplication

Used to create a default application. Applies to IOTAProjectCreator interface.

sConsole

Used to create a default console application. Applies to IOTAModuleCreator interface.

sForm

Used to create a default form. Applies to IOTAModuleCreator interface.

sLibrary

Used to create a default library. Applies to IOTAProjectCreator interface.

sPackage

Used to create a default package. Applies to IOTAProjectCreator interface.

sText

Used to create an empty text file. Applies to IOTAModuleCreator interface.

sUnit

Used as a default unit source file. Applies to IOTAModuleCreator interface.

In our example, we will use the SText creator type.

The method that actually generates and fills in the text for the Wizard's result file is the NewImplSource() function, which has been added to the wizard_memstatus.cpp source file and is shown in Listing 23.17.

Listing 23.17 Creator Class ” NewImplSource() Method

_di_IOTAFile __fastcall Creator::NewImplSource( const AnsiString ModuleIdent, const AnsiString FormIdent, const AnsiString AncestorIdent) { AnsiString dtstring; TDateTime adatetime; adatetime = adatetime.CurrentDateTime(); dtstring = adatetime.FormatString("mm/dd/yyyy hh:nn:ss am/pm"); // let's grab data from Wizard that we want in the text file. AnsiString form_source = "Memory Analysis Results \n\n"; form_source += "Project = " + wizard->projectname + "\n"; form_source += "Run Date = " + dtstring + "\n"; form_source += wizard->memtotal + "\n";; form_source += wizard->memstartfree + "\n";; form_source += wizard->memstopfree + "\n";; form_source += wizard->memfinalusage + "\n";; form_source += wizard->mempeakusage + "\n\n\n";; form_source += "Enter your notes below...";; _di_IOTAFile file = new File(form_source); return file; // Expand(form_source, ModuleIdent, FormIdent, AncestorIdent); }

You'll notice in this method that we access some of the public data we are now providing in our wizard class. This method returns a new file to our wizard for the current project. To support our NewImplSource() method we need a way to generate an _di_IOTAFile interface. This requires another custom class as shown in Listing 23.18, which has been added to the wizard_memstatus.h file.

Listing 23.18 File Class Declaration

class File : public IOTAFile { public: __fastcall File(const AnsiString source); virtual __fastcall ~File(); AnsiString __fastcall GetSource(); System::TDateTime __fastcall GetAge(); protected: // override IInterface methods virtual HRESULT __stdcall QueryInterface(const GUID&, void**); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); private: long ref_count; System::TDateTime age; AnsiString source; };

Utilizing Our Creator

Although that might have seemed like a lot of effort to create a couple of classes, utilizing our creator class is fairly simple. The bolded text in the following code excerpt (as shown in Listing 23.19) has been added to our wizard's Execute() method within the wizard_memstatus.cpp source file.

Listing 23.19 MemStatWizard Class ” Execute() Method Custom Creator Utilization

// little loop processing here - but don't tie up system (check and get out) if (FormMemStat) { while (FormMemStat->Visible) // check { if (!ProcessActive) // process is no longer active / shut it down { FormMemStat->SpeedButtonStopClick(0); // final measurement FormMemStat->Close(); } Application->HandleMessage(); //get out (process current messages) } if (ProcessActive) // wizard has been shut down, but app remains { int result = MessageBox(NULL, "MemStat Wizard has been shut down, but the application "\ "under test is still active. \n\n" \ "Do you wish to close application under test as well?", "MemStat Wizard - Terminated",MB_YESNO); if (result == IDYES) { _di_IOTAProcess Process; Process = DebuggerServices->CurrentProcess; if (Process) Process->Terminate(); } } memstopfree = FormMemStat->GetMemoryStopFree(); memfinalusage = FormMemStat->GetMemoryFinalUsage(); mempeakusage = FormMemStat->GetMemoryPeakUsage(); MessageServices->AddTitleMessage( AnsiString(GetName() + " - " + memstopfree),MessageGroup); MessageServices->AddTitleMessage( AnsiString(GetName() + " - " + memfinalusage),MessageGroup); MessageServices->AddTitleMessage( AnsiString(GetName() + " - " + mempeakusage),MessageGroup); // dump out log file with memory performance data _di_IOTAModule module = ModServices->CreateModule(new Creator(sText,this)); delete FormMemStat; } if (debugnotifier) // little clean-up { debugnotifier->Destroyed(); debugnotifier = NULL; } MessageServices->AddTitleMessage(GetName() + " - Completed",MessageGroup); }

In this newly added code, we call the CreateModule() associated to the project module we found earlier using ModServices , by passing in an instance to our Creator class. To instantiate this Creator object, we pass the type of file we want to create, sText , and the pointer to the wizard, which is represented by the this clause. This triggers a call to the NewImplSource() method for our Creator object, and produces our results text file, as shown in Figure 23.6.

Figure 23.6. New text file associated to project, which contains results of memory performance.


   
Top

Категории