Delphi - Overriding Properties of Windows Implemented Components

Window'ed components (controls partially implemented by the MS Windows operating system - edit controls, radio buttons, and the like) have two types of properties I already have a page covering properties that you have full control over.

Background | First Attempts (Did not work) | Simple Solution | Window'ed Components | Other Techniques | Final Code | Comment | Advice


Background

I was creating my own edit control based on the existing TEdit control. I wanted to change the background color to provide a visual indication of the component's ReadOnly state (property).

The following is the relevant code.

Normally, I would simply override the property setter (SetReadOnly) and add whatever new functionality I want ... not this time. Unfortunately, SetReadOnly is private.


First Attempts (Did not work)

In my opinion, all property setters should be protected and virtual. Unfortunately, that would make for larger and slower programs. On the other hand, if that was done, then the change (enhancement) I wanted to make would have been trivial.

The first thing I tried was to simply replace the existing property with a new definition.

Unfortunately, this code does not actually change the Read/Write property of the edit control. Since TEdit is actually a wrapper for a windows edit control, your code must tell windows what the properties are. In StdCtrls.pas, the associated code is The key line is the SendMessage statement .. without that, the function of the component does not change.


Simple Solution

Unfortunately, there is no way to directly access the setter method (since it is private). Instead, I was able to access the parent property using the following.

My first attempt to accomplish this failed. I have no idea why (since I can not reproduce the problem). Perhaps it was my error, perhaps not. The help suggests that overriding a property completely hides the original definition. At any rate, it works now.


Window'ed Components

As I said, my first attempt at the simple solution (above) failed. Next I tried copying the code from TCustomEdit.SetReadOnly to my property .. and it also failed.

That's right, this code works perfectly in the original component and totally failed in my code. Well, not "totally". I placed a checkbox and an edit component on a form to test the code and everything worked ok. Then I started the program with the ReadOnly property set true .. and was able to edit its contents.

When I set a breakpoint and single stepped the code, it worked .. when I ran it without breakpoints, it failed. The reason was far from obvious.

(To debug this type of problem, you must enable Debug DUCs under Project / Options... / Compiler.)

I eventually determined that when properties are set as the program starts, none of the windows implemented objects exist. As a result, HandleAllocated returns false because FHandle equals zero. However, when setting breakpoints and single stepping the program, I let the mouse hover over the Handle variable .. and THIS caused the program to go ahead and create the edit window.

To be clear, when I

the program ran as expected. But, if I simply ran the program without breakpoints, the program failed.

(I love intermittent software .. don't you?)

This is because window'ed components (such as TEdit) are not created until AFTER TForm.FormCreate is called. As a result, the code that actually creates the components must read the available properties and send them to windows. In the case of ReadOnly, I had overridden the original definition and used my own FReadOnly variable. When the component was finally created, the following code used the original variable.

My solution was to simply override CreateParams and set (or clear) the appropriate bit, as required.


Other Techniques

I know that this works. (See above) This failed. (Need to verify it again.) I need to test this. (Should work) From C:\Program Files\Borland\Delphi5\Source\Vcl\mask.pas


Final Code

This is the final code I used. It is similar to what is above .. except .. it only replaces the setter method and not the private variable. (Note: This is just a fragment of the complete component .. just the part related to the ReadOnly property.)


Comment

I am sure that this information is written down somewhere in the help files, but I have been doing Delphi development for many years and was not aware of how, or when, the window'ed components were created.

I hope you find these notes useful.


Advice

Always test your code in every way you can imagine - there is always something you have missed. Oh .. and write down the steps so that you can repeat them (and improve them).


Author: Robert Clemenzi - clemenzi@cpcug.org
URL: http:// cpcug.org / user / clemenzi / technical / Languages / Delphi / OverridingProperties.html