Einzelnen Beitrag anzeigen

EWeiss
(Gast)

n/a Beiträge
 
#9

AW: FileOpenDialog Ownerdraw

  Alt 19. Mai 2017, 03:14
Habe jetzt ein funktionierte Lösung erarbeitet um den Hintergrund des SysListView32 Farbig zu gestalten.

1. Subclass und UnSubclass erstellen.
Delphi-Quellcode:
procedure SysListSubClass(WinHandle: HWND);
begin

  FSysListInstance := MakeObjectInstance(OpenDialog.SysListSubClassProc);

  FPrevSysListProc := Pointer(GetWindowLong(WinHandle, GWL_WNDPROC));
  SetWindowLong(WinHandle, GWL_WNDPROC, Integer(FSysListInstance));
end;

procedure SysListUnSubClass(WinHandle: HWND);
begin

  SetWindowLong(WinHandle, GWL_WNDPROC, Integer(FPrevSysListProc));
  FreeObjectInstance(FSysListInstance);
end;
2. Die Winproc dafür
Delphi-Quellcode:
function SysListProc(WinHandle: HWND; Msg: UINT; wp: WPARAM; lp: LPARAM): longint; stdcall;
begin

   Result := 0;
   case Msg of

    WM_ERASEBKGND:
      begin
        UpdateColors(WinHandle); // Das ist der Trick
        ListView_SetSelectedColumn(WinHandle, -1); // und das!
        Result := 1;
        Exit;
      end;

    WM_DESTROY:
      begin
        SysListUnSubClass(WinHandle);
        Result := 1;
        Exit;
      end;
   end;
   if (Result = 0) then
    Result := CallWindowProc(FPrevSysListProc, WinHandle, Msg, wp, lp);
end;
3. Die Farben zuweisen.
Delphi-Quellcode:
procedure UpdateColors(Handle: HWND);
var
  Color1, Color2: COLORREF;
begin
  SkinEngine.SplitColorARGB(SkinEngine.SK_INACTIVECAPTION, Alpha, Red, Green, Blue);
  Color1 := RGB(Red, Green, Blue);

  SkinEngine.SplitColorARGB(SkinEngine.SK_ACTIVECAPTION, Alpha, Red, Green, Blue);
  Color2 := RGB(Red, Green, Blue);

  ListView_SetBkColor(Handle, Color1);
  ListView_SetTextBkColor(Handle, Color1);
  ListView_SetTextColor(Handle, Color2);
end;
Die Weiterleitung der Messagen
Delphi-Quellcode:
procedure TOpenDialog.SysListSubClassProc(var Message: TMessage);
begin

  with Message do
  begin
    case Msg of
      WM_DESTROY:
        Result := SysListProc(hSysList, Integer(Msg), Message.WPARAM, Message.LPARAM);
      WM_ERASEBKGND:
        Result := SysListProc(hSysList, Integer(Msg), Message.WPARAM, Message.LPARAM);
    end;
    if (Result = 0) then
      Result := CallWindowProc(FPrevSysListProc, hSysList, Msg, WPARAM, LPARAM)
  end;

end;
Das ganze läuft so ab.
Wenn ein Folder geändert wird zerstört sich das Windows selbst.
In dem Fall wird dann WM_DESTROY aufgerufen was zur folge hat das die SubClass entladen wird über UnSubclass.

Damit die Farben aber erhalten bleiben muss man logischerweise die SubClass neu generieren.
Das geht so.

Delphi-Quellcode:
    WM_NOTIFY:
      begin
        case (POFNotify(lp)^.hdr.code) of
          CDN_FOLDERCHANGE:
            begin
              // Handles zurücksetzen
              hSysList := 0;
              hDefview := 0;
              // Handles neu einlesen
              hDefview := FindWindowEx(DlgHandle, 0, 'SHELLDLL_Defview', nil);
              hSysList := FindWindowEx(hDefview, 0, 'SysListView32', nil);
              // Neue SubClass erstellen
              if hSysList <> 0 then
                SysListSubClass(hSysList);
            end;
        end;
      end;
Das Ergebnis sieht dann so aus.
Die Header mache ich demnächst noch..
Der Dialog kann auch ohne Skins gestartet werden siehe das OverTheTaskBar Projekt.

gruss

Geändert von EWeiss (11. Jul 2019 um 15:47 Uhr)
  Mit Zitat antworten Zitat