ListBox - usando o ownerdraw

Top  Previous  Next

{

 Esta tela tem uma listbox e um timage.

 mostra como usar o ownerdraw da listbox

 

 Setar ListBox.Style := lbOwnerDrawFixed

 

}

 

unit fXList;

 

interface

 

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,

  StdCtrls, ExtCtrls;

 

type

  TForm1 = class(TForm)

    ListBox1: TListBox;

    Image1: TImage;

    Label1: TLabel;

    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer;

      Rect: TRect; State: TOwnerDrawState);

    procedure ListBox1MeasureItem(Control: TWinControl; Index: Integer;

      var Height: Integer);

    procedure ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X,

      Y: Integer);

    procedure FormResize(Sender: TObject);

 

  private

 

  public

 

  end;

 

procedure ListBoxDrawItem(Control: TWinControl; Index: Integer;

  ARect: TRect; State: TOwnerDrawState; Image: TBitmap );

procedure ListBoxMeasureItem(Control: TWinControl; Index: Integer;

  var Height: Integer; Image: TBitmap);

procedure ListBoxMouseMove(Sender: TObject; Shift: TShiftState;

  X, Y: integer; Image: TBitmap);

procedure ListBoxRefresh(Control: TWinControl; Image: TBitmap);

 

var

  Form1: TForm1;

 

implementation

 

{$R *.DFM}

 

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;

  Rect: TRect; State: TOwnerDrawState);

begin

  ListBoxDrawItem(Control, Index, Rect, State, Image1.Picture.Bitmap );

end;

 

procedure TForm1.ListBox1MeasureItem(Control: TWinControl;

  Index: Integer;

  var Height: Integer);

begin

  ListBoxMeasureItem(Control, Index, Height, Image1.Picture.Bitmap);

end;

 

procedure TForm1.ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X,

  Y: Integer);

begin

  ListBoxMouseMove(Sender, Shift, X, Y, Image1.Picture.Bitmap);

end;

 

procedure TForm1.FormResize(Sender: TObject);

begin

  ListBoxRefresh (ListBox1, Image1.Picture.Bitmap);

end;

 

procedure ListBoxDrawItem(Control: TWinControl; Index: Integer;

  ARect: TRect; State: TOwnerDrawState; Image: TBitmap);

var

  s: string;

  R: Trect;

  lst: TlistBox;

  Ident: integer;

  sOption: integer;

begin

  if Index = -1 then exit;

 

  lst:= TlistBox(Control);

 

  if lst.Style = lbStandard then exit;

 

  R := ARect;

  if R.Top > lst.Height then exit;

 

  S := lst.Items[Index];

  sOption := 0;

  case lst.BiDiMode of

    bdLeftToRight: sOption := 0;

    bdRightToLeft: sOption := DT_RIGHT + DT_RTLREADING;

    bdRightToLeftNoAlign: sOption := DT_RTLREADING;

    bdRightToLeftReadingOnly: sOption := DT_RTLREADING;

  end;

 

  if lst.Style = lbOwnerDrawVariable then

    sOption := sOption + DT_WORDBREAK + DT_EDITCONTROL ;

 

 

  if Image <> nil then

    Ident := Image.Width + 4

  else

    Ident := 2;

 

  if lst.BiDiMode = bdRightToLeft then

    Dec(R.Right, Ident)

  else

    Inc(R.Left, Ident);

 

  lst.Canvas.Font := lst.Font ;

  lst.Canvas.Brush.Color := lst.color;

 

  if odSelected in state then

    begin

      lst.Canvas.Font.Color := clWhite;

      lst.Canvas.Brush.Color := $00E7A66B;

    end;

 

  if (odFocused in state) and (odSelected in state) then

    begin

      lst.Canvas.Brush.Color := $00C4500B;

      lst.Canvas.Font.Color := clWhite;

    end;

 

 

 

  if not (odDefault in state) then

    lst.Canvas.FillRect (Arect)

  else

    lst.Canvas.FillRect (R);

 

  Drawtext(lst.Canvas.Handle, PChar(s), length(s), R, sOption);

 

 

  R := ARect;

  if lst.BiDiMode = bdRightToLeft then

    R.Left := R.Right - Ident + 2

  else

    Inc(R.Left,  2);

 

  R.Right := R.Left + Image.Width;

  if not (odDefault in state) then

    lst.Canvas.Draw (R.Left, R.top + 1, Image);

 

end;

 

procedure ListBoxMouseMove(Sender: TObject; Shift: TShiftState;

 X, Y: integer; Image: TBitmap);

var

  APoint: TPoint;

  Index: integer;

  lst: TListBox;

 

  s: string;

  R: Trect;

  Ident: integer;

  sOption: integer;

  X1,X2: integer;

 

begin

 

  lst:= TlistBox(Sender);

  if lst.Style = lbStandard then exit;

 

  X1 := 0;   // just to stop editor hint nagging.

  X2 := 0;

 

  if Image <> nil then

    Ident := Image.Width + 2

  else

    Ident := 2;

 

  APoint.X := X;

  APoint.Y := Y;

  Index := lst.ItemAtPos(APoint, True);

 

  R := lst.ItemRect(Index);

 

  if Index <> -1 then

    begin

      X2 := lst.Canvas.TextWidth (lst.Items[Index]);

      if lst.BiDiMode = bdRightToLeft then

        X1 := r.Right - X2 - Image.Width - 4

      else

        X1 := r.Left + Image.Width + 4;

 

      X2 := X1 + X2;

    end;

 

 

 

  if (ssLeft in Shift) then exit;

 

  if (x < X1) or (x > X2) then

    begin

      lst.Cursor := crDefault;

      if Index = lst.ItemIndex then exit;

      if lst.Tag = lst.ItemIndex then exit;

        if lst.Tag <> -1 then

          begin

            if lst.Selected[lst.Tag] then

              ListBoxDrawItem(lst, lst.Tag, lst.ItemRect(lst.Tag),

                              [odSelected], Image)

            else

              ListBoxDrawItem(lst, lst.Tag, lst.ItemRect(lst.Tag),

                              [odDefault], Image);

             lst.Tag := -1;

          end;

 

      exit;

    end;

 

  if (lst.Tag = Indexand (lst.Cursor = crHandPoint) then

    exit// Drawn before

 

  lst.Cursor := crHandPoint;

 

  sOption := 0;

  case lst.BiDiMode of

    bdLeftToRight: sOption := 0;

    bdRightToLeft: sOption := DT_RIGHT + DT_RTLREADING;

    bdRightToLeftNoAlign: sOption := DT_RTLREADING;

    bdRightToLeftReadingOnly: sOption := DT_RTLREADING;

  end;

 

  if lst.Style = lbOwnerDrawVariable then

    sOption := sOption + DT_WORDBREAK + DT_EDITCONTROL;

 

 

  if lst.ItemIndex <> Index then

    begin

      R := lst.ItemRect(Index);

 

      S := lst.Items[Index];

 

      if lst.BiDiMode = bdRightToLeft then

        Dec(R.Right, Ident + 2)

      else

        Inc(R.Left, Ident + 2);

 

      if lst.Selected[Index] then

        lst.Canvas.Font.Color := clWhite

      else

        lst.Canvas.Font.Color := clBlue;

      lst.Canvas.Font.Style  := lst.Font.Style + [fsUnderLine];

 

      SetBkModE(lst.Canvas.Handle, TRANSPARENT);

      Drawtext(lst.Canvas.Handle, PChar(s), length(s), R, sOption);

 

    end;

 

    if not (ssMiddle in Shift) and

           (lst.Tag <> -1and

           (lst.Tag <> Indexand

           (lst.Tag <> lst.ItemIndex) then   //What? Do you need more?

        if lst.Selected[lst.Tag] then

           ListBoxDrawItem(lst, lst.Tag, lst.ItemRect(lst.Tag),

                           [odSelected], Image)

         else

           ListBoxDrawItem(lst, lst.Tag, lst.ItemRect(lst.Tag),

                           [odDefault], Image);

 

 

  lst.Tag := Index;

 

end;

 

procedure ListBoxRefresh(Control: TWinControl; Image: TBitmap);

var

  lst: TListBox;

  i, Count, H: integer;

begin

  lst := TListBox(Control);

  if lst.Style = lbStandard then exit;

  if lst.Style = lbOwnerDrawFixed then

    Count := 1

  else

    Count := lst.Items.Count - 1;

  for i := 0 to Count - 1 do

    begin

      ListBoxMeasureItem(lst, i, H, Image);

      lst.Perform (LB_SETITEMHEIGHT, i, MAKELPARAM(H, 0));

    end;

 

  lst.refresh;

 

end;

 

procedure ListBoxMeasureItem(Control: TWinControl; Index: Integer;

  var Height: Integer; Image: TBitmap );

var

  s: string;

  lst: TListBox;

  R: TRect;

  sOption: integer;

begin

   lst := TListBox(Control);

   if lst.Style = lbStandard then exit;

   sOption := 0;

   case lst.Style of

     lbStandard:

       begin

         Height := lst.ItemHeight;

         exit;

       end;

     lbOwnerDrawFixed: sOption := 0;

     lbOwnerDrawVariable: sOption := DT_WORDBREAK;

   end;

   R := lst.ClientRect;

 

   Dec(R.Right, Image.width + 4 );

   S := lst.Items[Index];

   lst.Canvas.Font.Assign(lst.Font);

   Height := DrawTextEx(lst.Canvas.Handle,

                        PChar(s),

                        length(s),

                        R,

                        sOption or DT_CALCRECT or DT_EXTERNALLEADING,

                        nil);

 

   Inc(Height, 4);

   if (Image.Height + 2) > Height then

     Height := Image.Height + 2;

end;

 

end.