Ответ 1
То, что для PopupMode
и PopupParent
свойств для.
Например, вы можете:
Dialog1.PopupMode := pmExplicit;
Dialog1.PopupParent := self;
Dialog1.ShowModal;
Это говорит Windows о правильном Z-порядке.
Много раз после эпохи Windows 98 мы столкнулись с тем, что некоторые диалоги теряют свой Z-порядок и возвращаются к предыдущей форме.
Например:
Dialog1.ShowModal;
Dialog1.OnClickButton() : ShowMessage('anything');
Когда появляется MessageBox, он иногда не имеет фокуса и перемещается под Dialog1. Пользователи смущены этим, они говорят: мое приложение замерло!!! Но если они используют Alt + Tab для перехода в другое приложение и обратно, фокус возвращается в MessageBox, и это будет окно переднего плана.
Мы испытали это с ShowMessage, MessageBox, нормальными формами, а также с формами QuickReport.
Кто-нибудь знает об этом? Это ошибка Windows? Как вы можете это предотвратить? Как это поймать?
Спасибо за вашу помощь: дд
Я действительно сказал, что ПОСЛЕ Win98, поэтому все ОС (Win7 также) затронуты этой проблемой. Мы использовали Delphi 6 Prof, поэтому свойства не работают с формами по умолчанию.
Кто-то сказал, что диалоговые окна сообщений управляются с помощью MessageBox + MB_APPLMODAL. Это хорошая новость, но у нас много старых форм и компонентов, сторонних инструментов.
Так что тяжелая работа - сделать совершенно новое приложение с заменой форм.
Но мы постараемся сделать это.
Я думаю, что ответ - это проблема с половинным приложением и проблема с половиной Windows. Если Windows иногда обрабатывает это, а иногда и нет - кажется, это ошибка Windows. Но если мы сможем заставить хорошие модальные окна сделать, это ошибка программирования.
Может кто-нибудь объяснить мне, что означает флаг WS_POPUP? Имеет ли он какой-то побочный эффект или нет?
Спасибо: дд
То, что для PopupMode
и PopupParent
свойств для.
Например, вы можете:
Dialog1.PopupMode := pmExplicit;
Dialog1.PopupParent := self;
Dialog1.ShowModal;
Это говорит Windows о правильном Z-порядке.
Для старых версий delphi (до Delphi 2007), в формах OTHER, чем ваша основная форма:
interface
TMyForm = Class(TForm)
protected
procedure CreateParams(var Para: TCreateParams); override;
end;
...
implementation
...
procedure TMyForm.CreateParams(var Para: TCreateParams);
begin
inherited;
Para.Style := Para.Style or WS_POPUP;
{ WinXP Window manager requires this for proper Z-Ordering }
// Para.WndParent:=GetActiveWindow;
Para.WndParent := Application.MainForm.Handle;
end;
Для сообщений в MBF необходимо указать MB_TOPMOST:
Application.MessageBox(PChar(amessage), PChar(atitle), otherflags or MB_TOPMOST);
Я просмотрел эту страницу и часто задаваемые вопросы в течение получаса и все еще не могу найти, как опубликовать комментарий, поэтому простите меня за это нарушение протокола.
Прежде всего, я хотел бы пояснить, что плакат IMHO не использует Windows 98. Он пишет "после эпохи Windows 98", который, как я понимаю, означает, что у него такая проблема с версиями Windows после 98.
Поскольку у меня тоже есть эта проблема (CB2009), я хотел бы подчеркнуть вопрос о плакате "Это ошибка Windows?", о которой я не видел. Если это ошибка Delphi/Builder, возможно, есть способ избежать этого? Я не вижу, как перехватывать все потенциальные диалоги является работоспособным решением или не использовать fsStayOnTop. У меня есть форма настроек, которая должна оставаться поверх моей основной формы, но форма настроек может включать и вызывать всплывающие диалоги, которые при определенных условиях исчезают в форме настроек.
Было бы очень полезно, если бы я понял, где поддержка z-порядка идет не так, поскольку она может предложить ключ к тому, как этого избежать.
Трюк, который я использовал недавно, заключался в применении этих двух строк кода при создании каждой формы:
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);
Ручка - это дескриптор формы (Form1.Handle). Часть WS_EX_APPWINDOW делает каждое окно появляться на панели задач, удаляя его, если вы не хотите этого дополнительного эффекта.
В моей основной форме я использую эту строку:
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_TOPMOST);
Я также использую эту функцию для создания собственных диалоговых окон (я создал новую функцию для каждого стиля диалога - ошибка, подтверждение и т.д.):
function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm;
begin
Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton);
with Result do
begin
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow);
FormStyle := fsStayOnTop;
BringToFront;
end;
end;
Конечно, часть FormStyle := fsStayOnTop;
является необязательной, но я использую ее, чтобы убедиться, что мои диалоги подтверждения и ошибки всегда отображаются пользователю.
Кажется, что немного работы, но чистый эффект заключается в том, что мне больше не нужно беспокоиться о формах, случайно скрывающихся за другими формами.