Register custom frame

In Delphi 2009, in one of my projects, I have a custom frame with some controls that I want to use as a base class for some other controls. I want to register this frame as an IDE wizard, which will be available in the New Items list. When I add my new added item (my custom frame) to the project, I expect it to be:

  • Show all properties and events that I added to the user frame in the object inspector.
  • Output the newly created frame from my custom frame, not TFrame.

Well, to show my properties and events in the Object Inspector, I register the user module in the IDE. It does not work properly for frames. Fortunately, someone mentioned this on StackOverflow, and the answer is:

Display additional TFrame child properties in the object inspector

Then, to load the DFM of my custom frame, I added the InitInheritedComponent to my custom frame constructor. Something like that:

constructor TMyFrame.Create(AOwner: TComponent); override; begin inerited; if (ClassType <> TMyFrame) and not (csDesignInstance in ComponentState) then begin if not InitInheritedComponent(Self, TMyFrame) then raise EResNotFound.CreateFmt('Resource %s not found', [ClassName]); end; end; 

This does not work! It still creates an empty constructor in the designer, and not in my own frame. If I do not register the user module in the IDE, it displays my frame correctly, without even requiring an InitInheritedComponent, but additional properties are not displayed in the Object Inspector!

if I change the constructor source to this (Replacing TMyFrame with TFrame):

 constructor TMyFrame.Create(AOwner: TComponent); override; begin inerited; if (ClassType <> TFrame) and not (csDesignInstance in ComponentState) then begin if not InitInheritedComponent(Self, TFrame) then raise EResNotFound.CreateFmt('Resource %s not found', [ClassName]); end; end; 

The frame was added to the constructor correctly, and additional properties are visible in the Object Inspector, but the application starts to fail because it complains that the components in the frame already exist.

So my question is: what is the solution for creating the Delphi IDE wizard, which creates a derived frame from a custom frame (not a form) with DFM and shows its additional properties in the Object Inspector?

By the way, I don’t want to create controls in the frame at runtime, because I need them to be available at design time as well.

I hope someone can make this clear to me.

Hello

Edition:

These frames are actually used as pages for the wizard component. My wizard component creates them at runtime. I want the user to have an option in the "New Item" menu to add a wizard page for the project, as well as design its layout in the IDE designer and register it using my wizard component, which will be shown in the wizard. I inherit the base class from TFrame because my wizard pages must have some required controls and some custom properties and events.

+4
source share
5 answers

I studied in some detail using TFrames (and their related inheritance) as the basis for component development, and could talk about what I found if it was useful, but I never had to use RegisterCustomModule - I just create directly from TFrames, using the usual frame inheritance, and then register the final versions received in the standard component registration block. This, apparently, allows you to use the best of both worlds (visual development + inheritance, plus a component palette + object inspector function).

There are a few small tricks for this, and besides, just like what you call TFrame, make sure that the DFM files use the “object” or “inherited” in the first line correctly and, in general, I have found it very useful for stability complex inheritance trees create a “base frame” that inherits from TFrame but adds NOTHING to it ... and then inherits everything else from there. (This is especially true when adding published properties, etc.).

Please tell us about why you, in particular, want to use the IDE wizard, and perhaps, if this will not be used as an approach, I can help.

+4
source

Yes, it can be done!

I did exactly what you ask in Delphi 2007 and 2009, and you can say that it works well for both versions regardless of the update level. On the way, I ran into some interesting problems, but the final solution was very direct in the opposite direction (after I hit my head against the wall during the day). More on this below in my answer.

I put my custom frame in the runtime package that my component development package references. This was necessary to ensure that the frame can be used in applications using run-time packages, as well as to be able to use the same frame in other custom component packages. A special module expert was also added to the designtime package to add a frame to the File → New → Other ... → "New Items" gallery and to create custom module code by default. This later part was mostly convenient for saving coding time during actual use and was a royal pain to get right. I do this before the learning curve, because I could not find a complete example that matched my situation.

Code from calculated DPK:

 requires DesignIDE, FramePageListD11R, ... contains FramePageListPkgReg in 'FramePageListPkgReg.pas', 

And from FramePageListPkgReg

 implementation {$R FramePageListIcons.res} procedure Register; begin ... RegisterCustomModule(TBaseDisplayFrame, TCustomModule); RegisterPackageWizard(TDisplayFrameModuleExpert.Create); end; 

In my frame implementation there were no visual components on the frame, since my goal was to introduce virtual methods, published properties, events and implement my own interface for my dynamic frame processing logic. Below is the contents of the DFM file and part of the PAS file for reference. Please ignore the IDisplayFrameEvent interface as it is not related to the current topic of discussion.

 object BaseDisplayFrame: TBaseDisplayFrame Left = 0 Top = 0 Width = 500 Height = 300 HorzScrollBar.Smooth = True HorzScrollBar.Style = ssHotTrack HorzScrollBar.Tracking = True VertScrollBar.Smooth = True VertScrollBar.Style = ssHotTrack VertScrollBar.Tracking = True TabOrder = 0 end TBaseDisplayFrame = class(TFrame, IDisplayFrameEvent) private FOnPageShow : TDisplayFrameEvent; FOnPageHide : TDisplayFrameEvent; ... published ... property OnPageShow: TDisplayFrameEvent read FOnPageShow write FOnPageShow; property OnPageHide: TDisplayFrameEvent read FOnPageHide write FOnPageHide; end; 

As for loading DFM, I do not need special encoding. I found that there is a bug in the Delphi environment that involves including the form in the package. I don’t remember all the details, but the problem was easily fixed by manually editing the generated DPK code. Below is the relevant part of the DPK for reference. I suspect this is your main problem. Pay particular attention to the comment part, as this is critical to include DFM in the package.

 contains BaseDisplayFrameModule in 'BaseDisplayFrameModule.pas' {BaseDisplayFrame: TFrame}; 

Once everything works, you can create frames as usual, and then modify the PAS file and DFM to inherit from the frame. As Jamo noted, remember to change the “object” to “inherited” in the first line of the DFM. The only quirk I've seen is that the name of the event handlers on the inherited frame does not match typical Delphi naming conventions, but rather comes from the base class of the frame. This is purely cosmetic, and I did not take the time to find out if there is an easy solution.

Good luck

+2
source

I suspect that this may have been fixed with Update 3 , since I have no problem with what you are describing. I just created a TFrame descendant, added two properties (boolean and event), added a panel, etc. Created a new package with the specified frame registered, installed package, added the path to the search path.

Then I created a new vcl application, created a new form, added my new frame component, and it is editable in accordance with the normal one and both new properties are available in the Object Inspector.

If this does not work, I saw a workaround listed in QC 5230

+1
source

Given your actual purpose, have you looked perhaps at using inline forms? I played with similar things to what you are trying to accomplish using AppControls TacEmbeddedForm in conjunction with Greatis Form Designer (now also available in a slightly different form like TMS Scripter Studio ), with positive results. So far, nothing has ended, but it seems like a promising route for providing some of the runtime tuning features you are looking for.

+1
source

Fro om my perspective Frames can be an extremely useful tool for a Delphi developer. However - I highly recommend placing frames on forms (or on other frames) dynamically (for example, from code not from the form constructor). Within the form, DFM information is placed on the forms, and if you accidentally move several buttons in such a statically placed frame, Delphi will place the change information in the DFM forms. Later, changes in the position of this button on the actual frame will sometimes not be transferred to the placed frame.

0
source

All Articles