Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Hint от ToolBar выводит на передний план Form1  (Прочитано 14103 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Shouldercannon
Постоялец

ru
Offline Offline

« : 30-06-2010 10:21 » 

Открыл все три формы. На двух из них есть ToolBar с одной кнопкой имеющей Hint. При наведении курсора мыши на кнопку в Toolbar, после вывода Hint все остальные формы становятся позади основной (Form1) и причём вывести их можно на передний план только по клику на заголовоке, а не на теле формы. Даже если на Form2 навести курсор на кнопку ToolBar, то после вывода Hint снова на переднем плане Form1. Что за баг такой? И почему при двух открытых формах (Form1, Form2) при нажатии на кнопку в Form2 при показе Form3, Form2 уходит на задний план за Form1 и Form3, Должно же быть так: поверх Form1 Form2, а поверх Form2 Form3?

* Projects.rar (9.9 Кб - загружено 840 раз.)
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #1 : 30-06-2010 12:28 » 

а зачем понадобился Params.WndParent := GetDesktopWindow;? без него работает, вроде бы, корректно.
Записан

Shouldercannon
Постоялец

ru
Offline Offline

« Ответ #2 : 30-06-2010 14:09 » new

а зачем понадобился Params.WndParent := GetDesktopWindow;? без него работает, вроде бы, корректно.
Форма должна быть как "независимое приложение"

Проблема заключалась в Params.WndParent := GetDesktopWindow;.
Убрав Params.WndParent := GetDesktopWindow; появилась новая проблема. Открыты две формы, каждая из них имеет кнопку на панели задач. Если свернуть вторую форму, то всё нормально как были две кнопки на панели задач так и остались, но если свернуть первую (основную), то на панели задач остаётся кнопка только главной формы, а второй нет. Может есть альтернатива Params.WndParent := GetDesktopWindow;, менее проблематичная?
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #3 : 30-06-2010 14:57 » 

да есть, наверное, какая-то альтернатива, играться надо. например, попробовать ShowMainForm := FALSE; первую форму создавать также, как и вторую с парентом DeskTopWindow, и т.д.

но мне кажется, если "форма должна быть как независмое приложение" - легче и сделать её как независимое приложение, обеспечив взаимодействие между ними. через банальный SendMessage, например.
Записан

zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #4 : 30-06-2010 15:05 » 

Код:
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
 inherited CreateParams(Params);
 Params.ExStyle := Params.ExStyle or WS_Ex_AppWindow;
end;
И так для всех форм.
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #5 : 30-06-2010 15:17 » 

я так пробовал. но остаётся висеть иконка самого Application, а если втыкать ShowMainForm := FALSE - начинаются танцы с бубном.

ну, у меня, по крайней мере Улыбаюсь

з.ы. и один фиг при сворачивании основного окна сворачиваются и все остальные.
Записан

zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #6 : 30-06-2010 16:23 » 

1. Создаем пустую невидимую главную форму - TForm0
2. Главная форма при создании создает Form1
3. Все формы, кроме Form0 делаем  WS_Ex_AppWindow
4. При закрытии Form1 закрываем Form0.
Исправленный проект прилагаю.

* Projects.rar (188.18 Кб - загружено 804 раз.)
Записан
Shouldercannon
Постоялец

ru
Offline Offline

« Ответ #7 : 01-07-2010 09:15 » 

Пересмотрим систему. Убираем procedure CreateParams(var Params: TCreateParams); override; и переходим на
Код:

Код:
procedure TForm2.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_APPWINDOW);
end;

Теперь осталось решить проблему сворачиваниях всех открытых форм при сворачивании Form1 (Главной формы).
Записан
zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #8 : 01-07-2010 09:50 » 

Пересмотрим систему. Убираем procedure CreateParams(var Params: TCreateParams); override; и переходим на
Код:

Код:
procedure TForm2.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_APPWINDOW);
end;
А смысл? Что в лоб, что по лбу. Я понимаю, если бы менять стили надо было динамически, а у тебя они все равно при создании окна меняются.
Цитата
Теперь осталось решить проблему сворачиваниях всех открытых форм при сворачивании Form1 (Главной формы).
Не понял. Из твоих объяснений я понял, что наоборот плохо, когда при сворачивании главной формы сворачиваются и все остальные. Ну если нужен такой функционал, то порядок действий следующий:
1. В главной форме (то бишь в Form1) перехватываем мессагу WM_SYSCOMMAND
2. Проверяем у нее параметр wParam
if wParam = SC_MINIMIZE then
3. Посылаем остальным формам (предварительно проверив их на валидность) SendMessage(Form2.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0)
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #9 : 01-07-2010 14:41 » 

всё-таки, мне кажется, изврат это. если нужны две независимые проги - так и надо писать две независимые проги, а не пытаться в одну прогу засунуть два независимых окна. имха.
Записан

Shouldercannon
Постоялец

ru
Offline Offline

« Ответ #10 : 02-07-2010 08:46 » 

А если использовать мультипоточность?
Записан
zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #11 : 02-07-2010 10:39 » 

 RTFM
Записан
Vadikus
Новенький

ru
Offline Offline

« Ответ #12 : 12-10-2013 01:37 » 

Подведу резюме.

Сам долго искал решение и собрав его по разрозненным данным описываю.
Я опишу даже немного более общий случай, нежели топикстартер.

Задача:

Иногда, требуется написать программу, состоящую из нескольких независимых окон. Например, в вашем приложении можно вызвать какой-то диалог-утилиту, и нужно иметь возможность переключиться обратно на главное окно и вообще работать в обоих окнах одновременно и не мешая друг другу. Имеется в виду, что окна должны получить свою кнопку в таскбаре, независимо сворачиваться и т.п.

Проблема:

При решении "влоб", когда мы просто устанавливаем родительское окно в ноль у всех других форм, кроме главной:
Код:
SetWindowLong(Handle, GWL_HWNDPARENT, 0);
у каждой формы действительно получится своя кнопка в таскбаре, но всплывает много проблем, например:
  • всплывающие подсказки (Hint) всегда активируют первую форму, что в принципе становится не юзабельно.
  • все сочетания клавиш из главного меню первой формы все равно работают во всех формах. Это часто не нужно, например в главной форме есть хоткеи из одной буквы (типа быстрые действия), и после этого во второй форме нельзя набирать текст, потому что буквы обрабатываются как хоткеи в главной форме.
  • OpenDialog и прочие подобные штуки при вызове активируют главную форму на передний план, что не красиво.
  • Короче говоря, действия с другими окнами всегда получают какую-нибудь нежелательную связь с главной формой.

Решение:

1. Создаем форму-заглушку. Она примет на себя роль "главной формы", т.е. её нужно поставить первой на создание в файле .dpr, но она всегда будет скрыта. В её конструкторе пишем так:
Код: (Delphi)
procedure TFormAppStub.FormCreate(Sender: TObject);
begin
  Application.ShowMainForm := false;
  SetWindowLong(Handle, GWL_HWNDPARENT, 0);
  SetWindowLong(Application.Handle, GWL_HWNDPARENT, Handle);
end;
Здесь меняются местами дочернесть окна приложения и нашей формы. Если этого не сделать, то в таскбаре останется кнопка от окна приложения, что нам не надо.

2. Все формы, которые будут "самостоятельными", создаем с такими параметрами:
Код: (Delphi)
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. Формы, которые не должны получать своей кнопки, должны работать как раньше, но для надежности лучше им явно указывать родительское окно:
Код: (Delphi)
procedure TFormListItemEdit.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle, GWL_HWNDPARENT, FormList.Handle);
end;

4. Не забываем, что теперь завершение приложения это закрытие уже не главной формы с точки зрения Application, а нашей новой главной формы. В общем, если так задумано, то пишем:
Код: (Delphi)
procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Application.Terminate;
end;

Всё, мы получили независимые окна, которые никоим образом не мешают друг другу жить.
А дальше у каждого своя голова, как это поднастроить под ваши задачи.
Надеюсь кому-нибудь пригодиться.
« Последнее редактирование: 12-10-2013 07:54 от RXL » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines