Как определить, находится ли окно вне экрана? - PullRequest
9 голосов
/ 13 января 2011

В Windows XP и выше, учитывая дескриптор окна (HWND), как я могу узнать, оставляет ли окно и размер окна безвозвратно за пределами экрана?Например, если строка заголовка доступна для курсора, окно можно перетащить обратно на экран.Мне нужно выяснить, является ли окно действительно видимым или, по крайней мере, доступным для пользователя.Думаю, мне также нужно знать, как обнаруживать и реагировать на изменения разрешения и как работать с несколькими мониторами.Это кажется довольно большой сделкой.Я использую C ++ и обычный SDK, поэтому, пожалуйста, ограничьте свои ответы этой платформой, а не вызывайте C # или аналогичный.

Ответы [ 3 ]

18 голосов
/ 13 января 2011

Windows позволяет относительно просто определить размер рабочей области пользователя на основном мониторе (т. Е. Область экрана, не скрытую панелью задач).Вызовите функцию SystemParametersInfo и укажите флаг SPI_GETWORKAREA для первого параметра (uiAction).Параметр pvParam должен указывать на RECT структуру , которая будет получать координаты рабочей области в координатах виртуального экрана.

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


Желание поддерживать несколько мониторов несколько усложняет ситуацию.Документация для SystemParametersInfo предполагает, что вам нужно вместо этого вызвать GetMonitorInfo функцию , чтобы получить рабочую область монитора, отличную от основного.Он заполняет структуру, называемую MONITORINFOEX, которая содержит элемент rcWork, который определяет рабочую область этого монитора, снова выраженную в координатах виртуального экрана как структура RECT.

Чтобы сделать это правильно, вам нужно перечислить все мониторы, которые пользователь подключил к системе, и получить рабочую область каждого из них, используя GetMonitorInfo.

. Есть несколькопримеры этого можно найти в Интернете:


Наконец, вы упомянули, что хотите обнаружить изменения разрешения.Это гораздо проще, чем вы могли себе представить.Как вы знаете, если вы занимались программированием на Windows, основной способ взаимодействия операционной системы с вашим приложением - это отправка сообщений в вашу WindowProc функцию .
В этом случае вы будетехотите отслеживать сообщение WM_DISPLAYCHANGE , которое отправляется во все окна при изменении разрешения дисплея.wParam содержит новую глубину изображения в битах на пиксель;младшее слово lParam указывает разрешение по горизонтали, а старшее слово lParam определяет разрешение экрана по вертикали.

3 голосов
/ 21 марта 2018

Вы можете использовать MonitorFromRect или MonitorFromPoint, чтобы проверить, содержатся ли верхняя левая точка или нижняя правая точка окна на каком-либо мониторе (вне экрана).

POINT p;
p.x = x;
p.y = y;
HMONITOR hMon = MonitorFromPoint(p, MONITOR_DEFAULTTONULL);
if (hMon == NULL) {
    // point is off screen
}
0 голосов
/ 14 января 2011

Проверка видимости действительно проста.

RECT rtDesktop, rtView;

GetWindowRect( GetDesktopWindow(), &rtDesktop );
GetWindowRect( m_hWnd, &rtView );

HRGN rgn = CreateRectRgn( rtDesktop.left, rtDesktop.top, rtDesktop.right, rtDesktop.bottom );

BOOL viewIsVisible = RectInRegion( rgn, &rtView );

DeleteObject(rgn);

Вам не нужно использовать RectInRegion, я использовал для сокращения кода.

Дисплей, мониторинг изменения разрешения также прост, если вы обрабатываете сообщение WM_SETTINGCHANGE.

http://msdn.microsoft.com/en-us/library/ms725497(v=vs.85).aspx

UPDATE

Как заметил @Cody Grey, я думаю, что WM_DISPLAYCHANGE более подходит, чем WM_SETTINGCHANGE. Но библиотека MFC 9.0 использует WM_SETTINGCHANGE.

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