public void Refresh() { if (this == null) { return; } if (_thumbHandle == IntPtr.Zero) { return; } if (this != null) { NativeMethods.DwmQueryThumbnailSourceSize(_thumbHandle, out NativeMethods.PSIZE size); var props = new NativeMethods.DWM_THUMBNAIL_PROPERTIES { fVisible = true, dwFlags = NativeMethods.DWM_TNP_VISIBLE | NativeMethods.DWM_TNP_RECTDESTINATION | NativeMethods.DWM_TNP_OPACITY, opacity = ThumbnailOpacity, rcDestination = Rect }; if (this != null) { if (size.x < Rect.Width) { props.rcDestination.Right = props.rcDestination.Left + size.x; } } if (this != null) { if (size.y < Rect.Height) { props.rcDestination.Bottom = props.rcDestination.Top + size.y; } } if (this != null) { NativeMethods.DwmUpdateThumbnailProperties(_thumbHandle, ref props); } } }
public void Refresh() { if (this == null) { return; } if (_thumbHandle == IntPtr.Zero) { return; } if (this != null) { NativeMethods.DwmQueryThumbnailSourceSize(_thumbHandle, out NativeMethods.PSIZE size); double aspectRatio = (double)size.x / size.y; var props = new NativeMethods.DWM_THUMBNAIL_PROPERTIES { fVisible = true, dwFlags = NativeMethods.DWM_TNP_VISIBLE | NativeMethods.DWM_TNP_RECTDESTINATION | NativeMethods.DWM_TNP_OPACITY, opacity = ThumbnailOpacity, rcDestination = Rect }; if (this != null) { if (size.x <= Rect.Width && size.y <= Rect.Height) { // do not scale props.rcDestination.Top += (Rect.Height - size.y) / 2; props.rcDestination.Left += (Rect.Width - size.x) / 2; props.rcDestination.Right = props.rcDestination.Left + size.x; props.rcDestination.Bottom = props.rcDestination.Top + size.y; } else { // scale, preserving aspect ratio and center double controlAspectRatio = (double)Rect.Width / Rect.Height; if (aspectRatio > controlAspectRatio) { // wide int height = (int)(Rect.Width / aspectRatio); props.rcDestination.Top += (Rect.Height - height) / 2; props.rcDestination.Bottom = props.rcDestination.Top + height; } else if (aspectRatio < controlAspectRatio) { // tall int width = (int)(Rect.Height * aspectRatio); props.rcDestination.Left += (Rect.Width - width) / 2; props.rcDestination.Right = props.rcDestination.Left + width; } } } if (this != null) { NativeMethods.DwmUpdateThumbnailProperties(_thumbHandle, ref props); } } }
private void UpdateThumbProps() { if( thumbId != IntPtr.Zero ) { Size sourceSize; Marshal.ThrowExceptionForHR( NativeMethods.DwmQueryThumbnailSourceSize(this.thumbId, out sourceSize) ); NativeMethods.DWM_THUMBNAIL_PROPERTIES dwmProps = new NativeMethods.DWM_THUMBNAIL_PROPERTIES(); dwmProps.dwFlags = NativeMethods.DWM_TNP.VISIBLE | NativeMethods.DWM_TNP.OPACITY | NativeMethods.DWM_TNP.RECTDESTINATION | NativeMethods.DWM_TNP.SOURCECLIENTAREAONLY; dwmProps.fVisible = this.Visible; dwmProps.opacity = this.Opacity; dwmProps.fSourceClientAreaOnly = this.SourceClientAreaOnly; dwmProps.rcDestination = new NativeMethods.RECT( this.AbsoluteLocation.X, this.AbsoluteLocation.Y, this.AbsoluteLocation.X + this.Width, this.AbsoluteLocation.Y + this.Height ); if( this.SourceArea != Rectangle.Empty ) { sourceSize = this.SourceArea.Size; //override original size dwmProps.dwFlags |= NativeMethods.DWM_TNP.RECTSOURCE; dwmProps.rcSource = new NativeMethods.RECT( this.SourceArea.X, this.SourceArea.Y, this.SourceArea.X + this.SourceArea.Width, this.SourceArea.Y + this.SourceArea.Height ); } if( !this.ScaleAboveNativeSize ) { if( sourceSize.Width < this.Width ) dwmProps.rcDestination.Right = dwmProps.rcDestination.Left + sourceSize.Width; if( sourceSize.Height < this.Height ) dwmProps.rcDestination.Bottom = dwmProps.rcDestination.Top + sourceSize.Height; } Marshal.ThrowExceptionForHR( NativeMethods.DwmUpdateThumbnailProperties(this.thumbId, ref dwmProps) ); } }
/// <summary> /// Make a full-size thumbnail of the captured window on a new topmost form, and capture /// this new form with a black and then white background. Then compute the transparency by /// difference between the black and white versions. /// This method has these advantages: /// - the full form is captured even if it is obscured on the Windows desktop /// - there is no problem with unpredictable Z-order anymore (the background and /// the window to capture are drawn on the same window) /// Note: now that GDI capture is more robust, DWM capture is not that useful anymore. /// </summary> /// <param name="handle">handle of the window to capture</param> /// <param name="windowRect">the bounds of the window</param> /// <param name="redBGImage">the window captured with a red background</param> /// <param name="captureRedBGImage">whether to do the capture of the window with a red background</param> /// <returns>the captured window image</returns> private static Image CaptureWindowWithTransparencyDWM(IntPtr handle, Rectangle windowRect, out Bitmap redBGImage, bool captureRedBGImage) { Image windowImage = null; redBGImage = null; using (Form form = new Form()) { form.FormBorderStyle = FormBorderStyle.None; form.ShowInTaskbar = false; form.BackColor = Color.White; form.TopMost = true; form.Bounds = windowRect; IntPtr thumb; NativeMethods.DwmRegisterThumbnail(form.Handle, handle, out thumb); SIZE size; NativeMethods.DwmQueryThumbnailSourceSize(thumb, out size); if (size.x <= 0 || size.y <= 0) { return(null); } form.Location = new Point(windowRect.X, windowRect.Y); form.Size = new Size(size.x, size.y); form.Show(); NativeMethods.DWM_THUMBNAIL_PROPERTIES props = new NativeMethods.DWM_THUMBNAIL_PROPERTIES(); props.dwFlags = NativeMethods.DWM_TNP_VISIBLE | NativeMethods.DWM_TNP_RECTDESTINATION | NativeMethods.DWM_TNP_OPACITY; props.fVisible = true; props.opacity = (byte)255; props.rcDestination = new RECT(0, 0, size.x, size.y); NativeMethods.DwmUpdateThumbnailProperties(thumb, ref props); NativeMethods.ActivateWindowRepeat(handle, 250); Bitmap whiteBGImage = CaptureRectangle(windowRect) as Bitmap; form.BackColor = Color.Black; form.Refresh(); NativeMethods.ActivateWindowRepeat(handle, 250); Bitmap blackBGImage = CaptureRectangle(windowRect) as Bitmap; if (captureRedBGImage) { form.BackColor = Color.Red; form.Refresh(); NativeMethods.ActivateWindowRepeat(handle, 250); redBGImage = CaptureRectangle(windowRect) as Bitmap; } form.BackColor = Color.White; form.Refresh(); NativeMethods.ActivateWindowRepeat(handle, 250); Bitmap whiteBGImage2 = CaptureRectangle(windowRect) as Bitmap; // Don't do transparency calculation if an animated picture is detected if (whiteBGImage.AreBitmapsEqual(whiteBGImage2)) { windowImage = GraphicsMgr.ComputeOriginal(whiteBGImage, blackBGImage); } else { FileSystem.AppendDebug("Detected animated image => cannot compute transparency"); form.Close(); Application.DoEvents(); Image result = new Bitmap(whiteBGImage.Width, whiteBGImage.Height, PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(result)) { // Redraw the image on a black background to avoid transparent pixels artifacts g.Clear(Color.Black); g.DrawImage(whiteBGImage, 0, 0); } windowImage = result; } NativeMethods.DwmUnregisterThumbnail(thumb); blackBGImage.Dispose(); whiteBGImage.Dispose(); whiteBGImage2.Dispose(); } return(windowImage); }