Newsgroup: it.comp.lang.delphi
Titolo: Aiuto su TListView

Vorrei poter spostare le righe in una TListView usando il mouse, qualcuno ha
qualche suggerimento?
Massimiliano Etere
maxe...@infinito.it

Ciao, ti propongo una soluzione un po' empirica... spero che gli altri del
NG nn me ne vogliano :)
Apri il file ComCtrls.pas (nella cartella
C:\programmi\borland\delphi5\source\vcl) e sposta il metodo SetItem da
privato a pubblico: 
  TListItems = class(TPersistent)
  private
    FOwner: TCustomListView;
    FUpdateCount: Integer;
    FNoRedraw: Boolean;
    procedure ReadData(Stream: TStream);
    procedure WriteData(Stream: TStream);
  protected
    procedure DefineProperties(Filer: TFiler); override;
    function CreateItem(Index: Integer; ListItem: TListItem): TLVItem;
    function GetCount: Integer;
    function GetHandle: HWND;
    function GetItem(Index: Integer): TListItem;
    procedure SetCount(Value: Integer);
    procedure SetUpdateState(Updating: Boolean);
  public
    constructor Create(AOwner: TCustomListView);
    destructor Destroy; override;
    function Add: TListItem;
    procedure Assign(Source: TPersistent); override;
    procedure BeginUpdate;
    procedure Clear;
    procedure Delete(Index: Integer);
    procedure EndUpdate;
    function IndexOf(Value: TListItem): Integer;
    function Insert(Index: Integer): TListItem;
    property Count: Integer read GetCount write SetCount;
    property Handle: HWND read GetHandle;
			GUARDA SOLO QUI IL RESTO E' TUTTO UGUALE!!!! :)
    /////////////////////////////////////////////////////////////////// 
    procedure SetItem(Index: Integer; Value: TListItem);  <-- questo prima
era privato
    ///////////////////////////////////////////////////////////////////	
    property Item[Index: Integer]: TListItem read GetItem write SetItem;
default;
    property Owner: TCustomListView read FOwner;
  end;
Ricordati di posizionarlo PRIMA della property Item[Index: Integer] se no
fa casini.
Ok, il primo step è fatto.
adesso salva il file modificato (se nn ti fidi fatti prima una copia del
vecchio ;)  e  apri un nuovo progetto, quindi appiccica una bella ListView
sulla form.
Ecco il sorgente della form:
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls;
type
  TForm1 = class(TForm)
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
    procedure ListView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure ListView1DragDrop(Sender, Source: TObject; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
var
  anItem: TListItem;  //Usata per creare dinamicamente un item
begin
  //Setto le proprietà che mi interessano
  //Drag automatico
  ListView1.DragMode := dmAutomatic;
  //Niente multiselezione!
  ListView1.MultiSelect := false;
  //Seleziona per righe
  ListView1.RowSelect := true;
  //e fammi vedere tutto come un report!
  ListView1.ViewStyle := vsReport;
  //Aggiungo un po' di item...
  anItem := ListView1.Items.add;
  anItem.Caption := 'PrimaRiga';
  anItem := ListView1.Items.add;
  anItem.Caption := 'SecondaRiga';
  anItem := ListView1.Items.add;
  anItem.Caption := 'TerzaRiga';
  anItem := ListView1.Items.add;
  anItem.Caption := 'QuartaRiga';
  anItem := ListView1.Items.add;
  anItem.Caption := 'QuintaRiga';
  anItem := ListView1.Items.add;
  anItem.Caption := 'SestaRiga';
  //...ok puo' bastare! :)
end;
{
  L'evento di DragOver si verifica quando trascini un oggetto
  Il parametro Source è l'oggetto che stai trascinando
  x, y sono le coordinate sulle quali ti trovi
  Accept è un parametro che indica se l'oggetto di destinazione accetta o -
l'oggetto che stai trascinando
}
procedure TForm1.ListView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  //Accettiamo solo se il sorgente è una ListView
  accept := (Source.ClassName = 'TListView');
end;
{
  L'evento di DragDrop si verifica quando rilasci l'oggetto che stavi
trascinando.
  Il parametro Source è l'oggetto che stai trascinand
  x, y sono le coordinate sulle quali ti trovi
  Se l'oggetto che tentiamo di rilasciare sulla ListView deriva anch'esso
dalla listview
  (cioè è un suo item) e ci troviamo con il mouse sopra un item della
listview
  allora eseguiamo uno "scambio" tra l'item selezionato (che è quello che
stiamo trascinando)
  e quello che si trova sotto il puntatore del mouse
}
procedure TForm1.ListView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  anItem: TListItem;  //Usato per lo scambio come variabile d'appoggio
begin
  //Se proveniamo da una ListView
  if (Source.ClassName = 'TListView') then
    Begin
      with Source as TListView do
        Begin
          //Se sotto il mouse si trova un item della listview
          if (htOnLabel in GetHitTestInfoAt(x, y)) then
            Begin
              //creo un item temporaneo
              anItem := TListItem.Create(ListView1.Items);
              //gli assegno l'item che si trova sotto il mouse
              anItem.assign(TListView(Source).GetItemAt(x, y));
              //al posto dell'item puntato dal mouse ci metto quello che
stavo trascinando
              //nota che utilizziamo il metodo SetItem che abbiamo appena
trasformato in pubblico!! :O
 
TListView(Source).Items.SetItem(TListView(Source).GetItemAt(x, y).Index,
TListView(Source).ItemFocused);
              //e assegno all'item che stavo trascinando (e che ho
rilasciato)
              //l'item che avevo memorizzato temporaneamente
              //(e che guardacaso è quello che stato "sostituito"
              TListView(Source).ItemFocused.Assign(anItem);
            End;  //if (htOnLabel in GetHitTestInfoAt(x, y)) then
        End;  //with Source as TListView do
    End;  //if (Source.ClassName = 'TListView') then
end;
end.
Da me funziona, giuro... l'ho scritto un po' di fretta qiundi nn badare
al'itagggliano usato nei commenti xche' in effetti fa abb schifo...
Se hai bisogno altri chiarimenti posta pure :)
Ciao & in bocca al lupo! 
Leonardo Foderaro
ps: mi sa che dopo le caxxate di questa risposta gli altri del NG mi
"nomineranno" ...  sigh!

 NG nn me ne vogliano :)
Miii!!! Questo si può fare nell'edizione enterprise... ma io che ho la
standard? ;)
Massimiliano Etere
maxe...@infinito.it

Guarda... io delphi lo uso solo da 5-6 mesi quindi nn ti so dire... xo'
prova a guardare se hai un filez che si chiama ComCtrls.dcu che forse C'HO
un'idea :)
fammi sapere in fretta! :)