Заказчику нужно было окно, которое появляется поверх других приложений.
Мотивация такая: "Когда диспетчер смотрит фильм, необходимо чтобы тревога выскакивала у него поверх всего".
К счастью код на скрипте так и заработал.
Скрипт использует VCL от Builder6 для создания окон.
Код окна такой:
За стили отвечают выделенные фрагменты.
Не скажу точно, как оно ложится на WIN API.
Если надо, могу посмотреть Spy++.
Вопрос в том, почему это работает?
Бывает пытаешься создать такое окно, а оно не выходит.
Помигает твоё приложение в taskbar и всё. Мол пользователь сам княпнуть должен, чтобы сделать приложение
(главное окно приложения) активным.
Читал, что по дизайну это некошерно, когда выскакивают окна неактивных приложений.
Поэтому, код, который это делает, теперь только мигает в taskbar'e.
А тут само появилось. При определённых условиях вообще от него фиг избавишься.
Окно выскакивает и в XP, и в Win7.
Или некошерно только для модальных окон?
В общем кто может авторитетно просветить по этому вопросу?
Здравствуйте, Шебеко Евгений, Вы писали:
ШЕ>За стили отвечают выделенные фрагменты. ШЕ>Не скажу точно, как оно ложится на WIN API. ШЕ>Вопрос в том, почему это работает?
В твоем коде судя по названиям окну добавляются стили WS_EX_TOPMOST и WS_EX_TOOLWINDOW. Окно показывает стиль WS_EX_TOPMOST. Но обычно он не делает окно активным как SetForegroundWindow(), только показывает поверх других.
Здравствуйте, CoolCmd, Вы писали:
CC>Здравствуйте, Шебеко Евгений, Вы писали:
ШЕ>>За стили отвечают выделенные фрагменты. ШЕ>>Не скажу точно, как оно ложится на WIN API. ШЕ>>Вопрос в том, почему это работает? CC>В твоем коде судя по названиям окну добавляются стили WS_EX_TOPMOST и WS_EX_TOOLWINDOW. Окно показывает стиль WS_EX_TOPMOST. Но обычно он не делает окно активным как SetForegroundWindow(), только показывает поверх других.
Активным его делает (и вообще показывает) fm.Show();
Вот исходники VCL. Там вообще много кода, особенно связанными со свойствами.
Я выдрал только часть.
procedure TCustomForm.Show;
begin
Visible := True;
BringToFront;
end;
procedure TCustomForm.SetVisible(Value: Boolean);
begin
if fsCreating in FFormState then
if Value then
Include(FFormState, fsVisible) else
Exclude(FFormState, fsVisible)
else
beginif Value and (Visible <> Value) then SetWindowToMonitor;inherited Visible := Value;
end;
end;
procedure TControl.BringToFront;
begin
SetZOrder(True);
end;
procedure TWinControl.SetZOrder(TopMost: Boolean);
const
WindowPos: array[Boolean] of Word = (HWND_BOTTOM, HWND_TOP);
var
N, M: Integer;
begin
if FParent <> nil then
begin
if TopMost then N := FParent.FWinControls.Count - 1 else N := 0;
M := 0;
if FParent.FControls <> nil then M := FParent.FControls.Count;
SetZOrderPosition(M + N);
end
else if FHandle <> 0 then SetWindowPos(FHandle, WindowPos[TopMost], 0, 0, 0, 0,
SWP_NOMOVE + SWP_NOSIZE);end;
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Шебеко Евгений, Вы писали:
ШЕ>>fm.FormStyle=fsStayOnTop;[/b]
PD>Подозреваю, что это CreateWindowEx/WS_EX_TOPMOST.
PD>Создаем в VC++ Win32 проект и в нем меняем
PD> hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, PD> CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
PD>на
PD> hWnd = CreateWindowEx(WS_EX_TOPMOST,szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, PD> CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
PD>Сидит наверху как влитое, как ни переключайся на другие окна.
PD>Можно также менять по ходу работы
PD>SetWindowPos c HWND_TOPMOST / HWND_NOTOPMOST
У вас на win7 этот способ работает?
Дело в том, что я недавно как раз с этим возился. На XP да, работает как часы.
Но на Win7 сработал только способ со сбросом таймаута в ноль (SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT).
Ни SetWindowPos, ни какие-либо манипуляции с z-order не помогли.
Re[3]: окно поверх других приложений когда и почему
5er>У вас на win7 этот способ работает? 5er>Дело в том, что я недавно как раз с этим возился. На XP да, работает как часы. 5er>Но на Win7 сработал только способ со сбросом таймаута в ноль (SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT). 5er>Ни SetWindowPos, ни какие-либо манипуляции с z-order не помогли.
Работает. Я только что проверил.
Только это ведь единственное окно приложения.
Скажем будет ли такое же работать, если:
1. основное окно не WS_EX_TOPMOST
2. Запустили приложение и переключились в другое.
3. А потом возникает ещё одно окно нашего приложения уже с WS_EX_TOPMOST
Вопрос в том, вылезет ли оно поверх чужого приложения или нет?
Re[3]: окно поверх других приложений когда и почему
Здравствуйте, Шебеко Евгений, Вы писали:
5er>>У вас на win7 этот способ работает? 5er>>Дело в том, что я недавно как раз с этим возился. На XP да, работает как часы. 5er>>Но на Win7 сработал только способ со сбросом таймаута в ноль (SystemParametersInfo SPI_SETFOREGROUNDLOCKTIMEOUT). 5er>>Ни SetWindowPos, ни какие-либо манипуляции с z-order не помогли.
ШЕ>Работает. Я только что проверил. ШЕ>Только это ведь единственное окно приложения.
Делаем заново Win32 проект, без моих изменений. Там есть диалог About. В его функции
case WM_INITDIALOG:
SetWindowPos(hDlg, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
return (INT_PTR)TRUE;
Основное окно теперь не topmost, а диалог, если его показать сидит как влитой, хоть что делай.
With best regards
Pavel Dvorkin
Re[5]: окно поверх других приложений когда и почему
PD>Основное окно теперь не topmost, а диалог, если его показать сидит как влитой, хоть что делай.
Да,да я проверил.
У меня здесь основное окно обычное, а по таймеру через 10 секунд создаётся About с WS_EX_TOPMOST.
Я допёр. Окно чудно появляется поверх всех окон даже в Win7.
Но оно неактивное. В том плане, что фокус остаётся у другого приложения.
Так что всё честно
Обычно все джигиты, которые делают топ(мост)-окна, забывают о юзерах, которые, например, набирают текст в блокноте. Юзер смотрит в клаву и набирает текст, тут джигит поднимает своё гордое окно поверх всех окон, юзер в наборе текста жмёт пробел — тынц, окно закрылось! Юзер смотрит на экран и думает, а чё это часть текста не пропечаталась?...
Здравствуйте, CEMb, Вы писали:
CEM>Обычно все джигиты, которые делают топ(мост)-окна, забывают о юзерах, которые, например, набирают текст в блокноте. Юзер смотрит в клаву и набирает текст, тут джигит поднимает своё гордое окно поверх всех окон, юзер в наборе текста жмёт пробел — тынц, окно закрылось! Юзер смотрит на экран и думает, а чё это часть текста не пропечаталась?...
Тьфублин, я чё сказать-то хотел! Вот у outpost сделано нормально — там окно появляется поверх всех окон, но оно — неактивное! Так делать надо