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



balromAsked:
Who is Participating?
 
moduloConnect With a Mentor Commented:
Closed, 500 points refunded.

modulo
Community Support Moderator
0
 
TheRealLokiSenior DeveloperCommented:
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;
0
 
balromAuthor Commented:
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?
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
TheRealLokiSenior DeveloperCommented:
it behaves a bit better if you put
        (sender as TListView).Repaint;
at the bottom of the DragOver event

0
 
balromAuthor Commented:
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?
0
 
TheRealLokiSenior DeveloperCommented:
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;
0
 
balromAuthor Commented:
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
0
 
balromAuthor Commented:
this is a bit more complicated?
0
 
TheRealLokiSenior DeveloperCommented:
hmm, can you post your code snippet here so i can test.
0
 
TheRealLokiSenior DeveloperCommented:
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
0
 
balromAuthor Commented:
Are there news?
0
 
balromAuthor Commented:
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
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.