Einzelnen Beitrag anzeigen

snook

Registriert seit: 25. Jun 2010
94 Beiträge
 
Delphi 2005 Professional
 
#1

ListView Drag&Drop mit OwnerDraw wird einfach nichts

  Alt 13. Okt 2011, 18:52
hallo,

ich habe 2 listview's wobei ich per Drag&Drop items von dem einen in den anderen ziehen kann. der empfänger der items hat jetzt ownerdraw := true gesetzt, und desweiteren färbe ich in diesem die spalten. das klappt auch alles, allerdings gibt es ein problem, wenn ich langsam aus den spalten "raus-dragge". Mein erklärung dafür ist ungefähr die folgende, allerdings fällt mir keine lösung mehr ein:

ich halte mir eine referenz auf das listitem, über das ich gerade dragge (FLastDraggedOver)
wenn ich jetzt mit der maus dieses listitem verlasse und in den freien bereich des listview gehe,
wird noch einmal das letzte item neu gezeichnet(InvalidateRect(.., FLastDraggedOver.DisplayRect, ..) ). wenn jetzt noch ein teil des "Drag-Bildes" (wie soll ich es nennen, das teil halt das man als symbol für das gezogene item am mauszeiger sieht) über dem letzten item liegt, dann kommt es zu diesen unschönen effekten im bild. vermutlich wird wohl eine region erstellt wenn dort gemalt wird, und die verhindert wohl, dass mein item dahinter ordentlich dargestellt wird. hat jemand eine idee wie ich das verhondern kann? oder evtl das zeichnen des drag-images abfangen und dann noch korrekturen durchführen?

hier sind noch die dragover und die drawitem des listviews der als empfänger dient:

Delphi-Quellcode:

procedure TFormConnectionMgr.ListViewSlotsDrawItem(Sender: TCustomListView;
  Item: TListItem; Rect: TRect; State: TOwnerDrawState);
var CItem: TConnectionItem;
    i : integer;
    r, g, b: Byte;
    ValidSlot: boolean;
    oldcl : TColor;
    LVItem : TListItem;
    rc: TRect;
    p : TPoint;
begin
  ValidSlot := false;
  ListViewSlots.Canvas.Brush.Color := RGB2TColor(255, 130, 130);
  CItem := FConnectionMgr.ConnectionItems[TSlotItemData(Item.Data).ItemHandle];

  if Assigned(CItem) then
  begin
    i := CItem.IndexOfSlot(PChar(Item.Caption));
    ValidSlot := (i > -1) and (CItem.Slots[i].Locked);
  end;

  if not FDragging then
  begin
    if (odSelected in State) or (odGrayed in State){ or (odFocused in State)} then
    begin
      with ListViewSlots.Canvas.Brush do
        if ValidSlot then
          Color := $00DF00
        else
          Color := clRed;
    end
    else
      if ValidSlot then
        ListViewSlots.Canvas.Brush.Color := RGB2TColor(75, 255, 73);
  end
  else
  begin
    GetCursorPos(p);
    LVItem := ListViewSlots.GetItemAt(2, ListViewSlots.ScreenToClient(p).Y);
    ValidSlot := SenderAcceptsSourceInterface(LVItem, ListViewPublIntf.Selected);
    if (LVItem = Item) then // drawed item is below cursor
    begin
      with ListViewSlots.Canvas.Brush do
        if ValidSlot then
          Color := $00DF00
        else
          Color := clRed
    end
    else // if not below cursor do only highlight if is drag selected
         // and of course if there is an Item under the mouse
      if Assigned(LVItem) and Assigned(Item.Data) and
         TSlotItemData(Item.Data).DragSelected then
        with ListViewSlots.Canvas.Brush do
          if ValidSlot then
            Color := $00DF00
          else
            Color := clRed
      else
      begin
        // if not item below cursor and not item is dragged selected
        // treat it like non-dragging
        if Assigned(CItem) then
        begin
          i := CItem.IndexOfSlot(PChar(Item.Caption));
          if (i > -1) and (CItem.Slots[i].Locked) then
            ListViewSlots.Canvas.Brush.Color := RGB2TColor(75, 255, 73);
        end;

      end;
  end;

  with ListViewSlots.Canvas do
  begin
{    pen.Width := 1;
    if odFocused in State then
    begin
      pen.Color := clBlack;
      pen.Style := psDot;
    end
    else
    begin
      Pen.Color := Color;
      Pen.Style := psSolid;
    end;        }

    FillRect(Rect);

    with Item.DisplayRect(drLabel) do
    begin
      TextOut(Left + 2, Top + max(0, (Bottom - Top - TextHeight(Item.Caption)) div 2), Item.Caption);
      for i := 0 to Item.SubItems.Count - 1 do
        if LongBool(ListView_GetSubItemRect(Item.ListView.Handle, Item.Index,
                                            i + 1, LVIR_BOUNDS, @rc)) then
          with rc do
            TextOut(Left + 2,
                    Top + max(0, (Bottom - Top - TextHeight(Item.SubItems[i])) div 2),
                    Item.SubItems[i]);
    end;
  end;
end;


procedure TFormConnectionMgr.ListViewSlotsDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var LVSource,
    LVSender : TListItem;
    r : TRect;
begin
  Accept := false;
  if Assigned(FLastDraggedOver) then
    r := FLastDraggedOver.DisplayRect(drBounds);

  if not (Source.InheritsFrom(TListView) or (TListItem(Sender).ListView = ListViewPublIntf)) or
     not Sender.InheritsFrom(TListView) then
  begin
    ListViewPublIntf.DragCursor := crNoDrop;
    ListViewSlots.Selected := nil;
    if Assigned(FLastDraggedOver) then
      InvalidateRect(ListViewSLots.Handle, @r, true);
    FLastDraggedOver := nil;
    exit;
  end;

  LVSource := TListView(Source).Selected;
  LVSender := TListView(Sender).GetItemAt(2, Y);
  if not Assigned(LVSender) {or
    (((State = dsDragEnter) or (State = dsDragLeave)) and FDragging) }
 then
  begin
    ListViewPublIntf.DragCursor := crNoDrop;
    ListViewSlots.Selected := nil;
    if Assigned(FLastDraggedOver) then
    begin
      InvalidateRect(ListViewSLots.Handle, @r, true);
      PostMessage(self.Handle, CM_ERASEGHOST, 0, 0);
    end;
    FLastDraggedOver := nil;
    exit;
  end;

  if (FLastDraggedOver <> LVSender) then
  begin
    if Assigned(FLastDraggedOver) then
    begin
      r := FLastDraggedOver.DisplayRect(drBounds);
      InvalidateRect(ListViewSlots.Handle, @r, true);
    end;
    FLastDraggedOver := LVSender;
    r := LVSender.DisplayRect(drBounds);
    InvalidateRect(ListViewSlots.Handle, @r, true);
  end;

  Accept := SenderAcceptsSourceInterface(LVSender, LVSource);

  if Accept then
    ListViewPublIntf.DragCursor := crDefault
  else
    ListViewPublIntf.DragCursor := crNoDrop;
  Invalidate;
end;
viele grüße sebastian
Miniaturansicht angehängter Grafiken
unbenannt.jpg  
  Mit Zitat antworten Zitat