Форум: "WinAPI";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
ВнизОкно на передний план ! Найти похожие ветки
← →
gdaujk © (2005-06-13 13:50) [0]Столкнулся со следующей проблеммой. Мне надо, что бы при получении окошком моей программы сообщения WM_XXX, оно(окошко) показалось пользователю на глаза. В оконной процедуре пишу:
if Msg = WM_XXX then
begin
ShowWindow(MainWnd, SW_SHOWNORMAL);
SetForegroundWindow(MainWnd);
end;
Если моё окошко было свёрнуто до получения WM_XXX, то оно восстанавливается и выходит на передний план, как и задумывалось.
Но если окно свёрнуто не было, а просто находилось на заднем плане, то на передний оно не выходит, а начинает мигать на панели задач. Нехорошо :-).
PS: Eсли те же две функции вызвать из другого приложения, передав им хендл моего окошка, то всё работает отлично - окно показывается в любом случае.
Подскажите, как сделать, что бы оконце выходила на передний план в любом случае?
← →
gdaujk © (2005-06-13 15:33) [1]Ну и...
← →
Ученик (2005-06-13 19:47) [2]>gdaujk © (13.06.05 13:50)
Возможно, поможет
var
hForeGround : HWnd;
begin
hForeGround := GetForegroundWindow;
AttachThreadInput(GetWindowThreadProcessId(hForeGround, nil),
GetWindowThreadProcessId(Handle, nil), True);
SetForegroundWindow(Handle);
end;
← →
gdaujk © (2005-06-14 07:49) [3]Неа, AttachThreadInput не помог.
Попробую поставить проблему шире. Использую мьютексы для избежания повтороного запуска приложения. Так вот второй экземпляр в самом начале узнаёт, что но не первый :-) Ему конечно можно просто вырубиться, но лучше чтоб он перед этим передал управление первому экземпляру. Для эого он и посылает первому (да и всем остальным окнам) сообщение WM_XXX. А тот при получении сообщения, по моему замыслу, показывает себя пользователю. Вот последний пункт и не выходит :-(
PS: Видел вариант, при котором первый экземпляр после получения WM_XXX слал второму ответное сообщение - WM_YYY, в котором передавал хендал своего окна, а тот уже занимался выводом первого на глаза ползователю. Но там у обоих экземпляров приложения уже были созданы окна. У меня же окно только у первого. Как же ему передать хендал?
← →
dmitry501 © (2005-06-14 08:45) [4]gdaujk © (14.06.05 7:49) [3]
Мигание кнопки на панели задач
Время, отведенное на мигание
Когда программа требует ввода данных, она может либо выскочить на передний план, либо начать мигать кнопкой на панели задач. Вы можете установить время,в течении которого программа будет сигнализировать перед этим выходом. Для этого нужно в разделе
HKEY_CURRENT_USER\Control Panel\Desktop создать или изменить параметр ForegroundLockTimeout типа DWORD и установить его значение на время задержки до "перехвата" фокуса в миллисекундах: 0 — окно сразу выскакивает вперед, 200 000 — значение по умолчанию.
Количество миганий
Также вы можете установить число миганий кнопки. Для этого надо в этом же разделе создать или изменить DWORD-параметр ForegroundFlashCount и установить его значение на нужное число миганий для привлечения внимания пользователя. Значения устанавливаются в десятичной системе: 0 заставит кнопку мигать бесконечно, по умолчанию значение равно 3
← →
Ботвин Дмитрий (2005-06-14 08:51) [5]Попробуй BringWindowToTop(Handle)
← →
DVM © (2005-06-14 10:06) [6]Windows 98/2000 doesn"t want to foreground a window when
some other window has the keyboard focus.
ForceForegroundWindow is an enhanced SetForeGroundWindow/bringtofront
function to bring a window to the front.
}
{
Manchmal funktioniert die SetForeGroundWindow Funktion
nicht so, wie sie sollte; besonders unter Windows 98/2000,
wenn ein anderes Fenster den Fokus hat.
ForceForegroundWindow ist eine "verbesserte" Version von
der SetForeGroundWindow API-Funktion, um ein Fenster in
den Vordergrund zu bringen.
}
function ForceForegroundWindow(hwnd: THandle): Boolean;
const
SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
var
ForegroundThreadID: DWORD;
ThisThreadID: DWORD;
timeout: DWORD;
begin
if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE);
if GetForegroundWindow = hwnd then Result := True
else
begin
// Windows 98/2000 doesn"t want to foreground a window when some other
// window has keyboard focus
if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or
((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and
(Win32MinorVersion > 0)))) then
begin
// Code from Karl E. Peterson, www.mvps.org/vb/sample.htm
// Converted to Delphi by Ray Lischner
// Published in The Delphi Magazine 55, page 16
Result := False;
ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil);
ThisThreadID := GetWindowThreadPRocessId(hwnd, nil);
if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then
begin
BringWindowToTop(hwnd); // IE 5.5 related hack
SetForegroundWindow(hwnd);
AttachThreadInput(ThisThreadID, ForegroundThreadID, False);
Result := (GetForegroundWindow = hwnd);
end;
if not Result then
begin
// Code by Daniel P. Stasinski
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),
SPIF_SENDCHANGE);
BringWindowToTop(hwnd); // IE 5.5 related hack
SetForegroundWindow(hWnd);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE);
end;
end
else
begin
BringWindowToTop(hwnd); // IE 5.5 related hack
SetForegroundWindow(hwnd);
end;
Result := (GetForegroundWindow = hwnd);
end;
end; { ForceForegroundWindow }
// 2. Way:
//**********************************************
procedure ForceForegroundWindow(hwnd: THandle);
// (W) 2001 Daniel Rolf
// http://www.finecode.de
// rolf@finecode.de
var
hlp: TForm;
begin
hlp := TForm.Create(nil);
try
hlp.BorderStyle := bsNone;
hlp.SetBounds(0, 0, 1, 1);
hlp.FormStyle := fsStayOnTop;
hlp.Show;
mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
SetForegroundWindow(hwnd);
finally
hlp.Free;
end;
end;
// 3. Way:
//**********************************************
// by Thomas Stutz
{
As far as you know the SetForegroundWindow function on Windows 98/2000 can
not force a window to the foreground while the user is working with another window.
Instead, SetForegroundWindow will activate the window and call the FlashWindowEx
function to notify the user. However in some kind of applications it is necessary
to make another window active and put the thread that created this window into the
foreground and of course, you can do it using one more undocumented function from
the USER32.DLL.
void SwitchToThisWindow (HWND hWnd, // Handle to the window that should be activated
BOOL bRestore // Restore the window if it is minimized
);
}
procedure SwitchToThisWindow(h1: hWnd; x: bool); stdcall;
external user32 Name "SwitchToThisWindow";
{x = false: Size unchanged, x = true: normal size}
procedure TForm1.Button2Click(Sender: TObject);
begin
SwitchToThisWindow(FindWindow("notepad", nil), True);
end;
← →
gdaujk © (2005-06-14 12:00) [7]>>Ботвин Дмитрий
Не помогает, но спасибо :-)
>>DVM
Щас попробую, только с учёбы пришёл :-) Спасибо...
← →
gdaujk © (2005-06-14 12:34) [8]SwitchToThisWindow - делает то же самое, поэтому наверное и не документированна.
А вот вариант один, правда урезанный мной до:
if IsIconic(MainWnd)
then ShowWindow(MainWnd, SW_RESTORE)
else
begin
AttachThreadInput(
GetWindowThreadProcessId(GetForegroundWindow, nil),
GetWindowThreadProcessId(MainWnd, nil), True);
SetForegroundWindow(MainWnd);
AttachThreadInput(
GetWindowThreadProcessId(GetForegroundWindow, nil),
GetWindowThreadProcessId(MainWnd, nil), False);
end;
в XP работет замечательно.
Только можно объяснить, зачем
BringWindowToTop(hwnd); // IE 5.5 related hack
и зачем проверка номера Винды, если
Windows 98/2000 doesn"t want...???
← →
gdaujk © (2005-06-14 12:39) [9]Вариант два совсем не пойдёт, ибо:
1. Я не создаю окно второго экземпляра, не буду создавать и второе окно у первого, это слишком долго...
2. VCL, а я пишу на API...
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.012 c