Подведу резюме.Сам долго искал решение и собрав его по разрозненным данным описываю.
Я опишу даже немного более общий случай, нежели топикстартер.
Задача:Иногда, требуется написать программу, состоящую из нескольких независимых окон. Например, в вашем приложении можно вызвать какой-то диалог-утилиту, и нужно иметь возможность переключиться обратно на главное окно и вообще работать в обоих окнах одновременно и не мешая друг другу. Имеется в виду, что окна должны получить свою кнопку в таскбаре, независимо сворачиваться и т.п.
Проблема:При решении "влоб", когда мы просто устанавливаем родительское окно в ноль у всех других форм, кроме главной:
SetWindowLong(Handle, GWL_HWNDPARENT, 0);
у каждой формы действительно получится своя кнопка в таскбаре, но всплывает много проблем, например:
- всплывающие подсказки (Hint) всегда активируют первую форму, что в принципе становится не юзабельно.
- все сочетания клавиш из главного меню первой формы все равно работают во всех формах. Это часто не нужно, например в главной форме есть хоткеи из одной буквы (типа быстрые действия), и после этого во второй форме нельзя набирать текст, потому что буквы обрабатываются как хоткеи в главной форме.
- OpenDialog и прочие подобные штуки при вызове активируют главную форму на передний план, что не красиво.
- Короче говоря, действия с другими окнами всегда получают какую-нибудь нежелательную связь с главной формой.
Решение:1. Создаем форму-заглушку. Она примет на себя роль "главной формы", т.е. её нужно поставить первой на создание в файле .dpr, но она всегда будет скрыта. В её конструкторе пишем так:
procedure TFormAppStub.FormCreate(Sender: TObject);
begin
Application.ShowMainForm := false;
SetWindowLong(Handle, GWL_HWNDPARENT, 0);
SetWindowLong(Application.Handle, GWL_HWNDPARENT, Handle);
end;
Здесь меняются местами дочернесть окна приложения и нашей формы. Если этого не сделать, то в таскбаре останется кнопка от окна приложения, что нам не надо.
2. Все формы, которые будут "самостоятельными", создаем с такими параметрами:
procedure TFormMain.FormCreate(Sender: TObject);
begin
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_APPWINDOW);
SetWindowLong(Handle, GWL_HWNDPARENT, 0);
end;
Здесь мы делаем форму полностью самостоятельным окном - устанавливаем принудительный стиль "главного окна" (это означает, что windows в любом случае выдаст личную кнопку в таскбаре) и убираем родительское окно, которое по умолчанию окно application.
Хочу заметить, что работать будет и если оставить только одну из этих строк, причем любую, но не всегда, точно не помню, но какой-то из описанных юзкейсов, из начала этого поста, заработает неправильно. В общем, одновременно обе строки работют хорошо, исключительно мой опыт.
3. Формы, которые не должны получать своей кнопки, должны работать как раньше, но для надежности лучше им явно указывать родительское окно:
procedure TFormListItemEdit.FormCreate(Sender: TObject);
begin
SetWindowLong(Handle, GWL_HWNDPARENT, FormList.Handle);
end;
4. Не забываем, что теперь завершение приложения это закрытие уже не главной формы с точки зрения Application, а нашей новой главной формы. В общем, если так задумано, то пишем:
procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Application.Terminate;
end;
Всё, мы получили независимые окна, которые никоим образом не мешают друг другу жить.
А дальше у каждого своя голова, как это поднастроить под ваши задачи.
Надеюсь кому-нибудь пригодиться.