2011-01-13 5 views
9

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

15

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.

+0

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

+0

@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 –

+0

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

1

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.