![]() |
ListView Header Farbe (Win32)
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 |
AW: ListView Header Farbe (Win32)
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; |
AW: ListView Header Farbe (Win32)
Zitat:
Danke. Nein das Handle kann man einfacher erfahren eine Zeile Code.
Delphi-Quellcode:
HeaderHandle := ListView_GetHeader(WinHandle);
btw. komplett.
Delphi-Quellcode:
Ich habe Columns auf der ListView ich benötige den Hintergrund von allen Columns. (Scheint irgendein Frame zu sein.
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; 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 |
AW: ListView Header Farbe (Win32)
Zitat:
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? Zitat:
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? |
AW: ListView Header Farbe (Win32)
Zitat:
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:
Dieser erstreckt sich über den gesamten Bereich der ListView hinter den eigentlichen Columns. Zeichnen tue ich ihn so. Headerproc..
Delphi-Quellcode:
DrawHeaderItem
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;
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:
gruss |
AW: ListView Header Farbe (Win32)
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:
Das mache ich ja auch.
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; 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 |
AW: ListView Header Farbe (Win32)
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 |
AW: ListView Header Farbe (Win32)
Funktioniert jetzt wollte nur das Ergebnis mitteilen.
Subclass Header
Delphi-Quellcode:
Drawitems
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;
Delphi-Quellcode:
Ergebnis siehe Pic.
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; Kann mich jetzt mit den Header Icons beschäftigen. gruss |
AW: ListView Header Farbe (Win32)
Hallo,
könntet ihr vielleicht zu dem Thema (ListView Header Farbe setzen) ein kleines Demoprogramm anhängen? Gruß, Eric |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:24 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