Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Probleme mit dem ListView (https://www.delphipraxis.net/196502-probleme-mit-dem-listview.html)

MicMic 26. Mai 2018 16:35

Probleme mit dem ListView
 
Hallo,

ich zeichne bei meinem ListView die Einträge selbst (OnCustomDrawItem). Nutze es im "vsList" Modus.
Für meinem Zweck stelle ich mir die Breite für die Einträge entsprechend ein und schalte das HotTracking aus.

SetWindowTheme(Listview.Handle, '', nil);
ListView_SetColumnWidth(Listview.Handle,0,500);

Mit SetWindowTheme schalte ich das HotTracking aus, denn die Eigenschaft "HotTrack" auf "False" zu setzen, hilft nicht. Mit "ListView_SetColumnWidth" stelle ich mir die Breite für den Inhalt ein.
Das Problem ist jedoch, wenn ich in der Laufzeit die Anzeigeneinstellung von Windows 10 ändere (also die Schriftgröße ändere), dass meine ListView das HotTracking wieder anschaltet und die Breite ebenfalls wieder auf Standard (hier wohl AutoSize) gesetzt wird. Also überlegte ich mir, dass ich die "WM_DPICHANGED" abfange und die beiden Befehle einfach wieder ausführe. Aber das geht dort nicht. Die beiden Befehle in einem Button.OnClick auszuführen, funktioniert aber problemlos. Irgendwie scheint "WM_DPICHANGED" zu früh zu sein.

Hat jemand vielleicht eine Idee, wie man die o.g. Befehle so anwendet, dass diese auch immer funktionieren?

Gruß Michael

KodeZwerg 26. Mai 2018 16:50

AW: Probleme mit dem ListView
 
Willkommen in DP!
Hast Du SetProcessDpiAwareness für Deine Applikation aktiviert? Sonst gibt es kein Ereignis.
WM_DPICHANGED schau da mal unter Remarks.

MicMic 26. Mai 2018 18:36

AW: Probleme mit dem ListView
 
Zitat:

Zitat von KodeZwerg (Beitrag 1403063)
Willkommen in DP!
Hast Du SetProcessDpiAwareness für Deine Applikation aktiviert? Sonst gibt es kein Ereignis.
WM_DPICHANGED schau da mal unter Remarks.


WM_DPICHANGED wird empfangen aber habe nichts mit "SetProcessDpiAwareness" gemacht.
Habe einfach "Procedure WMDpiChanged(var Message: TMessage); Message WM_DPICHANGED;" genommen aber ich lese mich mal bezüglich "SetProcessDpiAwareness" durch. Danke für die Info.

Michael

KodeZwerg 26. Mai 2018 19:11

AW: Probleme mit dem ListView
 
Delphi-Quellcode:
type
  TListView = class(Vcl.ComCtrls.TListView)
  protected
    procedure CreateWnd; OVERRIDE;
  end;

procedure TListView.CreateWnd;
begin
  inherited; // <- super wichtig!
  SetWindowTheme(Form/Window-Handle, nil, nil);
// oder direkter
  SetWindowTheme(Form/Window-Handle, 'explorer', '');
end;
So klappt es bei mir. Problem gelöst?

KodeZwerg 26. Mai 2018 19:37

AW: Probleme mit dem ListView
 
Zitat:

Zitat von MicMic (Beitrag 1403062)
SetWindowTheme(Listview.Handle, '', nil);

Es könnte auch sein das es bereits funktionieren würde wenn Du aus Listview.Handle ein Form/Application/Window-Handle machst.
*ungetestet*

MicMic 26. Mai 2018 20:43

AW: Probleme mit dem ListView
 
Das mit dem "CreateWnd" hatte ich mal probiert, aber es hatte nicht funktioniert.
Jetzt geht es aber damit. Versuche die Fehlerquelle gerade herauszubekommen aber es geht jetzt irgendwie immer. Auch die eingestellte Breite passt sich automatisch an, wie gewünscht. Zwar etwas langsam nach einer Änderung der Schriftgröße in den Anzeigeeinstellungen aber besser als wenn es gar nicht geht :) Also mal Danke. Hoffe es bleibt auch so. Listview ist so ein Thema. Auch "LVS_EX_INFOTIP" musste ich abstellen, da manchmal ein ToolTip außerhalb meiner Anwendung (Bildschirmposition X=0,Y=0) angezeigt wurde.

Bei mir schaut es jetzt so aus:
Code:
Type
  TListView = Class(Vcl.ComCtrls.TListView)
    Protected
      Procedure CreateWnd; Override;
  End;

Procedure DisableLVToolTips(H : THandle);
Var Styles : DWord;
Begin
 Styles := ListView_GetExtendedListViewStyle(H);
 Styles := Styles And Not LVS_EX_INFOTIP;
 ListView_SetExtendedListViewStyle(H, Styles);
End;

procedure TListView.CreateWnd;
begin
 Inherited;
 SetWindowTheme(WindowHandle, Nil, Nil);
 ListView_SetColumnWidth(WindowHandle,0,500);
 DisableLVToolTips(WindowHandle);
end;
Gruß Michael

EWeiss 26. Mai 2018 21:23

AW: Probleme mit dem ListView
 
Delphi-Quellcode:
SetWindowTheme(WindowHandle, Nil, Nil);

Delphi-Quellcode:
SetWindowTheme(Listview.Handle, '', nil);

Delphi-Quellcode:
SetWindowTheme(Form/Window-Handle, nil, nil);


sorry das ist definitiv falsch seit ihr hier am raten?

das muss so sein.
Delphi-Quellcode:
SetWindowTheme(WindowHandle, '', '');

ansonsten wird sie für dieses Fenster nicht deaktiviert.
Ist zwar PWideChar aber auf Nil zu casten ist falsch.

Zudem wenn du die Theme nur für das ListView ausschalten willst musst du auch deren Handle nehmen.

EDIT:
Für die ungläubigen. Siehe shots.
Ich möchte meinen ToolTip OwnerDrawn dann muss ich die Theme für den ToolTip deaktivieren.
Aber nicht mit NIL denn das hat keinen Effekt!
Der einfachste weg kompiliere deine Anwendung ohne Manifest! Alles andere ist Spielerei.

gruss

KodeZwerg 27. Mai 2018 00:27

AW: Probleme mit dem ListView
 
Zitat:

Zitat von MicMic (Beitrag 1403070)
Also mal Danke.

Ja gerne.
Zitat:

Zitat von EWeiss (Beitrag 1403071)
seit ihr hier am raten?

Hmmm, da weiß ich gerade keine passende Antwort nur anzumerken das es beim TE und mir mit nil funktioniert, auch mit "" so ist es ja nicht (zumindest bei mir). Wenn ich mir MSDN durchlese gebe ich Dir Recht, NULL solls sein für alles.

himitsu 27. Mai 2018 00:38

AW: Probleme mit dem ListView
 
Zitat:

Probleme mit dem Titel
Man stelle sich mal vor, man könnte im Titel schon erkennen worum es geht.

Mit ListViews haben viel Probleme, da sogar ganz Andere,
und dein Problem haben alle Controls, wo jemand an der VCL vorbei irgendwas macht.


Delphi-Quellcode:
  TWinControl = class(TControl, IWinControl)
  protected
    procedure CreateHandle; virtual;
    procedure CreateParams(var Params: TCreateParams); virtual;
    procedure CreateWindowHandle(const Params: TCreateParams); virtual;
    procedure CreateWnd; virtual;
    //procedure RecreateWnd;
Es gibt da mehrere Ereignisse, wo man sich reinhängen könnte.

KodeZwerg 27. Mai 2018 01:02

AW: Probleme mit dem ListView
 
Ich habe hier noch etwas gefunden, die Quelle weiß ich leider nicht mehr.
Delphi-Quellcode:
unit ThemesApp;

interface


procedure EnableThemesApp;
procedure DisableThemesApp;


implementation

uses
Controls,
Forms,
Messages,
UxTheme,
Sysutils,
Windows;

type
  TJumpOfs = Integer;
  PPointer = ^Pointer;

  PXRedirCode = ^TXRedirCode;
  TXRedirCode = packed record
    Jump: Byte;
    Offset: TJumpOfs;
  end;

  PAbsoluteIndirectJmp = ^TAbsoluteIndirectJmp;
  TAbsoluteIndirectJmp = packed record
    OpCode: Word;
    Addr: PPointer;
  end;

var
 UseThemesBackup: TXRedirCode;

function GetActualAddr(Proc: Pointer): Pointer;
begin
  if Proc <> nil then
  begin
    if (Win32Platform = VER_PLATFORM_WIN32_NT) and (PAbsoluteIndirectJmp(Proc).OpCode = $25FF) then
      Result := PAbsoluteIndirectJmp(Proc).Addr^
    else
      Result := Proc;
  end
  else
    Result := nil;
end;


procedure HookProc(Proc, Dest: Pointer; var BackupCode: TXRedirCode);
var
  n: DWORD;
  Code: TXRedirCode;
begin
  Proc := GetActualAddr(Proc);
  Assert(Proc <> nil);
  if ReadProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n) then
  begin
    Code.Jump := $E9;
    Code.Offset := PAnsiChar(Dest) - PAnsiChar(Proc) - SizeOf(Code);
    WriteProcessMemory(GetCurrentProcess, Proc, @Code, SizeOf(Code), n);
  end;
end;

procedure UnhookProc(Proc: Pointer; var BackupCode: TXRedirCode);
var
  n: Cardinal;
begin
  if (BackupCode.Jump <> 0) and (Proc <> nil) then
  begin
    Proc := GetActualAddr(Proc);
    Assert(Proc <> nil);
    WriteProcessMemory(GetCurrentProcess, Proc, @BackupCode, SizeOf(BackupCode), n);
    BackupCode.Jump := 0;
  end;
end;

function UseThemesH:Boolean;
Var
 Flag : DWORD;
begin
  Flag:=GetThemeAppProperties;
  if ( (@IsAppThemed<>nil) and (@IsThemeActive<>nil) ) then
    Result := IsAppThemed and IsThemeActive and ((Flag and STAP_ALLOW_CONTROLS)<>0)
  else
    Result := False;
end;

procedure HookUseThemes;
begin
  HookProc(@UxTheme.UseThemes, @UseThemesH, UseThemesBackup);
end;

procedure UnHookUseThemes;
begin
  UnhookProc(@UxTheme.UseThemes, UseThemesBackup);
end;


Procedure DisableThemesApp;
begin
  SetThemeAppProperties(0);
  SendMessage(Application.Handle,WM_THEMECHANGED,0,0);
  SendMessage(Application.MainForm.Handle,CM_RECREATEWND,0,0);
end;

Procedure EnableThemesApp;
begin
  SetThemeAppProperties(STAP_ALLOW_NONCLIENT or STAP_ALLOW_CONTROLS or STAP_ALLOW_WEBCONTENT);
  SendMessage(Application.Handle,WM_THEMECHANGED,0,0);
  SendMessage(Application.MainForm.Handle,CM_RECREATEWND,0,0);
end;

initialization
 HookUseThemes;
finalization
 UnHookUseThemes;
end.
Unit einbinden, wo auch immer, wann auch immer EnableThemesApp bzw DisableThemesApp aufrufen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:11 Uhr.
Seite 1 von 2  1 2      

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