Hi all,

I've been struggling a bit trying to get a custom component read for use in Lazarus, but it seems my setbacks are fruitful. I have it working exactly as I want it to under Delphi 2007.

Specifically the problems that I have are:

1. Siting the component at design time causes the mouse down and mouse up events to not fire at runtime. Creating the component at runtime it works perfectly, at least in respect to firing the mousedown and mouseup events.

2. I am trying to center text which I draw to the canvas in the OnPaint event vertically. This works also very well in D2007, but does not seem to work correctly in Lazarus, especially with larger fonts, which seem to push the rect written to towards the top of the ClientRect.

I have attached the .pas file created for this component as I'm sure that is something that I am missing in getting it to work correctly in lazarus, although as I said before, its working perfectly under Delphi 2007.

Thanks you for your help.

p.s. I signed up for another account on the bug tracker about between 30 and 45 minutes ago. Is this usual to wait this long to get the confirmation email? I've had many problems trying to get an account activated for some reason, not certain why however. This last time, I opted to create a whole new profile. I have checked and re-checked my junk mail filters and junk mail folder. I am convinced it doesn't like me :)

--

Warm Regards,

Lee

unit pos_button;
{< Contains TPOSButton which is a custom drawn button inherited from
   TShape as a simple button widget that displays the same in windows
   or linux.}

{$IFDEF FPC}
   {$MODE DELPHI}
{$ENDIF}
 
interface

uses
  SysUtils
  ,Classes
  ,Windows
  ,Graphics
  ,Controls
  ,ExtCtrls
  ,StdCtrls
  ,Forms
  ,Messages
  ;

type

  TPOSButtonState = (bsUp, bsDown);

  // -----------------------------------------------------------------
  //  Class Objects
  // -----------------------------------------------------------------
  { TDTPOSButton class }
  TPOSButton = class(TShape)
  private
    FUpColor: TColor;
    FOnButtonClick: TNotifyEvent;
    FButtonPicture: TBitmap;
    FButtonState: TPOSButtonState;
    FDownBorderColor: TColor;
    FCaption: string;
    FButtonFont: TFont;
    FUpBorderColor: TColor;
    FDataString: string;
    FDownColor: TColor;
    FBorderWidth: Integer;
    FData: TObject;
    FDownFont: TFont;
    FWidgetClass: string;
     // private methods
    procedure   DoOnFontChanged(Sender: TObject);
    function    GetParentColor: TColor;
    procedure DrawBorder;
    procedure Resize;
    procedure SetBorderWidth(const Value: Integer);
    procedure SetButtonFont(const Value: TFont);
    procedure SetButtonPicture(const Value: TBitmap);
    procedure SetButtonState(const Value: TPOSButtonState);
    procedure SetCaption(const Value: string);
    procedure SetData(const Value: TObject);
    procedure SetDataString(const Value: string);
    procedure SetDownBorderColor(const Value: TColor);
    procedure SetDownColor(const Value: TColor);
    procedure SetDownFont(const Value: TFont);
    procedure SetOnButtonClick(const Value: TNotifyEvent);
    procedure SetUpBorderColor(const Value: TColor);
    procedure SetUpColor(const Value: TColor);
    procedure SetWidgetClass( const AValue: string) ;
  protected
    { Determines if the passed in control is the same as a control at location
      x & y. }
    function    IsSameControl(x, y: Integer): Boolean;
    { Handles mousedown event to change image.}
    procedure   HandleMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    { Handles mouseup event to change image back. }
    procedure   HandleMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    { Draw the Up state button and the caption. }
    procedure   DoDrawUpStateNew;
    { Draw the Down state button. }
    procedure   DoDrawDownStateNew;

    procedure   DoDrawButton;
    procedure   Paint; override;

  published
    // ---> Properties
    property    Caption: string read FCaption write SetCaption;
    property    ButtonFont: TFont read FButtonFont write SetButtonFont;
    property    ButtonPicture: TBitmap read FButtonPicture write 
SetButtonPicture;
    property    OnButtonClick: TNotifyEvent read FOnButtonClick write 
SetOnButtonClick;
    property    UpColor: TColor read FUpColor write SetUpColor;
    property    UpBorderColor: TColor read FUpBorderColor write 
SetUpBorderColor;
    property    DownColor: TColor read FDownColor write SetDownColor;
    property    DownBorderColor: TColor read FDownBorderColor write 
SetDownBorderColor;
    property    DownFont: TFont read FDownFont write SetDownFont;
    property    WidgetClass: string read FWidgetClass write SetWidgetClass;
  public
    // ---> Construction Ahead
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    // ---> Properties
    property    Data: TObject read FData write SetData;
    property    DataString: string read FDataString write SetDataString;

    property    ButtonState: TPOSButtonState read FButtonState write 
SetButtonState;
  end;

  procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('DataTrak', [TPOSButton]);
end;

{ TDTPOSButton }

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

  FButtonState := bsUp;

  // reduce flicker?
  ControlStyle := ControlStyle + [csOpaque];

  // create font objects to use.
  FButtonFont := TFont.Create;
  FDownFont := TFont.Create;
  
  //{$IFDEF FPC}
    //FButtonFont.OnChange := @DoOnFontchanged;
  //{$ELSE}
    FButtonFont.OnChange := DoOnFontchanged;
  //{$ENDIF}

  //{$IFDEF fpc}
    //Self.OnMouseDown := @HandleMouseDown;
    //self.OnMouseUp := @HandleMouseUp;
  //{$ELSE}
    Self.OnMouseDown := HandleMouseDown;
    self.OnMouseUp := HandleMouseUp;
//    FLabel.OnMouseDown := HandleMouseDown;
//    FLabel.OnMouseUp := HandleMouseUp;
  //{$ENDIF}

  
end;

destructor TPOSButton.Destroy;
begin
  FButtonFont.Free;
  FDownFont.Free;
  inherited;
end;

procedure TPOSButton.DoDrawButton;
begin
  if FButtonState = bsUp then
    DoDrawUpStateNew
  else
    DoDrawDownStateNew;
end;

procedure TPOSButton.DoDrawDownStateNew;
var
  lRect, lTempRect: TRect;
  lFlags: Integer;

begin
  // setup rect
  lRect.Left := 5;
  lRect.Top := 0;
  lRect.Right := Width -5;
  lRect.Bottom := Height;
  DrawBorder;

  Canvas.Font.Assign(FDownFont);
  Canvas.Brush.Style := bsClear;

  lFlags := DT_WORDBREAK or DT_CENTER;
  lTempRect := ClientRect;
  {$IFDEF FPC}
    DrawText(Canvas.Handle, PChar(AnsiToUtf8(FCaption)), Length(FCaption), 
lTempRect, lFlags or DT_CALCRECT);
    lRect.Top := (Height div 2) - lTempRect.Bottom ;
    DrawText(Canvas.Handle, PChar(AnsiToUtf8(FCaption)), -1, lRect, lFlags);
  {$ELSE}
    DrawText(Canvas.Handle, PChar(FCaption), Length(FCaption), lTempRect, 
lFlags or DT_CALCRECT);
    lRect.Top := (Height div 2) - lTempRect.Bottom;
    DrawText(Canvas.Handle, PChar(FCaption), -1, lRect, lFlags);
  {$ENDIF}

end;

procedure TPOSButton.DoDrawUpStateNew;
var
  lRect, lTempRect: TRect;
  lFlags: integer;
begin
  // setup rect
  lRect.Left := 5;
  lRect.Top := 0;
  lRect.Right := Width -5 ;
  lRect.Bottom := Height ;
  DrawBorder;

  Canvas.Font.Assign(FButtonFont);
  Canvas.Brush.Style := bsClear;

  lFlags := DT_WORDBREAK or DT_CENTER;
  lTempRect := ClientRect;
  {$IFDEF FPC}
    DrawText(Canvas.Handle, PChar(AnsiToUtf8(FCaption)), Length(FCaption), 
lTempRect, lFlags or DT_CALCRECT);
    lRect.Top := (Height div 2) - lTempRect.Bottom;
    DrawText(Canvas.Handle, PChar(AnsiToUtf8(FCaption)), -1, lRect, lFlags);
  {$ELSE}
    DrawText(Canvas.Handle, PChar(FCaption), Length(FCaption), lTempRect, 
lFlags or DT_CALCRECT);
    lRect.Top := (Height div 2) - lTempRect.Bottom;
    DrawText(Canvas.Handle, PChar(FCaption), -1, lRect, lFlags);
  {$ENDIF}
end;

procedure TPOSButton.DoOnFontChanged(Sender: TObject);
begin
  //FLabel.Font.Assign(FButtonFont);
  //DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.DrawBorder;
begin
  if FButtonState = bsUp then
    begin
      Pen.Color := FUpBorderColor;
      Brush.Color := FUpColor;
    end
  else
    begin
      Pen.Color := FDownBorderColor;
      Brush.Color := FDownColor;
    end;
end;

function TPOSButton.GetParentColor: TColor;
begin
  if Parent is TPanel then
    result := TPanel(Parent).Color
  else if Parent is TForm then
    result := TForm(Parent).Color
  {$ifdef fpc}
    ;
  {$else}
    else if parent is TFlowPanel then
      result := TFlowPanel(Parent).Color;
  {$endif}
end;

procedure TPOSButton.HandleMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then
    begin
      FButtonState := bsDown;
      DoDrawDownStateNew;
    end;
end;

procedure TPOSButton.HandleMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbLeft then
    begin
      FButtonState := bsUp;
      DoDrawUpStateNew;

      if IsSameControl(x, y) then
        if Assigned(FOnButtonClick) then
          FOnButtonClick(Self);
    end;
end;

function TPOSButton.IsSameControl(x, y: Integer): Boolean;
var
  lControl: TControl;
  lPoint: TPoint;
begin
  // Check to see if control a location x,y is self.
  lPoint.X := x;
  lPoint.Y := y;
  {$IFDEF FPC}
    // Note: Does not seem to work un FPC/Lazarus
    lControl := Parent.ControlAtPos(lPoint, [capfAllowDisabled,
      capfAllowWinControls]);
  {$ELSE}
    lControl := Parent.ControlAtPos(lPoint, True, True, false);
  {$ENDIF}
  result := (lControl = Self);
end;

procedure TPOSButton.Paint;
begin
  inherited Paint;
  DoDrawButton;
end;

procedure TPOSButton.Resize;
begin
  inherited;
  //DoDrawButton;
  //Invalidate;
end;

procedure TPOSButton.SetBorderWidth(const Value: Integer);
begin
  FBorderWidth := Value;
end;

procedure TPOSButton.SetButtonFont(const Value: TFont);
begin
  FButtonFont := Value;
  //DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.SetButtonPicture(const Value: TBitmap);
begin
  FButtonPicture := Value;
end;

procedure TPOSButton.SetButtonState(const Value: TPOSButtonState);
begin
  FButtonState := Value;
end;

procedure TPOSButton.SetCaption(const Value: string);
begin
  {$IFDEF FPC}
    FCaption := AnsiToUtf8(Value);
  {$ELSE}
    FCaption := Value;
  {$ENDIF}
  //DoDrawButton;
  //Invalidate;
end;

procedure TPOSButton.SetData(const Value: TObject);
begin
  FData := Value;
end;

procedure TPOSButton.SetDataString(const Value: string);
begin
  FDataString := Value;
end;

procedure TPOSButton.SetDownBorderColor(const Value: TColor);
begin
  FDownBorderColor := Value;
//  DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.SetDownColor(const Value: TColor);
begin
  FDownColor := Value;
  //DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.SetDownFont(const Value: TFont);
begin
  FDownFont := Value;
  //DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.SetOnButtonClick(const Value: TNotifyEvent);
begin
  FOnButtonClick := Value;
end;

procedure TPOSButton.SetUpBorderColor(const Value: TColor);
begin
  FUpBorderColor := Value;
  //DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.SetUpColor(const Value: TColor);
begin
  FUpColor := Value;
  //DoDrawButton;
  Invalidate;
end;

procedure TPOSButton.SetWidgetClass( const AValue: string) ;
begin
  if FWidgetClass= AValue then exit;
  FWidgetClass:= AValue;
end;

end.
_______________________________________________
Lazarus mailing list
[email protected]
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to