2005. október 19., szerda

How to clip a TBitmap inside an irregular shape


Problem/Question/Abstract:

If I have an irregular shape, say a rectangle with the top corners rounded. How can I fill the inside of that shape with a bitmap or limit pen drawing to inside the area of the shape?

Answer:

Below is a small sample of how the problem can be resolved, using a Path converting the Path to a Region and setting the ClippingRgn:

procedure DrawHeader
var
  Bmp: TBitmap;
  clEnd, clStart: TColor;
  R: TRect;
  Rd: Integer;
  Rgn: HRGN;
begin
  Rd := spnTest.IntValue;
  GetActiveColors(clStart, clEnd);
  Bmp := TBitmap.Create;
  try
    R.Left := btnClipGradient.Left + btnClipGradient.Width + 20;
    R.Top := btnClipGradient.Top;
    R.Right := R.Left + 100;
    R.Bottom := R.Top + 100;
    with Bmp do
    begin
      Height := 20;
      Width := 100;
      DrawGradient(Canvas, Rect(0, 0, 100, 20), 50, goHorizontal, clStart, clEnd);
    end;
    with Canvas do
    begin
      BeginPath(Handle);
      Pen.Color := clYellow;
      Pen.Style := psSolid;
      {Bottom line}
      MoveTo(R.Left, R.Bottom);
      LineTo(R.Right, R.Bottom);
      {Right Line}
      LineTo(R.Right, R.Top + (Rd div 2));
      {Top Right}
      ArcTo(Handle, R.Right - Rd + 1, R.Top, R.Right + 1, R.Top + Rd, R.Right + 1,
        R.Top + (Rd div 2), R.Right - (Rd div 2) + 1, R.Top);
      {Top Line}
      LineTo(R.Right - (Rd div 2), R.Top);
      {Top Left}
      ArcTo(Handle, R.Left, R.Top, R.Left + Rd, R.Top + Rd, R.Left + (Rd div 2),
        R.Top, R.Left, R.Top + (Rd div 2));
      {Left line}
      LineTo(R.Left, R.Top + (Rd div 2));
      EndPath(Handle);
      Rgn := PathToRegion(Handle);
      SelectClipRgn(Handle, Rgn);
      Draw(R.Left + 1, R.Top + 1, Bmp);
      SelectClipRgn(Handle, HRGN(nil));
      Pen.Color := clYellow;
      Pen.Style := psSolid;
      {Bottom line}
      MoveTo(R.Left, R.Bottom);
      LineTo(R.Right, R.Bottom);
      {Right Line}
      LineTo(R.Right, R.Top + (Rd div 2));
      {Top Right}
      ArcTo(Handle, R.Right - Rd + 1, R.Top, R.Right + 1, R.Top + Rd, R.Right + 1,
        R.Top + (Rd div 2), R.Right - (Rd div 2) + 1, R.Top);
      {Top Line}
      LineTo(R.Right - (Rd div 2) + 1, R.Top);
      {Top Left}
      ArcTo(Handle, R.Left, R.Top, R.Left + Rd, R.Top + Rd, R.Left + (Rd div 2),
        R.Top, R.Left, R.Top + (Rd div 2));
      {Left line}
      LineTo(R.Left, R.Bottom);
      DeleteObject(Rgn);
    end;
  finally
    Bmp.Free;
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése