Форум: "WinAPI";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
ВнизЧто передать в качестве окна для SetForegroundWindow ? Найти похожие ветки
← →
ANB © (2005-06-21 11:40) [0]Сделал вот такую функцию для перевода окна наверх :
procedure Set_Foreground_Window (hWindow : THandle);
var i : Integer;
dwTimeout : DWord;
begin
if (hWindow = 0) then Exit;
i := 0;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @dwTimeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, 0);
try
repeat
SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, SC_HOTKEY, hWindow);
SwitchToThisWindow(hWindow, True);
SetForegroundWindow(hWindow);
Inc(i);
until ((hWindow = GetForegroundWindow) or (i > 5));
finally
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, @dwTimeout, 0);
end;
end;
Есть избыточность, причем я еще и 5 раз это прокручиваю. Вставил в эту функцию отладку - проверяю - стало ли окно верхним (hWindow = GetForegroundWindow), прогнал с ней - постоянно ругается, типа хендлы не совпадают. Хотя на вид, визуально, вроде все работает. Собственно проблема следующая :
если я передаю хендл окна верхнего уровня - все пашет, а вот что передавать, если мне нужно поднять наверх MDI Child окно ? (хэндл самого окна или хэндл родительского окна ? Или есть еще какие варианты ?)
← →
Игорь Шевченко © (2005-06-21 12:50) [1]
> а вот что передавать, если мне нужно поднять наверх MDI
> Child окно
Надо вызывать функцию BringWindowToTop, SetWindowPos или аналогичную.
← →
ANB © (2005-06-21 14:50) [2]
> Игорь Шевченко © (21.06.05 12:50) [1]
- а им какой хендл передать ? И поможет ли ?
← →
Игорь Шевченко © (2005-06-21 14:52) [3]ANB © (21.06.05 14:50) [2]
> - а им какой хендл передать
handle нужного окна ? :)
> И поможет ли ?
Практика - критерий истины
← →
ANB © (2005-06-21 14:58) [4]
> Практика - критерий истины
- дык и в текущем варианте вроде все работает, тока пикает постоянно.
> handle нужного окна ? :)
- точно хэндл главного окна никуда подсовывать не надо ?
← →
Игорь Шевченко © (2005-06-21 15:19) [5]ANB © (21.06.05 14:58) [4]
> - точно хэндл главного окна никуда подсовывать не надо ?
Ну почему же - если приложение не на переднем плане, то его надо туда поместить
← →
ANB © (2005-06-21 16:00) [6]То есть оптимально сначала поднять приложение, а потом Child окно ?
А почему я сейчас поднимаю только Child и все работает, только не очень устойчиво (2-3% сбоев) и бибикает ?
← →
Игорь Шевченко © (2005-06-21 16:03) [7]ANB © (21.06.05 16:00) [6]
> А почему я сейчас поднимаю только Child и все работает,
> только не очень устойчиво (2-3% сбоев) и бибикает ?
А почему, когда я пью газировку, меня шибает не в нос, а в самую маковку ?
← →
ANB © (2005-06-21 17:04) [8]
> А почему, когда я пью газировку, меня шибает не в нос, а
> в самую маковку ?
- а меня тоже в маковку шибает.
← →
ANB © (2005-06-21 20:49) [9]Попробовал воткнуть в цепочку BringWindowToTop, сделал сначала подъем главного окна - стало еще хуже. Сбивается парой кликов по другим окнам. Вернул все на место - так надежнее.
← →
Dimaxx © (2005-06-21 21:49) [10]А саму ф-цию SetForegroundWindow из winapi не пробовал юзать??
← →
ANB © (2005-06-21 22:11) [11]
> Dimaxx © (21.06.05 21:49) [10]
- а чего, есть такая ? И работает ?
← →
volser (2005-06-22 19:26) [12]Попробовал первоначальный пример, у меня эксплорер вылетает.
Хотя окно становится активным.
А че, тоже вариант :-)
← →
ANB © (2005-06-22 19:32) [13]
> volser (22.06.05 19:26) [12]
- это, я цикл то убрал уже, толку с него, тока тормозит. Ща получше работает. А на какой винде у тебя вылетало ?
← →
Игорь Шевченко © (2005-06-22 22:49) [14]ANB © (21.06.05 11:40)
> если я передаю хендл окна верхнего уровня - все пашет, а
> вот что передавать, если мне нужно поднять наверх MDI Child
> окно ?
Надо поднять главное окно приложения на передний план, все именно так, как ты делаешь, через SETFOREGROUNDLOCKTIMEOUT и SetForegroundWindows, а затем нужно послать окну клиентской части MDI (это дочернее окно главного окна с классом MDICLIENT) сообщение WM_MDIACTIVATE указав в качестве wParam Handle того MDI-child окна, которое должно стать активным. Попробуй, если будут проблемы, напиши код, которым пользуешься.
← →
ANB © (2005-06-22 23:07) [15]
> Игорь Шевченко © (22.06.05 22:49) [14]
Интересно, я сегодня проэкспериментирую.
Тут проблема, программа, которой я управляю, написана на Magic. Действительно, магическая система, с окнами творит бог знает что. Сообщения клавиатуры не понимает, вот и приходится юзать keybd_event, а для его работы нужно окно постоянно наверх дергать, чтобы тест не упал при случайных кликах мыши. Наши пробовали и Rational Robot и WinRunner притаскивали, только старый - всех глючит от этой программы. Кнопку может сама догенерить, не убирая старой. Эдиты на окнах просто нарисованы, а появляются только при клике по ним. Если кликнуть по главному окну, до дочерние MDI окна закрываются. Магия, короче.
← →
Игорь Шевченко © (2005-06-22 23:20) [16]ANB © (22.06.05 23:07) [15]
> программа, которой я управляю, написана на Magic
Мне, к сожалению, этот термин ничего не говорит. Но если в Winsight можно увидеть, что она имеет окна, и, соответственно, дочерние окна MDI, то я надеюсь, что мой способ сможет пригодиться, возможно, с некоторыми изменениями, так как механизм работы с окнами от Magic, смею надеяться, мало зависит.
← →
Dimaxx © (2005-06-23 03:00) [17]у меня через SetForegroundWindow окно (чей хэндл передан) становится активным. в чем вопрос тогда??
← →
ANB © (2005-06-23 08:21) [18]> Игорь Шевченко © - применил твой способ. Чуть подправил свою функцию. Теперь вообще замечательно работает. Не дергается, не моргает. Но бибикает. Сейчас выяснил - что от иммитации кликов по кнопкам. Получилось вот так :
function GetMainWindow (hWindow : THandle) : THandle;
var hMainWindow, hW : THandle;
begin
hMainWindow := hWindow;
hW := hWindow;
repeat
hW := GetParent(hW);
if (hW <> 0)
then hMainWindow := hW;
until (hW = 0);
Result := hMainWindow;
end;
procedure Set_Foreground_Window (hWindow : THandle);
var dwTimeout : DWord;
hMainWindow, hFGW, hMDIClient : THandle;
begin
if (hWindow = 0) then Exit;
// Получим главное окно
hMainWindow := GetMainWindow(hWindow);
// Узнаем какое окно сейчас наверху
hFGW := GetForegroundWindow;
// Если не наше - будем поднимать
if (hMainWindow <> hFGW) then begin
// Отключим моргание вместо подъема окна
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @dwTimeout, 0);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, nil, 0);
try
// Попробуем разными способами поднять окно
SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, SC_HOTKEY, hMainWindow);
SwitchToThisWindow(hMainWindow, True);
SetForegroundWindow(hMainWindow);
// Для MDI окон
if (hWindow <> hMainWindow) then begin
// Найдем MDI Client
hMDIClient := FindWindowEx(hMainWindow, 0, "MDIClient", "");
// Пошлем ему сообщение WM_MDIACTIVATE
SendMessage(hMDIClient, WM_MDIACTIVATE, hWindow, 0);
end;
finally
// Восстановим моргание
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, @dwTimeout, 0);
end;
end;
end;
Тут еще надо бы поставить проверку, что юзер не сменил само MDI окно, но в Magic щелканье по окнам все равно может все сломать, проще запретить это организационно, а нормальных MDI приложений я не гоняю, делфовые - с обычными окнами верхнего уровня, да им эта примочка и не нужна, там прекрасно клавиатура сообщениями эмулируется.
← →
ANB © (2005-06-23 08:22) [19]Чуть не забыл.
> Игорь Шевченко ©
- большое спасибо за помощь.
← →
Grief © (2005-06-23 10:48) [20]ANB, я долго мучился с выводом окна на передний план и предлагаю так:
SetWindowPos(Wnd, HWnd_TopMost, Mouse.X - Trunc((Rect.Right - Rect.Left) / 2), Mouse.Y - Trunc((Rect.Bottom - Rect.Top) / 2), (Rect.Right - Rect.Left), (Rect.Bottom - Rect.Top), SWP_ShowWindow);
SetWindowPos(Wnd, HWnd_NoTopMost, Mouse.X - Trunc((Rect.Right - Rect.Left) / 2), Mouse.Y - Trunc((Rect.Bottom - Rect.Top) / 2), (Rect.Right - Rect.Left), (Rect.Bottom - Rect.Top), SWP_ShowWindow);
Именно эти две строчки. Если только первое - окно на первом плане останется навсегда, а если только вторую - оно появится и исчезнет, закрывшись другими окнами. Метода проще я не знаю.
Отсюда вопрос: кто знает, почему не работает просто HWnd_Top?
← →
Игорь Шевченко © (2005-06-23 19:19) [21]
> я долго мучился с выводом окна на передний план и предлагаю
> так
SetWindowPos - это не совсем вывод окна на передний план. Это перемещение окон в одном приложении друг относительно друга.
← →
Grief © (2005-06-23 19:58) [22]Вот это именно поможет вывести окно поверх других приложений. И при ентом это самый короткий вариант среди ваших. Кстати, респект liandri за этот пример ;)
← →
alpet © (2005-06-23 20:20) [23]Grief © (23.06.05 19:58) [22]
SetWindowPos(Wnd, HWnd_TopMost, Mouse.X - Trunc((Rect.Right - Rect.Left) / 2), Mouse.Y - Trunc((Rect.Bottom - Rect.Top) / 2), (Rect.Right - Rect.Left), (Rect.Bottom - Rect.Top), SWP_ShowWindow);
SetWindowPos(Wnd, HWnd_NoTopMost, Mouse.X - Trunc((Rect.Right - Rect.Left) / 2), Mouse.Y - Trunc((Rect.Bottom - Rect.Top) / 2), (Rect.Right - Rect.Left), (Rect.Bottom - Rect.Top), SWP_ShowWindow);
Простите за любопытство, но ведь для изменения положения окна в Z-порядке, не нужно такое количество параметров задавать (в смысле позиция и размер окна). Может проще обойтись так:
SetWindowPos (wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOOWNERZORDER);
← →
GrayFace © (2005-06-23 20:55) [24]ANB © (23.06.05 8:21) [18]
Это какая-то каша из разных решений проблемы, вобравшая в себя глюки каждого из них.
Либо делай так: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);
ЛибоSwitchToThisWindow(hMainWindow, True);
Либо тот сомнительный вариант с SC_HOTKEY.
Либо [23], хотя кто его знает, всегда ли будет работать.
Еще добавь проверку на версию: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
...
end else
begin
BringWindowToTop(hwnd); // IE 5.5 related hack
SetForegroundWindow(hwnd);
end;
← →
ANB © (2005-06-28 09:10) [25]
> GrayFace © (23.06.05 20:55) [24]
- Каша, не каша, но работает.
Вообще то мне не очень то нужно было поднимать окно наверх. Мне нужно было надежно установить на него фокус ввода с клавиатуры для эмуляции через keyb_event. Кстати, обнаружил прикольный глюк - если ручками окно минимизировать, окно обратно автоматом не восстанавливается, но продолжает реагировать на клавиатуру !
← →
Игорь Шевченко © (2005-06-28 10:21) [26]
> Кстати, обнаружил прикольный глюк - если ручками окно минимизировать,
> окно обратно автоматом не восстанавливается, но продолжает
> реагировать на клавиатуру !
Это вовсе не глюк. На клавиатуру реагирует окно, имеющее фокус ввода, вне зависимости от состояния его размера.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.08.21;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.035 c