Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[98.84.18.52] |
|
Сообщ.
#1
,
|
|
|
Тут у нас несколько раз подымались темки о прозрачности формы в ХР, но так чтобы были не прозрачны контролы или на оборот. Но единственное чем заканчивались подобные темы – «Не возможно в XP такое». Ну, как говорится «Если сильно хочется то можна». Темболее что этот эффект уже используется в нескольких программах (например фотошоп десятый).
Что мы зделаем? Создадим две формы и зделаем так чтобы они реагировали как одна. Приступим. Создадим новый модуль (В последствии его будем подключать к нашим формам). Создим два типа: TChildForm (дочернее окно), TParentForm (родительское окно). TChildForm = class(TForm) private protected ParentForm: TParentForm; procedure CreateParams(var Params: TCreateParams); override; procedure WMActivate(var Message: TWMActivate); message WM_ACTIVATE; procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; public constructor Create(AOwner: TComponent); override; end; TParentForm = class(TForm) private protected FChildForm:TChildForm; procedure WMWindowPosChanged(var MSG: TWMWindowPosChanged); message WM_WINDOWPOSCHANGED; public function GetRect:TRect; published property ChildForm:TChildForm read FChildForm write FChildForm; end; Если Вы заметили то в каждом класе в нутри будет хранится дочерняя/родительская форма. Теперь по порядку с обработчиками дочирной формы: Кто создаст тот и родитель constructor TChildForm.Create(AOwner: TComponent); begin if AOwner<>nil then ParentForm:=TParentForm(AOwner); inherited; end; Ну и самое главное перекрыть CreateParams, так как нам нужно чтобы дочирняя форма всегда была над родительской. procedure TChildForm.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); with Params do begin if ParentForm <> nil then WndParent := ParentForm.handle; // вот после этой строки мы и будет она висеть сверху // но если форма главная то этот код делать не обязательно // SetWindowLong(ParentForm.Handle, GWL_STYLE, Style); // тут можна передать стиль дочерней формы в Style := WS_POPUP; // делаем форму без бордюра меню и тд. end; end; Ну и дополнтеные, не столь важные обработчики. Отслежывание изминения заголовка procedure TChildForm.CMTextChanged(var Message: TMessage); begin if ParentForm <> nil then ParentForm.Caption := Caption; end; поддержка авкивности бордюра, когда активна дочерняя форма procedure TChildForm.WMActivate(var Message: TWMActivate); begin if ParentForm <> nil then SendMessage(ParentForm.Handle, WM_NCACTIVATE, 1, 0); end; Теперь обработчики главной формы: Обработка ресайза или перемещения формы procedure TParentForm.WMWindowPosChanged(var MSG: TWMWindowPosChanged); begin inherited; if FChildForm <> nil then FChildForm.BoundsRect := GetRect; end; Получение позиции для дочерней формы function TParentForm.GetRect: TRect; var iBorder,iFrame,iCaption:integer; begin iBorder := GetSystemMetrics(SM_CXBORDER); iFrame := GetSystemMetrics(SM_CYDLGFRAME); iCaption := GetSystemMetrics(SM_CYCAPTION); result.Left := BoundsRect.Left + iBorder + iFrame; result.Right := BoundsRect.Right - iBorder - iFrame; result.Bottom := BoundsRect.Bottom - iBorder - iFrame; result.Top := BoundsRect.Top + iBorder + iFrame + iCaption; // то что сверху и снизу бедут делать идентычну работу // я просто зделал по меньше вызовов процедуры GetSystemMetrics { result.Left:=BoundsRect.Left + GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CYDLGFRAME); result.Right:=BoundsRect.Right - GetSystemMetrics(SM_CYBORDER) - GetSystemMetrics(SM_CYDLGFRAME); result.Bottom:=BoundsRect.Bottom - GetSystemMetrics(SM_CXBORDER) - GetSystemMetrics(SM_CYDLGFRAME); result.Top:=BoundsRect.Top + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYDLGFRAME) + GetSystemMetrics(SM_CYCAPTION); } end; Теперь если вы создадите две формы. подключите этот модуль. В одной форме поменяете родительский клас на TParentForm а в дочерней на TChildForm и запустите на выполнения то не должно ничего показывать того что это две формы. При этом вы можете поменять параметры AlphaBlend . Но когда вам захочется закрыть форму то тут они будут разноглавствовать. Ну что ж… перекрываем в главной обработчик CloseQuery … function CloseQuery: Boolean; override; … function TParentForm.CloseQuery: Boolean; var CAction: TCloseAction; begin result := true; FCloseFlag := true; // ставим флаг, что главная занимается закритием дочерней формы if FChildForm <> nil then with FChildForm do begin result := CloseQuery; // вызываем у дочерней обработчик CloseQuery (вдруг пользователь чтото сохранить хочет) if result then begin CAction := caNone; DoClose(CAction); // вызываем обработчик Close (но нам побарабону что он там вернет ведь решает главная ) free; // Уничтожаем end; end; FCloseFlag := not result; end; Теперь при закрытии главной формы будет закрыватся и дочерняя, при этом будут вызваны все пользовательские обработчики. Но что будет если закрытие поступит из дочерней? И эта проблема решается В поле public созадем процедуру close которая заменит оригинальную procedure TChildForm.close; begin if ParentForm <> nil then if not ParentForm.CloseFlag then ParentForm.Close; // проверяем. Может главная уже делает закритие дочерней // если нет то закрываем главную, а не дочернюю end; вот и все. Теперь вы можете експерементировать дальше. Например если к дочерней форме применить пример Rouse_ Делаем прозрачное окно то будут не прозрачны только контролы. Весь пример прикрепляю (в нутри архива положил и скрин шот как это выглядит у меня) Эта тема была разделена из темы "Прозрачная форма и НЕ прозрачные компоненты" Прикреплённый файлAlphaForm.zip (22.4 Кбайт, скачиваний: 403) |