2015-08-22 24 views
8

Sto provando ad acquisire finestre desktop in C# in base alle maniglie di Windows. Sto usando .NET e usando PInvoke per GetWindowRect() per catturare il rettangolo della finestra. Ho la selezione della finestra e la cattura del rettangolo funziona bene.Recupera dimensione finestra senza ombre Windows

Tuttavia, i rettangoli di finestra catturati includono non solo le dimensioni effettive della finestra, ma anche gli ornamenti della finestra come l'ombra attorno ad esso. Quando provo a ritagliare la finestra su una bitmap, la bitmap contiene l'area e l'ombra. In Windows 10 ottengo la zona d'ombra trasparente compreso qualsiasi contenuto che potrebbe essere visibile sotto la finestra attiva:

enter image description here

Il codice che uso è abbastanza semplice catturare la finestra usando Win32 GetWindowRect() tramite PInvoke chiamata:

var rect = new Rect(); 
GetWindowRect(handle, ref rect); 
var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top); 
var result = new Bitmap(bounds.Width, bounds.Height); 

using (var graphics = Graphics.FromImage(result)) 
{ 
    graphics.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size); 
} 

return result; 

Quindi catturare l'immagine e assegnarla a una finestra di immagine.

Inoltre, sembra che ci siano alcune variazioni tra le finestre: alcune finestre hanno ombre che altre no. La maggior parte lo fa, ma alcuni come Visual Studio e Chrome non lo fanno, quindi non si tratta nemmeno di eliminare i pixel estranei.

Ho provato a utilizzare GetClientRect() ma questo mi fa solo l'area client che non è quello che ho dopo. Quello che mi piacerebbe ottenere è il rettangolo Window effettivo con bordi ma senza ombre.

Esiste comunque?

+0

Potrebbe essere necessario controllare [SystemInformation] (https://msdn.microsoft.com/en-us/library/system.windows.forms.systeminformation.aspx) per ottenere una dimensione di bordo coerente, aggiungere che sulla zona del cliente. – t0mm13b

+0

Invece di copiare dallo schermo, dovresti copiare dal DC della finestra ('GetWindowDC') - questo otterrà la finestra anche se è coperta da un'altra. Inoltre, vedere il terzo commento [in questa pagina] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633519.aspx). –

+0

Vedi questa [domanda] (http://stackoverflow.com/questions/16493698/drop-shadow-on-a-borderless-winform) modifica temporaneamente i parametri di creazione di windows per rimuovere l'ombra invertendo il flag 'CS_DROPSHADOW', cattura la finestra e ripristina la maschera. – t0mm13b

risposta

1

Sto utilizzando Windows 10 e ho riscontrato lo stesso problema durante la scrittura di un'applicazione per l'apertura di finestre nella parte superiore o inferiore dello schermo. Ho trovato DwmGetWindowAttribute() per funzionare. Esso restituisce un rettangolo con valori leggermente diversi rispetto GetWindowRect() ...

I risultati di una finestra di esempio:

GetWindowRect(): {X = 88, Y = 26, Width = 871, Height = 363}

DwmGetWindowAttribute(): {X = 95, Y = 26, Width = 857, Height = 356}

mio test ha mostrato che GetWindowRect() incluso gli ornamenti, mentre DwmGetWindowAttribute() non ha fatto.

Se si ottengono risultati identici da entrambi i metodi su una finestra con ornamenti, potrebbe essere che quella finestra particolare stia disegnando i propri ornamenti o che ci sia qualche altro attributo o proprietà impostato sulla finestra che deve essere preso in considerazione.

+0

Si trattava dei limiti del frame esteso recuperati da DwmGetWindowAttribute? – NetMage

+0

DwmGetWindowAttribute() mi ha fornito il bordo effettivo, mentre GetWindowRect() includeva l'ombra traslucida "fuzzy" attorno al bordo. – dynamichael