Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi TListView - Problem mit HotTrack und Selektion bei Verwendung AdvancedCustomDrawItem (https://www.delphipraxis.net/172889-tlistview-problem-mit-hottrack-und-selektion-bei-verwendung-advancedcustomdrawitem.html)

eholzer 27. Jan 2013 18:44

TListView - Problem mit HotTrack und Selektion bei Verwendung AdvancedCustomDrawItem
 
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.

eholzer 29. Jan 2013 08:44

AW: TListView - Problem mit HotTrack und Selektion bei Verwendung AdvancedCustomDrawI
 
Hi,

keine Ideen, wie man richtig HotTrack selber zeichnet?
Mich würde auch eine Info freuen, wie man den HotTrack bei der aktiven Theme richtig steuern kann (aktivieren, deaktiviren).

Danke
Eric

Volker Z. 29. Jan 2013 14:28

AW: TListView - Problem mit HotTrack und Selektion bei Verwendung AdvancedCustomDrawI
 
Hallo,

Zitat:

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).
Füge doch mal folgendes vor dem Canvas.Lock in Deine Methode DrawShortedCaption ein:
Delphi-Quellcode:
  if cdsHot in State then
    Exit;
 
  Sender.Canvas.Lock;
Zitat:

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?
Mir ist im Moment keine Möglichkeit geläufig, die Spaltenbreite auf eine fixe Breite trimmt. Du kannst aber mal versuchen, ob folgender Code Dein Problem lösen würde.
Delphi-Quellcode:
  TmyListView = class(TListView)
    private
      procedure MouseMove (Shift: TShiftState; X, Y: Integer); override;

procedure TmyListView.MouseMove (Shift: TShiftState; X: Integer; Y: Integer);
var
  i : TListItem;
begin
  inherited MouseMove (Shift, X, Y);

  if X < Columns [0].Width then
    begin
      i := GetItemAt (4, Y); // das mit der 4 ist nicht schön, vielleicht Intervall-Halbierung
      if Assigned (i) then
        SendMessage (Handle, LVM_SETHOTITEM, i.Index, 0)
    end
end;
Gruß

eholzer 1. Feb 2013 13:31

AW: TListView - Problem mit HotTrack und Selektion bei Verwendung AdvancedCustomDrawI
 
Danke Volker für die Antwort.

Wenn jemand an der Lösung für HotTrack interessiert ist: https://forums.embarcadero.com/threa...82449&tstart=0.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz