Link to home
Start Free TrialLog in
Avatar of balrom
balrom

asked on

Listview ondragover event problem

It's difficult for me to explain this problem, but i try:

I'm just making a little ftp program that use a listview to display files and directory. I'm using the vsIcon style.

When i drag a file over my ftp listview the item under the mouse pointer became droptarget (i can see this by querying the droptarget property in the listview) and this is ok.
But when the mouse leave an item and move in an empty area of the control, the last overflyed item remain drop target !!
I need that in this situation no droptarget is acquired, also during the drag operation.

Can anyone help me?  

Best regards



Avatar of TheRealLoki
TheRealLoki
Flag of New Zealand image

here's an example i wrote for you
use th eOnDragOver event to see if you are over an item.
If you are, mark it as selected (assuming multiselect false on destination)
if you are not over an item, set selected to nil.
Then oin the Drop event, check the selected property so you know whether to replace or add to the list

procedure TForm1.ListView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
    var
        LI: TListItem;
    begin
        Accept := Source is TListview;

        LI := (Sender as TListView).GetItemAt(X,Y);
        if LI = nil then
        begin
            (Sender as TListView).Selected := nil;
        end
        else
        begin
            LI.Selected := True;
        end;
        caption := format('x = %d, y = %d', [x, y]);
    end;

procedure TForm1.ListView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    begin
        if (Sender is TListView) and (Source is TListView) then
        begin
            with Sender as TListView do
            begin
                if (sender as TListview).Selected = nil then
                  Showmessage('dropped on empty space')
                else
                  showmessage('dropped on item with caption: ' + (sender as TListview).Selected.Caption);
            end;
        end
        else
          showmessage('not dropped');
    end;
Avatar of balrom
balrom

ASKER

Ok, this is a workaround , i have done the same thing with droptarget property of the listview

The problem is that when the mouse leave the items, they are not redrawed correctly (seems to be partial selected).

have you any idea?
it behaves a bit better if you put
        (sender as TListView).Repaint;
at the bottom of the DragOver event

Avatar of balrom

ASKER

Thank you for your help TheRealLoki,
Yes, it look a bit (just a bit) better, but now when the mouse moves over the listview is flickering.

is there a better solution?
with just this code
I'm not getting any problem. I had been seeing bad redraws like you described, until I realised I was developing in a virtual machine, so the display wasn't so clever :)
when I ran the app in my main pc (windows 2000 as opposed to nt4 VM) it redrew fine.
Could this be the same issue for you?

procedure TForm1.ListView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
    var
        LI: TListItem;
    begin
        Accept := Source = Listview2; //is TListview;
        LI := (Sender as TListView).GetItemAt(X,Y);

        if LI = nil then
          (Sender as TListView).Selected := nil;
        else
          LI.Selected := True;
    end;

procedure TForm1.ListView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    begin
        if (Sender is TListView) and (Source is TListView) then
        begin
            with Sender as TListView do
            begin
                if (sender as TListview).Selected = nil then
                  Showmessage('dropped on empty space')
                else
                  showmessage('dropped on item with caption: ' + (sender as TListview).Selected.Caption);
            end;
        end
        else
          showmessage('not dropped');
    end;
Avatar of balrom

ASKER

I'm not using a virtual machine, i'm using a windows 2000 pro machine with delphi 7.0.
The only difference is that i use business skin form component (of almedia dev www.almediadev.com) that are skinned wrappers of delphi base components.

I've done the same thing with the vcl standard lisview component, and have the same problem (bad/partial redraws).

regards
Avatar of balrom

ASKER

this is a bit more complicated?
hmm, can you post your code snippet here so i can test.
a lot of these problems can be acused by the COMCTL32.DLL file.
make sure you have the correct one for your machine, a newer one which resolves issues like this may be available
Avatar of balrom

ASKER

Are there news?
Avatar of balrom

ASKER

Ok, After a lot of work, i've found the solution, adding an else in ComCtrls.TCustomListView.DoDragOver:

procedure TCustomListView.DoDragOver(Source: TDragObject; X, Y: Integer; CanDrop: Boolean);
var
  Item: TListItem;
  Target: TListItem;
begin
  { This is the original code
  Item := GetItemAt(X, Y);
  if Item <> nil then
  begin
    Target := DropTarget;
    if (Item <> Target) or (Item = FLastDropTarget) then
    begin
      FLastDropTarget := nil;
      TDragObject(Source).HideDragImage;
      Update;
      if Target <> nil then
        Target.DropTarget := False;
      Item.DropTarget := CanDrop;
      Update;
      TDragObject(Source).ShowDragImage;
    end;
  end;}

  Item := GetItemAt(X, Y);
  if Item <> nil then
  begin
    Target := DropTarget;
    if (Item <> Target) or (Item = FLastDropTarget) then
    begin
      FLastDropTarget := nil;
      TDragObject(Source).HideDragImage;
      Update;
      if Target <> nil then
        Target.DropTarget := False;
      Item.DropTarget := CanDrop;
      Update;
      TDragObject(Source).ShowDragImage;
    end;
  end
  else // This added by me
  begin
     Target := DropTarget;
     FLastDropTarget := nil;
     TDragObject(Source).HideDragImage;
     if Target <> nil then
       Target.DropTarget := False;
     Update;
     TDragObject(Source).ShowDragImage;
  end;

end;

Regards,
  Bart
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial