Title: Edit listbox items in-place
Question: It would be nice to click on a listbox and be able to edit the selected item directly, instead of opening another form or having a parellel edit control. Peter Below, one of the Delphi gods, shows how.
Answer:
An in-place editor that pops up when you double-click in an item in a listbox. It would probably be feasable to make it active permanently and move it with the
selection but you would also have to move it when the listbox is scrolled, for instance, and that would get complicated rather fast.
Implementing an in-place editor for a listbox:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
StdCtrls;
const
UM_DESTROYCONTROL = WM_USER +230;
type
TForm1 = class(TForm)
ListBox1: TListBox;
procedure ListBox1DblClick(Sender: TObject);
private
{ Private declarations }
Procedure EditDone( Sender: TObject );
Procedure UmDestroyControl(Var msg: TMessage);
message UM_DESTROYCONTROL;
public
{ Public declarations }
procedure EditMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.EditDone(Sender: TObject);
begin
listbox1.Items[ listbox1.itemindex ] :=
(Sender As TEdit).Text;
PostMessage( handle, UM_DESTROYCONTROL, 0, Integer(Sender));
end;
procedure TForm1.EditMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
If not PtInrect( (Sender As TControl).ClientRect, Point(X,y) ) Then
EditDone(Sender);
end;
procedure TForm1.ListBox1DblClick(Sender: TObject);
var
r: TRect;
lb: TListbox;
ed: TEdit;
begin
lb := (sender as TListbox);
if lb.ItemIndex ed:= Tedit.Create(self);
r:= lb.ItemRect( lb.itemindex );
r.topleft := lb.ClientToScreen( r.topleft );
r.BottomRight := lb.clienttoscreen( r.bottomright );
r.topleft := ScreenToClient( r.topleft );
r.BottomRight := screenToClient( r.bottomright );
ed.text := lb.Items[lb.itemindex];
ed.setbounds( r.left, r.top-2,
lb.clientwidth,
r.bottom-r.top+4 );
ed.OnExit := EditDone;
ed.OnMouseDown:= EditMouseDown;
ed.Parent := Self;
SetCapturecontrol( ed );
ed.SetFocus;
end;
procedure TForm1.UmDestroyControl(var msg: TMessage);
begin
TObject(msg.lparam).Free;
end;
end.
This code is Peter Below's (so you know it works, unlike mine!)