2011-01-13 18 views
9

W Windows XP i powyżej, biorąc pod uwagę uchwyt okna (HWND), jak mogę stwierdzić, czy pozycja okna i rozmiar pozostawia nieodwracalnie okno poza ekranem? Na przykład, jeśli pasek tytułu jest dostępny dla kursora, wówczas okno można przeciągnąć z powrotem na ekran. Muszę sprawdzić, czy okno jest w rzeczywistości widoczne lub co najmniej dostępne dla użytkownika. Sądzę, że muszę wiedzieć, jak wykrywać i reagować na zmiany rozdzielczości i jak radzić sobie z wieloma monitorami. Wydaje się to dość dużą sprawą. Używam C++ i zwykłego SDK, więc ogranicz swoje odpowiedzi do tej platformy, zamiast wywoływać C# lub podobne.Jak określić, czy okno jest poza ekranem?

Odpowiedz

15

System Windows sprawia, że ​​określenie obszaru roboczego użytkownika na głównym monitorze jest stosunkowo proste (tzn. Obszar ekranu nie jest zasłonięty przez pasek zadań). Zadzwoń pod SystemParametersInfo function i podaj flagę pierwszego parametru(). Parametr pvParam powinien wskazywać wartość RECT structure, która będzie otrzymywać współrzędne obszaru roboczego we współrzędnych ekranu wirtualnego.

Po uzyskaniu współrzędnych opisujących obszar roboczy, wystarczy porównać je z bieżącą pozycją okna aplikacji, aby ustalić, czy leży ona w tych granicach.


Chęć obsługi wielu monitorów nieco komplikuje sprawę. Dokumentacja dla SystemParametersInfo sugeruje, że musisz zadzwonić pod numer GetMonitorInfo function, aby uzyskać obszar roboczy monitora innego niż główny. Wypełnia on strukturę o nazwie MONITORINFOEX, która zawiera element rcWork, który definiuje obszar roboczy tego monitora, ponownie wyrażony we współrzędnych ekranu wirtualnego jako struktura RECT.

Aby to zrobić, musisz wyliczyć wszystkie monitory, które użytkownik podłączył do systemu i pobrać obszar roboczy każdego z nich za pomocą GetMonitorInfo.

Istnieje kilka próbek tego można znaleźć w całym internecie:

  • MSDN ma jakiś przykładowy kod Positioning Objects on a Multiple Display Setup.
  • Jeśli używasz MFC, oto, co wygląda na an excellent example obsługi wielu monitorów.
  • Nawet jeśli nie używasz MFC, ten artykuł odnosi się do the following link, co wygląda na prawdziwy klejnot, jeśli chodzi o wyjaśnienie, w jaki sposób obsługa wielu monitorów działa w systemie Windows, nawet jeśli jest to trochę stara szkoła. Podoba się lub nie, bardzo niewiele z tego zmieniło się w późniejszych wersjach systemu Windows.


Wreszcie, wspomniano chcąc wykryć zmiany rozdzielczości. Jest to o wiele prostsze, niż pewnie sobie wyobrażałeś. Jak wiesz, jeśli wykonałeś jakieś programowanie w systemie Windows, podstawowym sposobem, w jaki system operacyjny komunikuje się z twoją aplikacją, jest wysyłanie wiadomości na numer WindowProc function.
W takim przypadku należy zwrócić uwagę na numer WM_DISPLAYCHANGE message, który jest wysyłany do wszystkich okien po zmianie rozdzielczości ekranu. wParam zawiera nową głębię obrazu w bitach na piksel; słowo niższego rzędu z lParam określa rozdzielczość poziomą, a słowo wyższego rzędu z lParam określa pionową rozdzielczość ekranu.

+0

Dzięki, to doskonały początek - nie mogę uwierzyć, że wcześniej nie natknąłem się na SystemParametersInfo. Nadal mam problem z tym, czy pasek tytułu jest widoczny i co się stanie, jeśli rozdzielczość się zmieni. – hatcat

+0

@hatcat: Nie ma powodu się bić; Windows API jest duży i nikt nie wie wszystkiego. Nie jestem pewien, jak można jeszcze utknąć na widoczności paska tytułu. Sprawdź, czy region okna zawierającego pasek tytułu znajduje się w obszarze roboczym ekranu, z którego korzystasz z którejś z funkcji opisanych powyżej. I nagle zapomniałem o wykrywaniu zmian rozdzielczości; Zaktualizuję moją odpowiedź. –

+0

Dziękujemy! Programowałem system Windows od 1992 roku, wierz lub nie. Myślę, że najtrudniej jest wiedzieć, jaka funkcjonalność została zastąpiona, kiedy i czy należy trzymać się tego, co wiesz. Część paska tytułu miała większy związek z odzyskiwaniem tego regionu, więc mogłem go przetestować. Po prostu sprawdzę dziesięć najlepszych pikseli i dziesięć bocznych pikseli, które powinny wystarczyć. – hatcat

1

Kontrola widoczności jest naprawdę łatwa.

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); 

Nie musisz używać RectInRegion, użyłem do skrócenia kodu.

Wyświetlanie, monitorowanie zmiany rozdzielczości jest również łatwe, jeśli obsługujesz wiadomość WM_SETTINGCHANGE.

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

UPDATE

Jak zauważył @Cody Szary, myślę WM_DISPLAYCHANGE jest bardziej odpowiednie niż WM_SETTINGCHANGE. Ale biblioteka MFC 9.0 korzysta z WM_SETTINGCHANGE.

Powiązane problemy