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
大硬盘服务器、存储服务器、Chia矿机。RackNerd,2019年末成立的商家,主要提供各类KVM VPS主机、独立服务器和站群服务器等。当前RackNerd正在促销旗下几款美国大硬盘服务器,位于洛杉矶multacom数据中心,亚洲优化线路,非常适合存储、数据备份等应用场景,双路e5-2640v2,64G内存,56G SSD系统盘,160T SAS数据盘,流量是每月200T,1Gbps带宽,配5...
justhost怎么样?justhost是一家俄罗斯主机商,2006年成立,提供各种主机服务,vps基于kvm,有HDD和SSD硬盘两种,特色是200Mbps不限流量(之前是100Mbps,现在升级为200Mbps)。下面是HDD硬盘的KVM VPS,性价比最高,此外还有SSD硬盘的KVM VPS,价格略高。支持Paypal付款。国内建议选择新西伯利亚或者莫斯科DataLine。支持Paypal付...
老薛主机怎么样?老薛主机这个商家有存在有一些年头。如果没有记错的话,早年老薛主机是做虚拟主机业务的,还算不错在异常激烈的市场中生存到现在,应该算是在众多商家中早期积累到一定的用户群的,主打小众个人网站业务所以能持续到现在。这不,站长看到商家有在进行夏季促销,比如我们很多网友可能有需要的香港vps主机季度及以上可以半价优惠,如果有在选择不同主机商的香港机房的可以看看老薛主机商家的香港vps。点击进入...
syntaxhighlighter为你推荐
Applicationto请各矿将表填好后于2017年3月1日前发至zhxsh411@163.com邮箱.contentgoogleIOJsios8getIntjava支持ipad支持ipad支持ipad支持ipad尺寸(mm)操作區域手控
美国虚拟空间 免费域名注册 域名备案信息查询 linuxapache虚拟主机 香港ufo 阿里云os buyvm 电影服务器 私人服务器 网站保姆 华为云主机 租空间 ca4249 美国十次啦服务器 hostker 股票老左 东莞数据中心 空间合租 中国网通测速 鲁诺 更多