Как надежно найти окно переднего плана, когда оно не имеет фокуса - PullRequest
6 голосов
/ 26 февраля 2010

Итак, я думал, что это будет просто, и, ну, я был неправ. Вот упрощенное описание проблемы:

Я пишу небольшое приложение для наших производственных пользователей, которое будет щелкать скриншот всего рабочего стола, а также окна переднего плана, когда они щелкают значок приложения на панели задач. В настоящее время я использую метод Win32 «GetforegroundWindow» в событии MouseMove объекта NotifyIcon, чтобы сохранить дескриптор окна переднего плана и сделать снимок экрана в событии Click.

Иногда это работает, но если я щелкаю по значку очень быстро, я фактически получаю панель задач вместо окна переднего плана. Я не уверен, почему это происходит (я понимаю, что панель задач является окном, я не понимаю, почему иногда кажется, что он имеет фокус в MouseMove, прежде чем я нажал), и мне не повезло с использованием метода EnumWindows также, вероятно, потому что я не совсем понимаю, как это работает.

Казалось бы, если бы я мог получить позицию z каждого окна, используя только дескриптор окна, это было бы легко решить с помощью EnumWindows. Однако я не нашел способа сделать это.

Итак, я вас спрашиваю, ребята; Как бы вы написали метод для надежного определения местоположения окна переднего плана, учитывая, что оно может не фокусироваться в данный момент? Либо мой гугл-фу подводит меня, либо информации об этом немного. Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 26 февраля 2010

Панель задач является таким же допустимым окном переднего плана, как и любое другое. Когда вы щелкнете по нему, это будет временно окно переднего плана. И если вы нажмете Пуск и нажмете Escape, например, это будет окно переднего плана, пока вы не щелкнете по нему.

Вероятно, вы можете использовать GetWindow с передачей HWND_NEXT в дескрипторе окна панели задач.

Неважно, поскольку панель задач является верхним окном, GetWindow (или GetNextWindow и т. Д.) Будет работать по-другому. Я бы предложил пересмотреть решение EnumWindows , которое, вероятно, является лучшим выбором.

0 голосов
/ 26 февраля 2010

Если форма, с которой вы хотите сделать снимок, совпадает с формой, связанной с панелью задач, вам действительно не нужно использовать GetforegroundWindow. Просто используйте Form.hWnd и передайте это в функцию, получающую снимок. Возможно, вам придется сделать его верхним окном, позвонив по номеру

[DllImport( "user32.dll" )]
public static extern IntPtr SetForegroundWindow( IntPtr hWnd );

или

[DllImport( "user32.dll" )]
public static extern bool BringWindowToTop( HandleRef hWnd );

Если вам нужен весь рабочий стол, то вам, вероятно, нужно просто вставить Thread.Sleep, чтобы убедиться, что у окна переднего плана достаточно, чтобы подняться наверх, прежде чем получить снимок рабочего стола.

добавление источника из моего комментария для лучшей печати

[DllImport( "user32.dll" )]
public static extern IntPtr GetForegroundWindow();

[DllImport( "user32.dll" )] 
public static extern IntPtr GetActiveWindow(); 

// this or the next line not both
IntPtr curWindow = GetActiveWindow(); 
IntPtr curWindow = GetForegroundWindow(); 

BringWindowToTop( window ); 
System.Threading.Thread.Sleep( 500 ); 

Где спящий поток дает окну достаточно времени, чтобы подняться на вершину Z-порядка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...