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
Moack怎么样?Moack(蘑菇主机)是一家成立于2016年的商家,据说是国人和韩国合资开办的主机商家,目前主要销售独立服务器,机房位于韩国MOACK机房,网络接入了kt/lg/kinx三条线路,目前到中国大陆的速度非常好,国内Ping值平均在45MS左右,而且商家的套餐比较便宜,针对国人有很多活动。不过目前如果购买机器如需现场处理,由于COVID-19越来越严重,MOACK办公楼里的人也被感染...
物语云计算怎么样?物语云计算(MonogatariCloud)是一家成立于2016年的老牌国人商家,主营国内游戏高防独服业务,拥有多家机房资源,产品质量过硬,颇有一定口碑。本次带来的是特惠活动为美国洛杉矶Cera机房的不限流量大带宽VPS,去程直连回程4837,支持免费安装Windows系统。值得注意的是,物语云采用的虚拟化技术为Hyper-v,因此并不会超售超开。一、物语云官网点击此处进入物语云...
国庆钜惠 最低5折起 限量促销CYUN专注海外精品服务器资源,主营香港CN2 GIA、美国CERA、美国高防服务器资源,实体公司,ISP/IDC资质齐全,客服配备齐全。本次针对国庆推出非常给力的促销活动,旗下所有平台同享,新老客户同享,限时限量,售完截止。活动截止时间:2021年10月9日官网地址:www.cyun.net参与机型:香港CN2 GIA云服务器、香港双程CN2云服...
syntaxhighlighter为你推荐
三星itunes支持ipad支持ipad支付apple模块iphonephotoshop技术什么是ps技术用itunes备份iphone怎么从itunes备份恢复iphonewifi为什么我的苹果手机连不上wifi重庆电信宽带管家重庆电信宽带多少钱一个月win7关闭135端口如何用命令关闭135端口
高防服务器租用qy 北京vps主机 高防直连vps lamp安装 国外php主机 tightvnc 上海域名 howfile 微软服务器操作系统 smtp虚拟服务器 空间登入 网通服务器 服务器维护 什么是web服务器 杭州电信宽带优惠 主机返佣 卡巴斯基试用版下载 netvigator 脚本大全 删除域名 更多