First knowledge: Delphi / interface / VCL component package / COM (Understanding)
Difficulty: ★★ ☆☆☆
Before this article officially begins, I first apologize to everyone. Because this month's column articles should be released very early, but because of some things, they have been postponed until now, and this month is only released. Also, about this article I think I should thank several friends on 9CBS, they are Chechy, Framesniper, Pankun, especially for Chechy, let me know the interesting of Delphi Open Tools API (hereinafter referred to as OTA) and decided Some energy is put above. And introduced me quite good information. Although the title is called XXXXX (1), the next article may not be xxxxx (2) Because each article of this series will be an independent content, the reason why XXX (1) is because I Will write some things about OTA in a subsequent article.
Oh, I said so much nonsense, start now! But in the beginning, I have to go again. Probably introduce OTA OTA is a set of interesting interfaces available in each version of Delphi, using it you can extend the Delphi IDE to make it in line with your needs. For example, you can extend the IDE menu, code editor, window designer, attribute editor, and control editor (this already explained in the previous series of articles on VCL development), etc., almost all where you want. Even the code inside function can expand! This exciting feature has achieved better development after Delphi5, and it is easier to use. Make developers can use very little, very basic code to complete these interesting extensions to achieve powerful features. Through OTA, you can also appreciate the perfect design of Delphi IDE, based on COM technology, making Delphi IDEs to be easily expanded without re-compiling IDEs.
Before conducting this example, you should point out that the best information you want to learn is a Toolsapi.PAS file in the SourceàToolsapi in the Delphi installation directory, which lists all OTA interfaces and more detailed annotations. In addition to OTA sites, you can go to http://delphi.about.com/library/weekly/aa033099.htm and http://www.tempeest-sw.com/opentools/ to see, you can also go to Borland's news Group borland.public.delphi.opentoolsapi participates in the discussion. Of course, 26 chapters in the Delphi5 Developer Guide also introduced some OTA's knowledge and demonstrated how to realize the guide in a delphi (this article does not tell this), you can also go see.
Since Delphi OTA's version is relatively large, the content in this article is premised using Delphi7. When Delphi IDE is running, there is an important instance we should clearly (instance) is BorlandIDeServices, which implements many OTA interfaces, in order to get a lot of interfaces from BorlandIDeServices, and these interfaces have been run at Delphi Really realized, we can easily get a lot of things, such as menus, windows, etc. In order to be able to expand Delphi IDE, we must go to Delphi to enter, which means we have two ways to achieve our delphi extension (can also be called plug-ins) and release it out, one way is to design a plugin When the VCL component package (this article takes this form, please see the article I published before the VCL component package), allowing customers to install at the Delphi runtime. Another way is to register the plug-in based on a DLL and in the registry. Entrance point, Delphi IDE loads your plugin after restarting (this method will be explained in later articles). The latter provides a possible possible plug-in installer, the former needs to install the same as the installation component in the Delphi operation. Our example will add a menu (name called HK.Barton) to the main menu of Delphi, click on the first item to insert a specified code in the code of the first code editor of the current project, 2 simple display of information. When you don't want to use this menu, you only need to uninstall it like the uninstallation of the general component. First, let's take a look at the project file of the component package. If you have seen my previous article about the VCL, it should be very familiar: package package1;
/ / ... omit the compiler instruction, pay attention to design this component as design (Design Time)
Requires
RTL,
VCL,
DesignIde;
Contains
NTAMENU IN 'NTAMENU.PAS';
End.
You can see our plug-in in NTAMENU.PAS, in which we mainly use the following interface: Iotaservices, interfaces that are directly implemented by BorlandideServices, is an OTA's foundation interface, we use its getParentHandle method to Get the handle of the Delphi IDE; intaservices, the interface that is implemented at the Delphi runtime, you can use its method to get the Delphi ID of MainMenu, ImageLis, ActionList, Toolbar, which we can do it directly; IotamoduleServices, Iotamodule, IotaEditor, IotasourceEditor, IOTAEDITVIEW, you can see that we can use these interfaces to get the code editor step by step and finally get a IOTAEDITPSISION interface that can handle data in the code. We use it to insert a sentence to the current cursor. Code, you can use the IOTAEDITWRITER interface to insert a large number of code segments. With regard to the interface methods used in the following code we will explain in the comments, no interfaces and other methods don't forget to view the Toolsapi.Pas file. It can also be noted that the following code is detected in many places to ensure that the code is trying to do not have problems after running and can reasonably release resources reasonably when an abnormality occurs. Don't forget, our purpose is to expand Delphi, but not to bring the face of Delphi ID. Unit NTAMENU;
Interface
Uses
Sysutils, Classes, Menus, Toolsapi, Controls, Imglist, Graphics, Forms, Comctrls, Windows
Type
TNTATEST = Class
Private
FmainMenu: TMAINMENU; // Used to store Delphi IDE's main menu
NEWMENU: TMENUITEM; / / We will insert menu
Fimagelist: tcustomImagelist; // Imagelist used to store Delphi IDE main menu and toolbar
ImageIndex1: integer; // Test, please see the following code
IDEHANDLE: HWND; // Storage IDE Handle
protected
Procedure addmenu; // Add to our menu
Procedure removemenu; // Uninstall our menu
Procedure RecodeEditer (Sender: TOBJECT); // Menu item one event
Procedure Aboutform (Sender: TOBJECT); // Menu item II Event
public
Constructor crete;
DESTRUCTOR DESTROY; OVERRIDE;
END;
PROCEDURE register;
VAR
MYNTATEST: TNTATEST;
IMPLEMENTATION
PROCEDURE register;
Begin
Myntatest.addmenu;
/ / Unlike the same name method of traditional components, there is no icon on the component panel.
/ / But call AddMenu method to add our menu
END;
{TNTATEST}
Constructor TNTATEST.CREATE;
Begin
IDEHANDLE: = (BorlandideServices as Iotaservices) .Getparenthandle;
// We have obtained your IDE's handle using the getParentHandle method of the Iotaservices interface.
END;
Procedure TNTATEST.ADDMENU;
VAR
Menuitem: array [0..2] of tmenuitem;
i: integer;
Icon1: ticon; // menu item one icon begin
FmainMenu: = (BorlandIdeServices as intaservices) .mainMenu;
// We have directly obtained the main menu of IDE with the mainment of Intaservices.
Fimagelist: = (BorlandIdeServices as intaservices) .imagelist;
// We use intaservices' imagelist properties to get the image list of IDE directly
NewMenu: = TMenuitem.create (FmainMenu);
// Create our menu
NEWMENU.caption: = 'hk.barton';
ImageIndex1: = - 1; // No loading icon
// The following code uses for and case to add two menu items, but
/ / We show a more common way to add more menu items without having to copy the code.
For i: = 0 to 2 do
Begin
Menuitem [I]: = TMenuItem.create (newMenu); // Creating submenu items
Case I of
0:
Begin
Menuitem [i] .caption: = 'inserttext';
Icon1: = ticon.create;
Try
Icon1.LoadFromFile ('D: /myworks/mycomponent/otatest/newform.ico');
// I load an icon as a menu item from the hard disk.
Except
ON E: Exception DO
Begin
Raise Exception.create (E.MESSAGE);
EXIT;
END;
END;
ImageIndex1: = fimagelist.addicon (icon1);
/ / Add that loaded icon and return an imageIndex
Menuitem [i] .imageIndex: = imageIndex1;
Menuitem [i] .onclick: = recodeediter; // Add event handler
END;
1: Menuitem [i] .caption: = '-'; / / of course there is also a split symbol, in fact, 3 menu items
2:
Begin
Menuitem [i] .caption: = 'About';
Menuitem [i] .onclick: = Aboutform;
END;
END;
NewMenu.Add (MenuItem [i]); // Add menu item
END;
FmainMenu.Items.Add (newMenu); // Last Add our menu to the IDE main menu
END;
Procedure TNTATEST.RECODEEDITER (Sender: TOBJECT);
VAR
Module: IotamoduleServices;
CurentMoudle: Iotamodule;
IOTAEDITOR;
IotasourceEditor;
EditView: IotaEditView;
Editwriterpos: IotaEditPosition;
i: integer;
Begin
Module: = BorlandideServices as IotamoduleServices;
CurentMoudle: = module.currentmodule;
// CurrentModule method using IOTAMODULESERVICES Get the currently open engineering module
If curentmoudle = nil dam
Begin
MessageBox (IDEHANDLE, 'There is currently no open project file', 'HKTEST', MB_ICONITION;
END;
// Traverse all the files that have been opened in the project
For i: = 0 to curentmoudle.ModuleFileCount-1 do
Begin
INTFEDITOR: = CurentMoudle.ModuleFileEditors [i];
// iotamodule's modulefileEditors [] attribute gets an IOTAEDITOR
If IntFeditor.Queryinterface (IotasourceEditor, Editor) = S_OK THEN
/ / View whether the file traveled is whether the code file is a code file and has begun to edit in the code editor.
// If you get an instance of IotasourceEditor, you get an instance of IotasourceEditor through an OUT parameter Editor.
Break;
END;
IF editor = nil then
Begin
MessageBox (IDEHANDLE, 'currently has no code editing window', 'hkTest', MB_ICONITION);
EXIT;
END;
EditView: = Editor.editViews [i];
// Get an IOTAEDITVIEW with the EditViews [] property of IotasourceEditor
Editwriterpos: = EditView.Position;
// The position attribute using IOTAEDITVIEW finally get an IOTAEditPosition
EditWriterPos.Iserttext ('{/// this is add by the otatest of hk.barton, enjoy days! ///}');
// otaeditposition's InsertText method inserts a row code to the current cursor location, here is a row of comments.
END;
Procedure TNTATEST.ABOUTFORM (Sender: TOBJECT);
// A simple amount about dialog, pay attention to IDEHANDLE in the parameter
Begin
MessageBox (IDEHANDLE, 'this is a test of ota write by hk.barton', 'hktest', mb_iconification);
END;
Procedure TNTATEST.RemoveMenu;
// Uninstall menu
Begin
IF assigned (newmenu) THEN
NEWMENU.FREE;
END;
DESTRUCTOR TNTATEST.DESTROY;
Begin
Myntatest.removemenu;
IF imageIndex1 <> - 1 THEN
// If there is an exception in the previous load icon, you will not release the icon, otherwise it will be released to the icon used by Delphi itself.
Myntatest.fimagelist.delete (Myntatest.imageIndex1);
inherited;
END;
INITIALIZATION
// Create TNTATAST when the component is first installed
Myntatest: = TNTATEST.CREATE;
Finalization
// Release Myntatest when the component is unloaded
MYNTATEST.FREE;
End.