Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
14-1122443534
Layner
2005-07-27 09:52
2005.08.21
Можно ли в среде D7 показывать строки


1-1122888615
Гомункул
2005-08-01 13:30
2005.08.21
Писать в текстовый файл


1-1122904145
BFG9k
2005-08-01 17:49
2005.08.21
Перемещение компонента по форме


14-1122888239
Gost'
2005-08-01 13:23
2005.08.21
Документ нужен...


14-1122389458
Makhanev A.S.
2005-07-26 18:50
2005.08.21
Проблема с ЖК монитором





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский