Question

I have a custom button component that I have derived from TCustomButton.

To make it ownerdrawn I have overrided the CreateParams like so:

procedure TMyButton.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do
  begin
    Style := Style or BS_OWNERDRAW;
  end;
end;

My button works ok with my own painting etc, but what I would like to do is provide a Boolean Property in the Object Inspector which can be used to tell my button whether it should be ownerdrawn or not.

For example, if the Property is enabled the button paints with my own paint routines as an ownerdrawn button, if the Property is toggled off then it should paint as the themed Windows button style (like a regular TButton).

CreateParams tells my button it should be ownerdawn, but I want to provide an option to tell the button whether it should be ownerdrawn or not. By changing the property at designtime or through code at runtime, I want to tell my button whether to ownerdraw or not.

Is this possible to do and if so how?

Was it helpful?

Solution

Adding the property and make CreateParams behave accordingly is not the problem I suppose. Taking the new setting in effect immediately probably is.

Call RecreateWnd when the property is toggled. This will lead to dropping the current Windows handle, and recreating it, including making use of your overriden CreateParams routine.

All in all:

type
  TMyButton = class(TButtonControl)
  private
    FOwnerDraw: Boolean;
    procedure SetOwnerDraw(Value: Boolean);
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  published
    property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw
      default False;
  end;

procedure TMyButton.CreateParams(var Params: TCreateParams);
const
  OwnerDraws: array[Boolean] of DWORD = (0, BS_OWNERDRAW);
begin
  inherited CreateParams(Params);
  Params.Style := Params.Style or OwnerDraws[FOwnerDraw];
end;

procedure TMyButton.SetOwnerDraw(Value: Boolean);
begin
  if FOwnerDraw <> Value then
  begin
    FOwnerDraw := Value;
    RecreateWnd;
  end;
end;

OTHER TIPS

You can do it like this:

  1. Make an OwnerDraw property.
  2. Test that property in CreateParams and switch behaviour accordingly.
  3. Call RecreateWnd whenever the property changes.

Instead of item 3 you may be able to simply change the window style with a call to SetWindowLong. Do make sure that you test HandleAllocated before attempting to do this. No point forcing the window to be created needlessly. However, you presumably also need to force a paint cycle whenever this happens.

Personally, I think I'd be inclined to force window recreation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top