unit AlertOverlay; { Reusable overlays for spectrum-like bitmap surfaces. } {$IFDEF FPC} {$MODE Delphi} {$ENDIF} interface uses Graphics, Types, Math; procedure DrawAlertOverlay(Target: TBitmap; C: TCanvas; W, H: Integer; const Title, Detail: string); implementation procedure BlendRect(Target: TBitmap; const Rct: TRect; R, G, B, Alpha: Byte); var Y, X, InvA: Integer; Row: PByte; RR: TRect; begin if (Target = nil) or (Alpha = 0) then Exit; RR := Rct; if RR.Left < 0 then RR.Left := 0; if RR.Top < 0 then RR.Top := 0; if RR.Right > Target.Width then RR.Right := Target.Width; if RR.Bottom > Target.Height then RR.Bottom := Target.Height; if (RR.Right <= RR.Left) or (RR.Bottom <= RR.Top) then Exit; InvA := 255 - Alpha; Target.BeginUpdate(False); try for Y := RR.Top to RR.Bottom - 1 do begin Row := PByte(Target.ScanLine[Y]); if Row = nil then Continue; Inc(Row, RR.Left * 4); for X := RR.Left to RR.Right - 1 do begin Row[0] := Byte((Alpha * B + InvA * Row[0]) div 255); Row[1] := Byte((Alpha * G + InvA * Row[1]) div 255); Row[2] := Byte((Alpha * R + InvA * Row[2]) div 255); Inc(Row, 4); end; end; finally Target.EndUpdate(False); end; end; procedure DrawAlertOverlay(Target: TBitmap; C: TCanvas; W, H: Integer; const Title, Detail: string); const PAD = 12; INNER_X = 12; ACCENT_W = 4; var R, AccentR: TRect; TW, DW, BoxW, BoxH: Integer; begin if (Target = nil) or (C = nil) then Exit; if (W < 220) or (H < 60) then Exit; C.Font.Name := 'Courier New'; C.Font.Style := [fsBold]; C.Font.Size := 9; TW := C.TextWidth(Title); C.Font.Style := []; C.Font.Size := 7; DW := C.TextWidth(Detail); BoxW := Max(TW, DW) + INNER_X * 2 + ACCENT_W + 8; BoxH := 42; R := Rect(W - PAD - BoxW, PAD, W - PAD, PAD + BoxH); BlendRect(Target, R, $A8, $10, $16, 118); BlendRect(Target, Rect(R.Left, R.Top, R.Right, R.Top + 1), $FF, $68, $68, 80); C.Brush.Style := bsClear; C.Pen.Style := psSolid; C.Pen.Width := 1; C.Pen.Color := TColor($003838C8); C.Rectangle(R); AccentR := Rect(R.Left + 7, R.Top + 7, R.Left + 7 + ACCENT_W, R.Bottom - 7); C.Brush.Style := bsSolid; C.Brush.Color := TColor($002828F0); C.Pen.Style := psClear; C.FillRect(AccentR); C.Brush.Style := bsClear; C.Font.Name := 'Courier New'; C.Font.Style := [fsBold]; C.Font.Size := 9; C.Font.Color := TColor($008888FF); C.TextOut(R.Left + INNER_X + ACCENT_W + 8, R.Top + 7, Title); C.Font.Style := []; C.Font.Size := 7; C.Font.Color := TColor($00C8C8E8); C.TextOut(R.Left + INNER_X + ACCENT_W + 8, R.Top + 25, Detail); end; end.