How to clip a TBitmap inside an irregular shape (Views: 30)
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; |