In Windows XP e versioni successive, dato un handle di finestra (HWND), come posso sapere se la posizione e le dimensioni della finestra lasciano irrimediabilmente fuori dallo schermo la finestra? Ad esempio, se la barra del titolo è disponibile per il cursore, la finestra può essere trascinata sullo schermo. Devo scoprire se la finestra è effettivamente visibile o almeno disponibile per l'utente. Suppongo di dover anche sapere come rilevare e rispondere alle modifiche della risoluzione e come gestire più monitor. Questo sembra un grosso problema. Sto usando C++ e il normale SDK, quindi limita le tue risposte a quella piattaforma piuttosto che invocare C# o simili.Come determinare se una finestra è fuori dallo schermo?
risposta
Windows rende relativamente semplice determinare le dimensioni dell'area di lavoro di un utente sul monitor principale (ad esempio, l'area dello schermo non oscurata dalla barra delle applicazioni). Chiama lo SystemParametersInfo
function e specifica il flag SPI_GETWORKAREA
per il primo parametro (uiAction
). Il parametro pvParam
deve puntare a un RECT
structure che riceverà le coordinate dell'area di lavoro nelle coordinate dello schermo virtuale.
Una volta ottenute le coordinate che descrivono l'area di lavoro, è semplice confrontarle con la posizione corrente della finestra dell'applicazione per determinare se si trova all'interno di tali limiti.
Il desiderio di supportare più monitor rende le cose leggermente più complicate. La documentazione per SystemParametersInfo
suggerisce che è necessario chiamare lo GetMonitorInfo
function per ottenere l'area di lavoro di un monitor diverso dal primario. Riempie una struttura denominata che contiene il membro rcWork
che definisce l'area di lavoro di quel monitor, ancora espressa nelle coordinate dello schermo virtuale come una struttura RECT
.
Per fare ciò, è necessario enumerare tutti i monitor che un utente si è connesso al sistema e recuperare l'area di lavoro di ciascuno utilizzando GetMonitorInfo
.
Ci sono alcuni esempi di questo che si trovano su Internet:
- MSDN ha qualche codice di esempio per Positioning Objects on a Multiple Display Setup.
- Se si utilizza MFC, ecco quello che sembra essere an excellent example di supporto per più monitor.
- Anche se non si utilizza MFC, tale articolo si riferisce a the following link che sembra un vero gioiello per quanto riguarda la spiegazione di come funzionano più monitor in Windows, anche se è un po 'vecchia scuola. Piaccia o no, molto poco di questo è cambiato nelle versioni successive di Windows.
Infine, hai menzionato il desiderio di rilevare le modifiche di risoluzione. Questo è molto più semplice di quanto probabilmente immaginassi. Come saprai, se hai eseguito una programmazione Windows, il modo principale con il quale il sistema operativo comunica con la tua applicazione è inviare messaggi al tuo WindowProc
function.
In questo caso, ti consigliamo di guardare il WM_DISPLAYCHANGE
message, che viene inviato a tutte le finestre quando la risoluzione dello schermo è cambiata. wParam
contiene la nuova profondità dell'immagine in bit per pixel; la parola di ordine basso di lParam
specifica la risoluzione orizzontale e la parola di ordine elevato di lParam
specifica la risoluzione verticale dello schermo.
Controllo di visibilità è davvero facile.
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);
Non è necessario utilizzare RectInRegion, utilizzato per il codice abbreviato.
Visualizzazione, il monitoraggio del cambio di risoluzione è anche semplice se si gestisce il messaggio WM_SETTINGCHANGE.
http://msdn.microsoft.com/en-us/library/ms725497(v=vs.85).aspx
UPDATE
Come osservato @Cody grigio, ritengo WM_DISPLAYCHANGE è più appropriato di WM_SETTINGCHANGE. Ma la libreria MFC 9.0 utilizza WM_SETTINGCHANGE.
Grazie, è un ottimo inizio - Non posso credere di non aver incontrato SystemParametersInfo in precedenza. Sono ancora bloccato con il problema se la barra del titolo sia visibile o meno, e cosa succede se la risoluzione cambia. – hatcat
@hatcat: non c'è motivo di batterti; l'API di Windows è grande e nessuno sa tutto. Non sono sicuro di come potresti rimanere bloccato sulla visibilità della barra del titolo. Controlla se la regione della finestra che contiene la barra del titolo si trova all'interno dell'area di lavoro della schermata che hai utilizzato con una delle funzioni sopra descritte. E ho subito dimenticato di rilevare i cambiamenti di risoluzione; Aggiornerò la mia risposta –
Grazie! Ho programmato Windows dal 1992, che ci crediate o no. Penso che la cosa più difficile sia sapere quale funzionalità è stata sostituita, e quando, e se si dovrebbe o meno restare fedele a ciò che si sa. La parte della barra del titolo era più legata al recupero di quella regione, così ho potuto testarla. Vado solo a controllare i dieci pixel più in alto e i dieci pixel laterali, che dovrebbero essere sufficienti. – hatcat