A: The basic technique involved subclassing the MDI client window (ClientHandle property) and responding to WM_ERASEBKGND by tiling the bitmap on the client window. However, there were a couple of problems; scrolling the main window to bring an off-screen child into view would screw up the background, and the background didn't get painted correctly behind the child window icons.
Well, HOORAY! I think I've whupped both those problems. Here's the code,
for those who are interested. I'll start with the child form's code, followed
by the main form's (units are named MDIWAL2U.PAS and MDIWAL1U.PAS). The
main form is assumed to have the desired bitmap in a TImage named Image1.
...
private
{ Private declarations }
procedure WMIconEraseBkgnd(VAR Message: TWMIconEraseBkgnd);
message WM_ICONERASEBKGND;
...
USES MdiWal1u;
procedure TForm2.WMIconEraseBkgnd(VAR Message: TWMIconEraseBkgnd);
BEGIN
TForm1(Application.Mainform).PaintUnderIcon(Self, Message.DC);
Message.Result := 0;
END;
================================================================
...
{ Private declarations }
bmW, bmH : Integer;
FClientInstance,
FPrevClientProc : TFarProc;
PROCEDURE ClientWndProc(VAR Message: TMessage);
public
PROCEDURE PaintUnderIcon(F: TForm; D: hDC);
...
PROCEDURE TForm1.PaintUnderIcon(F: TForm; D: hDC);
VAR
DestR, WndR : TRect;
Ro, Co,
xOfs, yOfs,
xNum, yNum : Integer;
BEGIN
{calculate number of tilings to fill D}
GetClipBox(D, DestR);
WITH DestR DO
BEGIN
xNum := Succ((Right-Left) DIV bmW);
yNum := Succ((Bottom-Top) DIV bmW);
END;
{calculate offset of image in D}
GetWindowRect(F.Handle, WndR);
WITH ScreenToClient(WndR.TopLeft) DO
BEGIN
xOfs := X MOD bmW;
yOfs := Y MOD bmH;
END;
FOR Ro := 0 TO xNum DO
FOR Co := 0 TO yNum DO
BitBlt(D, Co*bmW-xOfs, Ro*bmH-Yofs,
bmW, bmH,
Image1.Picture.Bitmap.Canvas.Handle,
0, 0, SRCCOPY);
END;
PROCEDURE TForm1.ClientWndProc(VAR Message: TMessage);
VAR Ro, Co : Word;
begin
with Message do
case Msg of
WM_ERASEBKGND:
begin
FOR Ro := 0
TO ClientHeight DIV bmH DO
FOR Co := 0 TO ClientWIDTH DIV bmW DO
BitBlt(TWMEraseBkGnd(Message).DC,
Co*bmW, Ro*bmH, bmW, bmH,
Image1.Picture.Bitmap.Canvas.Handle,
0, 0, SRCCOPY);
Result := 1;
end;
WM_VSCROLL,
WM_HSCROLL :
begin
Result := CallWindowProc(FPrevClientProc,
ClientHandle, Msg, wParam, lParam);
InvalidateRect(ClientHandle,
NIL, True);
end;
else
Result := CallWindowProc(FPrevClientProc,
ClientHandle, Msg, wParam,
lParam);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
bmW := Image1.Picture.Width;
bmH := Image1.Picture.Height;
FClientInstance := MakeObjectInstance(ClientWndProc);
FPrevClientProc := Pointer(
GetWindowLong(ClientHandle, GWL_WNDPROC));
SetWindowLong(ClientHandle, GWL_WNDPROC,
LongInt(FClientInstance));
end;