AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

ListView Header Farbe (Win32)

Ein Thema von EWeiss · begonnen am 17. Jan 2017 · letzter Beitrag vom 8. Okt 2017
Antwort Antwort
EWeiss
(Gast)

n/a Beiträge
 
#1

ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 07:55
Wie kann ich die Hintergrundfarbe des ListView Headers ändern?
Nicht die der Columns sondern den Hintergrund davon.

Am besten wäre Transparent .. ka ob das geht.
Wenn ich an den Bereich herankäme könnte ich den Hintergrund des ListViews dort hinein kopieren um einen
Transparenten Effekt zu emulieren.

gruss

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

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 10:38
Du brauchst also nur das Handle davon?
Vielleicht reicht es aus, wenn du WM_PARENTNOTIFY abgreifst und dir wie unten gezeigt das Headerhandle holst?!

Delphi-Quellcode:
  TWMParentNotify = record
    Msg: Cardinal;
    MsgFiller: TDWordFiller;
    case Word of
      WM_CREATE, WM_DESTROY: (
        Unused1: Word;
        ChildID: Word;
        EventChildIDFiller: TDWordFiller;
        ChildWnd: HWnd);
      WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN: (
        Unused2: Word;
        Value: Word;
        EventValueFiller: TDWordFiller;
        XPos: Smallint;
        YPos: Smallint;
        XYPosFiller: TDWordFiller);
      0: (
        Event: Word;
        Value1: Word;
        EventValue1Filler: TDWordFiller;
        Value2: LPARAM;
        Result: LRESULT);
  end;

...

procedure WMParentNotify(var Message: TWMParentNotify); message WM_PARENTNOTIFY;

...

procedure TCustomListView.WMParentNotify(var Message: TWMParentNotify);
begin
  with Message do
    if (Event = WM_CREATE) and (FHeaderHandle = 0) then
    begin
      FHeaderHandle := ChildWnd;
      FDefHeaderProc := TWindowProcPtr(GetWindowLong(FHeaderHandle, GWL_WNDPROC));
{$IFDEF CLR}
      SetWindowLong(FHeaderHandle, GWL_WNDPROC, FLVInstances.FHeaderInstance);
{$ELSE}
      SetWindowLong(FHeaderHandle, GWL_WNDPROC, Winapi.Windows.LPARAM(FHeaderInstance));
{$ENDIF}
    end;
  inherited;
end;
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 10:53
Zitat:
TCustomListView
Win32

Danke. Nein das Handle kann man einfacher erfahren eine Zeile Code.
  HeaderHandle := ListView_GetHeader(WinHandle);

btw. komplett.
Delphi-Quellcode:
procedure TSkinListView.SubClass(WinHandle: hWnd);
begin

  FClientInstance := MakeObjectInstance(ClientWndProc);

  FPrevClientProc := Pointer(GetWindowLong(WinHandle, GWL_WNDPROC));
  SetWindowLong(WinHandle, GWL_WNDPROC, Integer(FClientInstance));

  FHeaderInstance := MakeObjectInstance(HeaderClientWndProc);
  HeaderHandle := ListView_GetHeader(WinHandle);
  FPrevHeaderProc := Pointer(GetWindowLong(HeaderHandle , GWL_WNDPROC));
  SetWindowLong(HeaderHandle , GWLP_WNDPROC, Integer(FHeaderInstance));
end;
Ich habe Columns auf der ListView ich benötige den Hintergrund von allen Columns. (Scheint irgendein Frame zu sein.
Der schwarze Bereich wie gezeigt.

Nebenbei:
Ein Qual ein ListView selbst zu zeichnen. (Na was soll's hab sonst nix zu tun).
Muss ich wohl irgendwie selbst lösen.

gruss

Geändert von EWeiss (17. Jan 2017 um 12:29 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 13:08
Zitat:
TCustomListView
Win32

Danke. Nein das Handle kann man einfacher erfahren eine Zeile Code.
  HeaderHandle := ListView_GetHeader(WinHandle);
Ja nun, es geht ja um die prinzipielle Vorgehensweise, wie man das Handle holen kann.
Die TCustomListView ist ja auch nichts weiter als ein Objekt-orientierter Wrapper um die entsprechenden Windowsfunktion-/SendMessage-Aufrufe. Was anderes bastelst du ja auch nicht.

Bei mir kommt nur 0 zurück, wenn man das Handle der ListView in ListView_GetHeader übergibt.
Das funktioniert bei dir?

Ich habe Columns auf der ListView ich benötige den Hintergrund von allen Columns. (Scheint irgendein Frame zu sein.
Der schwarze Bereich wie gezeigt.
Prinzipiell geht das von dir gewünschte, hast du eine Delphiversion höher als XE2? Dann könntest du dir mal in den ComCtrls.TListViewStyleHook anschauen. Mit aktivierten VCL-Styles werden auch die Columns mitgeskinnt und es wird über diese Hook-Klasse gezeichnet.

Wie zeichnest du denn die Column-Header links vom schwarzen Bereich im von dir angehängten Bild?
Da wo Time steht. Hier hast du doch schon den Hintergrund selbst gezeichnet, oder?
Warum wendest du diese Vorgehensweise nicht auch auf den Column-Header daneben an?

Geändert von TiGü (17. Jan 2017 um 13:10 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 17:16
Zitat:
Bei mir kommt nur 0 zurück, wenn man das Handle der ListView in ListView_GetHeader übergibt.
Das funktioniert bei dir?
Ja das funktioniert so wie gezeigt weil das ListView gesubclassed ist.

Delphi-Quellcode:
function TSkinListView.CreateWindow(ParentHandle: hWnd): hWnd;
begin

  InitCommonControlsEx(iccex);

  if Visible then
  begin
    LStyle := WS_CHILD or LVS_REPORT or WS_CLIPCHILDREN or WS_CLIPSIBLINGS
      or LVS_SHOWSELALWAYS or LVS_SHAREIMAGELISTS or LVS_OWNERDRAWFIXED or WS_VISIBLE;
  end
  else
    LStyle := WS_CHILD or LVS_REPORT or WS_CLIPCHILDREN or WS_CLIPSIBLINGS
      or LVS_SHOWSELALWAYS or LVS_SHAREIMAGELISTS or LVS_OWNERDRAWFIXED;

  FHListView := CreateWindowEx(WS_EX_TRANSPARENT, WC_LISTVIEW, nil, LStyle,
    Left, Top, Width, Height, ParentHandle, DlgItemID, hInstance, nil);

  if FHListView <> 0 then
  begin
    SubClass(Handle);

    ImgBack := SkinEngine.skCreateImageFromFile(SelectedImg);
   
    if not assigned(PropList) then
      PropList := TStringList.Create;

    SetProperty(Handle, PROP_IMAGE_SELECTED, ImgBack);
    ShowWindow(Handle, Integer(Visible));

    ListView_SetExtendedListViewStyle(Handle, LVS_EX_FULLROWSELECT);

    HookedScrollbar(ParentHandle);
  end;

  Result := FHListView;
end;
Zitat:
Warum wendest du diese Vorgehensweise nicht auch auf den Column-Header daneben an?
Weil es keinen Column Header daneben gibt.
Dieser erstreckt sich über den gesamten Bereich der ListView hinter den eigentlichen Columns.

Zeichnen tue ich ihn so.
Headerproc..

Delphi-Quellcode:
function TSkinListView.ListViewHeaderProc(WinHandle: hWnd; Msg: UINT; wP: WParam; lP: LParam)
  : LRESULT;
var
  ps: TPaintstruct;
  rc, rcHeader: TRect;
  Dc: Hdc;
  ItemCount: Integer;
  IntI: Integer;
begin

  case Msg of
    WM_ERASEBKGND:
      begin
        Result := 1;
        exit;
      end;

    WM_LBUTTONDBLCLK:
      begin
        SkinEngine.FInvalidateRect(WinHandle, True);
      end;

    WM_PAINT:
      begin
        GetClientRect(WinHandle, rc);

        Dc := BeginPaint(WinHandle, ps);

        if not SkinEngine.Composited(WinHandle) then
          Dc := SkinEngine.DoubleBuffer(ps.Hdc, rc.Right, rc.bottom, CreateBuffer);

        ItemCount := Header_GetItemCount(WinHandle);
        for IntI := 0 to ItemCount do
        begin
          Header_GetItemRect(WinHandle, IntI, @rcHeader);

          DrawHeaderItem(WinHandle, DC, IntI, rcHeader, True);
        end;

        if not SkinEngine.Composited(WinHandle) then
          SkinEngine.DoubleBuffer(0, 0, 0, DestroyBuffer)
        else
          ReleaseDC(WinHandle, Dc);

        EndPaint(WinHandle, ps);
        Result := 0;
        exit;
      end;

  end;
  Result := CallWindowProc(FPrevHeaderProc, WinHandle, Msg, wP, lP);
end;
DrawHeaderItem
Delphi-Quellcode:
procedure TSkinListView.DrawHeaderItem(WinHandle: hWnd; Dc: Hdc; Index: Integer; Rect: TRect;
  Selected: Bool);
var
  Text: PWideChar;
  buf: array [0 .. 255] of Char;
  Item: THDItem;
  rcHeader: TRect;
  Img: Cardinal;
  Graphics: Cardinal;
  rc: TRect;
begin
  Item.mask := HDI_TEXT or HDI_FORMAT or HDI_WIDTH;
  Item.pszText := buf;
  Item.fmt := HDF_LEFT and HDF_OWNERDRAW and HDF_STRING;
  Item.cchTextMax := sizeof(buf);

  Header_GetItemRect(WinHandle, Index, @rcHeader);

  ZeroMemory(@buf, sizeof(buf));
  Header_GetItem(WinHandle, Index, Item);
  Text := buf;

  SetBkMode(Dc, TRANSPARENT);

  if GetShadow then
  begin
    if IsWindowEnabled(WinHandle) then
      Color := GetShadowColor
    else
    Color := RGB(255, 255, 255);

    Rect.Top := ((rcHeader.Bottom - FPointSize) div 2) div 2 + 1;
    DrawTextToDC(DC, Text, Rect, Color, FFontName, FPointSize, FFontStyle, 0, 0);

    if IsWindowEnabled(WinHandle) then
    begin
      if Selected then
        Color := AktForecolor
      else
      Color := InAktForecolor;
    end
    else
    Color := RGB(140, 140, 140);

    DrawTextToDC(DC, Text, Rect, Color, FFontName, FPointSize, FFontStyle,
      FShadowOffset, 0);

    if GdipCreateFromHDC(DC, Graphics) = OK then
    begin
      Img := Cardinal(GetProperty(Handle, PROP_IMAGE_SELECTED));
      GetClientRect(WinHandle, rc);
      // Hintergrund der Columns (Zeichne ich hier die Farbe anstelle des Button dann werden die Columns übermalt.)
      // bsp. FillRect.. bla. bla.
      SkinEngine.PaintButton(Graphics, 4, Img, rc.Left, rc.Top, rc.Right, rc.bottom, BS_PUSHBUTTON);
      // Columns
      SkinEngine.PaintButton(Graphics, 4, Img, rcHeader.Left, rcHeader.Top, rcHeader.Right - rcHeader.Left,
        rcHeader.bottom, BS_PUSHBUTTON);

      GdipDeleteGraphics(Graphics);
    end;
  end;
end;
Zitat:
hast du eine Delphiversion höher als XE2?
Nein D2010.

gruss

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

n/a Beiträge
 
#6

AW: ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 17:38
Das Problem ist folgendes.
Ich habe ja nur ein DC das vom HeaderHandle das mit DrawHeaderItem übergeben wird.
Das bedeutet will ich den Hintergrund des Header ausmalen muss ich in Reihenfolge vorgehen.

Also erst den Hintergrund zeichnen und dann die Columns.
Delphi-Quellcode:
    if GdipCreateFromHDC(DC, Graphics) = OK then
     begin
       Img := Cardinal(GetProperty(Handle, PROP_IMAGE_SELECTED));
       GetClientRect(WinHandle, rc);
       // Hintergrund der Columns (Zeichne ich hier die Farbe anstelle des Button dann werden die Columns übermalt.)
       // bsp. FillRect.. bla. bla.
       SkinEngine.PaintButton(Graphics, 4, Img, rc.Left, rc.Top, rc.Right, rc.bottom, BS_PUSHBUTTON);
       // Columns
       SkinEngine.PaintButton(Graphics, 4, Img, rcHeader.Left, rcHeader.Top, rcHeader.Right - rcHeader.Left,
         rcHeader.bottom, BS_PUSHBUTTON);

       GdipDeleteGraphics(Graphics);
     end;
Das mache ich ja auch.

Ich kann aber nicht auf den Hintergrund selbst zeichnen dafür benötige ich ein eigenes DC für den Columns Hintergrund.
Scheint es wohl nicht zu geben.

Auch der erste Button wird von den Columns übermalt deshalb die Farbunterschiede.
Die Columns bekommen dann kräftigere Farben da sich diese durch den Hintergrund und weil sie Transparent sind duplizieren.

gruss

Geändert von EWeiss (17. Jan 2017 um 17:44 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#7

AW: ListView Header Farbe (Win32)

  Alt 17. Jan 2017, 18:17
Geänderte Version. So wie es aussehen sollte.
Ich kopiere jetzt den Hintergrund in ein temporäres DC um die Transparenz zu emulieren.
Das Problem ist aber genauso wie vorher ich kann das Window nicht aktualisieren
deshalb wird das DC immer wieder mit dem gleichen Inhalt übermalt.

Ich kann innerhalb des Threads WM_PAINT kein Invalidate aufrufen.
Krise hoch 3.

Delphi-Quellcode:
procedure TSkinListView.DrawHeaderItem(WinHandle: hWnd; Dc: Hdc; Index: Integer; Rect: TRect;
  Selected: Bool);
var
  Text: PWideChar;
  buf: array [0 .. 255] of Char;
  Item: THDItem;
  rcHeader: TRect;
  Img: Cardinal;
  Graphics: Cardinal;
  rc: TRect;
  rw: TRect;
  hDCBack: HDC;
  lp: TPoint;
begin
  Item.mask := HDI_TEXT or HDI_FORMAT or HDI_WIDTH;
  Item.pszText := buf;
  Item.fmt := HDF_LEFT and HDF_OWNERDRAW and HDF_STRING;
  Item.cchTextMax := sizeof(buf);

  Header_GetItemRect(WinHandle, Index, @rcHeader);

  ZeroMemory(@buf, sizeof(buf));
  Header_GetItem(WinHandle, Index, Item);
  Text := buf;

  SetBkMode(Dc, TRANSPARENT);
// Neu
  hDCBack := CreateCompatibleDC(DC);
  GetClientRect(WinHandle, rc);

  GetWindowRect(WinHandle, rw);
  lp.x := rw.Left;
  lp.y := rw.Top;
  ScreenToClient(GetParent(Handle), lp);

  SelectObject(hDCBack, SkinEngine.GetBackBitmap(GetParent(Handle)));
  BitBlt(DC, 0, 0, rc.Right, rc.Bottom, hDCBack, lp.x, lp.y, SRCCOPY);
// end Neu
  if GetShadow then
  begin
    if IsWindowEnabled(WinHandle) then
      Color := GetShadowColor
    else
    Color := RGB(255, 255, 255);

    Rect.Top := (((rcHeader.Bottom - FPointSize) div 2) div 2 + 1) + lp.y;
    Rect.Left := Rect.Left + lp.x; // Neu
    DrawTextToDC(hDCBack, Text, Rect, Color, FFontName, FPointSize, FFontStyle, 0, 0);

// Rect.Top := (((rcHeader.Bottom - FPointSize) div 2) div 2 + 1);
// DrawTextToDC(DC, Text, Rect, Color, FFontName, FPointSize, FFontStyle, 0, 0);

    if IsWindowEnabled(WinHandle) then
    begin
      if Selected then
        Color := AktForecolor
      else
      Color := InAktForecolor;
    end
    else
    Color := RGB(140, 140, 140);

    DrawTextToDC(hDCBack, Text, Rect, Color, FFontName, FPointSize, FFontStyle,
      FShadowOffset, 0);

// DrawTextToDC(DC, Text, Rect, Color, FFontName, FPointSize, FFontStyle,
// FShadowOffset, 0);

// if GdipCreateFromHDC(DC, Graphics) = OK then
    if GdipCreateFromHDC(hDCBack, Graphics) = OK then
    begin
      Img := Cardinal(GetProperty(Handle, PROP_IMAGE_SELECTED));
      GetClientRect(WinHandle, rc);
// SkinEngine.PaintButton(Graphics, 4, Img, rc.Left, rc.Top, rc.Right, rc.bottom, BS_PUSHBUTTON);

      SkinEngine.PaintButton(Graphics, 4, Img, rc.Left + lp.x, lp.y, rc.Right, rc.bottom, BS_PUSHBUTTON);
// SkinEngine.PaintButton(Graphics, 4, Img, rcHeader.Left, rcHeader.Top, rcHeader.Right - rcHeader.Left,
// rcHeader.bottom, BS_PUSHBUTTON);
      SkinEngine.PaintButton(Graphics, 4, Img, rcHeader.Left + lp.x, lp.y, rcHeader.Right - rcHeader.Left,
        rcHeader.bottom, BS_PUSHBUTTON);

      GdipDeleteGraphics(Graphics);
    end;
    DeleteDC(hDCBack);
  end;
end;

gruss

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

n/a Beiträge
 
#8

AW: ListView Header Farbe (Win32)

  Alt 19. Jan 2017, 10:01
Funktioniert jetzt wollte nur das Ergebnis mitteilen.
Subclass Header
Delphi-Quellcode:
    WM_PAINT:
      begin
        GetClientRect(WinHandle, rc);

        Dc := BeginPaint(WinHandle, ps);

        if not SkinEngine.Composited(WinHandle) then
          Dc := SkinEngine.DoubleBuffer(ps.Hdc, rc.Right, rc.Bottom, CreateBuffer);

        hDCBack := CreateCompatibleDC(Dc);

        GetWindowRect(WinHandle, rw);
        p.x := rw.Left;
        p.y := rw.Top;
        ScreenToClient(GetParent(Handle), p);

        SelectObject(hDCBack, SkinEngine.GetBackBitmap(GetParent(Handle)));
        BitBlt(Dc, 0, 0, rcHeader.Right, rcHeader.Bottom, hDCBack, p.x, p.y, SRCCOPY);

        ItemCount := Header_GetItemCount(WinHandle);
        for IntI := 0 to ItemCount - 1 do
        begin
          Header_GetItemRect(WinHandle, IntI, @rcHeader);

          DrawHeaderItem(WinHandle, Dc, IntI, rcHeader, True);
        end;
        DeleteDC(hDCBack);

        if not SkinEngine.Composited(WinHandle) then
          SkinEngine.DoubleBuffer(0, 0, 0, DestroyBuffer)
        else
          ReleaseDC(WinHandle, Dc);

        EndPaint(WinHandle, ps);
        Result := 0;
        exit;
      end;

  end;
  Result := CallWindowProc(FPrevHeaderProc, WinHandle, Msg, wP, lP);
end;
Drawitems
Delphi-Quellcode:
procedure TSkinListView.DrawHeaderItem(WinHandle: hWnd; Dc: Hdc; Index: Integer; Rect: TRect;
  Selected: Bool);
var
  Text: PWideChar;
  buf: array [0 .. 255] of Char;
  Item: THDItem;
  rcHeader: TRect;
  Img: Cardinal;
  Graphics: Cardinal;
  rc: TRect;
  rw: TRect;
  lP: TPoint;
begin
  Item.mask := HDI_TEXT or HDI_FORMAT { or HDI_BITMAP } or HDI_WIDTH;
  Item.pszText := buf;
  Item.fmt := HDF_LEFT or HDF_OWNERDRAW { or HDF_BITMAP } or HDF_STRING;
  Item.cchTextMax := sizeof(buf);

  Header_GetItemRect(WinHandle, Index, @rcHeader);

  ZeroMemory(@buf, sizeof(buf));
  Header_GetItem(WinHandle, Index, Item);
  Text := buf;

  SetBkMode(Dc, TRANSPARENT);

  if GetShadow then
  begin
    if IsWindowEnabled(WinHandle) then
      Color := GetShadowColor
    else
      Color := RGB(255, 255, 255);

    Rect.Top := (((rcHeader.Bottom - FPointSize) div 2) div 2 + 1);
    DrawTextToDC(Dc, Text, Rect, Color, FFontName, FPointSize, FFontStyle, 0, 0);

    if IsWindowEnabled(WinHandle) then
    begin
      if Selected then
        Color := AktForecolor
      else
        Color := InAktForecolor;
    end
    else
      Color := RGB(140, 140, 140);

    DrawTextToDC(Dc, Text, Rect, Color, FFontName, FPointSize, FFontStyle, FShadowOffset, 0);

    if GdipCreateFromHDC(Dc, Graphics) = OK then
    begin
      Img := Cardinal(GetProperty(Handle, PROP_IMAGE_SELECTED));
      GetClientRect(WinHandle, rc);

      GetWindowRect(WinHandle, rw);
      lP.x := rw.Left;
      lP.y := rw.Top;
      ScreenToClient(GetParent(Handle), lP);

      SkinEngine.PaintButton(Graphics, 4, Img, rc.Left, rc.Top, rc.Right, rc.Bottom, BS_PUSHBUTTON);

      SkinEngine.PaintButton(Graphics, 4, Img, rcHeader.Left, rcHeader.Top,
        rcHeader.Right - rcHeader.Left, rcHeader.Bottom, BS_PUSHBUTTON);

      GdipDeleteGraphics(Graphics);
    end;
  end;
end;
Ergebnis siehe Pic.
Kann mich jetzt mit den Header Icons beschäftigen.

gruss

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

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

AW: ListView Header Farbe (Win32)

  Alt 8. Okt 2017, 20:48
Hallo,

könntet ihr vielleicht zu dem Thema (ListView Header Farbe setzen) ein kleines Demoprogramm anhängen?

Gruß,
Eric
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:14 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