Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.21;
Скачать: CL | DM;

Вниз

Что передать в качестве окна для 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 вся ветка

Текущий архив: 2005.08.21;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.043 c
1-1122983493
DeVid
2005-08-02 15:51
2005.08.21
Как отловить событие нажатия Ctrl+Alt+<буква>?


14-1122629003
MaksimkaP
2005-07-29 13:23
2005.08.21
Доступ в локальную сеть с двух машин


4-1120299815
Alex_Korn
2005-07-02 14:23
2005.08.21
Помещение готового *.res файла в другую программу.


3-1120630001
Shopot
2005-07-06 10:06
2005.08.21
BDE. Бывают проблемы с сохранением данных в базе.


4-1120064577
ВломПридумывать
2005-06-29 21:02
2005.08.21
HELP !!!