Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi GDI+ und AntiAliasing: mal geht' s, mal nicht (https://www.delphipraxis.net/107818-gdi-und-antialiasing-mal-geht-s-mal-nicht.html)

DeddyH 2. Feb 2008 18:41


GDI+ und AntiAliasing: mal geht' s, mal nicht
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallöle,

ich wollte meinen runden Button um einen Style erweitern (weitere sind geplant). Leider wird der neue Style nicht rund gezeichnet. Kann mir mal jemand zeigen, wo es hakt?

Paint-Methode:
Delphi-Quellcode:
  for i := Low(TBmType) to High(TBmType) do
    begin
      FStates[i].Width := Self.Width;
      FStates[i].Height := Self.Height;
      FStates[i].Canvas.Brush.Color := FTransparentColor;
      FStates[i].Canvas.FillRect(Rect(0,0,Self.Width,Self.Height));

      graphics[i] := TGPGraphics.Create(FStates[i].Canvas.Handle);
      try
        graphics[i].SetSmoothingMode(SmoothingModeAntiAlias); //<-- explizit eingeschaltet

        case FDrawType of
          dtMembrane: DrawMembrane(i);
          dtBubble : DrawBubble(i);
        end;
       
        DrawGDIPCaption(i);

      finally
        graphics[i].Free;
      end;

      FStates[i].TransparentColor := FStates[i].Canvas.Brush.Color;
      FStates[i].Transparent := True;

    end; //for
DrawMembrane (AntiAliasing funktioniert):
Delphi-Quellcode:
    procedure DrawMembrane(const aState: TBmType);
    begin
      Col1 := FFirstColor;
      Col2 := AddHalfTones(FFirstColor);

      case aState of
        btUp     : begin
                       Col1 := AddHalfTones(FFirstColor);
                       Col2 := FFirstColor;
                     end;
        btDisabled: begin
                       Col1 := AddHalfTones(FFirstColor);
                       Col2 := FDisabledColor;
                     end;
      end;

      linGrBrush := TGPLinearGradientBrush.Create(
                         MakePoint(0, 0),
                         MakePoint(Pred(self.Width), Pred(self.Height)),
                         ColorToGPColor(Col1),
                         ColorToGPColor(Col2));

      linGrBrush.SetGammaCorrection(FGammaCorrection);

      try
        graphics[aState].FillEllipse(linGrBrush,0,0,
                                     Self.Width - 1,
                                     Self.Height - 1);
      finally
        linGrBrush.Free;
      end;
    end;
DrawBubble (AntiAliasing funktioniert nicht):
Delphi-Quellcode:
    procedure DrawBubble(const aState: TBmType);
    type TPoints = array[Boolean] of Single;
         Tcolors = array[0..1] of TGPColor;
         THighColors = array[Boolean] of TColor;
    var
      path           : TGPGraphicsPath;
      pthGrBrush     : TGPPathGradientBrush;
      count          : Integer;
      PointsX, PointsY: TPoints;
      colors         : Tcolors;
      HighColors     : THighColors;
    begin

      if aState = btDisabled then
        colors[0] := ColorToGPColor(FDisabledColor)
      else
        colors[0] := ColorToGPColor(FFirstColor);

      colors[1] := ColorToGPColor(clYellow);

      HighColors[false] := $EAEAEA;
      HighColors[true] := AddHalfTones(FFirstColor);
     
      path:= TGPGraphicsPath.Create;
      try
        path.AddEllipse(0, 0, Self.Width - 1, Self.Height - 1);

        pthGrBrush:= TGPPathGradientBrush.Create(path);
        try

          PointsX[false] := Self.Width / 5;
          PointsY[false] := Self.Height / 5;

          PointsX[true] := Self.Width / 2;
          PointsY[true] := Self.Height / 2;

          pthGrBrush.SetCenterPoint(MakePoint(PointsX[aState = btDown],
                                              PointsY[aState = btDown]));

          pthGrBrush.SetCenterColor(ColorToGPColor(HighColors[aState = btDown]));

          count := 1;
          pthGrBrush.SetSurroundColors(@colors[0], count);
          pthGrBrush.SetGammaCorrection(FGammaCorrection);

          graphics[aState].FillPath(pthGrBrush,path);

          if aState = btDown then
            begin
              pthGrBrush.SetFocusScales(0.85,0.85);
              graphics[aState].FillPath(pthGrBrush,path);
            end;
        finally
          pthGrBrush.Free;
        end;
      finally
        path.Free;
      end;
    end;
Kann das sein, dass es an der Verwendung der Paths liegt? Ich hänge mal eine Demo an, damit man das auch mal sieht.

[edit] Ich vergaß zu sagen, dass die beiden Draw...-Prozeduren Unterprozeduren von Paint sind, die Variablen sind also bekannt. [/edit]

DeddyH 3. Feb 2008 12:03

Re: GDI+ und AntiAliasing: mal geht' s, mal nicht
 
Liste der Anhänge anzeigen (Anzahl: 1)
Problem gelöst: es lag an der Funktion SetSurroundColors. Diese kann anscheinend mit dem AntiAliasing nicht umgehen. Nun habe ich es so gemacht, dass ich den Path um ein Pixel in jede Richtung verkleinere und mit einem SolidBrush in derselben Farbe die "Grundierung" zeichne. Nun sieht das aus wie beabsichtigt :mrgreen: :bouncing4:

pustekuchen 3. Mai 2012 07:30

AW: GDI+ und AntiAliasing: mal geht' s, mal nicht
 
Liste der Anhänge anzeigen (Anzahl: 1)
Guten Morgen,

ich habe mir eine Prozedur erstellt, um einen Kreis mit einem Loch zu zeichnen. Ich habe es ähnlich wie du gemacht und habe um einen außeren Rand mit AA zu bekommen, einfach eine Ellipse drüber gezeichnet.

Das Problem ist nur, das es beim inneren Kreis nicht funktioniert. Es bleibt immernoch dieser hässliche Rand.

Delphi-Quellcode:
procedure TForm1.DrawGradiantEllipse(Handle: HDC; X, Y, Width, Height,
  RingWidth: integer; OuterColor, InnerColor: cardinal; UseGradient: boolean);
var
  g: TGPGraphics;
  pBrush: TGPPathGradientBrush;
  region: TGPRegion;
  pen: TGPPen;
  OuterRect: TGPRect;
  InnerRect: TGPRect;
  InnerPath: TGPGraphicsPath;
  OuterPath: TGPGraphicsPath;
  Count: integer;
  white:cardinal;
  FocusScale: double;
begin
  g := TGPGraphics.Create(Handle);
  region := TGPRegion.Create;
  pBrush := TGPPathGradientBrush.Create;
  pen := TGPPen.Create(OuterColor, RingWidth);
  try
    FocusScale := 1 - (RingWidth / Width);
    g.SetSmoothingMode(SmoothingModeAntiAlias);
    if UseGradient then
    begin
      // Create Outer/Inner Rect
      OuterRect := MakeRect(x,y,Width,Height);
      InnerRect := MakeRect(OuterRect.X + RingWidth div 2,
                            OuterRect.Y + RingWidth div 2,
                            OuterRect.Width - RingWidth,
                            OuterRect.Height - RingWidth);
      // Create Outer/Inner Ellipse Path
      InnerPath := TGPGraphicsPath.Create;
      OuterPath := TGPGraphicsPath.Create;
      InnerPath.AddEllipse(InnerRect);
      OuterPath.AddEllipse(OuterRect);
      // Create PathGradientBrush
      pBrush := TGPPathGradientBrush.Create(OuterPath);
      pBrush.SetCenterColor(InnerColor);
      // Always a single Color
      count := 1;
      pBrush.SetSurroundColors(@OuterColor,count);
      pBrush.SetFocusScales(FocusScale,FocusScale);
      pBrush.SetBlendTriangularShape(0.5,FocusScale);
      // Create Region of InnerPath
      region := TGPRegion.Create(InnerPath);
      // "Erases" the Inner Ellipse
      g.SetClip(region,CombineModeExclude);
      g.FillEllipse(pBrush,OuterRect);
      // Set PenWidth for Ellipse with AA
      pen.SetWidth(1);
      pen.SetColor(MakeColor(225,0,255,0)); // Just for Debug
      g.DrawEllipse(pen,x + Ringwidth div 2,y + Ringwidth div 2,Width - Ringwidth,Height - Ringwidth);
    end;
    pen.SetColor(MakeColor(225,255,0,0));  // Just for Debug
    g.DrawEllipse(pen,x,y,Width,Height);
  finally
    region.Free;
    pBrush.Free;
    g.Free;
    pen.Free;
  end;
end;
Wüßte jemand wie man das Problem lösen kann?

Bummi 3. Mai 2012 07:57

AW: GDI+ und AntiAliasing: mal geht' s, mal nicht
 
Clipping ist "böse" und lässt sich vermeiden:
Delphi-Quellcode:
procedure TForm2.DrawGradiantEllipse(Handle: HDC; X, Y, Width, Height,
  RingWidth: integer; OuterColor, InnerColor: cardinal; UseGradient: boolean);
var
  g: TGPGraphics;
  pBrush: TGPPathGradientBrush;
  region,region2: TGPRegion;
  pen: TGPPen;
  OuterRect: TGPRect;
  InnerRect: TGPRect;
  InnerPath: TGPGraphicsPath;
  OuterPath: TGPGraphicsPath;
  Count: integer;
  white:cardinal;
  FocusScale: double;
begin
  g := TGPGraphics.Create(Handle);
  region := TGPRegion.Create;
  pBrush := TGPPathGradientBrush.Create;
  pen := TGPPen.Create(OuterColor, RingWidth);
  try
    FocusScale := 1 - (RingWidth / Width);
    g.SetSmoothingMode(SmoothingModeHighQuality);//(SmoothingModeAntiAlias);
    if UseGradient then
    begin
      // Create Outer/Inner Rect
      OuterRect := MakeRect(x,y,Width,Height);
      InnerRect := MakeRect(OuterRect.X + RingWidth div 2,
                            OuterRect.Y + RingWidth div 2,
                            OuterRect.Width - RingWidth,
                            OuterRect.Height - RingWidth);
      // Create Outer/Inner Ellipse Path
      InnerPath := TGPGraphicsPath.Create;
      OuterPath := TGPGraphicsPath.Create;
      InnerPath.AddEllipse(InnerRect);
      OuterPath.AddEllipse(OuterRect);
      // Create PathGradientBrush
      pBrush := TGPPathGradientBrush.Create(OuterPath);
      pBrush.SetCenterColor(InnerColor);
      // Always a single Color
      count := 1;
      pBrush.SetSurroundColors(@OuterColor,count);
      pBrush.SetFocusScales(FocusScale,FocusScale);
      pBrush.SetBlendTriangularShape(0.5,FocusScale);
      // Create Region of InnerPath
      region := TGPRegion.Create(OuterPath);
      region2 := TGPRegion.Create(InnerPath);
      region.Exclude(region2);
      // "Erases" the Inner Ellipse
     // g.SetClip(region,CombineModeExclude);
      //g.FillEllipse(pBrush,OuterRect);
      g.FillRegion(pbrush,region);
      // Set PenWidth for Ellipse with AA
      pen.SetWidth(1);
    //  pen.SetColor(MakeColor(225,0,255,0)); // Just for Debug
      g.DrawEllipse(pen,x + Ringwidth div 2,y + Ringwidth div 2,Width - Ringwidth,Height - Ringwidth);
    end;
    pen.SetColor(MakeColor(225,255,0,0)); // Just for Debug
    g.DrawEllipse(pen,x,y,Width,Height);
  finally
    region.Free;
    region2.Free;
    pBrush.Free;
    g.Free;
    pen.Free;
  end;
end;

pustekuchen 3. Mai 2012 08:11

AW: GDI+ und AntiAliasing: mal geht' s, mal nicht
 
Zitat:

Zitat von Bummi (Beitrag 1164667)
Clipping ist "böse" und lässt sich vermeiden

Ich habs gemerkt, ganz ganz phöse! Vielen Dank, so klappt es wunderbar :)

btw: Warum SmoothingModeHighQuality und nicht SmoothingModeAntiAlias?
Laut SmoothingMode benutzen beide den selben Filter. Gibt es andere gründe weshalb du explizit HighQuality genoimmen hast?

Bummi 3. Mai 2012 09:11

AW: GDI+ und AntiAliasing: mal geht' s, mal nicht
 
@pustekuchen

nein, ich habe nur "meinen" üblichen Standard ausprobiert ... einfach ignorieren


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