AmericasHeadquartersEMEAHeadquartersAsia-PacificHeadquartersExtendingtheDelphiIDEBrunoFierensMarch2011100CaliforniaStreet,12thFloorSanFrancisco,California94111YorkHouse18YorkRoadMaidenhead,BerkshireSL61SF,UnitedKingdomL7.
313LaTrobeStreetMelbourneVIC3000AustraliaExtendingtheDelphiIDEand-1-INTRODUCTIONEmbarcaderoDelphioffersarichAPIthatenablesdeveloperstocustomizeandextendtheIDEinmanyways.
ThegoalofthiswhitepaperistointroduceanumberoftheseAPIstoyouandprovidesamplesonhowtheycanbeused.
AmongthesesamplesarealsoanumberoffreeIDEextensionsprovidedbyTMSsoftware.
TheAPIsavailabletoextendtheIDEareundertheumbrella"OTAPI",whichisanacronymforOpenToolsAPI.
ThiswhitepaperandthesampleshavebeenwrittenforandtestedwithDelphiXE.
ADDITIONALINFORMATIONOtherthanthiswhitepaper,alotofinformationonOTAPIcanbefoundinthesourcecodethatisprovidedwithDelphiXE.
TheAPIisdeclaredintheunitTOOLSAPI.
PAS.
ForDelphiXE,thisunitcanbefound,bydefault,inthefolder:C:\ProgramFiles\Embarcadero\RADStudio\8.
0\source\ToolsAPIItnotonlycontainsthedefinitionsoftheinterfacesbutalsohasalotofusefulcommentsinthesourcecodethatcanhelpinlearningthepurposeoftheinterfaces.
Youwillregularlywanttorefertothisvaluablesourceofinformation.
.
AnotherinterestingsourceofinformationistheGExpertssourcecodeandOTAPIFAQpagewhichyoucanfindat:http://www.
gexperts.
org/otafaq.
htmlBASICARCHITECTURETheAPIisheavilybasedoninterfaces.
TheinterfacestypicallystartwiththeprefixIOTAorINTA.
TheIDEexposesalotofinterfacesthatcanbecalledfromtheplugin;conversely,theIDEitselfcanalsocallcodefromthepluginwhenaspecificactionistriggeredintheIDE.
ToinformtheIDEthatthepluginhasahandlerfortheseactions,inmostcases,thisisdonebywritingaclassdescendingfromTNotifierObjectthatimplementsaninterfaceandregistertheclasswiththeIDE.
Asapluginwriter,youwillfindyourselfmostlywritingcodethatcallstheIDEinterfacesandwriteclassesthatimplementinterfacesthatwillbecalledfromtheIDE.
AREASOFTHEIDETHATCANBEEXTENDEDTheDelphiIDEcanbeextendedinmanyways.
ThisisabriefoverviewofthemostcommonareasofextendingtheIDE:-CreateandaddcustomdockingpanelsExtendingtheDelphiIDEand-2-Itispossibletoaddcustomdockingpanelslikethecomponentpalettepanel,theobjectinspectorpaneletc.
.
.
-InteractwiththecodeeditorInterfacesareofferedtoprogrammaticallymanipulatetheDelphiIDEcodeeditor;forexample,toinsertsnippetsofcode,replacetext,handlespecialkeysequences,addcustomsyntaxhighlightersandmore.
.
.
-InteractwithCodeInsightCodeInsightintheeditorcanbecustomizedaswell,offeringcustomhelptextsonspecificconstructsinthecode.
-InteractwiththeProjectManagerTheIDEallowsyoutohavecustomcontextmenustoprojectsandfilesintheIDEProjectManagertoolpanel.
-Addcustomwizards,itemstotherepositoryItispossibletoaddcustomitemsorstartcustomwizardsfromitemsaddedtotheDelphirepository.
Fromthesewizards,newprojecttypes,specificformtypes,ordatamodulescanbecreated.
-InteractwithToDoitemsAnAPIisalsoavailabletointeractwithToDoitemsincodefromaDelphiIDEextension.
-Interactwithdebugger,createcustomdebuggervisualizersInnewerDelphiversions,anIDEextensioncanbeaddedthatprovidesacustomdisplayofaspecificdatatypewhiledebugging.
-InteractwiththeformdesignerFromaDelphiplugin,anAPIisavailabletointeractwiththeformdesigneraswell.
-SplashscreennotificationsAninterfaceisprovidedtoaddcustomtextonthesplashscreenduringthestartupoftheIDE.
Inthiswhitepaper,variouspartsoftheOTAPIwillbecoveredsuchascreatingcustomdockingpanels,accessingtheeditor,theprojectmanager,therepository,andextendingvariousmenus.
ExtendingtheDelphiIDEand-3-HISTORYOFTHEOPENTOOLSAPIAsDelphihasgrownthroughtheyears,sohastheAPItoextendtheIDE.
InDelphiXE,existingAPIstocustomizetheIDEhavebeenextended,andnewAPIshavebeenadded.
AstheOTAPIismainlyinterfacebased,newcapabilitiesaregenerallyofferedvianewinterfaces.
Tokeepthingsorganized,theDelphiteamadoptsthenamingconventionforadditionalinterfacesthatdescendfromanearlierinterfacebygivingthenewinterfacethenameoftheoriginalinterfacewithasuffixusingtheIDEversion.
PleasenotethattheIDEversionisdifferentfromthecompilerversion.
Forexample,theinterfacetoextendtherepositorywasoriginallyIOTARepositoryWizardandinlaterIDEversions,itwasextendedandnamedIOTARepositoryWizard60andlatertoIOTARepositoryWizard80.
IfapluginwantstotakeadvantageofsomenewcapabilitiesexposedinlaterversionsoftheIDE,itshouldprovideaclassthatimplementsthenewestinterface.
Atthesametime,apluginthatwascreatedforanolderIDEversionandthatimplementsforexampletheoriginalIOTARepositoryWizardinterfacewillkeepworking.
Forexample:-IOTARepositoryWizard=interface(IOTAWizard)Baseinterfaceforextendingtherepository.
-IOTARepositoryWizard60=interface(IOTARepositoryWizard)ExtendedinterfaceofferedfromDelphi7toprovideawaytodifferentiatebetweenVCLandCLXprojects.
-IOTARepositoryWizard80=interface(IOTARepositoryWizard60)NewinterfaceintroducedinDelphi2005toprovideaccesstothenewgalleryhierarchicalstructureoftherepositoryandaccesstomultiplepersonalitiestheIDEcanhost,inthecaseofDelphi2005beingVCLandVCL.
NET.
ThisisthelistofIDEversionnumbersthatarebeingusedinvariousOTAPIinterfaces:60=Delphi780=Delphi890=Delphi2005100=Delphi2006110=Delphi2007120=Delphi2009140=Delphi2010145=DelphiXEExtendingtheDelphiIDEand-4-ACCESSINGTHEIDEWhiletheIDEoffersvariousinterfacesforimplementationthatwillbecalledwhenaparticularpartoftheIDEisaccessed,inmanycases,itisnecessarytodirectlycallsomeIDEfunctionalityfromaplugin.
Toallowthis,Delphiexposesmanyinterfaces.
WhentheIDEstartsitcreatesaglobalvariableBorlandIDEServicesthatimplementsvariousinterfaces.
WhentheunitToolsAPIisintheuseslist,thisvariableBorlandIDEServicesisaccessibleandcanbeusedtoquerytheinterfaceneeded.
Forexample://checkiftheBorlandIDEServicesglobalvariableisassignedifAssigned(BorlandIDEServices)thenbegin//accesstheIOTAModuleServicesinterfaceimplementedinBorlandIDEServicesandcallCloseALLtocloseallmodules(BorlandIDEServicesasIOTAModuleServices).
CloseAll;end;ThefollowinginterfacesareexposedbytheDelphiXEIDE:-INTAServicesInterfacetoaccessIDEtoolbars,menu,imagelists,actions-IOTAActionServicesInterfacetoopen,close,savefiles-IOTACodeInsightServicesInterfacegivesaccesstothecodeinsightmanagersandtheirinterfaceIOTACodeInsightManager-IOTADebuggerServicesInterfacegivesaccesstodebuggerrelatedfunctionssuchasbreakpoints,eventlogging,processes-IOTAEditorServicesInterfacegivesaccesstotheIDEeditor,theeditbuffer,editview,options-IOTAEditorViewServicesInterfacegivesaccesstotheIDEeditorview-INTAEnvironmentOptionsServicesExtendingtheDelphiIDEand-5-InterfacetoaddoptionsintheIDETools,Optionsmenu-IOTAKeyBindingServicesInterfacetoaccessshortcutkeybindings-IOTAKeyboardServicesInterfacetogiveaccesstoIDEmacrorecording&playback-IOTAMessageServicesInterfacetoaccessthemessageview,allowsaddingcustommessagestotheIDEmessageview,clearmessages-IOTAModuleServicesInterfacetoaccessthemodules(e.
g.
projects,sourcefiles,formfiles,etc.
)openedintheIDE-IOTAPackageServicesInterfacetoaccessthelistofinstalledpackages&componentsintheIDE-IOTAServicesInterfaceexposinggeneralIDEinfolikeproductidentifier,applicationfolder,binfolder,installedlanguages-IOTAToDoServicesInterfacetoaccesstheToDoitemsforamodule-IOTAWizardServicesInterfacetoaccessandextendtheIDErepository-IOTAHighlightServicesInterfacetoaccessthesyntaxhighlightersandtoaddcustomsyntaxhighlighterinterfacesIOTAHighlighter-IOTAPersonalityServicesInterfacetoaccessinstalledIDEpersonalities,fileextensionassociationswithpersonalities-IOTACompileServicesInterfacetothecompilerallowtostartandstopcompilationofprojectsandhandlenotificationswhencompilingisdone.
ExtendingtheDelphiIDEand-6-GETTINGSTARTEDTOCREATEANIDEPLUGINIDEpluginsarecompiledpackagesinstalledintotheIDE.
ThismeanstheIDEwillloadthepackageduringstartup.
ThepackagecanperformitsinitializationbothwithcodeexecutedintheInitializationsectionoftheunitsinthepackageaswellasprovidingaRegistermethodfromwhereclassesareregisteredwiththeIDE.
ThisisverysimilartoapackagethatinstallsacomponentintheIDEwheretheRegisterprocedureiscalledbytheIDEfromwheretheRegisterComponents()callregistersthenewcomponentsintheIDE.
ToinstallanIDEpluginorextension,theminimumthatneedstobedoneiscreatingaclassofthetypeTNotifierObjectthatimplementstheIOTAWizardinterfaceoroneofitsdescendentsandregisterit:unitMyIDEPlugin;interfaceusesClasses,ToolsAPI;TMyIDEWizard=class(TNotifierObject,IOTAWizard)//implementinterfaceshereend;implementation//registerwiththeIDE:procedureRegister;beginReend;gisterPackageWizard(TMyIDEWizard.
Create);ItistheIDEthatwillthencalltheappropriateinterfacemethodswhenneeded.
ExtendingtheDelphiIDEand-7-EXTENDINGTHEIDEWITHCUSTOMREPOSITORYWIZARDSOurfirstindepthlookatextendingtheIDEisaboutcreatingcustomrepositorywizards.
Tocreateapluginthatwillextendtherepository,itisnecessarytowriteaclassthatimplementstheIOTAWizardinterfaceandtheIOTARepositoryWizardinterface.
TheIOTARepositoryWizardinterfacehas3versions.
ItwasextendedinDelphi7toenabledifferentiatingbetweenrepositoryitemsforVCLorCLXprojects.
ItwasextendedagaininDelphi2005wherehierarchicalcategoriesofrepositoryitemswereintroduced.
NotethatitisonlynecessarytoimplementthelatestIOTARepositoryWizard80interfaceifyouwanttotakeadvantageofthenewfeatures.
TheoriginalIOTARepositoryWizardinterfaceworksfineinDelphiXE.
Forthisexample,wewilltakeadvantageofthecategoriesexposedintheIOTARepositoryWizard80interface.
Assuch,wewillwriteaclassdescendingfromTNotifierObjectthatimplementstheIOTAWizardinterfaceandtheIOTARepositoryWizard.
ExtendingtheDelphiIDEand-8-TMyProjectWizard=class(TNotifierObject,IOTAWizard,IOTARepositoryWizard80)//implementinterfaceshereend;ThisclasswillthenberegisteredwiththeIDE:procedureRegister;beginRegisterPackageWizard(TMyProjectWizard.
Create);end;Thenextstepistoimplementtheinterfaces.
TheIOTAWizardinterfaceinformstheIDEofthepluginname,IDandprovideamethodtoexecutetheplugin.
TheIOTARepositoryWizardinterfaceprovidestheIDEwithinformationabouttherepositoryitem,theauthor,itsglyphandalsothecategoryandpersonalityforwhichtherepositoryitemisprovided.
Theclassdefinitionbecomes:TMyProjectWizard=class(TNotifierObject,IOTAWizard,IOTARepositoryWizard80)public//IOTAWizardfunctionGetIDString:string;functionGetName:string;functionGetState:TWizardState;procedureExecute;//IOTARepositoryWizardfunctionGetAuthor:string;functionGetComment:string;functionGetPage:string;functionGetGlyph:Cardinal;//IOTARepositoryWizard80functionGetGalleryCategory:IOTAGalleryCategory;functionGetPersonality:string;functionGetDesigner:string;ExtendingtheDelphiIDEand-9-end;Thefullimplementationofthewizardclassmethodscanbefoundinsample1.
OnepartoftheinterfaceinformstheIDEaboutthenewrepositoryitem,theExecutemethodwillbecalledwhentheuserclicksthatrepositoryitemintheIDE.
ItisinthisExecutemethodthatthepluginneedstotakethenecessarystepstocreatethesourcefilesfortheselectedrepositoryitem.
IntheExecutemethod,wegrabtheBorlandIDEServicesglobalvariableandusetheIOTAModuleServicesinterfacetoquerythedefaultunit,class,andfilenamethattheIDEproposesforcreatinganewinstanceoftherepositoryitem.
Withthisunit,classandfilename,theIOTAModuleServicesCreateModulemethodisthenusedtocreatetheactualnewmodulethatisaddedtotheactiveproject.
TheExecutemethodprocedureTTMSFormWizard.
Execute;varLProj:IOTAProject;beginifAssigned(BorlandIDEServices)thenbegin//usetheIOTAModuleServicesinterfacetoqueryanewdefaultunit,class&filename(BorlandIDEServicesasIOTAModuleServices).
GetNewModuleAndClassName('',FUnitIdent,FClassName,FFileName);FClassName:=SFormName+Copy(FUnitIdent,5,Length(FUnitIdent));LProj:=GetActiveProject;ifLProjnilthenbegin(BorlandIDEServicesasIOTAModuleServices).
CreateModule(TMyUnitCreator.
Create(LProj,FUnitIdent,FClassName,FFileName));end;end;end;ExtendingtheDelphiIDEand-10-ThemodulecreatorisaclassthatimplementstheIOTACreator,IOTAModuleCreatorinterfaces.
Viatheseinterfaces,theactualsourcecodefileandformfilecanbecreated.
TMyUnitCreator=class(TNotifierObject,IOTACreator,IOTAModuleCreator)public//IOTACreatorfunctionGetCreatorType:string;functionGetExisting:Boolean;functionGetFileSystem:string;functionGetOwner:IOTAModule;functionGetUnnamed:Boolean;//IOTAModuleCreatorfunctionGetAncestorName:string;functionGetImplFileName:string;functionGetIntfFileName:string;functionGetFormName:string;functionGetMainForm:Boolean;functionGetShowForm:Boolean;functionGetShowSource:Boolean;functionNewFormFile(constFormIdent,AncestorIdent:string):IOTAFile;functionNewImplSource(constModuleIdent,FormIdent,AncestorIdent:string):IOTAFile;functionNewIntfSource(constModuleIdent,FormIdent,AncestorIdent:string):IOTAFile;procedureFormCreated(constFormEditor:IOTAFormEditor);ThemostimportantmethodsinthisinterfacearetheNewFormFileandtheNewImplSourcemethods.
ThesefunctionsshouldreturnaclassimplementingtheIOTAFileinterfacethatwillreturntheactualcodeforthe.
DFMformfileandthe.
PASsourcecodefile.
TheNewIntfSourcefunctionisnotusedforDelphiformsorprojects,onlyforC++headerfiles.
TheIOTAFileinterfaceisaninterfacethatsimplyreturnsthecontentofthe.
DFMor.
PASfileasastringandthefileageasTDateTime.
TCodeFile=class(TInterfacedObject,IOTAFile)protectedfunctionGetSource:string;ExtendingtheDelphiIDEand-11-functionGetAge:TDateTime;end;Notethatitisimportantthatthe.
DFMand.
PASfilereturnedcontainvalidcode.
TheIDEwilltrytoparsetheformfileandsourcecodeandshouldtheparsingfail,theIDEwillnotcreatethefile.
Inthesample,theformunit&DFMfilearestoredinaresourcefilecreatedwithBRCC32fromthe.
RCfile:TCompanyFormSRC10"Unit1.
pas"TCompanyFormFRM10"Unit1.
DFM"andtheIOTAFileimplementingclassretrievesthesourcecode+DFMfilefromtheresource,replacestheformname,formclass,unitnamewiththenewnameandreturnsitviatheGetSourcefunction:functionTUnitFile.
GetSource:string;varText,ResName:AnsiString;ResInstance:THandle;HRes:HRSRC;beginResname:=AnsiString(SCodeResName);ResInstance:=FindResourceHInstance(HInstance);HRes:=FindResourceA(ResInstance,PAnsiChar(ResName),PAnsiChar(10));Text:=PAnsiChar(LockResource(LoadResource(ResInstance,HRes)));SetLength(Text,SizeOfResource(ResInstance,HRes));Result:=Format(string(Text),[FModuleName,FFormName,FAncestorName]);end;EXTENDINGTHEIDEWITHCUSTOMDOCKINGPANELSCreatingacustomdockpanelfortheIDEisadifferenttypeofIDEextensionandwedonotneedtoregisteraIOTAWizardinterfaceimplementingclasswiththeIDE.
Instead,theExtendingtheDelphiIDEand-12-pluginshouldcreateaninstanceofaform,provideawayfortheusertoshoworhidethedockingpanel,persistitsstatewiththeIDEdesktop,and,finally,destroythedockingpaneluponexitingtheIDE.
TheclassusedfortheIDEdockingpanelisimplementedintheunitsDockForm,DockToolFormthatarepartoftheDesignIDEpackage.
Twodifferenttypesexist:TDockableFormandTDockableToolBarForm.
WewillneedtowriteaRegisterprocedureinaunitofthepluginpackage.
ThisRegisterprocedurewillbecalledbytheIDEafterloadingthepackage.
FromthisRegisterprocedure,wecancreatethedockingpanelandinsertanewmenuitemintheIDEtoshow/hidethepanel.
ThecodeinthefinalizationsectionoftheunitwillbecalledwhentheIDEisclosedandthus,thepanelcanbedestroyedinthisphase.
Theskeletonfortheunittocreatethecustomdockingpanelanddestroyingitisassuch:unitMyIDEDockPanel;interfaceprocedureRegister;implementationusesMyDockForm;varMyIDEDockForm:TMyDockForm;procedureRegister;beginifMyIDEDockForm=nilthenbeginMyIDEDockForm:=TMyIDEDockForm.
Create(nil);end;end;finalizationMyIDEDockForm.
Free;end.
ExtendingtheDelphiIDEand-13-TMyDockFormisaclassthatdescendseitherfromTDockableFormandTDockableToolBarForm.
ToplaywellwiththeIDEdesktoppersistingfunctionality,itisrequiredtoinitializetheDeskSection,AutoSaveandSaveStateNecessarypropertiesofthebaseclass:constructorTMyIDEDockForm.
Create(AOwner:TComponent);begininherited;DeskSection:=Name;AutoSave:=True;SaveStateNecessary:=True;end;destructorTMyIDEDockForm.
Destroy;beginSaveStateNecessary:=True;inherited;end;Inaddition,thecustomdockingpanelclassshouldberegisteredwiththeIDEdesktopwiththecode:RegisterDesktopFormClass(TMyIDEDockForm,MyIDEDockForm.
Name,MyIDEDockForm.
Name);if@RegisterFieldAddressnilthenRegisterFieldAddress(MyIDEDockForm.
Name,@MyIDEDockForm);ExtendingtheDelphiIDEand-14-Theresultofthedockingpanelpluginis:FullcodeofthedockingpanelplugincanbefoundinthecodedownloadinthefolderDockForm.
ACCESSINGTHEDELPHICODEEDITORAccesstotheIDEcodeeditorismadepossibleviaIOTAEditorServicesinterfacethatisimplementedintheBorlandIDEServicesglobalvariable.
TheIOTAEditorServicesprovidesaccesstotheactiveeditorviewviaIOTAEditorServices.
TopView:IOTAEditView.
TheIOTAEditViewinterfaceprovidesaccesstoeditorbookmarks,cursorposition,scrolling,etc.
Inturn,thisIOTAEditViewprovidesaccesstotheeditorbuffer.
ThebufferexposestheinterfaceIOTAEditBuffer.
ThisIOTAEditBufferinterfaceallowsmanipulationoftext,forexampleinsertionanddeletion.
ExtendingtheDelphiIDEand-15-ThiscodesnippetwillgrabtheIOTAEditorServicesfromBorlandIDEServices,gettheIOTAEditViewinterfaceandaccesstheIOTAEditBuffertoinserttextatthetopofthesourcecodefileintheactiveeditorwindow:varEditorServices:IOTAEditorServices;EditView:IOTAEditView;copyright:string;copyright:='Copyright2011bytmssoftware.
com';EditorServices:=BorlandIDEServicesasIOTAEditorServices;EditView:=EditorServices.
TopView;ifAssigned(EditView)thenbegin//positioncursorat1,1EditView.
Buffer.
EditPosition.
Move(1,1);//insertcopyrightnoticeontopEditView.
Buffer.
EditPosition.
InsertText(copyright);end;EXTENDINGTHEDELPHIIDEMENUTheDelphiIDEprovidestheIOTAMenuWizardinterfacetoadditemstheDelphiIDEmainmenu.
Thelimitationofthisinterfaceisthatallmenuitemsaddedthiswaywillbeorganizedunderthehelpmenu.
WewillofferanalternativemethodtoinsertnewmenuitemsanywhereintheexistingDelphiIDEmainmenu.
ToaddanewmenuitemviaIOTAMenuWizard,createaclassthatdescendsfromTNotifierObjectandimplementsIOTAWizard,IOTAMenuWizard:TMyMenuItem=class(TNotifierObject,IOTAWizard,IOTAMenuWizard)functionGetIDString:string;functionGetName:string;functionGetState:TWizardState;procedureExecute;functionGetMenuText:string;end;ExtendingtheDelphiIDEand-16-andregisterthisclasswiththeIDEviatheunitRegisterprocedure:RegisterPackageWizard(TMyMenuItem.
Create);WhenthemenuitemisclickedintheIDE,DelphiwillcalltheExecutemethodfromwhereyourcustomactioncanbeperformed.
Alternatively,itispossibletogetaccesstotheDelphiIDEmainmenuasaTMainMenuclassandusethecommonTMainMenumethodstoinsertaTMenuIteminstanceinthismenu.
Todothis,usetheINTAServices40interfaceimplementedinBorlandIDEServicesandcallitsfunctionMainMenuthatreturnsaTMainMenuinstance.
varNTAServices:INTAServices40;mnuitem:TMenuItem;mnuitem:=TMenuItem.
Create(nil);mnuitem.
Caption:='Newitem';NTAServices:=BorlandIDEServicesasINTAServices40;NTAServices.
MainMenu.
Items.
Add(mnuitem);WhenthefirsttechniquewiththeIOTAMenuWizardisused,theIDEwillautomaticallyremovethemenuitemwhenthepluginisuninstalled.
Usingthesecondtechnique,we'llneedtoremovethemenuitemincode.
AstheinterfaceisbasedonTMainMenu,callItems.
Remove()toremovetheitemfromthemenuanddestroyitaswellastheobjectthathandlesthemenuclick.
Thefullcodetoaddandremovethemenuitembecomes:procedureAddIDEMenu;ExtendingtheDelphiIDEand-17-varNTAServices:INTAServices40;beginNTAServices:=BorlandIDEServicesasINTAServices40;//avoidinsertingtwiceifNTAServices.
MainMenu.
Items[5].
Find('INTAServices40Menu')=nilthenbeginCustomMenuHandler:=TCustomMenuHandler.
Create;mnuitem:=TMenuItem.
Create(nil);mnuitem.
Caption:='INTAServices40Menu';mnuitem.
OnClick:=CustomMenuHandler.
HandleClick;NTAServices.
MainMenu.
Items[5].
Add(mnuitem)end;end;procedureRemoveIDEMenu;varNTAServices:INTAServices40;beginifAssigned(mnuitem)thenbeginNTAServices:=BorlandIDEServicesasINTAServices40;NTAServices.
MainMenu.
Items[5].
Remove(mnuitem);mnuitem.
Free;ifAssigned(CustomMenuHandler)thenCustomMenuHandler.
Free;end;end;ThefullsampleforextendingtheIDEmainmenucanbefoundinthecodedownloadintheIDEMenufolder.
ExtendingtheDelphiIDEand-18-EXTENDINGTHEDELPHIPROJECTMANAGERCONTEXTMENUInthissection,wewillaccesstotheIDEprojectmanager,itscontextmenu,andtheprojects&filesopenedintheprojectmanager.
Furthermore,wewillextendthecontextmenuwithcustomactions.
Tostart,wewillmakeuseoftheIOTAProjectManagerinterface,availableintheBorlandIDEServicesglobalvariable.
TheIOTAProjectManagerinterfaceexposesthefunctionAddMenuItemCreatorNotifierthatneedstobecalledtopassaninstanceofaclassdescendingfromTNotifierObjectandimplementingtheIOTAProjectMenuItemCreatorNotifierinterface.
Basically,thisinformstheIDEthatbeforeitshowstheprojectmanagercontextmenu,thatitshouldqueryourpluginifoneormorecustomcontextmenuitemsshouldbeadded.
Theclassforthecontextmenuitemcreatoris:TMyProjectContextMenu=class(TNotifierObject,IOTAProjectMenuItemCreatorNotifier)procedureAddMenu(constProject:IOTAProject;constIdentList:TStrings;constProjectManagerMenuList:IInterfaceList;ltiSelect:Boolean);IsMuend;ViatheparameterIOTAProject,thecodecandetermineforwhichprojectthecontextmenuisshownandviatheparameterProjectManagerMenuList,instancesofaTMyProjectContextMenuLocalclasscanbeadded.
Inthissamplecodesnippet,acontextmenuitemisunconditionallyadded,regardlessofofwhichitemisright-clickedintheprojectmanager:procedureTMyProjectContextMenu.
AddMenu(constProject:IOTAProject;constIdentList:TStrings;constProjectManagerMenuList:IInterfaceList;IsMultiSelect:Boolean);varMnubeginItem:TMyProjectContextMenuLocal;MnuItem:=TMyProjectContextMenuLocal.
Create;ProjectManagerMenuList.
Add(MnuItem)end;ExtendingtheDelphiIDEand-19-TheIdentListisastringlistholdingstringidentifiersofwhatitemtypeisrightclicked.
ThisisdeclaredinTOOLSAPI.
PASandcanbe:sBaseContainer='BaseContainer';sFileContainer='FileContainer';sProjectContainer='ProjectContainer';sProjectGroupContainer='ProjectGroupContainer';sCategoryContainer='CategoryContainer';sDirectoryContainer='DirectoryContainer';sReferencesContainer='References';sContainsContainer='Contains';sRequiresContainer='Requires';Ifthecontextmenuitemshouldonlyappearwhentheprojectgroupisright-clicked,thecodewouldbe:procedureTMyProjectContextMenu.
AddMenu(constProject:IOTAProject;constIdentList:TStrings;constjectManagerMenuList:IInterfaceList;IsMultiSelect:Boolean);ProvarMnuItem:TMyProjectContextMenuLocal;beginif(IdentList.
IndexOf(sProjectGroupContainer)-1)thenbeginMnuItem:=TMyProjectContextMenuLocal.
Create;//SetmenuitempropertieshereMnuItem.
OnExecute:=MenuClickHandler;ProjectManagerMenuList.
Add(MnuItem)end;end;TheTMyProjectContextMenuLocalisaclassdescendingfromTProjectContextMenuLocalandshouldimplementtheinterfacesIOTALocalMenuandIOTAProjectManagerMenu.
Thisinterfaceconsistsofmethods:TMyProjectContextMenuItem=class(TProjectContextMenuLocal,IOTALocalMenu,IOTAProjectManagerMenu)public//IOTALocalMenuExtendingtheDelphiIDEand-20-functionGetCaption:string;functionGetChecked:Boolean;functionGetEnabled:Boolean;//IOTAProjectManagerMenuinterfacefunctionGetIsMultiSelectable:Boolean;procedureSetIsMultiSelectable(Value:Boolean);procedureExecute(constMenuContextList:IInterfaceList);overload;functionPreExecute(constMenuContextList:IInterfaceList):Boolean;functionPostExecute(constMenuContextList:IInterfaceList):Boolean;propertyIsMultiSelectable:BooleanreadGetIsMultiSelectablewriteSetIsMultiSelectable;end;WiththeIOTALocalMenu,wecansetthecaption,checkedstate,andenabledstateofthemenuitem.
WiththeIOTAProjectManagerMenuinterface,wecandefinewhetherornotthecontextmenuitemsupportsexecutingonmultipleselecteditemsintheprojectmanager.
ThemethodsPreExecute,Execute,PostExecutearecalled,respectively,beforeactualexecutionoftheExecute,whentheitemisselected,andaftertheactualexecutionofExecute.
TheparameteroftheExecutemethodsistheMenuContextListthatisalistofitemsselectedintheprojectmanager.
FromtheExecutemethod,theprojectopenedforwhichthecontextmenuitemwasselectedisretrievedwithfollowingcode:procedureTMyProjectContextMenuLocal.
Execute(constuContextList:IInterfaceList);MenvarMenuContext:IOTAProjectMenuContext;Project:IOTAProject;beginMenuContext:=MenuContextList.
Items[0]asIOTAProjectMenuContext;Prend;oject:=MenuContext.
Project;ExtendingtheDelphiIDEand-21-ExtendingtheDelphiIDEand-22-ThefullsampleforaddingaprojectmanagercontextmenuitemcanbefoundinthecodedownloadintheProjMenufolder.
ADDINGANIDEEDITORCONTEXTMENUITEMANDGRABBINGTHESELECTEDTEXTIfyourpluginwantstooffersomeprocessingonselectedtextintheeditor,youmaywanttoaddacustomitemintheIDEeditorcontextmenuthat,whenclicked,grabstheselectedtextandprocessesit.
Toaddsuchacontextmenu,weneedtogetaccesstothemenu,which,inturn,firstneedaccesstotheeditor.
PleasenotethattheeditorisnotimmediatelyavailableuponstartupoftheIDE,thereforewecan'tgetaccesstotheeditorintheplugininitializationcode.
WhatweneededistoregisteraclassthatimplementstheINTAEditServicesNotifierinterface.
TheIDEcallsthisinterfacewhentheeditorisactivatedintheIDE.
Atthatpoint,theplugincodecanbesurethattheeditorinstanceexists.
TheINTAEditServicesNotifierinterfaceoffersseveralmethodsofwhichonlyEditorViewActivatedisofinterest.
TheinterfaceofthisINTAEditServicesNotifierimplementingclassis:TEditNotifierHelper=class(TNotifierObject,IOTANotifier,INTAEditServicesNotifier)procedureWindowShow(constEditWindow:INTAEditWindow;Show,LoadedFromDesktop:Boolean);procedureWindowNotification(constEditWindow:INTAEditWindow;Operation:TOperation);procedureWindowActivated(constEditWindow:INTAEditWindow);procedureWindowCommand(constEditWindow:INTAEditWindow;Command,Param:Integer;varHandled:Boolean);procedureEditorViewActivated(constEditWindow:INTAEditWindow;constEditView:IOTAEditView);procedureEditorViewModified(constEditWindow:INTAEditWindow;constEditView:IOTAEditView);procedureDockFormVisibleChanged(constEditWindow:INTAEditWindow;DockForm:TDockableForm);procedureDockFormUpdated(constEditWindow:INTAEditWindow;DockForm:TDockableForm);ExtendingtheDelphiIDEand-23-procedureDockFormRefresh(constEditWindow:INTAEditWindow;DockForm:TDockableForm);end;ThisnotifierclassisregisteredwiththeIDEviathecode:procedureRegister;varServices:IOTAEditorServices;beginServices:=BorlandIDEServicesasIOTAEditorServices;NotifierIndex:=Services.
AddNotifier(TEditNotifierHelper.
Create);end;TheAddNotifierfunctionreturnsauniqueindexwithwhichtheclassisregistered.
ThisNotifierIndexvariableintheunitneedstobeusedtounregisterthenotifierclassagainwhenthepluginisuninstalled.
Assuch,weneedtoperformthisunregisterinthefinalizationsectionoftheunit:procedureRemoveNotifier;varServices:IOTAEditorServices;beginifNotifierIndex-1thenbeginServices:=BorlandIDEServicesasIOTAEditorServices;Services.
RemoveNotifier(NotifierIndex);NotifierIndex:=-1;end;end;finalizationRemoveNotifier;end.
Withthisnotifierinstalled,itisnowpossibletogetaccesstotheIDEeditorcontextmenuwhentheeditorfirstbecomesactiveandinstallourcustommenuitem.
Thecodeusedtodothisis:ExtendingtheDelphiIDEand-24-varcustommenu:TMenuItem;procedureTEditNotifierHelper.
EditorViewActivated(constEditWindow:INTAEditWindow;constEditView:IOTAEditView);beginifnotAssigned(custommenu)thenbeginAddEditContextMenu;end;end;procedureAddEditContextMenu;vareditview:IOTAEditView140;popupmenu:TPopupMenu;begineditview:=(BorlandIDEServicesasIOTAEditorServices).
TopView;popupmenu:=editview.
GetEditWindow.
Form.
FindComponent('EditorLocalMenu')asTPopupMenu;custommenu:=TMenuItem.
Create(nil);custommenu.
Caption:='Customcontextmenuitem';custommenu.
OnClick:=mnuHandler.
MenuHandler;popupmenu.
Items.
Add(custommenu);end;initializationcustommenu:=nil;finalizationcustommenu.
Free;end.
Tohandletheclickontheeditorcontextmenuitem,aclasswiththemethodMenuHandleriscreated:TMenuHandler=class(TComponent)procedureMenuHandler(Sender:TObject);end;ExtendingtheDelphiIDEand-25-andthisMenuHandler()methodcangetaccesstotheeditorviewandgettheselectedtextwith:procedureTMenuHandler.
MenuHandler(Sender:TObject);vareditview:IOTAEditView140;editblock:IOTAEditBlock;begineditview:=(BorlandIDEServicesasIOTAEditorServices).
TopView;//gettheselectedtextintheeditvieweditblock:=editview.
GetBlock;ShowMessage('Contextmenuclick:'+inttostr(editblock.
StartingColumn)+':'+inttostr(editblock.
StartingRow)inttostr(editblock.
EndingColumn)+':'+inttostr(editblock.
EndingRow));//ifthereisaselectionoftext,getitviaeditblock.
Textif(editblock.
StartingColumneditblock.
EndingColumn)or(editblock.
StartingRoweditblock.
EndingRow)thenShowMessage('Selectedtext:'+editblock.
Text);end;ThefullsampleforaddinganeditorcontextmenuitemcanbefoundinthecodedownloadintheEditorContextMenufolder.
ADDINGINFORMATIONONTHEDELPHISPLASHSCREENTogivetheIDEpluginwecreateafinishingtouchandtoinformtheuseritisproperlyinstalledintheIDE,wecanaddsomeinformationtothesplashscreenduringthestartupoftheIDE.
TheTOOLSAPIunitexposestheSplashScreenServicesIOTASplashScreenServicesinterface.
ThisinterfaceoffersthemethodAddPluginBitmap:procedureAddPluginBitmap(constACaption:string;ABitmap:HBITMAP;AIsUnRegistered:Boolean=False;constALicenseStatus:string='';constASKUName:string='');ExtendingtheDelphiIDEand-26-Theparametersare:-ACaption:texttoappearonthesplashscreen-ABItmap:bitmaphandletoshowinthesplashscreenassociatedwiththepluginfora24x24bitmap-AIsUnRegisterd:thisisabooleanparameterindicatingwhetherthetextshouldappearinredfontforunregisteredproductsorregularwhitetextforregisteredproducts.
-ALicenseStatus:thisisatextthatcandisplayforexample'Trial'or'Registered'.
-ASKUName:thistextcanshowthenameoftheSKUifdifferentSKUsexistfortheplugin.
IntheinitializationsectionofaunitwithinapackageloadedbytheIDE,wecanusethisinterfacetoaddcustominformationtothesplashscreenwhiletheIDEisloading:procedureAddSplashText;varbmp:TBitmap;beginbmp:=TBitmap.
Create;bmp.
LoadFromResourceName(HInstance,'PLUGINBITMAPRESOURCE');SplashScreenServices.
AddPluginBitmap('PluginproductXYZ2011byMyCompany',bmp.
Handle,false,'Registered','');bmp.
Free;end;initializationAddSplashText;end.
ThefullsampleforaddinganentryintheIDEsplashscreencanbefoundinthecodedownloadintheSplashScreenfolder.
ExtendingtheDelphiIDEand-27-FREETMSIDEPLUGINSFORDELPHIXEBasedonthetechniquespresentedinthiswhitepaper,weofferacoupleoffreeIDEpluginsforDelphiXE.
Thefreepluginscanbefoundinthefolder"TMSpluginsforDelphiXE"inthecodedownload.
TMSPROJECTMANAGERPLUGINThispluginusestheprojectmanagercontextmenuextensionandtheIDEmenuextensiontoofferaccesstothepluginoptions.
ItaddsacontextmenutotheProjectManagerwith3newoptions:1)ZIPproject:thisallowstocreateaZIPfilecontainingtheprojectfiles.
Inthepluginoptions,itcanbeconfiguredwhatfiletypestoincludeinaproject.
2)ZIP&Emailproject:thisoptionwilltrytousethedefaultemailclienttosendtheprojectZIPfilebyemail.
3)ZIP&Uploadproject:thisoptionwilltrytouploadtheprojectZIPfiletoanFTPserverdefinedinthepluginoptionsExtendingtheDelphiIDEand-28-TMSWHAT'SNEWPLUGINThispluginbuildsonthetechniquetocreateacustomIDEdockingform.
Thisdockingformhasthreetabs.
ItdisplaysthelatestcomponentreleasesfromTMSsoftware,theblogfeedaswellasthetweetsfromTMSsoftware.
ExtendingtheDelphiIDEand-29-TMSPRESENTATIONTOOLPLUGINTheTMSPresentationtoolpluginisalsobasedonthecustomIDEdockingformcapabilityaswellasinterfacewiththeIDEeditor.
Itofferstwotab.
Inthefirsttabisaclipboardmonitor.
Thisshowsalltextthatwasputontheclipboard.
Directdrag&dropfromthedockingformtotheIDEeditorispossible.
Thesecondtabisalistofsavedcodesnippets.
Thesecodesnippetscanbeusedforexamplewhengivingpresentation.
ExtendingtheDelphiIDEand-30-ABOUTTHEAUTHORBrunostudiedcivilelectronicengineeringatuniversityofGhentandstartedacareerasR&DdigitalhardwareengineeratBarcoGraphicsinBelgium.
HefoundedTMSsoftwarein1996,developingVCLcomponentsstartingwithDelphi1.
TMSsoftwarebecameBorlandTechnologyPartnerin1998anddevelopedtheDelphiInformantaward-winninggrid&schedulingcomponents.
In2001,hestarteddevelopmentonIntraWebcomponentandin2003,ASP.
NETcomponents.
Currently,BrunoisdevelopingandmanagingVCL,Silverlight,ASP.
NETandIntraWebcomponentdevelopmentprojects,aswellasconsultingandcustomprojectdevelopmentandmanagementonWindows,WebandiPadwithDelphiandXCode.
Hisspecialareasofinterestareuserinterfaces&hardware.
EmbarcaderoTechnologies,Inc.
istheleadingproviderofsoftwaretoolsthatempowerapplicationdevelopersanddatamanagementprofessionalstodesign,build,andrunapplicationsanddatabasesmoreefficientlyinheterogeneousITenvironments.
Over90oftheFortune100andanactivecommunityofmorethanthreemillionusersworldwiderelyonEmbarcadero'saward-winningproductstooptimizecosts,streamlinecompliance,andacceleratedevelopmentandinnovation.
Foundedin1993,EmbarcaderoisheadquarteredinSanFranciscowithofficeslocatedaroundtheworld.
Embarcaderoisonlineatwww.
embarcadero.
com.
Copyright2011TMSsoftware
极光KVM怎么样?极光KVM本月主打产品:美西CN2双向,1H1G100M,189/年!在美西CN2资源“一兆难求”的大环境下,CN2+大带宽 是很多用户的福音,也是商家实力的象征。目前,极光KVM在7月份的促销,7月促销,美国CN2 GIA大带宽vps,洛杉矶联通cuvip,14元/月起;香港CN2+BGP仅19元/月起,这次补货,机会,不要错过了。点击进入:极光KVM官方网站地址极光KVM七月...
2022年春节假期陆续结束,根据惯例在春节之后各大云服务商会继续开始一年的促销活动。今年二月中旬会开启新春采购季的活动,我们已经看到腾讯云商家在春节期间已经有预告活动。当时已经看到有抢先优惠促销活动,目前我们企业和个人可以领取腾讯云代金券满减活动,以及企业用户可以领取域名优惠低至.COM域名1元。 直达链接 - 腾讯云新春采购活动抢先看活动时间:2022年1月20日至2022年2月15日我们可以在...
弘速云怎么样?弘速云是创建于2021年的品牌,运营该品牌的公司HOSU LIMITED(中文名称弘速科技有限公司)公司成立于2021年国内公司注册于2019年。HOSU LIMITED主要从事出售香港vps、美国VPS、香港独立服务器、香港站群服务器等,目前在售VPS线路有CN2+BGP、CN2 GIA,该公司旗下产品均采用KVM虚拟化架构。可联系商家代安装iso系统,目前推出全场vps新开7折,...
syntaxhighlighter为你推荐
directional163Max163支持ipadwin7关闭445端口win7系统怎么关闭445和135这两个端口ipad如何上网iPad怎么上网?请高手指点127.0.0.1传奇服务器非法网关连接: 127.0.0.1tcpip上的netbiostcpip上的netbios是什么用的,有安全隐患吗?开启还是关上tcpip上的netbios禁用tcp/ip上的netbios对网络应用软件的正常运行有没有影响?phpecho为什么在PHP中使用echo FALSE;什么也输出不了?应该如何输出FALSE?谢谢!google中国地图求教谷歌中国地图~手机如何使用?
浙江vps 花生壳域名贝锐 金万维动态域名 cloudstack 商务主机 php空间申请 softbank邮箱 免费申请网站 如何注册阿里云邮箱 彩虹云 英国伦敦 杭州电信 japanese50m咸熟 ipower nic cc加速器 wannacry勒索病毒 域名商城 vim命令 赵荣博客 更多