Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi "Transparenz" bei eigener Komponente (https://www.delphipraxis.net/17127-transparenz-bei-eigener-komponente.html)

H4ndy 28. Feb 2004 15:27


"Transparenz" bei eigener Komponente
 
Hallo DP'ler!

Und zwar folgendes:
Ich habe angefangen, mich mal mit der Entwicklung
einer graphischen Komponente zu beschäftigen.
Dazu habe ich meine meine Komponente von TGroupBox
abgeleitet und habe auch schon einiges geschafft.

Nur scheitere ich jetzt daran, meine GroupBox transparent
zu machen, sprich den Hintergrund des Forms zu zeigen.
(Wie z.b. bei TextEd -> http://www.delphipraxis.net/internal...ect.php?t=8203 )

Bin ja schon auf die Idee gekommen mit CopyRect das zu
machen, nur weiss ich jetzt nicht, wie ich an das Canvas von dem
Form komme, auf welchem die Komponente plaziert wurde.

Weiss jemand rat?
( Ich hoffe das war jetzt verständlich genug :stupid: )

SirThornberry 28. Feb 2004 15:46

Re: "Transparenz" bei eigener Komponente
 
du musst dazu die Message wm_draw abfangen wenn du selbst zeichnen willst, oder du überschreibst die methode paint

H4ndy 28. Feb 2004 22:07

Re: "Transparenz" bei eigener Komponente
 
Zitat:

Zitat von SirThornberry
du musst dazu die Message wm_draw abfangen wenn du selbst zeichnen willst, oder du überschreibst die methode paint

Naja Paint hab ich ja schon überschrieben,
da ich ja die Caption beliebig ausrichten wollte.

Gibts ne einfachere Methode als wm_draw abzufangen,
um an das Canvas des Forms zu kommen?
Oder überhaupt ne andere Methode, dass
ich meine Komponente durchsichtig machen kann?

H4ndy 1. Mär 2004 13:12

Re: "Transparenz" bei eigener Komponente
 
Nach längerem nachforschen hab ich festgestellt, dass
sich die Transparenz nicht ohne weiteres einfügen lässt.

Hab meine Kompo jetzt von TGraphicControl abgeleitet.
Hat zwar jetzt keine "echte" GroupBox-Funktionalität,
schiebt aber trotzdem seine Dienst =)

franz 21. Jul 2004 22:42

Re: "Transparenz" bei eigener Komponente
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
Ich habe hier eine Lösung für alle Komponenten, die von TWinControl abgeleitet sind. Allerdings funktioniert die Lösung nicht mit folgenden Farben, was im übrigen gar nicht so schlimm ist, da die transparente Farbe automatisch ermittelt werden kann.

clScrollBar, clBackground, clActiveCaption, clInactiveCaption, clMenu, clWindow, clWindowFrame, clMenuText, clWindowText, clCaptionText, clActiveBorder, clInactiveBorder, clAppWorkSpace, clHighlight, clHighlightText, clBtnFace, clBtnShadow, clGrayText, clBtnText, clInactiveCaptionText, clBtnHighlight, cl3DdkShadow, cl3Dlight, clInfoText, clInfoBk


1. Grundlagen:
Ab Windows 95 unterstützt Windows beliebige Fensterformen.

Nach Microsoft Definition ist ein Fester, unter Windows, ein Objekt, das von einer registrierten Fensterklasse abgeleitet ist und über die Eigenschaften von TWinControl verfügt:

Also sind alle von TWinControl abgeleiteten Klassen Fenster.


2. Komponente transparent machen
Komponente, die von TGraphicControl abgeleitet sind, sind bereits transparent. Mit dem folgenden Code kann man nur Komponenten transparent machen, die von TWinControl abgeleitet sind (Erklärung siehe 1. Grundlagen).


Zunächst müssen wir sicherstellen, dass wir das Steuerelement wieder zurücksetzen können. Also die Transparenz wieder entfernen:

Hinweis: Die Prozedur UndoTransparent wird von MakeTransparent (weiter unten) aufgerufen
Delphi-Quellcode:
// Transparenz rückgängig machen
procedure UndoTransparent(Control: TWinControl);
var
  HR: HRgn;
begin
  if not Assigned(Control) then
     Exit;

  HR := CreateRectRgn(0,0,Control.Width,Control.Height);
  SetWindowRgn(Control.Handle, HR, true);
end;

Nun müssen wir einen ScreenShot des Steuerelements anfertigen, damit der Inhalt des Steuerelements nicht verloren geht und wir somit am Schluss gar nicht mehr sehen würden:

Hinweis: Die Prozedur TakeControlScreenShot wird von MakeTransparent (weiter unten) aufgerufen
Delphi-Quellcode:
// ScreenShot des Steuerelements anfertigen und an das übergebene Bitmap
// übergeben
procedure TakeControlScreenShot(Control: TWinControl; var Bitmap: TBitmap);

type
  LogPal = record
    lpal : TLogPalette;
    dummy: array[0..255] of TPaletteEntry;
  end;

var
  SysPal: LogPal;
  mImage: TImage;
  mPal:   HPalette;
  mHDC:   HDC;
  mCanvas: TCanvas;
  mRect:  TRect;
begin
  if not Assigned(Control) then
     Exit;

  mHDC := GetWindowDC(Control.Handle);

  SysPal.lPal.palVersion   := $300;
  SysPal.lPal.palNumEntries := 256;

  GetSystemPaletteEntries(mHDC, 0, 256, SysPal.lpal.PalpalEntry);
  mPal := CreatePalette(SysPal.lpal);

  mCanvas := TCanvas.Create;
  try
    mCanvas.Handle := mHDC;
    mRect := Rect(0, 0, Screen.Width, Screen.Height);

    mImage := TImage.Create(nil);
    try
      with mImage do
        begin
          Height := Control.Height;
          Width := Control.Width;

          Canvas.CopyRect(mRect, mCanvas, mRect);
          ReleaseDC(GetDeskTopWindow, mHDC);
          Picture.Bitmap.Palette := mPal;
        end;

      Bitmap.Assign(mImage.Picture.Bitmap);
    finally
      mImage.Free;
    end;

    ReleaseDC(GetDeskTopWindow, mHDC);
    ReleaseDC(Control.Handle, mCanvas.Handle)
  finally
    mCanvas.Free;
  end;
end;

Jetzt kommt erst die eigentliche Prozedur, die das Steuerelement transparent macht.
Dummerweise muss zu diesem Zweck die Pixels Eigenschaft von TBitmap.Canvas verwendet werden. Mit ScanLine hat es einfach nicht funktioniert.

Hinweis: Die Prozedur MakeTransparent muss logischerweise aufgerufen werden
Delphi-Quellcode:
// Steuerelement Transparent machen
procedure MakeTransparent(Control: TWinControl; TranspColor: TColor = clNone);
var
  HR, mBuf: HRgn;
  ix, iy:  Integer;
  Bitmap:  TBitmap;
begin
  // Objekte Prüfen
  [Edit]
     // Alter Quelltext:
     // Vorher wurde ein Bitmap an die Prozedur übergeben
     {if (not Assigned(Control)) or (not Assigned(Bitmap)) then
        Exit;}

     // Neuer Quelltext
     // Da das Bitmap nicht mehr an die Prozedur übergeben wird
     if (not Assigned(Control)) then
         Exit;
  [/Edit]

  // Transparenz rückgängig machen
  UndoTransparent(Control);

  // Steuerelement transparent machen
  HR    := CreateRectRgn(0,0,0,0);
  Bitmap := TBitmap.Create;
  try
    // Screen Shot des Steuerlement anfertigen
    TakeControlScreenShot(Control,Bitmap);

    // Transparente Farbe einstellen, falls nötig
    if TranspColor = clNone then
       TranspColor := Bitmap.Canvas.Pixels[0,0];

    // Sichtbaren Bereich erstellen
    for iy := 0 to Bitmap.Height-1 do
      begin
        if (iy mod 50) = 0 then
           Application.ProcessMessages;

        for ix := 0 to Bitmap.Width-1 do
          begin
            if Bitmap.Canvas.Pixels[ix,iy] <> TranspColor then
               begin
                 mBuf := CreateRectRgn(ix,iy,1+ix,1+iy);
                 try
                   CombineRgn(HR, HR, mBuf, RGN_OR);
                 finally
                   DeleteObject(mBuf);
                 end;
               end;
          end;
      end;

    // Sichtbaren Bereich dem Steuerelement zuordnen
    SetWindowRgn(Control.Handle, HR, true);
  finally
    DeleteObject(HR);
    Bitmap.Free;
  end;
end;

Aufgerufen wird das ganze folgendermaßen. Dabei wird GroupBox1 transparent gemacht.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  MakeTransparent(GroupBox1);
end;
Zunächst muss sichergestellt werden, dass das Steuerelement nicht mehr transparent ist. Danach wird es wieder transparent gemacht. Der zweite Parameter von MakeTransparent gibt die transparente Farbe an. Wenn nichts angegeben wird, wird als transparente Farbe die Farbe des ersten Pixels verwendet.

Warnung!
MakeTransparent greift auf die Eigenschaft TCanvas.Pixels zu. Dadurch kann je nach Größe des Steuerelements die Berechnung etwas dauern. Rufe NIEMALS MakeTransparent innerhalb von OnPaint auf! Sonst „steht“, unter Umständen, der Computer! Es empfiehlt sich einen Thread für das transparent machen eines Steuerelements zu verwenden.

SirThornberry 21. Jul 2004 23:49

Re: "Transparenz" bei eigener Komponente
 
das einfachste ist "CreateParams" zu überschreiben und einfach anzugeben das die Komponente transparent ist
Delphi-Quellcode:
procedure TNewCompo.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle + WS_EX_Transparent;
end;

Muetze1 21. Jul 2004 23:59

Re: "Transparenz" bei eigener Komponente
 
Moin!

Zitat:

Zitat von franz
Hi,
Ich habe hier eine Lösung für alle Komponenten, die von TWinControl abgeleitet sind. Allerdings funktioniert die Lösung nicht mit folgenden Farben, was im übrigen gar nicht so schlimm ist, da die transparente Farbe automatisch ermittelt werden kann.

clScrollBar, clBackground, clActiveCaption, clInactiveCaption, clMenu, clWindow, clWindowFrame, clMenuText, clWindowText, clCaptionText, clActiveBorder, clInactiveBorder, clAppWorkSpace, clHighlight, clHighlightText, clBtnFace, clBtnShadow, clGrayText, clBtnText, clInactiveCaptionText, clBtnHighlight, cl3DdkShadow, cl3Dlight, clInfoText, clInfoBk

Dazu kann ich Abhilfe geben. Diese Farben sind Konstanten mit einem negativen Wert und enthalten keine RGB Werte, weshalb sie nicht funktionieren bei dem Pixels[] Vergleich. Abhilfe schafft hier einfach, wenn man die Transparenzfarbe vorher durch ColorToRGB() durchjagt, danach sind diese Konstanten zu den aktuellen RGB Werten der Systemeinstellungen umgewandelt. Danach ist dann auch der Vergleich möglich.

MfG
Muetze1

CReber 1. Feb 2005 18:50

Re: "Transparenz" bei eigener Komponente
 
*Thread ausbuddel

Wollte grad dem von SirThornberry nachgehen und habe eine mit eine TTransPageControl gebastelt aber leider scheint es nur zur Hälfte zur funktionieren. Sobald TabSheets drauf sind ist da leider nichts mehr Transparent :)

Kann wer helfen?

Delphi-Quellcode:
unit uMain;

interface

uses
  Windows, Classes, Controls, ComCtrls, ExtCtrls;

type
  TTransPageControl = class(TPageControl)
  private
  public
    procedure CreateParams(var Params: TCreateParams); override;
  published
  end;

procedure Register;

implementation

procedure TTransPageControl.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle + WS_EX_Transparent;
end;

procedure Register;
begin
  RegisterComponents('Test', [TTransPageControl]);
end;

end.

delphifan2004 3. Feb 2005 13:23

Re: "Transparenz" bei eigener Komponente
 
Hallo Christian!

Ich vermute, dass dann das TabSheet auch explizit als TransTabSheet abgeleitet werden muß und dann anstelle des Delphi-eigenen TabSheets zu verwenden ist.

Delphifan2004 alias Wilfried

CReber 3. Feb 2005 17:00

Re: "Transparenz" bei eigener Komponente
 
Und wie weise ich dem TTransPageControl zu, dass es TTransTabSheets verwenden soll? Daran bin ich nämlich gescheitert ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:54 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