First knowledge: Delphi / interface / DLL / COM (Understanding)
Difficulty: ★★ ☆☆☆
Before you start, you will say some questions. During this time, I have been very busy (now I will have the final exam, and the worst is now busy preparing the upcoming English 4 exam), so I don't know if this article is enough. Not enough parts. The content of this article may not be too much, but I still have to write it out as an instance of our Delphi Open Tools API (2). In addition, I found some very nice about this information and websites, and I recommend it to everyone after I will.
Remember the last instance study one? We show an example of extending Delphi through a component package package. This time we will still make a practical Delphi plugin, the menu is still the same as the last time, but this time is not the last source file inserting a line of code, but add a development document to the current project, and display Provided to developers in the code editor of Delphi. (At the same time, it is also saved in the directory where the project file is located). However, this time I have a big difference with the last time, it is the place where this is the most important thing is: We will compile this plugin into a DLL, not the last component package, which gives yourself more humanity. Plug-in installer (instead of calling a user to open a component package to install) provides a chance.
Let's take a look at this key point, we have established a dynamic connection library project and implements our plugin classes within the first unit file. Unlike the last time, we don't use traditional component registration process REGISTER, but in unit class define a global function of TWIZARDINITPROC, and exported in the project file (Note: This name must be used. )
Exports
INITNEWMENU Name WizardEnTryPoint;
Below is the original shape and implementation of this function in the unit:
Function Initnewmenu (Const BorlandideRVices); IborlandIDeservices;
REGISTERPROC: TwizardRegisterProc; Var Terminate: twizardterminateproc): boolean; stdcall;
// registerproc: twizardregisterProc; parameter is used to create a wizard, in fact, this initialization function is used to create a DLL
// The form of traditional wizard can pass a class instance that implements IoTawizard to the RegisterProc parameter for this time.
// Registered Wizard, like this registerproc (xxx.create). Here we only use this function as an entry point of the initialization DLL
// So did not use this function, but directly myntatest: = tntatest.create; additional var terminate parameter is used to release
// You can assign it to it in the wizard, you can give it a normal process type such as Terminate: = xxx; xxx is a procedure
// This process is called to release the resource when the IDE is exit. Note that this function must be instructing in STDCALL.
VAR
SVCS: Iotaservices;
Begin
Result: = BorlandideServices <> nil;
IF results
Begin
SVCS: = BorlandideServices as Iotaservices;
/ / Save the BorlandIDeServices pointer
Toolsapi.borlandideServices: = BorlandIDeServices;
// Set the Host Application handle Application.Handle: = svcs.getparentHandle;
Myntatest: = TNTATEST.CREATE;
END;
END;
In addition, a new OTA interface is also used, mainly in the first event of menu items (we have completed the job to add a development document to the current project): IotaActionServices, this is a quite useful interface, in The IDE is run by the BorlandIDeServices, which can be used to complete the call to the Ide function. Such as: Closefile, OpenFile, OpenProject, ReloadFile, Savefile. The role of these features can guess according to their name. I also want to use the IoTaprojectOptions interface to get the current information and configuration options in the document file, but did not get the ideal results, with a list of strings on which Options for the project. We may be able to study a series of interfaces related to IoTaproject in the next article. Below is the code generated by the document section (corresponding to the first menu event of the menu item):
Procedure TNTATEST.ADDDocumentTopro (Sender: TOBJECT);
VAR
Templen, I, Temppos: Integer
DocumentFile: TextFile;
ModuleCount: Integer;
Tempstring, MoudlefilePath: String;
Begin
/ / Request IoTamoduleServices T interface
Supports (BorlandideServices, Iotamodules, MoudleService);
ModuleCount: = moudleService.modulect;
IF modulecount <> 0 THEN / / No file open
Begin
CurentMoudle: = moudleService.currentModule
// Get the current file name, we can use it to get the project path
Tempstring: = CurentMoudle.FileName;
// The following part uses to analyze strings and take out the path of the project.
I: = POS ('/', tempstring); Templen: = Length (Tempstring); Temppos: = i;
While i <> 0 do
Begin
Tempstring: = Rightstr (Tempstring, Templen-i);
I: = POS ('/', tempstring); templen: = length (tempstring); Temppos: = Temppos i;
END;
MoudlefilePath: = Leftstr (CurentMoudle.FileName, Temppos);
IOTAACTIONSERVICES, ACTIONSERVices
Begin
Assignfile (DocumentFile, MoudlefilePath 'DocumentFile.txt');
Rewrite (DocumentFile);
Try
Writeln (DocumentFile, 'project name:');
Writeln (DocumentFile, 'project master name:');
Writeln (DocumentFile, 'project number:');
Writeln (DocumentFile, 'Item Description:'); Writeln (DocumentFile, 'project group member:');
Writeln (DocumentFile, 'document establishment time:' datetimetostr (now));
Finally
Closefile (DocumentFile);
END;
/ Note, we use the OpenFile method of IOTAAAActionServices to open the document you have just saved.
ActionServices.openfile (MoudlefilePath 'DocumentFile.txt');
END;
end
Else
MessageBox (IDEHANDLE, 'THERE ISN' '' 'T Active Project.', 'DocucReator', MB_ICONWARNING);
END;
The rest of the code (such as adding menus to IDE, etc.), here we will omit, you can refer to the previous article (connection: http://www.9cbs.net/develop/read_arch .asp? id = 21725), you can also give me a letter to get the code (the address is the same as the last one). Finally, when we complete the code, we can compile it into a DLL file. Now let's take a look at how we will install our plug-in: first quit Delphi, open the registry, open the value of a string type under the hkey_current_user / software / borland / delphi / 7.0 / excerts key, named the name of our plugin , The value of the value of the DLL that we compiles. Now restart Delphi, how, the plugin starts working. With this approach, I believe that we can easily create an installer and anti-installer for our plug-in (nothing more than a simple operational registry, when you launch Delphi again, and delete the value that has just been established in the registry, restart Delphi will find that the plugin has been uninstalled), making it more friendly to the user, or more convenient for our release. Finally, I will explain: About debugging the DLL plug-in instructions, I recommend not returning too much error during the encoding process (when the run is running), you will find that you will have to start the plug-in, turn off Delphi This is a very annoying thing (it's marked), I suggest you first take the plug-in as a last component package form, so you don't have to restart Delphi, change it to DLL of. In addition, this plugin is still based on Delphi7, and there may be errors in the low version of Delphi. Last description, this plugin may make Delphi to generate an AV error when exiting, I have not solved this problem in the time being (I hope that I have advice), although I use String type, but I also quote ShareMem unit. I also try to assign a function that exits the release resource in the TERMINATE parameter, but the problem is still.
At the end of the article, I recommend some of my recent quite good sites and information about OTA recently:
Http://www.gexperts.org/opentools/ Here you will get an OTA FAQ, quite good.
Http://www.tempeest-sw.com/opentools/ Some old versions of OTA information
Http://home.quicknet.nl/qn/prive/rapp/delphi/delphi.html OTA part of the interface related materials and examples http://www.frasersoft.net/program/ delphi OTA Help Patch (Unofficial) , But quite incomplete