Einzelnen Beitrag anzeigen

eholzer

Registriert seit: 22. Okt 2009
51 Beiträge
 
#1

TListView - Problem mit HotTrack und Selektion bei Verwendung AdvancedCustomDrawItem

  Alt 27. Jan 2013, 19:44
Hallo,

ich habe ein Problem (eigentlich sind zwei) mit der ListView, wenn ich AdvancedCustomDrawItem verwende.
Wichtig: die Theme ist abgeschaltet with SetWindowTheme(Handle, 'explorer', '').

Problem 1:
In der ListView sollte HotTrack aktiv sein - in meiner ListView der HotTrack erscheint kurz und dann verschwindet. Wenn man kein AdvancedCustomDrawItem verwendet, dann der HotTrack ist die ganze Zeit sichtbar (wenn der Mauszeiger über dem Text ist).

Problem2:
Ich möchte gerne, dass die Selektion mit der Maus erfolgt in dem ganzen Spaltenbereich. Die ListView reagiert aber auf Mausklicks genauso, wie ohne AdvancedCustomDrawItem. ListView erlaubt den Selektionsbereich abzufragen Item.DisplayRect( drSelectBounds ), gibt es vielleicht die Möglichkeit den Selektionsbereich festzusetzen? Wenn nicht, wie kann man trotzdem so was erreichen?

Danke
Eric

Delphi XE2 on Win7/Win8

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.ComCtrls, Vcl.Themes, UxTheme;

type TmyListView = class(TListView)

      private
         procedure DrawShortedCaption(Sender: TCustomListView;
                        Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
                        var DefaultDraw: Boolean);
      protected
        Procedure CreateWnd; Override;
        procedure InternalAdvancedCustomDrawItem(Sender: TCustomListView;
                        Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
                        var DefaultDraw: Boolean);
      public
        constructor Create(AOwner: TComponent);override;
        destructor Destroy; override;
end;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }

    FListView: TmyListView;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
var col: TListColumn;
    litem: TListItem;
    i,j: integer;
    s: string;
    c: word;
begin
   FListView := TmyListView.Create(Self);
   FListView.Parent := Panel1;

   col := FListView.Columns.Add;
   col.Caption := 'COL1';
   col.Width := 200;
   col := FListView.Columns.Add;
   col.Caption := 'COL2';
   col := FListView.Columns.Add;
   col.Caption := 'COL3';
   col.Width := 250;

   FListView.ViewStyle := vsReport;

   for i := 0 to 100 do
   begin
     litem := FListView.Items.Add;
     s := '';
     for j := 0 to Random(25) do
     begin
        c := Random(Succ(90 - 65)) + 65;
        s := s + Chr(c);
     end;
     litem.Caption := s;
     litem.SubItems.Add('A'+IntToStr(i+1)+ '_1');
     litem.SubItems.Add('A'+IntToStr(i+1)+ '_2');
   end;
end;



//=========================== TmyListView ========================
Constructor TmyListView.Create(AOwner:TComponent);

begin
  inherited Create(AOwner);

  OnAdvancedCustomDrawItem := InternalAdvancedCustomDrawItem;
  Align := alClient;
  MultiSelect := true;
  RowSelect := false;
  DoubleBuffered := true;
  HoverTime := 0;
  HotTrack := false;
  HotTrackStyles := [htHandPoint, htUnderlineHot];


end;

procedure TmyListView.CreateWnd;
begin

  inherited CreateWnd;
  SetWindowTheme(Handle, 'explorer', '');

end;

destructor TmyListView.Destroy;
begin


  inherited Destroy;
end;

procedure TmyListView.InternalAdvancedCustomDrawItem(Sender: TCustomListView;
                        Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
                        var DefaultDraw: Boolean);
begin
  if not Assigned(Item) then exit;
  Case Stage of
      cdPrePaint:
        begin

        end;

      cdPostPaint:
        begin
          DrawShortedCaption(Sender, Item, State, Stage, DefaultDraw );
        end;
  End;
end;

procedure TmyListView.DrawShortedCaption(Sender: TCustomListView;
                        Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
                        var DefaultDraw: Boolean);
var R: TRect;
    labelRect: TRect;
    focusBorderRect: TRect;
    displayName: string;
    lblWidth: integer;

    procedure DefineCanvasColors(ACanvas: TCanvas;Item: TListItem; State: TCustomDrawState);
    begin
       if Item.Selected then begin
            if Item.Focused then
                ACanvas.Brush.Color := clGray
            else
                ACanvas.Brush.Color := clLtGray;
            ACanvas.Font.Color := ColorToRGB(clWindowText);
            if cdsHot in State then
               ACanvas.Font.Color := ColorToRGB(clGreen);
      end
      else if Item.Focused then begin
            ACanvas.Brush.Color := ColorToRGB(clMaroon);
            ACanvas.Font.Color := ColorToRGB(clWhite);
      end
      else if cdsHot in State then begin
            ACanvas.Brush.Color := ColorToRGB(clHotLight);
            ACanvas.Font.Color := ColorToRGB(clHighlightText);
      end
    end;

    procedure DrawBox( Canvas: TCanvas; Bounds: TRect; Color: TColor );
    begin
      Canvas.Pen.Color := Color;

      Canvas.MoveTo( Bounds.Left, Bounds.Top );
      Canvas.LineTo( Bounds.Left, Bounds.Bottom );

      Canvas.MoveTo( Bounds.Left, Bounds.Top );
      Canvas.LineTo( Bounds.Right, Bounds.Top );

      Canvas.MoveTo( Bounds.Right - 1, Bounds.Top );
      Canvas.LineTo( Bounds.Right - 1, Bounds.Bottom );

      Canvas.MoveTo( Bounds.Left, Bounds.Bottom - 1 );
      Canvas.LineTo( Bounds.Right, Bounds.Bottom - 1 );
    end;

begin
   Sender.Canvas.Lock;
   try
     R := Item.DisplayRect( drLabel );

     DefineCanvasColors(Sender.Canvas, Item, State);

     displayName := Item.Caption;
     focusBorderRect := R;
     Sender.Canvas.FillRect(R);

     labelRect := R;
     labelRect.Left := labelRect.Left +2;

     DrawText(Sender.Canvas.Handle, displayName, Length(displayName),labelRect,
                DT_END_ELLIPSIS or DT_SINGLELINE or DT_NOPREFIX or DT_VCENTER);

     if Item.Focused then
         DrawBox(Sender.Canvas, focusBorderRect, ColorToRGB(clBlack))
     else if Item.Selected then
         DrawBox(Sender.Canvas, focusBorderRect, ColorToRGB(clPurple));

     //SetBkMode(Sender.Canvas.Handle, TRANSPARENT); // important if theme active
     DefaultDraw := false;

    finally
       Canvas.Unlock;
    end;

end;



end.
  Mit Zitat antworten Zitat