![]() |
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 |
AW: Probleme mit dem ListView
Willkommen in DP!
Hast Du ![]() ![]() |
AW: Probleme mit dem ListView
Zitat:
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 |
AW: Probleme mit dem ListView
Delphi-Quellcode:
So klappt es bei mir. Problem gelöst?
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; |
AW: Probleme mit dem ListView
Zitat:
*ungetestet* |
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:
Gruß Michael
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; |
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 |
AW: Probleme mit dem ListView
Zitat:
Zitat:
|
AW: Probleme mit dem ListView
Zitat:
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:
Es gibt da mehrere Ereignisse, wo man sich reinhängen könnte.
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; |
AW: Probleme mit dem ListView
Ich habe hier noch etwas gefunden, die Quelle weiß ich leider nicht mehr.
Delphi-Quellcode:
Unit einbinden, wo auch immer, wann auch immer EnableThemesApp bzw DisableThemesApp aufrufen.
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. |
AW: Probleme mit dem ListView
Zitat:
gruss |
AW: Probleme mit dem ListView
Zitat:
Michael |
AW: Probleme mit dem ListView
Hey Emil, nur mal rein um meine Neugier zu befriedigen, könntest Du mal in Deinem Source eine Sache bitte ausprobieren?
Ersetze mal bitte die "" mit nil und gebe als Handle Dein Window-Handle an, also das vom Programm nicht vom Tooltip. Ist Dein Tooltip dann gefärbt oder Windows-Grau? |
AW: Probleme mit dem ListView
Zitat:
Selber nachbasteln endet idR bei einem langsameren Ergebis. |
AW: Probleme mit dem ListView
Liste der Anhänge anzeigen (Anzahl: 1)
Im Anhang ist ein Beispiel Projekt zu ShellListView geschrieben von Dave Murray.
Ich habs lediglich an Delphi 7 angepasst und ein Kompilat erstellt damit Du weiß worum es sich handelt. Ps: Source liegt auch bei. |
AW: Probleme mit dem ListView
Zitat:
Zitat:
Kein Chance ;) Ich will den TollTip deaktivieren nicht die komplette Anwendung. Aber ist erledigt das Thema für mich. Macht was ihr für richtig haltet. gruss |
AW: Probleme mit dem ListView
Zitat:
|
AW: Probleme mit dem ListView
Zitat:
Zwar ein kleines Problem mit dem Fokusrahmen aber hier kann man tricksen. Eine Möglichkeit die Komponente zu überschreiben, damit der Rahmen erst gar nicht gezeichnet wird, habe ich nicht gefunden. Mit "DrawFocusRect" kann man wenigstens was machen. Aber "ShellListView" kommt mal auf mein Notiz-Zettel. Vielen Dank Michael |
AW: Probleme mit dem ListView
Hallo Michael, ja tobe Dich mal mit der ListBox aus. FindFirst, FindNext und FindClose ist ein sehr sehr langsames Mittel.
Ich bin gespannt wie dein Resultat endet. Nach wie vor kannst Du Dir ja mal das ShellTreeView Demo von weiter oben anschauen und feststellen das es im Vergleich zum manuellen durchforsten eines Verzeichnisses ein gewaltiges plus an Geschwindigkeit gibt. Zur Demonstration als Vergleich empfehle ich das Windows/System32 Verzeichnis laden zu lassen. Hier hab ich ein Quelltext-Schnippsel von ![]()
Delphi-Quellcode:
Eine weitaus schnellere ListBox Methode wäre es so zu machen
var
Form1: TForm1; FilePath: TStringList; implementation {$R *.dfm} procedure FindFiles(FilesList: TStrings; FilesPath: TStrings; StartDir, FileMask: string); var SR: TSearchRec; DirList: TStringList; IsFound: Boolean; i: integer; begin if StartDir[length(StartDir)] <> '\' then StartDir := StartDir + '\'; IsFound := FindFirst(StartDir + FileMask, faAnyFile - faDirectory, SR) = 0; while IsFound do begin FilesPath.Add(StartDir + SR.Name); FilesList.Add(SR.Name); IsFound := FindNext(SR) = 0; end; FindClose(SR); DirList := TStringList.Create; IsFound := FindFirst(StartDir + '*.*', faAnyFile, SR) = 0; while IsFound do begin if ((SR.Attr and faDirectory) <> 0) and (SR.Name[1] <> '.') then DirList.Add(StartDir + SR.Name); IsFound := FindNext(SR) = 0; end; FindClose(SR); for i := 0 to DirList.Count - 1 do FindFiles(FilesList, FilePath, DirList[i], FileMask); DirList.Free; end; procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin FilePath.Free; end; procedure TForm1.sButton1Click(Sender: TObject); begin FilePath := TStringList.Create; FindFiles(sListBox1.Items, FilePath, EditStartDir.Text, '*.*'); {FilePath is where full file path saved, EditStartDir is where to search} end; procedure TForm1.sListBox1Click(Sender: TObject); begin If sListBox1.ItemIndex > -1 then sEdit2.Text := FilePath.Strings[sListBox1.ItemIndex]; end; end.
Delphi-Quellcode:
Viel Spass beim experimentieren!
var s: string;
begin s := 'c:\windows\*.*'#0; ListBox1.Perform(LB_DIR, DDL_READWRITE, LongInt(@s[1])); end; |
AW: Probleme mit dem ListView
Also mit der ListBox schaut es gut aus und ja, das "System32" Verzeichnis nehme ich auch immer. :)
Das ShellListView Demo habe ich mir angeschaut aber es ist recht vollgepackt. So viel schneller ist es auch nicht. Derzeit ist meines schneller aber ich bin ja auch noch nicht ganz fertig. Das mit FindFirst/FindNext geht bei mir auch etwas anders. Ich lade das Verzeichnis mit weiteren Infos in ein Record rein. In der Listbox hole ich mir dann im DrawItem Abschnitt die Infos, die ich benötige. Habe mich auch mal mit einem TThread probiert, um Icons im Hintergrund nachzuladen. Wäre das der richtige Weg? Das klappte aber noch nicht so ganz. Jetzt räume ich erst mal wieder das Listing auf. Das mache ich immer so. Erst ein wenig programmieren und wenn was geht, dann wird im Listing aufgeräumt, formatiert und kommentiert. Sonst verliert man den Durchblick :) Aber der Total-Commander ist schon recht schnell. Eine Meisterarbeit :) Michael |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:27 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz