Как определить, находится ли окно за пределами экрана?
в Windows XP и выше, учитывая дескриптор окна (HWND), как я могу сказать, если положение и размер окна оставляет окно безвозвратно с экрана? Например, если строка заголовка доступна курсору, то окно можно перетащить обратно на экран. Мне нужно выяснить, действительно ли окно видно или, по крайней мере, доступно пользователю. Думаю, мне также нужно знать, как обнаруживать и реагировать на изменения разрешения и как обращаться с несколькими мониторами. Это кажется довольно большим сделка. Я использую C++ и обычный SDK, поэтому, пожалуйста, ограничьте свои ответы этой платформой, а не вызывая C# или аналогичный.
3 ответов
Windows позволяет относительно просто определить размер рабочей области пользователя на основном мониторе (т. е. область экрана, не затемненная панелью задач). Вызовите SystemParametersInfo
функции и указать SPI_GETWORKAREA
флаг для первого параметра (uiAction
). The pvParam
параметр должен указывать на RECT
структура который получит координаты рабочей зоны в виртуальном экране координирует.
как только у вас есть координаты, описывающие рабочую область, это простой вопрос сравнения их с текущим положением окна вашего приложения, чтобы определить, находится ли он в этих границах.
Желание поддерживать несколько мониторов делает вещи немного сложнее. Документация для SystemParametersInfo
предполагает, что вам нужно позвонить GetMonitorInfo
функции вместо того, чтобы получить рабочую область монитор, отличный от основного. Он заполняет структуру под названием MONITORINFOEX
который содержит элемент rcWork
это определяет рабочую область этого монитора, снова выраженную в координатах виртуального экрана как RECT
структура.
чтобы сделать это правильно, вам нужно перечислить все мониторы, которые пользователь подключил к системе, и получить рабочую область каждого с помощью GetMonitorInfo
.
есть несколько примеров этого можно найти по всему интернету:
- MSDN имеет некоторый пример кода для позиционирование объектов на нескольких настройках дисплея.
- если вы используете MFC, вот что кажется отличный пример поддержки нескольких мониторов.
- даже если вы не используете MFC, эта статья ссылается следующей ссылке который выглядит настоящим сокровищем, поскольку объясняет, как несколько мониторов поддерживает работу в Windows, даже если это немного старомодно. Нравится вам это или нет, очень мало что изменилось в более поздних версиях Windows.
Наконец, вы упомянули о желании обнаружить изменения разрешения. Это гораздо проще, чем вы, вероятно, себе представляли. Как вы знаете, если вы занимались программированием Windows, основной способ, которым операционная система взаимодействует с вашим приложением, - это отправка сообщений на ваш WindowProc
функции.
В этом случае, вы захотите смотреть на WM_DISPLAYCHANGE
, который отправляется во все окна при изменении разрешения дисплея. The wParam
содержит новую глубину изображения в битах на пиксель; младшее слово lParam
задает горизонтальное разрешение и слово высокого порядка lParam
задает вертикальное разрешение экрана.
вы можете использовать MonitorFromRect или MonitorFromPoint, чтобы проверить, не содержится ли верхняя левая точка окна или нижняя правая точка в любом мониторе дисплея (вне экрана).
POINT p;
p.x = x;
p.y = y;
HMONITOR hMon = MonitorFromPoint(p, MONITOR_DEFAULTTONULL);
if (hMon == NULL) {
// point is off screen
}
проверка видимости очень проста.
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=против 85).aspx
обновление
Как отметил @Cody Gray, я думаю, что WM_DISPLAYCHANGE более подходит, чем WM_SETTINGCHANGE. Но MFC 9.0 библиотека использует WM_SETTINGCHANGE.