How to properly respond to focus messages in a custom control?

I need to create my own panel to be derived from TCustomPanel

. Here I will be doing my own painting in the panel, for example drawing the title at the top.

One of the requirements I need is that I need to be able to draw two different colors depending on whether my panel is focused or not, I also need a way to find out if a child control inside my panel also has focus - Of course although it is not known what the contents of the child might be.

So, for example, if the panel (or any child controls within the panel) has focus, then the color might be clSkyBlue

. If the panel (or none of the child controls inside the panel) has focus, then the color might be clWhite

.

Here's a quick layout for a custom panel: (to keep it simple, e.g. no header drawing, just a basic color change)

type
  TMyPanel = class(TCustomPanel)
  private
    //
  protected
    // procedure Paint; override;

    procedure WMMouseDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;        
    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Self.ParentBackground := False;
  Self.ParentColor := False;
end;

destructor TMyPanel.Destroy;
begin
  inherited Destroy;
end;

procedure TMyPanel.WMMouseDown(var Message: TWMLButtonDown);
begin
  Self.SetFocus;
end;

procedure TMyPanel.WMKillFocus(var Message: TWMKillFocus);
begin
  Self.Color := clWhite;
  Invalidate;
end;

procedure TMyPanel.WMSetFocus(var Message: TWMSetFocus);
begin
  Self.Color := clSkyBlue;
  Invalidate;
end;

      

The first problem I ran into makes the panel attractive, I am sure there will be a proper solution that I missed, but in this case I used a dirty trick, intercepting the message WM_LBUTTONDOWN

and making the panel centered.This of course also negates another requirement. which I mentioned earlier, when the child controls also determine what color the panel should have, depends on whether the panel or child controls are focused.

This is what happens when I click on my panel:

enter image description here

This is what happens when the child control is clicked:

enter image description here

As you can see the panel turned white, but I need it to turn into clSkyBlue

to indicate that the panel or its child content has focus, which should look like this:

enter image description here

So what is the solution to correctly identify if my custom control or its child controls have focus or not?

I was thinking about iterating through each child control inside the panel to determine if it has focus or not, but I'm not sure how I could trigger an event like this in the first place, since clicking directly on the child control would certainly ignore would be any messages that the custom panel is expecting to be intercepted.

+3


source to share


2 answers


All descendants are TWinControl

already configurable, as well as your descendant TCustomPanel

. There is no need to do additional work in this regard.

What is not automatically done for you (and I think you want to do) is to visually display the focus state of your component. One possible way to do this is to process messages CM_ENTER

and CM_EXIT

:



  TMyPanel = class(TCustomPanel)
  private
    procedure FocusChanged(Value: Boolean);
  protected
    procedure CMEnter(var Message: TCMEnter); message CM_ENTER;
    procedure CMExit(var Message: TCMExit); message CM_EXIT;
  end;

procedure TMyPanel.CMEnter(var Message: TCMEnter);
begin
  FocusChanged(True);
end;

procedure TMyPanel.CMExit(var Message: TCMExit);
begin
  FocusChanged(False);
end;

procedure TMyPanel.FocusChanged(Value: Boolean);
const
  Colors: array[Boolean] of TColor = (clWhite, clSkyBlue);
begin
  Color := Colors[Value];
end;

      

+5


source


The easy way is to create your own Edit instead of TPanel.

Your derivative Edit can handle events OnEnter();

and OnExit()

and have a parent color chance.



As you can see, you know how to intercept events, so this will be an easier approach.

0


source







All Articles