You can use this function to take a screen grab of the desktop area occupied by all of your visible forms:
USES System.Math, WinAPI.DwmApi;
FUNCTION ScreenGrab(IncludeShadow : BOOLEAN = FALSE ; BorderSize : Cardinal = 8 ; BackgroundColor : TColor = clBlack) : TBitMap;
VAR
MinX,MinY,MaxX,MaxY,I : INTEGER;
F : TForm;
DC : HDC;
R : TRect;
FUNCTION GetWindowRect(F : TForm) : TRect;
BEGIN
IF IncludeShadow THEN
Result:=F.BoundsRect
ELSE
DwmGetWindowAttribute(F.Handle,DWMWA_EXTENDED_FRAME_BOUNDS,@Result,SizeOf(TRect))
END;
BEGIN
MinX:=MAXINT; MinY:=MinX; MaxX:=-MAXINT; MaxY:=MaxX;
FOR I:=0 TO PRED(Screen.FormCount) DO BEGIN
F:=Screen.Forms[I];
IF F.Visible THEN BEGIN
R:=GetWindowRect(F);
MinX:=Min(MinX,R.Left); MinY:=Min(MinY,R.Top);
MaxX:=Max(MaxX,R.Left+R.Width); MaxY:=Max(MaxY,R.Top+R.Height)
END
END;
DEC(MinX,BorderSize); DEC(MinY,BorderSize);
INC(MaxX,BorderSize); INC(MaxY,BorderSize);
Result:=TBitMap.Create(MaxX-MinX,MaxY-MinY);
TRY
Result.PixelFormat:=pf24bit;
Result.Canvas.Brush.Style:=TBrushStyle.bsSolid;
Result.Canvas.Brush.Color:=BackgroundColor;
Result.Canvas.FillRect(Rect(0,0,Result.Width,Result.Height));
DC:=GetDC(0);
TRY
FOR I:=0 TO PRED(Screen.FormCount) DO BEGIN
F:=Screen.Forms[I];
IF F.Visible THEN BEGIN
R:=GetWindowRect(F);
BitBlt(Result.Canvas.Handle,R.Left-MinX,R.Top-MinY,R.Width,R.Height,DC,R.Left,R.Top,SRCCOPY)
END
END
FINALLY
ReleaseDC(0,DC)
END
EXCEPT
Result.Free;
RAISE
END
END;
Use "IncludeShadow" to include the shadow area around your forms (which may include screen info from the windows behind your forms). You can also specify a "BorderSize" around the grabbed area, and you may specify the background colour (of the area not occupied by your forms) of the returned image.
It also works if your forms are spread across multiple monitors. Please note, however, that if your monitors have different DPI, the composite image is of the raw pixels, so the forms may be of different scale in the final .BMP file, depending on which monitor they are located on.