using Ink_Canvas.Helpers; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Security.Principal; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Effects; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Shell; using System.Xml.Linq; using OSVersionExtension; using Vanara.PInvoke; using Color = System.Windows.Media.Color; using Shell32; using static Ink_Canvas.MainWindow; using OperatingSystem = OSVersionExtension.OperatingSystem; namespace Ink_Canvas.Popups { /// /// ScreenshotWindow.xaml 的交互逻辑 /// public partial class ScreenshotWindow : Window { private MainWindow mainWindow; private Settings settings; public ScreenshotWindow(MainWindow mainWin, Settings s) { InitializeComponent(); mainWindow = mainWin; settings = s; iconList = new Border[] { FullScreenIcon, WindowIcon, SelectionIcon, DesktopIcon }; WindowIcon.IsHitTestVisible = OSVersion.GetOperatingSystem() >= OperatingSystem.Windows10; WindowIcon.Opacity = OSVersion.GetOperatingSystem() >= OperatingSystem.Windows10 ? 1 : 0.5; foreach (var b in iconList) { b.MouseLeave += IconMouseLeave; b.MouseUp += IconMouseUp; b.MouseDown += IconMouseDown; b.Background = new SolidColorBrush(Colors.Transparent); } ReArrangeWindowPosition(); mainWin.Hide(); if (DwmCompositionHelper.DwmIsCompositionEnabled()) { AllowsTransparency = false; Background = new SolidColorBrush(Colors.Transparent); WindowChrome.SetWindowChrome(this, new WindowChrome() { GlassFrameThickness = new Thickness(-1), CaptionHeight = 0, CornerRadius = new CornerRadius(0), ResizeBorderThickness = new Thickness(0), }); } else { AllowsTransparency = true; Background = new SolidColorBrush(Color.FromArgb(1,0,0,0)); } ToggleSwitchCopyToClipBoard.IsChecked = settings.Snapshot.CopyScreenshotToClipboard; ToggleSwitchAttachInk.IsChecked = settings.Snapshot.AttachInkWhenScreenshot; ToggleSwitchCopyToClipBoard.Checked += ToggleSwitchCopyToClipBoard_CheckChanged; ToggleSwitchCopyToClipBoard.Unchecked += ToggleSwitchCopyToClipBoard_CheckChanged; ToggleSwitchAttachInk.Checked += ToggleSwitchAttachInk_CheckChanged; ToggleSwitchAttachInk.Unchecked += ToggleSwitchAttachInk_CheckChanged; WindowsItemsControl.ItemsSource = _winInfos; WindowScreenshotOverlay.Visibility = Visibility.Collapsed; WindowsSnapshotLoadingOverlay.Visibility = Visibility.Collapsed; EscBorder.MouseDown += EscBorder_MouseDown; EscBorder.MouseUp += EscBorder_MouseUp; EscBorder.MouseLeave += EscBorder_MouseLeave; var identity = WindowsIdentity.GetCurrent(); var principal = new WindowsPrincipal(identity); NeedAdminTextPanel.Visibility = principal.IsInRole(WindowsBuiltInRole.Administrator) ? Visibility.Collapsed : Visibility.Visible; if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { WindowsItemsScrollViewer.Margin = new Thickness(36, 148, 36, 0); } else { WindowsItemsScrollViewer.Margin = new Thickness(36, 178, 36, 0); } } private bool isEscBorderDown = false; private void EscBorder_MouseLeave(object sender, MouseEventArgs e) { if (!isEscBorderDown) return; isEscBorderDown = false; EscBorder.Background = new SolidColorBrush(Colors.Transparent); } private void EscBorder_MouseUp(object sender, MouseButtonEventArgs e) { if (!isEscBorderDown) return; if (isWindowsSnapshotLoaded == false) return; EscBorder_MouseLeave(null, null); ScreenshotPanel.Visibility = Visibility.Visible; WindowScreenshotOverlay.Visibility = Visibility.Collapsed; _winInfos.Clear(); isWindowsSnapshotLoaded = null; } private void EscBorder_MouseDown(object sender, MouseButtonEventArgs e) { if (isEscBorderDown) return; isEscBorderDown = true; EscBorder.Background = new SolidColorBrush(Color.FromRgb(39, 39, 42)); } private ObservableCollection _winInfos = new ObservableCollection(); private bool AllOneColor(Bitmap bmp) { // Lock the bitmap's bits. System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height); BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat); // Get the address of the first line. IntPtr ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap. int bytes = bmpData.Stride * bmp.Height; byte[] rgbValues = new byte[bytes]; // Copy the RGB values into the array. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); bool AllOneColor = true; for (int index = 0; index < rgbValues.Length; index++) { //compare the current A or R or G or B with the A or R or G or B at position 0,0. if (rgbValues[index] != rgbValues[index % 4]) { AllOneColor= false; break; } } // Unlock the bits. bmp.UnlockBits(bmpData); return AllOneColor; } private async Task AllOneColorAsync(Bitmap bmp) { var result = await Task.Run(() => AllOneColor(bmp)); return result; } public BitmapImage BitmapToImageSource(Bitmap bitmap) { using (MemoryStream memory = new MemoryStream()) { bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp); memory.Position = 0; BitmapImage bitmapimage = new BitmapImage(); bitmapimage.BeginInit(); bitmapimage.StreamSource = memory; bitmapimage.CacheOption = BitmapCacheOption.OnLoad; bitmapimage.EndInit(); return bitmapimage; } } private static ImageSource IconToImageSource(Icon icon) { ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon( icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); return imageSource; } private class WinInfo { public string Title { get; set; } public BitmapImage Snapshot { get; set; } public ImageSource Icon { get; set; } public HWND Handle { get; set; } public Bitmap OriginBitmap { get; set; } public double Width { get; set; } public double TextBlockWidth { get; set; } public bool IsAllOneColor { get; set; } public bool IsDisplayFailedBorder { get; set; } public Visibility ShouldDisplayFailedBorder { get => IsDisplayFailedBorder ? Visibility.Visible : Visibility.Collapsed; } public bool IsHidden { get; set; } public Visibility Visibility { get => IsHidden ? Visibility.Collapsed : Visibility.Visible; } } private Border lastDownIcon; private void ToggleSwitchCopyToClipBoard_CheckChanged(object sender, RoutedEventArgs e) { if (!mainWindow.isLoaded) return; mainWindow.ToggleSwitchCopyScreenshotToClipboard.IsOn = ToggleSwitchCopyToClipBoard.IsChecked ?? true; } private void ToggleSwitchAttachInk_CheckChanged(object sender, RoutedEventArgs e) { if (!mainWindow.isLoaded) return; mainWindow.ToggleSwitchAttachInkWhenScreenshot.IsOn = ToggleSwitchAttachInk.IsChecked ?? true; } private void ReArrangeWindowPosition() { var workAreaWidth = SystemParameters.WorkArea.Width; var workAreaHeight = SystemParameters.WorkArea.Height; var toolbarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.FullPrimaryScreenHeight - SystemParameters.WindowCaptionHeight; Left = (workAreaWidth - Width) / 2; Top = workAreaHeight - Height - toolbarHeight - 64; } private bool isCaptureButtonDown = false; private async void CaptureFullScreen() { LoadingOverlay.Visibility = Visibility.Visible; MainFuncPanel.Effect = new BlurEffect() { KernelType = KernelType.Gaussian, Radius = 24, RenderingBias = RenderingBias.Performance, }; try { var bm = await mainWindow.FullscreenSnapshot(new MainWindow.SnapshotConfig() { BitmapSavePath = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)), ExcludedHwnds = new HWND[] { new HWND(new WindowInteropHelper(this).Handle) }, IsCopyToClipboard = settings.Snapshot.CopyScreenshotToClipboard, IsSaveToLocal = true, OutputMIMEType = MainWindow.OutputImageMIMEFormat.Png, }); bm.Dispose(); LoadingOverlay.Visibility = Visibility.Collapsed; MainFuncPanel.Effect = null; mainWindow.ShowNewToast("已保存截图到桌面!", MW_Toast.ToastType.Success, 3000); await Task.Delay(1); Close(); } catch (Exception e) { LoadingOverlay.Visibility = Visibility.Collapsed; MainFuncPanel.Effect = null; mainWindow.ShowNewToast($"截图失败!{e.Message}", MW_Toast.ToastType.Error, 3000); await Task.Delay(1); Close(); } } private void IconMouseLeave(object sender, MouseEventArgs e) { if (lastDownIcon == null) return; lastDownIcon = null; var b = (Border)sender; b.Background = new SolidColorBrush(Colors.Transparent); } private void IconMouseDown(object sender, MouseButtonEventArgs e) { if (lastDownIcon != null) return; lastDownIcon = (Border)sender; var b = (Border)sender; b.Background = new SolidColorBrush(Color.FromArgb(22, 24, 24, 27)); } private bool? isWindowsSnapshotLoaded = false; private async void IconMouseUp(object sender, MouseButtonEventArgs e) { if (lastDownIcon == null) return; IconMouseLeave(sender, null); /*if (selectedMode == 1) { try { MainWindow.WindowInformation[] windows = await mainWindow.GetAllWindowsAsync(new HWND[] { new HWND(new WindowInteropHelper(this).Handle), new HWND(new WindowInteropHelper(mainWindow).Handle) }); _screenshotGridWindow = new WindowScreenshotGridWindow(windows, mainWindow); _screenshotGridWindow.Show(); } catch (TaskCanceledException) {} catch (Exception ex) {} } else { try { _screenshotGridWindow.Close(); } catch (Exception ex) { } }*/ if (Array.IndexOf(iconList, (Border)sender) == 0) { CaptureFullScreen(); } else if (Array.IndexOf(iconList, (Border)sender) == 3) { Shell shellObject = new Shell(); shellObject.ToggleDesktop(); } else if (Array.IndexOf(iconList, ((Border)sender)) == 1) { isWindowsSnapshotLoaded = false; await Dispatcher.InvokeAsync(() => { _winInfos.Clear(); ScreenshotPanel.Visibility = Visibility.Collapsed; WindowScreenshotOverlay.Visibility = Visibility.Visible; WindowsSnapshotLoadingOverlay.Visibility = Visibility.Visible; WindowScreenshotWindowsGrid.Effect = new BlurEffect() { KernelType = KernelType.Gaussian, RenderingBias = RenderingBias.Performance, Radius = 32, }; }); var wins = await mainWindow.GetAllWindowsAsync(new HWND[] { new HWND(new WindowInteropHelper(this).Handle) }); foreach (var windowInformation in wins) { var bitmapHeight = windowInformation.WindowBitmap.Height; var w = windowInformation.WindowBitmap.Width * (226D / bitmapHeight); var allonecolor = await AllOneColorAsync(windowInformation.WindowBitmap); _winInfos.Add(new WinInfo() { Title = windowInformation.Title, Snapshot = BitmapToImageSource(windowInformation.WindowBitmap.Clone(windowInformation.ContentRect,windowInformation.WindowBitmap.PixelFormat)), Handle = windowInformation.hwnd, OriginBitmap = windowInformation.WindowBitmap, Icon = windowInformation.AppIcon == null ? new BitmapImage(new Uri("pack://application:,,,/Resources/Icons-png/classic-icons/program-icon.png")) : IconToImageSource(windowInformation.AppIcon), Width = w, TextBlockWidth = w - 48 - 8, IsAllOneColor = allonecolor, IsDisplayFailedBorder = allonecolor, IsHidden = settings.Snapshot.OnlySnapshotMaximizeWindow, }); if (Array.IndexOf(wins, windowInformation)>= wins.Length - 1) Dispatcher.InvokeAsync(() => { WindowScreenshotWindowsGrid.Effect = null; WindowsSnapshotLoadingOverlay.Visibility = Visibility.Collapsed;}); } Dispatcher.InvokeAsync(() => { WindowScreenshotWindowsGrid.Effect = null; WindowsSnapshotLoadingOverlay.Visibility = Visibility.Collapsed;}); isWindowsSnapshotLoaded = true; } } private Border[] iconList = new Border[] { }; private void CloseButton_CloseWindow(object sender, MouseButtonEventArgs e) { Close(); } protected override void OnClosed(EventArgs e) { mainWindow.Show(); base.OnClosed(e); } private void ScreenshotWindow_OnKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) { if (isWindowsSnapshotLoaded==false) return; ScreenshotPanel.Visibility = Visibility.Visible; WindowScreenshotOverlay.Visibility = Visibility.Collapsed; _winInfos.Clear(); isWindowsSnapshotLoaded = null; } } public void WindowsItemsScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { var scrollViewer = (ScrollViewer)sender; var sb = new Storyboard(); var ofs = scrollViewer.VerticalOffset; var animation = new DoubleAnimation { From = ofs, To = ofs - e.Delta * 2.5, Duration = TimeSpan.FromMilliseconds(155) }; animation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut, }; Storyboard.SetTargetProperty(animation, new PropertyPath(ColorPalette.ScrollViewerBehavior.VerticalOffsetProperty)); Storyboard.SetTargetName(animation,"WindowsItemsScrollViewer"); sb.Children.Add(animation); scrollViewer.ScrollToVerticalOffset(ofs); sb.Begin(scrollViewer); } } }