1

I have created and implemented a New Component and inside this created component, there is a procedure InitCombo that needs to be invoked in the implementation.

How will I do that?

Here's the procedure InitCombo inside the New Component:

procedure TNewComponent.InitCombo;       //TComboBox ancestor
begin
  FStoredItems.OnChange := nil;
  StoredItems.Assign(Items);
  AutoComplete := False;
  FStoredItems.OnChange := StoredItemsChange;
  doFilter := True;
  StoredItemIndex := -1;
end;

Here's my attempt to invoke but returns an error message:

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  TNewComponent.InitCombo;
end;

Error Messages
[dcc32 Error] makeasale_u_v1.pas(84): E2076 This form of method call only allowed for class methods or constructor

Please note that compiling, building, the installation went well and it is working. Except only on how to invoke the procedure inside the component?

RickyBelmont
  • 619
  • 4
  • 11
  • 1
    `TNewComponent` is a type. You can't invoke a method on a type; you have to have an instance. It's unclear what you're actually trying to do, so it's hard to provide help. Also, `Procedure` is a keyword in Delphi/Pascal, so don't name a procedure `Procedure`. This is a good place for you to provide a [mre] that demonstrates the problem, instead of made up code that won't even come close to compiling. – Ken White Feb 09 '21 at 05:16
  • @KenWhite Noted on `Procedure`. I am trying to create a TComboBox that will filter in between the text of the items. Unfortunately, TComboBox filtering only the beginning of the text. Now the procedure in the new component able to filter in between. I tried to use the same method as a unit.pas of my project, it works! But my issue is, I cannot implement an event because it is created at runtime. I was hoping that I can do it with this approach. – RickyBelmont Feb 09 '21 at 05:51
  • Is it possible to assign SmartComboBox as unit.pas to a TComboBox component, so I will be able to access its event. What I am trying to say is to drop the TComboBox in a form and initialize it with SmartComboBox? – RickyBelmont Feb 09 '21 at 05:56
  • 1
    You can assign events at runtime! – Delphi Coder Feb 09 '21 at 06:10
  • @DelphiCoder Thanks for the tip! I just realized that's possible. I will create another question for this and do some readings. I think I figure this out. – RickyBelmont Feb 09 '21 at 06:26
  • Maybe you are looking for something that's called a class hack? – Delphi Coder Feb 09 '21 at 06:55
  • 1
    @DelphiCoder Calss hack: do you mean interposer class? – fpiette Feb 09 '21 at 07:04
  • @fpiette Yes, exactly – Delphi Coder Feb 09 '21 at 07:08
  • @DelphiCoder I am not really sure. All I wanted is to access the events of the TMyComboBox created at runtime. By the way, TMyComboBox is a unit.pas I created with TComboBox ancestor. – RickyBelmont Feb 09 '21 at 07:33
  • 1
    An interposer class has the same name it is derived from, e.g. TComboBox = class(StdCtrls.TComboBox). Now you can access private and protected fields and methods/properties of the original TComboBox. – Delphi Coder Feb 09 '21 at 07:45
  • 1
    Instead of having this discussion in comments, please [edit] your question and add the relevant details into the question, where they can be seen. You need to be clear and specific about what you're trying to do, so that we don't have to play "20 questions" to pry the information from you. – Ken White Feb 09 '21 at 15:08

1 Answers1

3

Based only on the following portion of the first paragraph of your question

there is a procedure InitCombo that needs to be invoked in the implementation.

It appears you're confused about at least a couple of things about writing components.

First, you initialize the component properties either in its constructor to initialize things, or in an overridden Loaded method, which is called after the component is streamed in from the .dfm file where the component was used. Note that Loaded changes should not touch properties or events that the user can set in the Object Inspector, because doing so will prevent the user's settings from being used.

constructor TNewComponent.Create(AOwner: TComponent);
begin
  inherited;
  // Do your stuff here
end;

procedure TNewComponent.Loaded;
begin
  // Do your stuff here
end;

Second, events that are published (that can be seen in the Events tab of the Object Inspector) belong to the programmer that is using the component, not the component author. Never do anything to those event handlers. Your component should never touch those events except to call them if the end user has assigned a handler. So the code below is absolutely incorrect, because the OnChange event belongs to the user of your component, not your component code:

procedure TNewComponent.InitCombo;       //TComboBox ancestor
begin
  FStoredItems.OnChange := nil;
  ...
  FStoredItems.OnChange := StoredItemsChange;
end;

If you absolutely must do this, you need to do it properly by saving any event handler the end user has assigned, and restore it afterward:

procedure TNewComponent.InitCombo;
var
  OldOnChange: TNotifyEvent;
begin
  OldOnChange := Self.OnChange;
  // Do your stuff here
  Self.OnChange := OldOnChange;
end;

Third, unless you're using a class procedure or class function, you cannot call a method on a class itself (in other words, you cannot use TNewComponent.DoSomething). You call methods or access properties on an instance of the component itself. In your component code, that would be done by using Self, which refers to the current implemented component, as in Self.DoSomething.

Ken White
  • 123,280
  • 14
  • 225
  • 444