Вопрос, поднятый в данной теме, заключается в необходимости обеспечения стабильности положения дочернего элемента TFrame относительно клиентской области родительского окна в среде разработки Delphi. Это может быть важно, например, при использовании прозрачного маскирующего слоя, который должен оставаться привязанным к клиентской области, даже если родительское окно перемещается.
Проблема
Разрабатывая дочерний класс TFrame, который может содержать различные элементы управления в runtime, разработчик столкнулся с необходимостью показать визуальный затемненный "маск", используя отдельный класс TCustomForm с функцией AlphaBlend. Для корректной работы маски форма не должна иметь родительского элемента. При этом, необходимо обеспечить привязку окна к клиентской области TMyFrame, независимо от его изменения размеров или перемещения.
Решение
Для обеспечения корректного изменения размеров достаточно переопределить метод Resize класса TMyFrame. Однако, когда речь заходит о перемещении, ситуация усложняется. Так как TMyFrame клиентски выровнен относительно главного окна, его свойства Left и Top не изменяются при перемещении главного окна, и сообщение WM_MOVE не отправляется на TMyFrame.
В качестве решения предлагается использовать перехват сообщений WM_WINDOWPOSCHANGING и WM_WINDOWPOSCHANGED, которые позволяют отследить изменения положения родительского окна. Это можно сделать, используя свойство WindowProc родительской формы или же с помощью функции SetWindowSubclass() для подклассирования окна родителя.
Пример кода
uses
Winapi.Windows;
procedure WindowPosChanged(Window: HWND; NewPos: TWindowPos); stdcall;
var
Frame: TFrame;
begin
Frame := TFrame(TFrameClass(WindowOwner(Window)).ClassType.Create(nil));
with Frame do
begin
Left := NewPos.x;
Top := NewPos.y;
// Обновление положения других элементов, если необходимо
end;
SetWindowPos(Window, 0, NewPos.x, NewPos.y, 0, 0, SWP_NOSIZE);
end;
procedure RegisterWindowHook(Frame: TFrame);
var
SubclassProc: TSubclassProc;
begin
SubclassProc := @WindowPosChanged;
SetWindowSubclass(Frame.Parent.WindowHandle, SubclassProc, 0, SizeOf(TWindowPos));
end;
Применение
Функцию RegisterWindowHook следует вызвать при создании TMyFrame, чтобы подключить необходимый хук:
constructor TMyFrame.Create(AOwner: TComponent); override;
begin
inherited;
RegisterWindowHook(Self);
end;
Альтернативный ответ
Также был предложен альтернативный способ - вставить невидимый контрол в целевую форму, который будет отправлять уведомление для отсоединенной тени. Это похоже на то, как работают окна MDI в Windows.
Заключение
Используя предложенные методы, разработчик может обеспечить стабильность положения дочернего элемента относительно клиентской области родительского окна, что позволит ему оставаться реузируемым и независимым от конкретного родительского окна в иерархии.
Вопрос об обеспечении стабильности положения дочернего элемента в клиентской области родительского окна в среде разработки Delphi, особенно при использовании визуального затемнения и перемещении окна.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.