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
无忧云怎么样?无忧云服务器好不好?无忧云值不值得购买?无忧云,无忧云是一家成立于2017年的老牌商家旗下的服务器销售品牌,现由深圳市云上无忧网络科技有限公司运营,是正规持证IDC/ISP/IRCS商家,自营有国内雅安高防、洛阳BGP企业线路、香港CN2线路、国外服务器产品等,非常适合需要稳定的线路的用户,如游戏、企业建站业务需求和各种负载较高的项目,同时还有自营的高性能、高配置的BGP线路高防物理...
80vps怎么样?80vps最近新上了香港服务器、美国cn2服务器,以及香港/日本/韩国/美国多ip站群服务器。80vps之前推荐的都是VPS主机内容,其实80VPS也有独立服务器业务,分布在中国香港、欧美、韩国、日本、美国等地区,可选CN2或直连优化线路。如80VPS香港独立服务器最低月付420元,美国CN2 GIA独服月付650元起,中国香港、日本、韩国、美国洛杉矶多IP站群服务器750元/月...
小欢互联成立于2019年10月,主打海外高性价比云服务器、CDN和虚拟主机服务。近期上线了自营美国CERA机房高速VPS,进行促销活动,为客户奉上美国/香港八折优惠码:Xxc1mtLB优惠码适用于美国CERA一区/二区以及香港一区/二区优惠时间:即日起至10月底优惠码可无限次使用,且续费同价!官网:https://idc.xh-ws.com购买地址:美国CERA一区:https://idc.xh-...
syntaxhighlighter为你推荐
methoxychromeCreatedwin7绑定ipad存在问题的应用软件名单(2020年第四批)xp如何关闭445端口请大家帮帮忙,怎样关闭135和445端口?netbios端口netbios ssn是什么意思?traceroute网络管理工具traceroute是什么程序ipad如何上网iPad怎么上网?请高手指点win10445端口怎么样打开电脑10800端口css下拉菜单CSS如何把下拉菜单改为上拉菜单
美国vps服务器 网站域名注册 域名拍卖 唯品秀 老鹰主机 国外服务器 圣迭戈 美国主机论坛 免费ftp空间 NetSpeeder 华为云主机 typecho 秒杀汇 免费吧 nerds 129邮箱 vip购优惠 gtt 卡巴斯基破解版 江苏双线服务器 更多