• The New Virtual List Box in Delphi 6


    http://users.atw.hu/delphicikk/listaz.php?id=2471&oldal=52

    Problem/Question/Abstract:

    What are the new virtual styles in the TListbox for, and whay are they important?

    Answer:

    One of the new features in Delphi 6 is the addition of styles lbVirtual and lbVirtualOwnerDraw to the standard TListBox. In all the Delphi 6 “What’s new” articles I’ve read this addition has received no more than a passing mention. 

    Why are Virtual List boxes important? 

    Have you ever been frustrated by the limitations of the TStrings' objects property or have had a need to create a custom display string in the list. Sure, you can assign any pointer you want to the object field of a string list but what if you already have a list container (like a Tlist) full of data. Why should you be forced to duplicate this data over to the TStrings associated with the TListBox. You should be able to just use it. Well, with a virtual list box you can. 

    During the past week I ran into a situation where I had a TInterfaceList and wanted to use the value returned from one of the Interface's functions as the text of the list item. Under Delphi 5 this required that I step down through the TInterfaceList calling the required interface method at each step to add the strings to the TListBox. Then I would need to synchronize any movement and selection in the list box with the TInterfaceList. Under Delphi 6, using a virtual list box, I was able merge my TInterfaceList and the TListbox into one highly usable pseudo object. That is, I was able to make the TListBox “aware” of the TInterfaceList directly. 

    (BTW, my original thought was to not use the TInterfaceList at all and just place the references to the Interface into the object field of the TStrings member of the list box.. As you all probably know, this was a bad idea since it totally screws the reference counting on the interface.) 

    Anyway I will not go into great detail about setting up a virtual list box since the Delphi help is pretty good on this. Basically you need to set the style to one of the 2 virtual styles, set the list box’s count to the number of items in the list and then fill in at few as one and as many as 3 events. 

    Here is a trivial sample that may help to fill in some blanks left by the lack of sample code in the help file. 

    I only wish that Borland could have also added this feature the other list controls like the comboboxes and the treeview. 

    unit Unit1;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
      System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, ovcbase, ovcviewr, Vcl.StdCtrls;
    
    type
      TForm3 = class( TForm )
        ListBox1 : TListBox;
        Button1 : TButton;
        lblNumber : TLabel;
        lblColor : TLabel;
        Edit1 : TEdit;
        procedure FormCreate( Sender : TObject );
        procedure FormDestroy( Sender : TObject );
        procedure ListBox1Data( Control : TWinControl; Index : Integer;
          var Data : string );
        procedure ListBox1DataObject( Control : TWinControl; Index : Integer;
          var DataObject : TObject );
        function ListBox1DataFind( Control : TWinControl; FindString : string )
          : Integer;
        procedure Button1Click( Sender : TObject );
        procedure ListBox1Click( Sender : TObject );
      private
        { Private declarations }
      public
        { Public declarations }
        ObjList : TList;
      end;
    
      TMyObj = class
        fColor : string;
        fNumber : Integer;
        constructor create( const color : string; const Number : Integer );
      end;
    
    var
      Form3 : TForm3;
    
    implementation
    
    {$R *.dfm}
    { TMyObj }
    
    constructor TMyObj.create( const color : string; const Number : Integer );
    begin
      fColor := color;
      fNumber := Number;
    end;
    
    procedure TForm3.Button1Click( Sender : TObject );
    begin
      ListBox1.ItemIndex := ListBox1.Items.IndexOf( Edit1.Text );
      // I don't think this next should be necessary but..
      //ListBox1Click( Self );
    end;
    
    procedure TForm3.FormCreate( Sender : TObject );
    begin
      // create a TList and add some data to it.
      ObjList := TList.create;
      ObjList.Add( TMyObj.create( 'Red', 1 ) );
      ObjList.Add( TMyObj.create( 'Yellow', 15 ) );
      ObjList.Add( TMyObj.create( 'Blue', 21 ) );
      ObjList.Add( TMyObj.create( 'Green', 37 ) );
      ObjList.Add( TMyObj.create( 'Brown', 16 ) );
      ObjList.Add( TMyObj.create( 'Black', 5135 ) );
      ObjList.Add( TMyObj.create( 'White', 4 ) );
      ObjList.Add( TMyObj.create( 'Orange', 333 ) );
      // ABSOLUTELY REQUIRED Set the count of the virtual listbox
      ListBox1.Count := ObjList.Count;
    end;
    
    procedure TForm3.FormDestroy( Sender : TObject );
    var
      I : Integer;
    begin
      for I := 0 to ObjList.Count - 1 do
        TMyObj( ObjList.Items[ I ] ).free;
      ObjList.free;
    end;
    
    procedure TForm3.ListBox1Click( Sender : TObject );
    begin
      lblColor.Caption :=
        TMyObj( ListBox1.Items.objects[ ListBox1.ItemIndex ] ).fColor;
      lblNumber.Caption :=
        IntToStr( TMyObj( ListBox1.Items.objects[ ListBox1.ItemIndex ] ).fNumber );
    
    end;
    
    procedure TForm3.ListBox1Data( Control : TWinControl; Index : Integer;
      var Data : string );
    begin
      Data := TMyObj( ObjList.Items[ index ] ).fColor;
    end;
    
    function TForm3.ListBox1DataFind( Control : TWinControl; FindString : string )
      : Integer;
    var
      I : Integer;
    begin
      // the simplest but most brain dead approach
      result := -1;
      for I := 0 to TListBox( Control ).Count - 1 do
        if TListBox( Control ).Items[ I ] = FindString then
          result := I;
    end;
    
    procedure TForm3.ListBox1DataObject( Control : TWinControl; Index : Integer;
      var DataObject : TObject );
    begin
      DataObject := ObjList.Items[ index ];
    end;
    
    end.
    object Form3: TForm3
      Left = 0
      Top = 0
      Caption = 'Form3'
      ClientHeight = 189
      ClientWidth = 780
      Color = clBtnFace
      Font.Charset = GB2312_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Fixedsys'
      Font.Style = []
      OldCreateOrder = False
      OnCreate = FormCreate
      OnDestroy = FormDestroy
      PixelsPerInch = 96
      TextHeight = 16
      object lblNumber: TLabel
        Left = 16
        Top = 144
        Width = 72
        Height = 16
        Caption = 'lblNumber'
      end
      object lblColor: TLabel
        Left = 168
        Top = 144
        Width = 48
        Height = 16
        Caption = 'Label1'
      end
      object ListBox1: TListBox
        Left = 16
        Top = 24
        Width = 737
        Height = 89
        Style = lbVirtual
        TabOrder = 0
        OnClick = ListBox1Click
        OnData = ListBox1Data
        OnDataFind = ListBox1DataFind
        OnDataObject = ListBox1DataObject
      end
      object Button1: TButton
        Left = 678
        Top = 141
        Width = 75
        Height = 25
        Caption = 'Button1'
        TabOrder = 1
        OnClick = Button1Click
      end
      object Edit1: TEdit
        Left = 312
        Top = 141
        Width = 121
    
        Height = 24
        TabOrder = 2
        Text = 'Orange'
      end
    end

     TListBoxStyle specifies the way a listbox control gets its data and how it is drawn.

    TListBoxStyle = (
      lbStandard,
      lbOwnerDrawFixed,
      lbOwnerDrawVariable,
      lbVirtual,
      lbVirtualOwnerDraw
    );

    The following table lists the values for the TListBoxStyle type:

    Value 
    Meaning 
    lbStandard  
    All items are strings, with each item the same height.  
    lbOwnerDrawFixed  
    The list box is owner-drawn, but each item in the list box is the height specified by the ItemHeight property. Each time an item is displayed in an lbOwnerDrawFixed list box, the OnDrawItem event occurs. The event handler for OnDrawItem draws the specified item. The ItemHeight property determines the height of each of the items.  
    lbOwnerDrawVariable  
    The list box is owner-drawn, and items in the list box can be of varying heights. Each time an item is displayed in an lbOwnerDrawVariable list box, two events occur. The first is the OnMeasureItem event. The code for the OnMeasureItem handler can set the height of each item. Then the OnDrawItem event occurs. The code for the OnDrawItem handler draws each item in the list box using the size specified by the OnMeasureItem handler.  
    lbVirtual  
    The list box is virtual, but all items are strings with the same height. You must indicate the number of items in the list box by setting the Count property. You must supply the items in the list box using an OnData event handler. If the items have associated objects, you must supply them using an OnDataObject event handler. In addition, you must supply an OnDataFind event handler to provide the mapping from the strings in the list box to their indexes.  
    lbVirtualOwnerDraw  
    The list box is virtual and owner-drawn. All items are the same height. As with lbOwnerDrawFixed, the item height is specified by the ItemHeight property, and you must draw items using an OnDrawItem event handler. As with lbVirtual, you must set the Count property and supply OnData and OnDataFind event handlers to provide the mapping between items and indexes. If items are associated with objects, you must also supply an OnDataObject event handler.  
  • 相关阅读:
    EntityFramework系列:MySql的RowVersion
    EntityFramework系列:SQLite.CodeFirst自动生成数据库
    怎么回事呢?
    为蛇么不现实
    发布到个人主页
    作别
    budao 首页
    中午吃饱了
    作业写好了吗?
    分类
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4037114.html
Copyright © 2020-2023  润新知