Lo primero a tener en cuenta es que lo que se arrastra de un contenedor tiene que ser compatible con el contenedor receptor. Lo habitual es que se arrastren y suelten strings (cadenas) entre listas de strings, es lo más básico. En el ejemplo se arrastrará y soltará desde una lista del tipo TFileListBox a otra del tipo TListBox.
Hay que preparar ambos objetos, el TFileListBox para que permita arrastrar sus ítems y a TListBox para que acepte lo que le llega de TFileListBox.
En un Form crear ambos componentes y dejarles su nombre por default (TFileListBox1 y ListBox1).
Desde el inspector de objetos seleccionamos FileListBox1 y establecemos dmAutomatic en la propiedad DragMode. Con esto solo conseguimos que los elementos contenidos en esa lista se puedan arrastrar. Y con este elemento no es necesario hacer más nada.
Ahora seleccionamos también desde el inspector de objetos ListBox1, en Eventos, definimos OnDragDrop y OnDragOver. (definimos = hacer click en el botón con los ‘…’).
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
if (Source is TFileListBox) then ListBox1.AddItem(FileListBox1.items[FileListBox1.ItemIndex],ListBox1);
end;
ListBox1 agregará ítems que provengan de objetos del tipo TFileListBox.
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept:=(Source is TFileListBox);
end;
ListBox1 aceptará que objetos del tipo TFileListBox le suelten ítems.
Visualmente le hemos agregado 4 botones para seleccionar todos los ítems o elementos y otro para des-seleccionar. También hemos activado el drag and drop del ListBox1 hacia el ListBox2.
Cómo hacer el drag and drop entre dos ListBox?
Desde el inspector de objetos, seleccionamos ListBox1y vamos a la pestaña de eventos, allí debemos seleccionar dmAutomatic en DragMode.
Ahora pasamos al ListBox2 y debemos definir los eventos OnDragOver y OnDragDrop.
Para ello debemos hacer click sobre los ... tanto en OnDragDrop como en OnDragOver para que Lazarus nos escriba el código de los eventos.
En el evento OnDragOver tenemos que decir que pasa cuando "sobre vuela" sobre el ListBox2 un elemento arrastrado con el mouse.
procedure TForm1.ListBox2DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept:=(Source is TListBox);
end;
Con esta línea de código indicamos que se acepte si viene de otro TListBox.
Es con el evento OnDragDrop donde especificamos que hacer con el elemento recibido, en este caso es agregar dicho elemento a la lista, pero podríamos definir cualquier otra acción.
procedure TForm1.ListBox2DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
btnAgregarClick(Self);
end;
Como ya tenemos un procedimiento para agregar, que es el evento OnClick del botón Agregar, por qué no utilizarlo y evitar escribir el código dos veces.
Eso es todo respecto de arrastrar y soltar.
Seleccionar todo y desmarcar todo: como ya está definido, resulta algo muy sencillo, no obstante, hay que saber de su existencia para no reinventar la rueda.
procedure TForm1.btnTodoL1Click(Sender: TObject);
begin
ListBox1.SelectAll;
end;
procedure TForm1.btnTodoL2Click(Sender: TObject);
begin
ListBox2.SelectAll;
end;
No hace falta explicar nada, SelectAll lo dice todo.
Para hacer lo contrario, des-seleccionar todo:
procedure TForm1.btnQuitarL1Click(Sender: TObject);
begin
ListBox1.ClearSelection;
end;
procedure TForm1.btnQuitarL2Click(Sender: TObject);
begin
ListBox2.ClearSelection;
end;
procedure TForm1.btnAgregarClick(Sender: TObject);
var
i:Integer;
begin
if ListBox1.Count<1 then exit; //Si no hay elementos no hace nada
for i:=0 to ListBox1.Count-1 do //Recorre todo el ListBox1
if ListBox1.Selected[i] then //Si el ítem está seleccionado
if not (YaExiste(ListBox1.Items.Strings[i])) then //Si el ítem a agregar ya existe no lo agrega
ListBox2.AddItem(ListBox1.Items.Strings[i],ListBox2); //Agrega el ítem
ListBox1.ClearSelection;
end;
procedure TForm1.btnAgregarTodosClick(Sender: TObject);
begin
ListBox2.Items:=ListBox1.Items;
ListBox1.ClearSelection;
end;
procedure TForm1.btnQuitarClick(Sender: TObject);
var
i:Integer;
begin
if ListBox2.SelCount > 0 then //Si hay ítems seleccionados
for i:=ListBox2.Items.Count-1 downto 0 do //Recorre todo el ListBox2
if ListBox2.Selected[i] then //Si el ítem está seleccionado
ListBox2.Items.Delete(i); //Borra el ítem
end;
procedure TForm1.btnQuitarL1Click(Sender: TObject);
begin
ListBox1.ClearSelection;
end;
procedure TForm1.btnQuitarL2Click(Sender: TObject);
begin
ListBox2.ClearSelection;
end;
procedure TForm1.btnQuitarTodosClick(Sender: TObject);
begin
ListBox2.Clear;
end;
procedure TForm1.btnTodoL1Click(Sender: TObject);
begin
ListBox1.SelectAll;
end;
procedure TForm1.btnTodoL2Click(Sender: TObject);
begin
ListBox2.SelectAll;
end;
procedure TForm1.ListBox2DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
btnAgregarClick(Self);
end;
procedure TForm1.ListBox2DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept:=(Source is TListBox);
end;
function TForm1.YaExiste(elemento: String): Boolean;
var
i:Integer;
ret:Boolean;
begin
ret:=False;
for i:=0 to ListBox2.Count-1 do
if elemento=ListBox2.Items.Strings[i] then ret:=True;
YaExiste:=ret;
end;