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
今天下午遇到一个网友聊到他昨天新注册的一个域名,今天在去使用的时候发现域名居然不见。开始怀疑他昨天是否付款扣费,以及是否有实名认证过,毕竟我们在国内域名注册平台注册域名是需要实名认证的,大概3-5天内如果不验证那是不可以使用的。但是如果注册完毕的域名找不到那也是奇怪。同时我也有怀疑他是不是忘记记错账户。毕竟我们有很多朋友在某个商家注册很多账户,有时候自己都忘记是用哪个账户的。但是我们去找账户也不办...
专心做抗投诉服务器的VirtVPS上线瑞士机房,看中的就是瑞士对隐私的保护,有需要欧洲抗投诉VPS的朋友不要错过了。VirtVPS这次上新的瑞士服务器采用E-2276G处理器,Windows/Linux操作系统可选。VirtVPS成立于2018年,主营荷兰、芬兰、德国、英国机房的离岸虚拟主机托管、VPS、独立服务器、游戏服务器和外汇服务器业务。VirtVPS 提供世界上最全面的安全、完全受保护和私...
欧路云怎么样?欧路云主要运行弹性云服务器,可自由定制配置,可选加拿大的480G超高防系列,也可以选择美国(200G高防)系列,也有速度直逼内地的香港CN2系列。所有配置都可以在下单的时候自行根据项目 需求来定制自由升级降级 (降级按天数配置费用 退款回预存款)。2021年7月14日美国 CERA 弹性云服务器 上新 联通CUVIP 线路!8折特惠中!点击进入:欧路云官方网站地址付款方式:PayPa...
syntaxhighlighter为你推荐
courses163回收卡巴斯基恶意win7支持ipadwin10关闭445端口如何进入注册表修改关闭445端口iphone连不上wifi为什么苹果手机连不上wifi微信都发不出去?css下拉菜单如何用css3做导航栏下拉菜单itunes备份itunes备份是什么iphonewifi苹果手机怎样设置Wi-Fi静态IP?360chromechrome是什么文件夹?是360急速浏览器吗?但是怎么没有卸载掉?
成都主机租用 域名解析服务器 阿云浏览器 新加坡主机 ddos 好玩的桌面 好看的桌面背景图片 云图标 169邮箱 cdn加速原理 服务器监测 西安服务器托管 smtp服务器地址 免费的域名 东莞主机托管 中国域名 镇江高防 徐州电信 万网注册 hdsky 更多