Recent

Author Topic: Assign event on runtime.  (Read 8272 times)

fredycc

  • Sr. Member
  • ****
  • Posts: 265
Assign event on runtime.
« on: May 11, 2010, 05:18:24 pm »
hi, I had a problem when I tried to display data into a combobox and retrieve the Id for the data selected some times is numeric anothers alphanumeric, but I found a piece of code that helps me displaying my data for columns; but I need write the same code for each comobobox into DrawItem, How Can I write just one time this event and assign it on runtime maybe?  %), the code is :

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer;
  ARect: TRect; State: TOwnerDrawState);
var
  sValor, sTodo: string;
  i, iPos: Integer;
  rc: TRect;
  AnchoColumna: array[0..3] of Integer;
begin
 
  ComboBox1.Canvas.FillRect( ARect );

   sTodo :=  ComboBox1.Items[Index];

  // Establecemos el ancho de las columnas
  AnchoColumna[0] := 0;
  AnchoColumna[1] := 200;  // Ancho de la columna 1
  AnchoColumna[2] := 300;  // Ancho de la columna 2
  AnchoColumna[3] := 0;    // Ancho de la columna 3

  // Leemos el texto de la primera columna
  iPos := Pos( ';', sTodo );
  sValor := Copy( sTodo, 1, iPos - 1 );

  for i := 0 to 2 do
  begin
    // Dibujamos la primera columna
    rc.Left   := ARect.Left + AnchoColumna + 2;
    rc.Right  := ARect.Left + AnchoColumna[i+1] - 2;
    rc.Top    := ARect.Top;
    rc.Bottom := ARect.Bottom;

    // Escribimos el texto
    Combobox1.Canvas.TextRect( rc, rc.Left, rc.Top, sValor );

    // Dibujamos las líneas que separan las columnas
    if i < 3 then
    begin
      Combobox1.Canvas.MoveTo( rc.Right, rc.Top );
      Combobox1.Canvas.LineTo( rc.Right, rc.Bottom );
    end;

    // Leemos el texto de la segunda columna
    sTodo := Copy( sTodo, iPos + 1, Length( sTodo ) - iPos );
    iPos := Pos( ';', sTodo );
    sValor := Copy( sTodo, 1, iPos - 1 );
  end;
end;


//Add Items to ComboBox
ComboBox1.Style:= csOwnerDrawVariable;

 with Combobox1.Items do
 begin
   Add( 'DOLLAR;USD1;' );
   Add( 'PESO;MX1;' );
   Add( 'EURO;EUR;' );
   Add( 'YEN;YEN;' );
 end;

eny

  • Hero Member
  • *****
  • Posts: 1587
Re: Assign event on runtime.
« Reply #1 on: May 11, 2010, 06:04:37 pm »
I'd say in true OO style  :)

Create a new class that does all the recurring actions.
Use for example the Combobox as a parameter in the new class constructur.
And define a method in the new class of type TDrawItemEvent that you assign to the Combobox OnDrawItem event.

Forgot something: the Decorator pattern.
« Last Edit: May 11, 2010, 06:10:38 pm by eny »
All posts based on: Win10 (Win64); Lazarus 1.8.0 'stable' (#56594 win64) unless specified otherwise...

mas steindorff

  • Sr. Member
  • ****
  • Posts: 426
Re: Assign event on runtime.
« Reply #2 on: May 11, 2010, 06:05:45 pm »
first check out these post for dynamic components

http://lazarus.freepascal.org/index.php/topic,8912.0.html

be sure to call each component's create()

As far as events, just set then to the function you have already written like this for a timer.

mytimer.ontimer := @MainForm.OnTimer;

when the event fires, your code will be run
windows 7/10 - laz 2.0 / 1.2.6 general releases

eny

  • Hero Member
  • *****
  • Posts: 1587
Re: Assign event on runtime.
« Reply #3 on: May 11, 2010, 06:57:02 pm »
Couldn't resist  :D
This gives you the basic idea.

Code: [Select]
unit CurrencyComboBoxDecorator;

{$mode objfpc}

interface

uses
  strutils,
  Controls, StdCtrls, Classes, SysUtils;

type

  { TCurrencyComboBoxDecorator }

  TCurrencyComboBoxDecorator = class
  private
    FCombo: TComboBox;
    AnchoColumna: array[0..3] of Integer;

    procedure InitializeCombo;
    procedure OnDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState);

  public
    constructor Create(pComboBox: TComboBox);
    destructor Destroy; override;

    property Combo: TComboBox read FCombo;
  end;

implementation

{ TCurrencyComboBoxDecorator }

constructor TCurrencyComboBoxDecorator.Create(pComboBox: TComboBox);
begin
  // Store combobox we want to decorate locally
  FCombo := pComboBox;

  // Establecemos el ancho de las columnas
  AnchoColumna[0] := 0;
  AnchoColumna[1] := 200;  // Ancho de la columna 1
  AnchoColumna[2] := 300;  // Ancho de la columna 2
  AnchoColumna[3] := 0;    // Ancho de la columna 3

  // And set up the combobox the way we want
  InitializeCombo;
end;

destructor TCurrencyComboBoxDecorator.Destroy;
begin
  Combo.OnDrawItem := nil;
  inherited Destroy;
end;

procedure TCurrencyComboBoxDecorator.InitializeCombo;
begin
  with Combo.Items do
  begin
    Clear;
    Add( 'DOLLAR;USD1;' );
    Add( 'PESO;MX1;' );
    Add( 'EURO;EUR;' );
    Add( 'YEN;YEN;' );
  end;
  Combo.Style := csOwnerDrawVariable;
  Combo.Text := '';
  Combo.OnDrawItem := @OnDrawItem;
end;

procedure TCurrencyComboBoxDecorator.OnDrawItem(Control: TWinControl; Index: Integer; ARect: TRect;
  State: TOwnerDrawState);
var
  i : Integer;
  rc: TRect;
begin
  Combo.Canvas.FillRect( ARect );
  for i := 0 to high(AnchoColumna)-1 do
  begin
    // Dibujamos la primera columna
    rc.Left   := ARect.Left + AnchoColumna[i] + 2;
    rc.Right  := ARect.Left + AnchoColumna[i+1] - 2;
    rc.Top    := ARect.Top;
    rc.Bottom := ARect.Bottom;

    // Escribimos el texto
    Combo.Canvas.TextRect( rc, rc.Left, rc.Top, ExtractWord(i+1,Combo.Items[Index], [';']) );

    // Dibujamos las líneas que separan las columnas
    Combo.Canvas.MoveTo( rc.Right, rc.Top );
    Combo.Canvas.LineTo( rc.Right, rc.Bottom );
  end;
end;

end.

In your form's creator, just add something like this:

Code: [Select]
  decorator: TCurrencyComboBoxDecorator; // Form variable
  ...
  decorator := TCurrencyComboBoxDecorator.Create(ComboBox1);
All posts based on: Win10 (Win64); Lazarus 1.8.0 'stable' (#56594 win64) unless specified otherwise...

fredycc

  • Sr. Member
  • ****
  • Posts: 265
Re: Assign event on runtime.
« Reply #4 on: May 11, 2010, 08:08:49 pm »
wow, thanks a lot eny & mas steindorff; fantastic eny, you save me ;D
« Last Edit: May 11, 2010, 08:19:43 pm by fredycc »

eny

  • Hero Member
  • *****
  • Posts: 1587
Re: Assign event on runtime.
« Reply #5 on: May 12, 2010, 05:24:48 pm »
De nada (and that's all Spanish I know   ;) )
All posts based on: Win10 (Win64); Lazarus 1.8.0 'stable' (#56594 win64) unless specified otherwise...