private static void EnableBlur(Window window) { var windowHelper = new WindowInteropHelper(window); var accent = new Dwm.AccentPolicy { AccentState = Dwm.AccentState.ACCENT_ENABLE_BLURBEHIND }; var accentStructSize = Marshal.SizeOf(accent); var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); var data = new Dwm.WindowCompositionAttributeData { Attribute = Dwm.WindowCompositionAttribute.WCA_ACCENT_POLICY, SizeOfData = accentStructSize, Data = accentPtr }; Dwm.SetWindowCompositionAttribute(windowHelper.Handle, ref data); Marshal.FreeHGlobal(accentPtr); }
/// <summary> /// Make sure the monitoring is disabled and the Thumbnail is unregistered /// </summary> /// <param name="e">EventArgs</param> protected override void OnClosed(EventArgs e) { _locationPool.Return(_thumbnailRect); _windowMonitor.Dispose(); _configurationMonitor.Dispose(); Dwm.DwmUnregisterThumbnail(_phThumbnail); base.OnClosed(e); }
private void UnregisterThumbnail() { if (_thumbnailHandle == IntPtr.Zero) { return; } Dwm.DwmUnregisterThumbnail(_thumbnailHandle); _thumbnailHandle = IntPtr.Zero; }
public Window GetWindow(IntPtr handle) { var interopWindow = InteropWindowFactory.CreateFor(handle); interopWindow.Fill(InteropWindowCacheFlags.Info | InteropWindowCacheFlags.Text); var windowInfo = interopWindow.Info.Value; Dwm.GetExtendedFrameBounds(handle, out var nativeBounds); var innerBounds = (Rectangle)nativeBounds; var outerBounds = (Rectangle)windowInfo.Bounds; Rectangle bounds; Thickness border; if (outerBounds.Width > 0 || outerBounds.Height > 0) { var rawBorder = innerBounds.GetBorder(outerBounds); if (rawBorder.Left < 0 || rawBorder.Top < 0 || rawBorder.Right < 0 || rawBorder.Right < 0) { bounds = new Rectangle( innerBounds.Left - Math.Min(rawBorder.Left, 0), innerBounds.Top - Math.Min(rawBorder.Top, 0), innerBounds.Width - Math.Min(rawBorder.Left, 0) - Math.Min(rawBorder.Right, 0), innerBounds.Height - Math.Min(rawBorder.Top, 0) - Math.Min(rawBorder.Bottom, 0)); border = new Thickness( Math.Max(rawBorder.Left, 0), Math.Max(rawBorder.Top, 0), Math.Max(rawBorder.Right, 0), Math.Max(rawBorder.Bottom, 0)); } else { bounds = innerBounds; border = rawBorder; } } else { bounds = innerBounds; border = Thickness.Empty; } var dpi = (int)NativeDpiMethods.GetDpiForWindow(handle); return(new Window { Handle = handle, Title = interopWindow.Text, Bounds = bounds, Border = border, Dpi = new Point(dpi, dpi), }); }
/// <summary> /// Change the thumbnail settings /// </summary> private void UpdateThumbnail() { Opacity = Math.Max((byte)0x01, _pipConfiguration.Opacity) / 255d; // Prepare the displaying of the Thumbnail var props = new DwmThumbnailProperties { Opacity = _pipConfiguration.Opacity, Visible = true, SourceClientAreaOnly = _pipConfiguration.SourceClientAreaOnly, Destination = new NativeRect(0, 0, Width, Height) }; Dwm.DwmUpdateThumbnailProperties(_phThumbnail, ref props); }
/// <summary> /// Create the thumbnail if the form is shown /// </summary> /// <param name="e">EventArgs</param> protected override void OnShown(EventArgs e) { base.OnShown(e); if (_phThumbnail == IntPtr.Zero) { var result = Dwm.DwmRegisterThumbnail(Handle, _hWnd, out _phThumbnail); if (result.Failed()) { Close(); return; } UpdateThumbnail(); } User32Api.BringWindowToTop(Handle); }
/// <summary> /// Show the thumbnail of the supplied window above (or under) the parent Control /// </summary> /// <param name="window">WindowDetails</param> /// <param name="parentControl">Control</param> public void ShowThumbnail(IInteropWindow window, Control parentControl) { UnregisterThumbnail(); Dwm.DwmRegisterThumbnail(Handle, window.Handle, out _thumbnailHandle); if (_thumbnailHandle == IntPtr.Zero) { return; } Dwm.DwmQueryThumbnailSourceSize(_thumbnailHandle, out var sourceSize); var thumbnailHeight = 200; var thumbnailWidth = (int)(thumbnailHeight * (sourceSize.Width / (float)sourceSize.Height)); if (parentControl != null && thumbnailWidth > parentControl.Width) { thumbnailWidth = parentControl.Width; thumbnailHeight = (int)(thumbnailWidth * (sourceSize.Height / (float)sourceSize.Width)); } Width = thumbnailWidth; Height = thumbnailHeight; // Prepare the displaying of the Thumbnail var props = new DwmThumbnailProperties { Opacity = 255, Visible = true, SourceClientAreaOnly = false, Destination = new NativeRect(0, 0, thumbnailWidth, thumbnailHeight) }; Dwm.DwmUpdateThumbnailProperties(_thumbnailHandle, ref props); if (parentControl != null) { AlignToControl(parentControl); } if (!Visible) { Show(); } // Make sure it's on "top"! if (parentControl != null) { User32Api.SetWindowPos(Handle, parentControl.Handle, 0, 0, 0, 0, WindowPos.SWP_NOMOVE | WindowPos.SWP_NOSIZE | WindowPos.SWP_NOACTIVATE); } }
/// <summary> /// Change the thumbnail settings /// </summary> private void UpdateThumbnail() { // Retrieve the current information about the window, this could changed var interopWindow = InteropWindowFactory.CreateFor(_hWnd).Fill(); var sourceBounds = interopWindow.Info.Value.Bounds; Opacity = Math.Max((byte)0x01, _pipConfiguration.Opacity) / 255d; // Prepare the displaying of the Thumbnail var props = new DwmThumbnailProperties { Opacity = _pipConfiguration.Opacity, Visible = true, SourceClientAreaOnly = _pipConfiguration.SourceClientAreaOnly, // This is the size of the DMW Thumbnail Destination = new NativeRect(0, 0, Width, Height), // Here it would be possible to select only a part of the window, but this is slightly tricky of someone resizes the window Source = new NativeRect(0, 0, sourceBounds.Width, sourceBounds.Height) }; Dwm.DwmUpdateThumbnailProperties(_phThumbnail, ref props); }
public void DecorateWindow() { try { // Obtain the window handle for WPF application IntPtr mainWindowPtr = new WindowInteropHelper(window).Handle; HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr); mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0); // Get System Dpi System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(mainWindowPtr); float DesktopDpiX = desktop.DpiX; float DesktopDpiY = desktop.DpiY; // Set Margins Dwm.MARGINS margins = new Dwm.MARGINS(); // Extend glass frame into client area // Note that the default desktop Dpi is 96dpi. The margins are // adjusted for the system Dpi. margins.cxLeftWidth = Convert.ToInt32(5 * (DesktopDpiX / 96)); margins.cxRightWidth = Convert.ToInt32(5 * (DesktopDpiX / 96)); //margins.cyTopHeight = Convert.ToInt32(((int) topBar.ActualHeight + 5) * (DesktopDpiX / 96)); margins.cyTopHeight = Convert.ToInt32((32 + 5) * (DesktopDpiX / 96)); margins.cyBottomHeight = Convert.ToInt32(5 * (DesktopDpiX / 96)); int hr = Dwm.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins); // if (hr < 0) { Debug.WriteLine("DwmExtendFrameIntoClientArea Failed"); //DwmExtendFrameIntoClientArea Failed } } // If not Vista, paint background white. catch (DllNotFoundException) { Application.Current.MainWindow.Background = Brushes.White; } }
/// <summary> /// Get the WindowInfo /// </summary> /// <param name="interopWindow">InteropWindow</param> /// <param name="forceUpdate">set to true to make sure the value is updated</param> /// <returns>WindowInfo</returns> public static WindowInfo GetInfo(this IInteropWindow interopWindow, bool forceUpdate = false) { if (interopWindow.Info.HasValue && !forceUpdate) { return(interopWindow.Info.Value); } var windowInfo = WindowInfo.Create(); User32Api.GetWindowInfo(interopWindow.Handle, ref windowInfo); // Now correct the bounds, for Windows 10 if (Dwm.IsDwmEnabled) { NativeRect extendedFrameBounds; bool gotFrameBounds = Dwm.GetExtendedFrameBounds(interopWindow.Handle, out extendedFrameBounds); if (gotFrameBounds && (interopWindow.IsApp() || WindowsVersion.IsWindows10OrLater && !interopWindow.IsMaximized())) { windowInfo.Bounds = extendedFrameBounds; } } interopWindow.Info = windowInfo; return(interopWindow.Info.Value); }
/// <summary> /// Get the WindowInfo /// </summary> /// <param name="interopWindow">InteropWindow</param> /// <param name="forceUpdate">set to true to make sure the value is updated</param> /// <param name="autoCorrect">enable auto correction, e,g, have the bounds cropped to the parent(s)</param> /// <returns>WindowInfo</returns> public static WindowInfo GetInfo(this IInteropWindow interopWindow, bool forceUpdate = false, bool autoCorrect = true) { if (interopWindow.Info.HasValue && !forceUpdate) { return(interopWindow.Info.Value); } var windowInfo = WindowInfo.Create(); User32Api.GetWindowInfo(interopWindow.Handle, ref windowInfo); // Test if we need to correct some values if (autoCorrect) { // Correct the bounds, for Windows 8+ if (Dwm.IsDwmEnabled) { // This only works for top level windows, otherwise a access denied is returned bool gotFrameBounds = Dwm.GetExtendedFrameBounds(interopWindow.Handle, out var extendedFrameBounds); if (gotFrameBounds && (interopWindow.IsApp() || WindowsVersion.IsWindows10OrLater && !interopWindow.IsMaximized())) { windowInfo.Bounds = extendedFrameBounds; } } var parentWindow = interopWindow.GetParentWindow(); if (interopWindow.HasParent) { var parentInfo = parentWindow.GetInfo(forceUpdate, true); windowInfo.Bounds = windowInfo.Bounds.Intersect(parentInfo.Bounds); windowInfo.ClientBounds = windowInfo.ClientBounds.Intersect(parentInfo.ClientBounds); } } interopWindow.Info = windowInfo; return(windowInfo); }
/// <summary> /// Capture DWM Window /// </summary> /// <param name="interopWindow">IInteropWindow</param> /// <param name="capture">Capture to fill</param> /// <param name="windowCaptureMode">Wanted WindowCaptureModes</param> /// <param name="autoMode">True if auto modus is used</param> /// <returns>ICapture with the capture</returns> public static ICapture CaptureDwmWindow(this IInteropWindow interopWindow, ICapture capture, WindowCaptureModes windowCaptureMode, bool autoMode) { var thumbnailHandle = IntPtr.Zero; Form tempForm = null; var tempFormShown = false; try { tempForm = new Form { ShowInTaskbar = false, FormBorderStyle = FormBorderStyle.None, TopMost = true }; // Register the Thumbnail Dwm.DwmRegisterThumbnail(tempForm.Handle, interopWindow.Handle, out thumbnailHandle); // Get the original size Dwm.DwmQueryThumbnailSourceSize(thumbnailHandle, out var sourceSize); if (sourceSize.Width <= 0 || sourceSize.Height <= 0) { return(null); } // Calculate the location of the temp form var windowRectangle = interopWindow.GetInfo().Bounds; var formLocation = windowRectangle.Location; var borderSize = new Size(); var doesCaptureFit = false; if (!interopWindow.IsMaximized()) { // Assume using it's own location formLocation = windowRectangle.Location; using (var workingArea = new Region(Screen.PrimaryScreen.Bounds)) { // Find the screen where the window is and check if it fits foreach (var screen in Screen.AllScreens) { if (!Equals(screen, Screen.PrimaryScreen)) { workingArea.Union(screen.Bounds); } } // If the formLocation is not inside the visible area if (!workingArea.AreRectangleCornersVisisble(windowRectangle)) { // If none found we find the biggest screen foreach (var screen in Screen.AllScreens) { var newWindowRectangle = new NativeRect(screen.WorkingArea.Location, windowRectangle.Size); if (workingArea.AreRectangleCornersVisisble(newWindowRectangle)) { formLocation = screen.Bounds.Location; doesCaptureFit = true; break; } } } else { doesCaptureFit = true; } } } else if (!WindowsVersion.IsWindows8OrLater) { //GetClientRect(out windowRectangle); borderSize = interopWindow.GetInfo().BorderSize; formLocation = new NativePoint(windowRectangle.X - borderSize.Width, windowRectangle.Y - borderSize.Height); } tempForm.Location = formLocation; tempForm.Size = sourceSize; // Prepare rectangle to capture from the screen. var captureRectangle = new NativeRect(formLocation.X, formLocation.Y, sourceSize.Width, sourceSize.Height); if (interopWindow.IsMaximized()) { // Correct capture size for maximized window by offsetting the X,Y with the border size // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing) captureRectangle = captureRectangle.Inflate(borderSize.Width, borderSize.Height); } else { // TODO: Also 8.x? if (WindowsVersion.IsWindows10) { captureRectangle = captureRectangle.Inflate(CoreConfiguration.Win10BorderCrop.Width, CoreConfiguration.Win10BorderCrop.Height); } if (autoMode) { // check if the capture fits if (!doesCaptureFit) { // if GDI is allowed.. (a screenshot won't be better than we comes if we continue) using (var thisWindowProcess = Process.GetProcessById(interopWindow.GetProcessId())) { if (!interopWindow.IsApp() && WindowCapture.IsGdiAllowed(thisWindowProcess)) { // we return null which causes the capturing code to try another method. return(null); } } } } } // Prepare the displaying of the Thumbnail var props = new DwmThumbnailProperties { Opacity = 255, Visible = true, Destination = new NativeRect(0, 0, sourceSize.Width, sourceSize.Height) }; Dwm.DwmUpdateThumbnailProperties(thumbnailHandle, ref props); tempForm.Show(); tempFormShown = true; // Intersect with screen captureRectangle = captureRectangle.Intersect(capture.ScreenBounds); // Destination bitmap for the capture Bitmap capturedBitmap = null; // Check if we make a transparent capture if (windowCaptureMode == WindowCaptureModes.AeroTransparent) { // Use white, later black to capture transparent tempForm.BackColor = Color.White; // Make sure everything is visible tempForm.Refresh(); Application.DoEvents(); try { using (var whiteBitmap = WindowCapture.CaptureRectangle(captureRectangle)) { // Apply a white color tempForm.BackColor = Color.Black; // Make sure everything is visible tempForm.Refresh(); if (!interopWindow.IsApp()) { // Make sure the application window is active, so the colors & buttons are right // TODO: Await? interopWindow.ToForegroundAsync(); } // Make sure all changes are processed and visible Application.DoEvents(); using (var blackBitmap = WindowCapture.CaptureRectangle(captureRectangle)) { capturedBitmap = ApplyTransparency(blackBitmap, whiteBitmap); } } } catch (Exception e) { Log.Warn().WriteLine(e, "Exception: "); // Some problem occurred, cleanup and make a normal capture if (capturedBitmap != null) { capturedBitmap.Dispose(); capturedBitmap = null; } } } // If no capture up till now, create a normal capture. if (capturedBitmap == null) { // Remove transparency, this will break the capturing if (!autoMode) { tempForm.BackColor = Color.FromArgb(255, CoreConfiguration.DWMBackgroundColor.R, CoreConfiguration.DWMBackgroundColor.G, CoreConfiguration.DWMBackgroundColor.B); } else { var colorizationColor = Dwm.ColorizationSystemDrawingColor; // Modify by losing the transparency and increasing the intensity (as if the background color is white) colorizationColor = Color.FromArgb(255, (colorizationColor.R + 255) >> 1, (colorizationColor.G + 255) >> 1, (colorizationColor.B + 255) >> 1); tempForm.BackColor = colorizationColor; } // Make sure everything is visible tempForm.Refresh(); if (!interopWindow.IsApp()) { // Make sure the application window is active, so the colors & buttons are right interopWindow.ToForegroundAsync(); } // Make sure all changes are processed and visible Application.DoEvents(); // Capture from the screen capturedBitmap = WindowCapture.CaptureRectangle(captureRectangle); } if (capturedBitmap != null) { // Not needed for Windows 8 if (!WindowsVersion.IsWindows8OrLater) { // Only if the Inivalue is set, not maximized and it's not a tool window. if (CoreConfiguration.WindowCaptureRemoveCorners && !interopWindow.IsMaximized() && !interopWindow.GetInfo().ExtendedStyle.HasFlag(ExtendedWindowStyleFlags.WS_EX_TOOLWINDOW)) { // Remove corners if (!Image.IsAlphaPixelFormat(capturedBitmap.PixelFormat)) { Log.Debug().WriteLine("Changing pixelformat to Alpha for the RemoveCorners"); var tmpBitmap = capturedBitmap.CloneBitmap(PixelFormat.Format32bppArgb) as Bitmap; capturedBitmap.Dispose(); capturedBitmap = tmpBitmap; } RemoveCorners(capturedBitmap); } } } capture.Bitmap = capturedBitmap; // Make sure the capture location is the location of the window, not the copy capture.Location = interopWindow.GetInfo().Bounds.Location; } finally { if (thumbnailHandle != IntPtr.Zero) { // Unregister (cleanup), as we are finished we don't need the form or the thumbnail anymore Dwm.DwmUnregisterThumbnail(thumbnailHandle); } if (tempForm != null) { if (tempFormShown) { tempForm.Close(); } tempForm.Dispose(); tempForm = null; } } return(capture); }
/// <summary> /// Retrieve if the window is Visible and not cloaked (different desktop) /// </summary> /// <param name="interopWindow">InteropWindow</param> /// <param name="forceUpdate">set to true to make sure the value is updated</param> /// <returns>bool true if minimizedIconic (minimized)</returns> public static bool IsVisible(this IInteropWindow interopWindow, bool forceUpdate = false) { if (!interopWindow.IsVisible.HasValue || forceUpdate) { interopWindow.IsVisible = User32Api.IsWindowVisible(interopWindow.Handle) && !Dwm.IsWindowCloaked(interopWindow.Handle); } return(interopWindow.IsVisible.Value); }