1. Home
  2. Computing & Technology
  3. Delphi Programming

Generic Solution to Coloring the Focused Entry Control
TScreen's OnActiveControlChange in action!

By , About.com Guide

Looking for the best approach to change the background color (and other properties) of the focused data entry control in a Delphi application? You already know that handling the OnEnter and OnExit events for each control is not the correct solution? Read on to exploit the powers of the RTTI and the TScreen Delphi object!

RTTI and TScreen to the rescue!

A much better approach is to handle the "got focus" and "lost focus" situations on a higher level.

The TScreen class exposes the OnActiveControlChange event immediately after input focus changes to a new windowed control. This event is fired by the global Screen object that all Delphi applications can exploit, by default. There's no need to handle each and every control's OnEnter and OnExit event. OnActiveControlChange is fired when the input focus shifts within the active form, and across forms to a new form when it becomes the active form. Great!

To get around the limitation of having to check the type of the control to type cast to the correct class in order to be able to access the Color property, you can reach for Delphi's RTTI.

By using Delphi's run-time type information you can check if a control exposes a particular property as public, get or set the new value - all this without worrying about the class of the control.

For a start, you need to define a value for the background color of the currently active (with the input focus) control. You also need to have two variables to hold the reference to the previously active control and its background color.

Add the following declarations to the interface section of your application's Main form:

const
   focusColor = clSkyBlue;

var
   lastFocused : TWinControl;
   originalColor : TColor;
Since there is no TScreen component you can drop on a form, you need to attach the event handler for the OnActiveControlChange event manually. The Main form's OnCreate event handler is the best place. You also need to make sure that you clean up the screen object when the form is freed by detaching the event handler from the event in the main form's OnDestroy event handler:
procedure TMainForm.FormCreate(Sender: TObject) ;
begin
   Screen.OnActiveControlChange := ScreenActiveControlChange;
end;

procedure TMainForm.FormDestroy(Sender: TObject) ;
begin
   Screen.OnActiveControlChange := nil;
end;
Here's the implementation of the "ScreenActiveControlChange" procedure.
procedure TMainForm.ScreenActiveControlChange(Sender: TObject) ;
var
   doEnter, doExit : boolean;
   previousActiveControl : TWinControl;
begin
   if Screen.ActiveControl = nil then
   begin
     lastFocused := nil;
     Exit;
   end;

   doEnter := true;
   doExit := true;

   //CheckBox
   if Screen.ActiveControl is TButtonControl then doEnter := false;

   previousActiveControl := lastFocused;

   if previousActiveControl <> nil then
   begin
     //CheckBox
     if previousActiveControl is TButtonControl then doExit := false;
   end;

   lastFocused := Screen.ActiveControl;

   if doExit then ExitColor(previousActiveControl) ;
   if doEnter then EnterColor(lastFocused) ;
end;
When the OnActiveControlChange is fired by the Screen object, the ScreenActiveControlChange is executed. Here's what we want to happen:
  • The "previousActiveControl" variable holds the reference to the control that had the input focus "last time".
  • The ActiveControl property (TWinControl type) of the Screen object Indicates which control currently has input focus on the screen (any of the forms in your project). Therefore, we first need to make sure the ActiveControl is assigned.
  • Some controls, like TCheckBox, do not look nice if we change their background color. The "doEnter" and "doExit" variables are used to ensure that we really want to change the background color on the active control (and restore on the last focused). The TCheckBox derives from a more generic TButtonControl - which encapsulates behavior common to button controls, check boxes, and radio buttons. In short, we do not want to change the back color of such controls.
  • Finally, a custom "ExitColor" procedure is called passing the reference to the control that had the input focus prior to OnactiveControlCnahge being raised. Naturally, "EnterColor" is called to change the background color of the currently focused control.
What's left is the implementation of the "EnterColor" and "ExitColor" procedures ... this is where the RTTI magic comes to the rescue ...
Explore Delphi Programming
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Using VCL Components
  5. TEdit, TMaskEdit
  6. Generic Solution to Coloring the Focused Data Entry Delphi Control

©2009 About.com, a part of The New York Times Company.

All rights reserved.