Replacing a component class in delphi












14














I know I've seen an example somewhere of a hack to define a custom version of an existing VCL component, like TButton or TEdit, with the same class name and do something to make it so that the DFM streamer will instantiate your version instead of the original. Unfortunately, I'm in a situation where I need to be able to do that and I can't find the write-up. Does anyone know where to find information on how to accomplish this?










share|improve this question




















  • 1




    Did you look in your bag of tricks? windwings.wordpress.com/2009/10/07/… ;-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 11:58










  • @Jørn, that is what this answer shows: stackoverflow.com/questions/4685863/…
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 12:57








  • 1




    @Jeroen, I know... I just needed to show @Mason his "seen it somewhere". :-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 13:15










  • ah - sorry, now I get it.
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 13:36
















14














I know I've seen an example somewhere of a hack to define a custom version of an existing VCL component, like TButton or TEdit, with the same class name and do something to make it so that the DFM streamer will instantiate your version instead of the original. Unfortunately, I'm in a situation where I need to be able to do that and I can't find the write-up. Does anyone know where to find information on how to accomplish this?










share|improve this question




















  • 1




    Did you look in your bag of tricks? windwings.wordpress.com/2009/10/07/… ;-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 11:58










  • @Jørn, that is what this answer shows: stackoverflow.com/questions/4685863/…
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 12:57








  • 1




    @Jeroen, I know... I just needed to show @Mason his "seen it somewhere". :-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 13:15










  • ah - sorry, now I get it.
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 13:36














14












14








14


15





I know I've seen an example somewhere of a hack to define a custom version of an existing VCL component, like TButton or TEdit, with the same class name and do something to make it so that the DFM streamer will instantiate your version instead of the original. Unfortunately, I'm in a situation where I need to be able to do that and I can't find the write-up. Does anyone know where to find information on how to accomplish this?










share|improve this question















I know I've seen an example somewhere of a hack to define a custom version of an existing VCL component, like TButton or TEdit, with the same class name and do something to make it so that the DFM streamer will instantiate your version instead of the original. Unfortunately, I'm in a situation where I need to be able to do that and I can't find the write-up. Does anyone know where to find information on how to accomplish this?







delphi controls






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 31 '14 at 1:47









AstroCB

10.2k144665




10.2k144665










asked Jan 13 '11 at 22:06









Mason Wheeler

62.6k34216405




62.6k34216405








  • 1




    Did you look in your bag of tricks? windwings.wordpress.com/2009/10/07/… ;-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 11:58










  • @Jørn, that is what this answer shows: stackoverflow.com/questions/4685863/…
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 12:57








  • 1




    @Jeroen, I know... I just needed to show @Mason his "seen it somewhere". :-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 13:15










  • ah - sorry, now I get it.
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 13:36














  • 1




    Did you look in your bag of tricks? windwings.wordpress.com/2009/10/07/… ;-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 11:58










  • @Jørn, that is what this answer shows: stackoverflow.com/questions/4685863/…
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 12:57








  • 1




    @Jeroen, I know... I just needed to show @Mason his "seen it somewhere". :-)
    – Jørn E. Angeltveit
    Jan 14 '11 at 13:15










  • ah - sorry, now I get it.
    – Jeroen Wiert Pluimers
    Jan 14 '11 at 13:36








1




1




Did you look in your bag of tricks? windwings.wordpress.com/2009/10/07/… ;-)
– Jørn E. Angeltveit
Jan 14 '11 at 11:58




Did you look in your bag of tricks? windwings.wordpress.com/2009/10/07/… ;-)
– Jørn E. Angeltveit
Jan 14 '11 at 11:58












@Jørn, that is what this answer shows: stackoverflow.com/questions/4685863/…
– Jeroen Wiert Pluimers
Jan 14 '11 at 12:57






@Jørn, that is what this answer shows: stackoverflow.com/questions/4685863/…
– Jeroen Wiert Pluimers
Jan 14 '11 at 12:57






1




1




@Jeroen, I know... I just needed to show @Mason his "seen it somewhere". :-)
– Jørn E. Angeltveit
Jan 14 '11 at 13:15




@Jeroen, I know... I just needed to show @Mason his "seen it somewhere". :-)
– Jørn E. Angeltveit
Jan 14 '11 at 13:15












ah - sorry, now I get it.
– Jeroen Wiert Pluimers
Jan 14 '11 at 13:36




ah - sorry, now I get it.
– Jeroen Wiert Pluimers
Jan 14 '11 at 13:36












2 Answers
2






active

oldest

votes


















19














In your form you can override the ReadState method like so:



type
TMyForm = class(TForm)
protected
procedure ReadState(Reader: TReader); override;
end;

procedure TMyForm.ReadState(Reader: TReader);
begin
Reader.OnFindComponentClass := FindComponentClass;
inherited;
end;

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
var ComponentClass: TComponentClass);
begin
if ComponentClass=TButton then begin
ComponentClass := TMySuperDuperButton;
end else if ComponentClass=TEdit then begin
ComponentClass := TMyTotallyAwesomeEdit;
end;
end;


There are likely numerous other ways to do this, but this is how I do it!



EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggests the hack that Mason recalls. The first line sets ClassType := Instance.ClassType. So I suspect that by changing the declaration in the pas file from Button1: TButton to Button1: MyUnit.TButton will result in your button being created. Or perhaps the hack was to add MyUnit to the uses clause right at the end so that your version of TButton is the one that is in scope. However, none of this sounds very practical.






share|improve this answer























  • I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
    – Eugene Mayevski 'Allied Bits
    Jan 13 '11 at 22:14










  • Interesting. I haven't heard of this version, but that might work for what I need to do.
    – Mason Wheeler
    Jan 13 '11 at 22:14






  • 4




    @Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
    – David Heffernan
    Jan 13 '11 at 22:23








  • 1




    @Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
    – David Heffernan
    Jan 13 '11 at 22:25






  • 1




    Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
    – Andreas Rejbrand
    Jan 13 '11 at 22:51



















11














I guess what you're trying to remember is an "interposer class": inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name. Since the class name is not changed, the dfm streaming mechanism is not disturbed. Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es. Obviously, you cannot have published properties in an interposed class.



type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;

TForm1 = class(TForm)
Button1: TButton;
[...]
private





share|improve this answer





















  • Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
    – Mason Wheeler
    Jan 14 '11 at 0:58











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4685863%2freplacing-a-component-class-in-delphi%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









19














In your form you can override the ReadState method like so:



type
TMyForm = class(TForm)
protected
procedure ReadState(Reader: TReader); override;
end;

procedure TMyForm.ReadState(Reader: TReader);
begin
Reader.OnFindComponentClass := FindComponentClass;
inherited;
end;

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
var ComponentClass: TComponentClass);
begin
if ComponentClass=TButton then begin
ComponentClass := TMySuperDuperButton;
end else if ComponentClass=TEdit then begin
ComponentClass := TMyTotallyAwesomeEdit;
end;
end;


There are likely numerous other ways to do this, but this is how I do it!



EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggests the hack that Mason recalls. The first line sets ClassType := Instance.ClassType. So I suspect that by changing the declaration in the pas file from Button1: TButton to Button1: MyUnit.TButton will result in your button being created. Or perhaps the hack was to add MyUnit to the uses clause right at the end so that your version of TButton is the one that is in scope. However, none of this sounds very practical.






share|improve this answer























  • I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
    – Eugene Mayevski 'Allied Bits
    Jan 13 '11 at 22:14










  • Interesting. I haven't heard of this version, but that might work for what I need to do.
    – Mason Wheeler
    Jan 13 '11 at 22:14






  • 4




    @Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
    – David Heffernan
    Jan 13 '11 at 22:23








  • 1




    @Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
    – David Heffernan
    Jan 13 '11 at 22:25






  • 1




    Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
    – Andreas Rejbrand
    Jan 13 '11 at 22:51
















19














In your form you can override the ReadState method like so:



type
TMyForm = class(TForm)
protected
procedure ReadState(Reader: TReader); override;
end;

procedure TMyForm.ReadState(Reader: TReader);
begin
Reader.OnFindComponentClass := FindComponentClass;
inherited;
end;

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
var ComponentClass: TComponentClass);
begin
if ComponentClass=TButton then begin
ComponentClass := TMySuperDuperButton;
end else if ComponentClass=TEdit then begin
ComponentClass := TMyTotallyAwesomeEdit;
end;
end;


There are likely numerous other ways to do this, but this is how I do it!



EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggests the hack that Mason recalls. The first line sets ClassType := Instance.ClassType. So I suspect that by changing the declaration in the pas file from Button1: TButton to Button1: MyUnit.TButton will result in your button being created. Or perhaps the hack was to add MyUnit to the uses clause right at the end so that your version of TButton is the one that is in scope. However, none of this sounds very practical.






share|improve this answer























  • I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
    – Eugene Mayevski 'Allied Bits
    Jan 13 '11 at 22:14










  • Interesting. I haven't heard of this version, but that might work for what I need to do.
    – Mason Wheeler
    Jan 13 '11 at 22:14






  • 4




    @Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
    – David Heffernan
    Jan 13 '11 at 22:23








  • 1




    @Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
    – David Heffernan
    Jan 13 '11 at 22:25






  • 1




    Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
    – Andreas Rejbrand
    Jan 13 '11 at 22:51














19












19








19






In your form you can override the ReadState method like so:



type
TMyForm = class(TForm)
protected
procedure ReadState(Reader: TReader); override;
end;

procedure TMyForm.ReadState(Reader: TReader);
begin
Reader.OnFindComponentClass := FindComponentClass;
inherited;
end;

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
var ComponentClass: TComponentClass);
begin
if ComponentClass=TButton then begin
ComponentClass := TMySuperDuperButton;
end else if ComponentClass=TEdit then begin
ComponentClass := TMyTotallyAwesomeEdit;
end;
end;


There are likely numerous other ways to do this, but this is how I do it!



EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggests the hack that Mason recalls. The first line sets ClassType := Instance.ClassType. So I suspect that by changing the declaration in the pas file from Button1: TButton to Button1: MyUnit.TButton will result in your button being created. Or perhaps the hack was to add MyUnit to the uses clause right at the end so that your version of TButton is the one that is in scope. However, none of this sounds very practical.






share|improve this answer














In your form you can override the ReadState method like so:



type
TMyForm = class(TForm)
protected
procedure ReadState(Reader: TReader); override;
end;

procedure TMyForm.ReadState(Reader: TReader);
begin
Reader.OnFindComponentClass := FindComponentClass;
inherited;
end;

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string;
var ComponentClass: TComponentClass);
begin
if ComponentClass=TButton then begin
ComponentClass := TMySuperDuperButton;
end else if ComponentClass=TEdit then begin
ComponentClass := TMyTotallyAwesomeEdit;
end;
end;


There are likely numerous other ways to do this, but this is how I do it!



EDIT: Inspecting TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggests the hack that Mason recalls. The first line sets ClassType := Instance.ClassType. So I suspect that by changing the declaration in the pas file from Button1: TButton to Button1: MyUnit.TButton will result in your button being created. Or perhaps the hack was to add MyUnit to the uses clause right at the end so that your version of TButton is the one that is in scope. However, none of this sounds very practical.







share|improve this answer














share|improve this answer



share|improve this answer








edited Jan 13 '11 at 22:34

























answered Jan 13 '11 at 22:11









David Heffernan

514k348131205




514k348131205












  • I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
    – Eugene Mayevski 'Allied Bits
    Jan 13 '11 at 22:14










  • Interesting. I haven't heard of this version, but that might work for what I need to do.
    – Mason Wheeler
    Jan 13 '11 at 22:14






  • 4




    @Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
    – David Heffernan
    Jan 13 '11 at 22:23








  • 1




    @Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
    – David Heffernan
    Jan 13 '11 at 22:25






  • 1




    Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
    – Andreas Rejbrand
    Jan 13 '11 at 22:51


















  • I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
    – Eugene Mayevski 'Allied Bits
    Jan 13 '11 at 22:14










  • Interesting. I haven't heard of this version, but that might work for what I need to do.
    – Mason Wheeler
    Jan 13 '11 at 22:14






  • 4




    @Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
    – David Heffernan
    Jan 13 '11 at 22:23








  • 1




    @Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
    – David Heffernan
    Jan 13 '11 at 22:25






  • 1




    Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
    – Andreas Rejbrand
    Jan 13 '11 at 22:51
















I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
– Eugene Mayevski 'Allied Bits
Jan 13 '11 at 22:14




I can be mistaken, but I'd also add the check for ClassName and not just ComponentClass. Just in case something has changed between Delphi 2 and Delphi XE ;)
– Eugene Mayevski 'Allied Bits
Jan 13 '11 at 22:14












Interesting. I haven't heard of this version, but that might work for what I need to do.
– Mason Wheeler
Jan 13 '11 at 22:14




Interesting. I haven't heard of this version, but that might work for what I need to do.
– Mason Wheeler
Jan 13 '11 at 22:14




4




4




@Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
– David Heffernan
Jan 13 '11 at 22:23






@Mason all forms in my app derive from TMyForm. That's something I'd recommend to everyone!
– David Heffernan
Jan 13 '11 at 22:23






1




1




@Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
– David Heffernan
Jan 13 '11 at 22:25




@Mason Otherwise you could just patch it at runtime in the way the Andreas Hausladen does with his stuff
– David Heffernan
Jan 13 '11 at 22:25




1




1




Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
– Andreas Rejbrand
Jan 13 '11 at 22:51




Congratulations, @David. By the way, if you continue like this, you will soon be at the very top of all lists! stackoverflow.com/tags/delphi/topusers
– Andreas Rejbrand
Jan 13 '11 at 22:51













11














I guess what you're trying to remember is an "interposer class": inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name. Since the class name is not changed, the dfm streaming mechanism is not disturbed. Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es. Obviously, you cannot have published properties in an interposed class.



type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;

TForm1 = class(TForm)
Button1: TButton;
[...]
private





share|improve this answer





















  • Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
    – Mason Wheeler
    Jan 14 '11 at 0:58
















11














I guess what you're trying to remember is an "interposer class": inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name. Since the class name is not changed, the dfm streaming mechanism is not disturbed. Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es. Obviously, you cannot have published properties in an interposed class.



type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;

TForm1 = class(TForm)
Button1: TButton;
[...]
private





share|improve this answer





















  • Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
    – Mason Wheeler
    Jan 14 '11 at 0:58














11












11








11






I guess what you're trying to remember is an "interposer class": inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name. Since the class name is not changed, the dfm streaming mechanism is not disturbed. Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es. Obviously, you cannot have published properties in an interposed class.



type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;

TForm1 = class(TForm)
Button1: TButton;
[...]
private





share|improve this answer












I guess what you're trying to remember is an "interposer class": inheriting a class giving the same name as the ancestor, by prefixing the ancestor's unit name. Since the class name is not changed, the dfm streaming mechanism is not disturbed. Would only affect the unit the class is re-declared in, unless it is put in a separate unit and that unit is included in the uses section after the base class'es. Obviously, you cannot have published properties in an interposed class.



type
TButton = class(stdctrls.TButton)
protected
procedure CreateParams(var Params: TCreateParams); override;
end;

TForm1 = class(TForm)
Button1: TButton;
[...]
private






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 14 '11 at 0:32









Sertac Akyuz

47.8k371127




47.8k371127












  • Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
    – Mason Wheeler
    Jan 14 '11 at 0:58


















  • Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
    – Mason Wheeler
    Jan 14 '11 at 0:58
















Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
– Mason Wheeler
Jan 14 '11 at 0:58




Yeah, that's what I was thinking of. But David's solution turned out to be more effective for the problem I was trying to solve.
– Mason Wheeler
Jan 14 '11 at 0:58


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f4685863%2freplacing-a-component-class-in-delphi%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas