Несколько людей уже спрашивали, как залить фон главной MDI-формы
повторяющимся изображением. Ключевым моментом здесь является работа с
дескриптором окна MDI-клиента (свойство ClientHandle) и заполнение изображением
окно клиента в ответ на сообщение WM_ERASEBKGND. Тем не менее здесь существует
пара проблем: прокрутка главного окна и перемещение дочернего MDI-окна за
пределы экрана портят фон, и закрашивание за иконками дочерних окон не
происходит.
Ну наконец-то! Похоже я нашел как решить обе проблемы. Вот код для тех, кому
все это интересно. Я начинаю с проблемы дочерних форм, ниже код для решения
проблемы с главной формой (модули с именами MDIWAL2U.PAS и MDIWAL1U.PAS). На
главной форме расположен компонент TImage с именем Image1, содержащий
изображение для заливки фона.
...
{ Private declarations }
bmW, bmH: Integer;
FClientInstance,
FPrevClientProc: TFarProc;
procedure ClientWndProc(varMessage: TMessage);
publicprocedure PaintUnderIcon(F: TForm; D: hDC);
...
procedure TForm1.PaintUnderIcon(F: TForm; D: hDC);
var
DestR, WndR: TRect;
Ro, Co,
xOfs, yOfs,
xNum, yNum: Integer;
begin{вычисляем необходимое число изображений для заливки D}
GetClipBox(D, DestR);
with DestR dobegin
xNum := Succ((Right - Left) div bmW);
yNum := Succ((Bottom - Top) div bmW);
end;
{вычисление смещения изображения в D}
GetWindowRect(F.Handle, WndR);
with ScreenToClient(WndR.TopLeft) dobegin
xOfs := X mod bmW;
yOfs := Y mod bmH;
end;
for Ro := 0 to xNum dofor 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(varMessage: TMessage);
var
Ro, Co: Word;
beginwithMessagedocase Msg of
WM_ERASEBKGND:
beginfor Ro := 0 to ClientHeight div bmH dofor 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;
Перевод контента на русский язык:
Код, предоставленный в этом решении, является решением для заполнения фона MDI-формы повторяющимся изображением. Ключевой момент заключается в обработке описания клиентского окна MDI (свойство ClientHandle) и заполнении клиентского окна изображением в ответ на сообщение WM_ERASEBKGND.
Однако, есть два проблемы: прокрутка основного окна и перемещение дочернего окна MDI за пределы области экрана портят фон; и рисование за иконками дочерних окон не происходит.
Автор, похоже, нашел решение для обоих проблем. Код использует компонент TImage с именем Image1, содержащий изображение, которое будет заполнять фон на основной форме. Процедура WMIconEraseBkgndOverride рисует за иконкой.
Вот некоторые наблюдения и предложения:
В процедуре WMIconEraseBkgndOverride вызов TForm1(Application.MainForm).PaintUnderIcon(Self, Message.DC) кажется ненужным, потому что не ясно, почему мы должны передавать сообщение другому форму.
Процедура ClientWndProc интересна, поскольку она обрабатывает различные сообщения, такие как WM_ERASEBKGND, WM_VSCROLL и WM_HSCROLL. Это может потенциально вызвать проблемы, если несколько форм используют этот код.
Альтернативное решение:
Вместо переопределения сообщения WMIconEraseBkgnd можно использовать объект TBitMap для рисования изображения в событии OnPaint вашей формы. Вот пример:
procedureTForm1.OnPaint(varPaintMessage:TPaintMessage);beginwithPaintMessage.CanvasdobeginBrush.Style:=bsSolid;Brush.Color:=clWhite;// или любое другое значение цвета, которое вы хотите для фонаFillRect(Rect(0,0,ClientWidth,ClientHeight));// Рисуйте ваше изображение здесь// Например:BitBlt(Canvas.Handle,0,0,Image1.Width,Image1.Height,Image1.Picture.Bitmap.Canvas.Handle,0,0,SRCCOPY);end;end;
В этом коде мы сначала рисуем фон белым цветом. Затем мы рисуем наше изображение с помощью BitBlt.
Это решение более простое и не требует обработки низкоуровневых сообщений, таких как WM_ERASEBKGND.
Заполнение изображением MDI-формы 2: решается проблема прокрутки главного окна и перемещения дочернего MDI-окна за пределы экрана, а также закрашивание за иконками дочерних окон.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.