TechTricks
Technical answers from the trenches 
 
 
 
 

     
   
Determining Data Source at Runtime
 
   
 Posted: 25 September 2000
 
   
 
 Applies to: Delphi v1.0x - 4.0x
 
   
 
Audience: Intermediate
 
       
   

Question: Is it possible to determine if the active control has a data source property and, if so, the value of that property while my application is running?

Answer: Yes, using RTTI (Run-Time Type Information). The following code sample shows one way to do this in Delphi v3.0x and v4.0x:

function tForm1.getActiveDataSource : tDataSource;
var
   pi : PPropInfo;
begin

   pi := getPropInfo( pTypeInfo(
            screen.activeControl.ClassInfo ), 'DataSource' );

   if ( pi <> NIL ) AND ( pi^.PropType^.Kind = tkClass ) AND

      ( ( getTypeData( pi^.PropType^ )^.ClassType =
          tDataSource ) AND

      ( tDataSource( getOrdProp(
         screen.activeControl, pi ) ) <> NIL ) THEN

      result := ( tDataSource( getOrdProp(
                     screen.ActiveControl, pi ) )

   else
      result := NIL;
end;

When reviewing this code, keep the following points in mind:

  • You'll need to add TYPINFO to a valid Uses block for this to compile.

  • You may need to add FORMS to a valid Uses block, depending on how you're implementing this.

  • The convoluted IF statement verifies that:

    1. The active control has a property named "DataSource".
    2. The property is a class property, as opposed to a simple type.
    3. The property's class corresponds to tDataSource.
    4. The property is assigned a value.

  • If all the tests pass, then the dataSource of the active control is returned; otherwise, the return value is NIL.

Again, the above sample works for Delphi 3 and 4. Earlier versions need a slight variation:

function tForm1.getActiveDataSource : tDataSource;
var
   pi : PPropInfo;
begin

   pi := getPropInfo( pTypeInfo(
            screen.activeControl.ClassInfo ), 'DataSource' );

   if ( pi <> NIL ) AND ( pi^.PropType.Kind = tkClass ) AND

      ( ( getTypeData( pi^.PropType )^.ClassType =
          tDataSource ) AND

      ( tDataSource( getOrdProp(
         screen.activeControl, pi ) ) <> NIL ) THEN

      result := ( tDataSource( getOrdProp(
                     screen.ActiveControl, pi ) )

   else
      result := NIL;
end;

The difference between the two is easily missed; the later versions require pointer derefrence caret (^) after each reference to PropType. This illustrates a hidden danger with using RTTI to solve problems. Specifially, Borland reserves the right to change the structure of RTTI at any time. This means you should heavily test any code that relies on a specific version of RTTI after upgrading your compiler to a new version.

Why would I want to do this?

By combining this with an event handler for OnActiveControlChange, you can use a single dbNavigator or similar component for your database applications. This means you can use a single toolbar for multi-table forms and that the toolbar will work with the current context of your application.

 

       

Top

Feedback About Paradox Delphi Assorted Web Stuff
 
 
Copyright © 2000-2004, techtricks.com; All Rights Reserved.
Acknowledgements, Disclaimers, Terms and Conditions.
Article last updated on 31 May 2003

 

Other Sites: Paradox, Delphi, Perl, Web Stuff, and More


 

[- End -]