dsListBox (part 3)

{
Whith this list box you can edit items directly in list box.
}


{
TdsListBox3 (edit items)

Let's start with a new project, save it into desired folder and declare
some vital things for our list box.
}

type
  TdsListBox3 = class(TListBox)
  private
    FListBoxEdit: TEdit;
  protected
    procedure ListBoxEditExit(Sender: TObject);
    procedure ListBoxEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  public
    constructor Create(AOwner: TComponent); override;
    procedure EditItem;
  end;
  
{
Ancestor for our TdsListBox1 will be TListBox.

First of all, we declare some things we'll need. It's one TEdit and few procedures.

Override the constructor and write:
}

constructor TdsListBox3.Create(AOwner: TComponent);
begin
  inherited;
  FListBoxEdit := TEdit.Create(Self);
  FListBoxEdit.BorderStyle := bsSingle;
  FListBoxEdit.Ctl3D := false;
  FListBoxEdit.OnKeyDown := ListBoxEditKeyDown;
  FListBoxEdit.OnExit := ListBoxEditExit;
end;

{
We create our edit in the constructor and set some things.
We will call EditItem for editing items. Here is the procedure.
}

procedure TdsListBox3.EditItem;
var
  R: TRect;
begin
  if (ItemIndex <> -1)then
  begin
    R := ItemRect(ItemIndex);

    FListBoxEdit.Parent := Self;    
    FListBoxEdit.BoundsRect := R;
    FListBoxEdit.Text := Items[ItemIndex];    
    FListBoxEdit.Visible := true;
    FListBoxEdit.BringToFront;
    FListBoxEdit.SetFocus;
  end;
end;

{
If any item is selected, we get rect of that item and set the right parameters
for our TEdit. It is quite obvious what we do here. We set position, text and
we bring that edit box to front.
Parent of that edit is also set here. As you know, as long as window is without
a parent, it doesn't show anywhere.
After that call, you are able to edit item. Now, how do I finish editing.
There are two events assigned to TEdit.
}

procedure TdsListBox3.ListBoxEditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_RETURN then
  begin
    Items[ItemIndex] := FListBoxEdit.Text;
    FListBoxEdit.Visible := false;
  end;

  if Key = VK_ESCAPE then
    FListBoxEdit.Visible := false;
end;

procedure TdsListBox3.ListBoxEditExit(Sender: TObject);
begin
  FListBoxEdit.Visible := false;
end;

{
If enter is pressed, itemin the list box is updated and edit box hides. If escape
is pressed, edit box hides. if you exit from the edit box, it also hides.

And that's all. Now write some code for the form.
}

procedure TForm1.FormCreate(Sender: TObject);
begin
  l := TdsListBox3.Create(Self);
  l.Parent := Self;
  l.Left := 50;
  l.top := 50;
  l.Width := 100;
  l.Height := 150;
  l.Items.Add('item 1');
  l.Items.Add('item 2');
  l.Items.Add('item 3');
  l.Items.Add('item 4');
  l.Items.Add('item 5');
  l.Items.Add('item 6');
  l.Items.Add('item 7');
  l.Items.Add('item 8');
  l.Items.Add('item 9');
  l.Items.Add('item 10');
  l.Items.Add('item 11');
  l.Items.Add('item 12');
  l.Items.Add('item 13');
  l.Items.Add('item 14');
  l.Items.Add('item 15');

  l.OnDblClick := lDblClick;
end;

{
Put a button on the form and assign next event to it.
}

procedure TForm1.lDblClick(Sender: TObject);
begin
  l.EditItem;
end;