2008-11-05 1 views
3

Я хочу определить, видимо ли какое-либо окно пользователю или скрыто/закрыто. В Windows XP я бы использовал функцию GetClipBox() и проверял значение NULLREGION или пустое значение RECT. Это работало отлично, но в Windows Vista это не работает, если другое окно закрывает окно. В этом случае GetClipBox() возвращает SIMPLEREGION с непустым RECT.Определение видимости окна в Vista

Кто-нибудь знает, почему это не работает в Vista, или если есть другой способ проверить, может ли окно быть видимым пользователем?

ответ

2

Простая причина GetClipBox() не возвращает NULLREGION с DWM включен, потому что вы не обрезаны! Вся точка DWM - это каждое окно (это не дочерний элемент, например кнопки или поля редактирования) получает собственный буфер для рисования, поэтому окна переднего плана можно перемещать, не заполняя окна позади них.

В качестве простого примера наведите указатель мыши на запись в окне панели задач, когда она находится в фоновом режиме, и посмотрите, как она обновляется в предварительном просмотре.

Также обратите внимание, что со стеклянными краями ваше окно может быть полностью закрыто другими окнами и должно быть видно! (Вы даже не можете тестировать клиентскую область из-за расширенного стекла, как использует проигрыватель Windows Media, - измените его размер настолько, насколько это будет возможно, и увидите, что он использует стекло для всей его области!) Конечно, слоистые окна (от XP on) и пользовательские области окна означали, что это всегда может быть так, но теперь это значение по умолчанию.

Резюме/TL; DR:

Если вы делаете тяжелые анимации/модные эффекты и хотите, чтобы уменьшить нагрузку на процессор при работе под DWM, вероятно, лучшее, что вы можете сделать, это определить, когда приложение теряет передний план и откажитесь от большего количества обновлений, совместимых с ЦП (НЕ обновляйте! Если вы получаете WM_PAINT и игнорируете его, потому что вы находитесь в фоновом режиме, вы не получите его, когда будете активированы!).

+0

Спасибо за подробное объяснение! Как вы уже догадались, мое приложение выполняет интенсивные анимации процессора, поэтому я стараюсь уменьшить использование ЦП, когда мое окно не видно. Проверка того, что мое приложение является передним окном, похоже на разумную работу, я попробую. – flashk 2008-11-22 19:17:42

1

Несколько грязный способ сделать это - получить положение/размер окна, которое вы хотите проверить, а затем перебрать все окна выше, чем в Z-порядке, и рассчитать, какие части вашего окна они обложка.

2

В вашей установке Vista включена компоновка оконного менеджера окон? Я бы предположил, что это так, и если вы отключите его, вы получите ожидаемое поведение XP. Проблема в том, что в Vista с составом DWM процесс обработки окон сильно изменился, и я не думаю, что будет простой способ получить то, что вы хотите.

1

В вашей установке Vista есть рабочий стол Состав оконного менеджера включен? Я бы предположил, что это так, и если вы выключите его, вы получите ожидаемое поведение XP . Проблема заключается в , что под Vista с составом DWM, способ, которым обрабатываются окна, имеет , многое изменилось, и я не думаю, что будет простой способ добраться до , что вы хотите.

Да, на моей машине включен DWM. Я попытался следующие, чтобы проверить свои предположения:

  1. правой кнопкой мыши мое приложение и выбрал «Свойства»
  2. нажимали на вкладке «Совместимость»
  3. Enabled «Отключить композицию рабочего стола» флажок
  4. Clicked «Применить»

После этого функция GetClipBox() работает правильно. Так что ваша догадка правильная. Я обнаружил, что я могу выполнить это программно с помощью следующей функции в моем приложении:

DwmEnableComposition(DWM_EC_DISABLECOMPOSITION); 

Однако, это отключает эффекты прозрачности в то время как мое приложение работает, что не желательно. Я предпочел бы менее навязчивое решение.

В любом случае, спасибо за совет!

0

Поскольку вы знаете, какой результат GetClipRect имеет как XP, так и Vista (с включенным и включенным DWM), вы можете создать функцию для определения этого, которая принимает разные пути на основе ОС. В псевдо-коде:

function bool IsWindowVisible() 
{ 
    bool isVisible = false; 

    if (OSVersion == "XP") 
    { 
     // GetClipRect tests which run on XP and set isVisible 
    } 
    else if (OSVersion == "Vista") 
    { 
     if (DWMCompisitionEnabled == true) 
     { 
     // GetClipRect tests for Vista with DWM enabled and set isVisible 
     } 
     else 
     { 
     // GetClipRect tests for Vista with DWM disabled and set isVisible 
     } 
    } 
    return isVisible; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^