[update] 简陋的全屏截图和窗口截图实现。

This commit is contained in:
Dubi906w 2024-07-30 21:58:44 +08:00
parent 20a2f21e0b
commit ede417fe8d
8 changed files with 659 additions and 4 deletions

View File

@ -160,6 +160,7 @@
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="OSVersionExt" Version="3.0.0" />
<PackageReference Include="PixiEditor.ColorPicker" Version="3.4.1" />
<PackageReference Include="Vanara.PInvoke.Magnification" Version="4.0.2" />
</ItemGroup>
<ItemGroup>
<COMReference Include="IWshRuntimeLibrary">

View File

@ -17,6 +17,12 @@
<Compile Update="Popups\FloatingBarWindowV2.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Popups\ScreenshotWindow.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Popups\WindowScreenshotGridWindow.xaml.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Page Update="MainWindow_cs\MW_ContextMenus.xaml">
@ -37,6 +43,12 @@
<Page Update="Popups\FloatingBarWindowV2.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Popups\ScreenshotWindow.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Popups\WindowScreenshotGridWindow.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Resources\GeometryIcons.xaml">
<SubType>Designer</SubType>
</Page>

View File

@ -23,6 +23,7 @@ using System.Text;
using System.Globalization;
using System.Windows.Data;
using System.Xml.Linq;
using Ink_Canvas.Popups;
using Image = System.Windows.Controls.Image;
namespace Ink_Canvas {
@ -1026,11 +1027,11 @@ namespace Ink_Canvas {
private async void SymbolIconScreenshot_MouseUp(object sender, MouseButtonEventArgs e) {
HideSubPanelsImmediately();
await Task.Delay(50);
SaveScreenShotToDesktop();
//SaveScreenShotToDesktop();
var scrwin = new ScreenshotWindow(this);
scrwin.Show();
}
private void ImageCountdownTimer_MouseUp(object sender, MouseButtonEventArgs e) {
LeftUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;
RightUnFoldButtonQuickPanel.Visibility = Visibility.Collapsed;

View File

@ -1,8 +1,17 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using OSVersionExtension;
using Vanara.PInvoke;
using OperatingSystem = OSVersionExtension.OperatingSystem;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
namespace Ink_Canvas
{
@ -33,8 +42,209 @@ namespace Ink_Canvas
}
}
private void SaveScreenShotToDesktop()
#region MagnificationAPI ICC窗口
public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
if (IntPtr.Size == 8)
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
else
return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
}
[DllImport("user32.dll", EntryPoint="SetWindowLong")]
private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", EntryPoint="SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint="GetWindowLong")]
static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
[DllImport("user32.dll", SetLastError=true)]
private static extern IntPtr CreateWindowEx(
uint dwExStyle,
string lpClassName,
string lpWindowName,
uint dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
public void SaveScreenshotToDesktopByMagnificationAPI(HWND[] excludedHwnds, Action<Bitmap> callbackAction) {
if (OSVersion.GetOperatingSystem() < OperatingSystem.Windows8 && OSVersion.GetOperatingSystem() > OperatingSystem.Windows10) return;
if (!Magnification.MagInitialize()) return;
// 創建宿主窗體
var mainWinMag = new Window();
mainWinMag.WindowState = WindowState.Maximized;
mainWinMag.WindowStyle = WindowStyle.None;
mainWinMag.ResizeMode = ResizeMode.NoResize;
mainWinMag.Background = new SolidColorBrush(Colors.Transparent);
mainWinMag.AllowsTransparency = true;
mainWinMag.Show();
var handle = new WindowInteropHelper(mainWinMag).Handle;
SetWindowPos(handle, new IntPtr(1), 0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, 0x0080); // SWP_HIDEWINDOW
SetWindowLongPtr(handle, -20, new IntPtr((int)GetWindowLongPtr(handle, -20) | 0x00080000));
SetLayeredWindowAttributes(handle,0, 255, (byte)0x2);
// 創建放大鏡窗體使用Win32方法
var hwndMag = CreateWindowEx(0,"Magnifier", "ICCMagnifierWindow", (uint)(0x40000000L | 0x10000000L), 0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
// 過濾窗口
var hwnds = new List<HWND> { new HWND(hwndMag) };
hwnds.AddRange(excludedHwnds);
if (!Magnification.MagSetWindowFilterList(new HWND(hwndMag),
Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE, hwnds.Count, hwnds.ToArray())) return;
// 保存數據
if (!Magnification.MagSetImageScalingCallback(new HWND(hwndMag),
(hwnd, srcdata, srcheader, destdata, destheader, unclipped, clipped, dirty) => {
Bitmap bm = new Bitmap((int)srcheader.width, (int)srcheader.height, (int)srcheader.width * 4,
PixelFormat.Format32bppRgb, srcdata);
callbackAction(bm);
return true;
})) return;
// 設置窗口Source
if (!Magnification.MagSetWindowSource(new HWND(hwndMag),
new RECT(0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return;
// 關閉宿主窗體
mainWinMag.Close();
}
#endregion
#region
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
{
if (IntPtr.Size > 4)
return GetClassLongPtr64(hWnd, nIndex);
else
return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
}
[DllImport("user32.dll", EntryPoint = "GetClassLong")]
public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows",
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool EnumDesktopWindows(IntPtr hDesktop, Delegate lpEnumCallbackFunction, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", EntryPoint = "GetWindowText",
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpWindowText, int nMaxCount);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr handle, out RECT rect);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
public Icon GetAppIcon(IntPtr hwnd) {
IntPtr iconHandle = SendMessage(hwnd,0x7F,2,0);
if(iconHandle == IntPtr.Zero)
iconHandle = SendMessage(hwnd,0x7F,0,0);
if(iconHandle == IntPtr.Zero)
iconHandle = SendMessage(hwnd,0x7F,1,0);
if (iconHandle == IntPtr.Zero)
iconHandle = GetClassLongPtr(hwnd, -14);
if (iconHandle == IntPtr.Zero)
iconHandle = GetClassLongPtr(hwnd, -34);
if(iconHandle == IntPtr.Zero)
return null;
Icon icn = System.Drawing.Icon.FromHandle(iconHandle);
return icn;
}
public struct WindowInformation {
public string Title;
public Bitmap WindowBitmap;
public Icon AppIcon;
public bool IsVisible;
public int Width;
public int Height;
public RECT Rect;
public WINDOWPLACEMENT Placement;
}
public struct WINDOWPLACEMENT {
public int length;
public int flags;
public int showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
public delegate bool EnumDesktopWindowsDelegate(IntPtr hWnd, int lParam);
public WindowInformation[] GetAllWindows() {
var windows = new List<WindowInformation>();
if (!EnumDesktopWindows(IntPtr.Zero, new EnumDesktopWindowsDelegate((hwnd, param) => {
var isvisible = IsWindowVisible(hwnd);
if (!isvisible) return true;
var icon = GetAppIcon(hwnd);
var length = GetWindowTextLength(hwnd) + 1;
var title = new StringBuilder(length);
GetWindowText(hwnd, title, length);
if (title.ToString().Length == 0) return true;
RECT rect;
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
GetWindowPlacement(hwnd, ref placement);
if (placement.showCmd == 2) return true;
GetWindowRect(hwnd, out rect);
var w = rect.Width;
var h = rect.Height;
if (w == 0 || h == 0) return true;
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
Graphics memoryGraphics = Graphics.FromImage(bmp);
IntPtr hdc = memoryGraphics.GetHdc();
PrintWindow(hwnd, hdc, 2);
windows.Add(new WindowInformation() {
AppIcon = icon,
Title = title.ToString(),
IsVisible = isvisible,
WindowBitmap = bmp,
Width = w,
Height = h,
Rect = rect,
Placement = placement,
});
memoryGraphics.ReleaseHdc(hdc);
return true;
}),
IntPtr.Zero)) return new WindowInformation[]{};
return windows.ToArray();
}
#endregion
private void SaveScreenShotToDesktop() {
var bitmap = GetScreenshotBitmap();
string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
bitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".png", ImageFormat.Png);

View File

@ -0,0 +1,118 @@
<Window x:Class="Ink_Canvas.Popups.ScreenshotWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Ink_Canvas.Popups"
xmlns:modern="http://schemas.inkore.net/lib/ui/wpf/modern"
mc:Ignorable="d" AllowsTransparency="True" Background="Transparent"
WindowStyle="None" ResizeMode="NoResize" ShowInTaskbar="False"
Title="ScreenshotWindow" Height="220" Width="360" Topmost="True">
<Grid>
<Border Background="#fafafa" BorderBrush="#3b82f6" BorderThickness="2" CornerRadius="24,12,24,24" Margin="12">
<modern:SimpleStackPanel Orientation="Vertical" Spacing="2">
<Grid Margin="16,12">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border Name="FullScreenIcon" Margin="0,0,4,0" Grid.Column="0" CornerRadius="18" Background="#1618181b" Height="78">
<modern:SimpleStackPanel Spacing="2" Orientation="Vertical" VerticalAlignment="Center">
<Image Width="40" Height="40">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing x:Name="FullScreenIconGeometry" Brush="#18181b" Geometry="F0 M24,24z M0,0z M2.58579,3.58579C2.96086,3.21071,3.46957,3,4,3L20,3C20.5304,3 21.0391,3.21071 21.4142,3.58579 21.7893,3.96086 22,4.46957 22,5L22,15C22,15.5304 21.7893,16.0391 21.4142,16.4142 21.0391,16.7893 20.5304,17 20,17L16,17 16,19 17,19C17.5523,19 18,19.4477 18,20 18,20.5523 17.5523,21 17,21L7,21C6.44772,21 6,20.5523 6,20 6,19.4477 6.44772,19 7,19L8,19 8,17 4,17C3.46957,17 2.96086,16.7893 2.58579,16.4142 2.21071,16.0391 2,15.5304 2,15L2,5C2,4.46957,2.21071,3.96086,2.58579,3.58579z M20,5L20,15 4,15 4,5 20,5z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<TextBlock Name="FullScreenIconText" Text="全屏截图" FontSize="14" HorizontalAlignment="Center"></TextBlock>
</modern:SimpleStackPanel>
</Border>
<Border Name="WindowIcon" Margin="4,0,4,0" Grid.Column="1" CornerRadius="18" Background="#1618181b" Height="78">
<modern:SimpleStackPanel Spacing="2" Orientation="Vertical" VerticalAlignment="Center">
<Image Width="40" Height="40">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing x:Name="WindowIconsGeometry" Brush="#18181b" Geometry="F0 M24,24z M0,0z M5,6C4.73478,6 4.48043,6.10536 4.29289,6.29289 4.10536,6.48043 4,6.73478 4,7L4,17C4,17.2652 4.10536,17.5196 4.29289,17.7071 4.48043,17.8946 4.73478,18 5,18L19,18C19.2652,18 19.5196,17.8946 19.7071,17.7071 19.8946,17.5196 20,17.2652 20,17L20,7C20,6.73478 19.8946,6.48043 19.7071,6.29289 19.5196,6.10536 19.2652,6 19,6L5,6z M2.87868,4.87868C3.44129,4.31607,4.20435,4,5,4L19,4C19.7957,4 20.5587,4.31607 21.1213,4.87868 21.6839,5.44129 22,6.20435 22,7L22,17C22,17.7957 21.6839,18.5587 21.1213,19.1213 20.5587,19.6839 19.7957,20 19,20L5,20C4.20435,20 3.44129,19.6839 2.87868,19.1213 2.31607,18.5587 2,17.7956 2,17L2,7C2,6.20435,2.31607,5.44129,2.87868,4.87868z M5,8C5,7.44772,5.44772,7,6,7L6.01,7C6.56228,7 7.01,7.44772 7.01,8 7.01,8.55228 6.56228,9 6.01,9L6,9C5.44772,9,5,8.55228,5,8z M9,7C8.44772,7 8,7.44772 8,8 8,8.55228 8.44772,9 9,9L9.01,9C9.56228,9 10.01,8.55228 10.01,8 10.01,7.44772 9.56228,7 9.01,7L9,7z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<TextBlock Name="WindowIconText" Text="窗口截图" FontSize="14" HorizontalAlignment="Center"></TextBlock>
</modern:SimpleStackPanel>
</Border>
<Border Name="SelectionIcon" Margin="4,0,0,0" Grid.Column="2" CornerRadius="18" Background="#1618181b" Height="78">
<modern:SimpleStackPanel Spacing="2" Orientation="Vertical" VerticalAlignment="Center">
<Image Width="40" Height="40">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing x:Name="SelectionIconGeometry" Brush="#18181b" Geometry="F0 M24,24z M0,0z M10,5C9.73478,5 9.48043,5.10536 9.29289,5.29289 9.10536,5.48043 9,5.73478 9,6L9,8 9,8.08584 12.0858,5 10,5z M7,7L7,6C7,5.20435 7.31607,4.44129 7.87868,3.87868 8.44129,3.31607 9.20435,3 10,3L18,3C18.7956,3 19.5587,3.31607 20.1213,3.87868 20.6839,4.44129 21,5.20435 21,6L21,14C21,14.7957 20.6839,15.5587 20.1213,16.1213 19.5587,16.6839 18.7957,17 18,17L17,17 17,18C17,18.7957 16.6839,19.5587 16.1213,20.1213 15.5587,20.6839 14.7957,21 14,21L6,21C5.20435,21 4.44129,20.6839 3.87868,20.1213 3.31607,19.5587 3,18.7956 3,18L3,10C3,9.20435 3.31607,8.44129 3.87868,7.87868 4.44129,7.31607 5.20435,7 6,7L7,7z M15,17L15,18C15,18.2652 14.8946,18.5196 14.7071,18.7071 14.5196,18.8946 14.2652,19 14,19L6,19C5.73478,19 5.48043,18.8946 5.29289,18.7071 5.10536,18.5196 5,18.2652 5,18L5,10C5,9.73478 5.10536,9.48043 5.29289,9.29289 5.48043,9.10536 5.73478,9 6,9L7,9 7,14C7,14.7957 7.31607,15.5587 7.87868,16.1213 8.44129,16.6839 9.20435,17 10,17L13.4822,17C13.4856,17 13.4889,17.0001 13.4923,17.0001 13.4981,17.0001 13.5039,17.0001 13.5097,17L15,17z M16,15L18,15C18.2652,15 18.5196,14.8946 18.7071,14.7071 18.8946,14.5196 19,14.2652 19,14L19,11.9103 15.9103,15 16,15z M9,13.5858L9,10.9143 14.9143,5 17.5858,5 9,13.5858z M10.4142,15L19,6.41419 19,9.08185 13.0819,15 10.4142,15z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<TextBlock Name="SelectionIconText" Text="选区截图" FontSize="14" HorizontalAlignment="Center"></TextBlock>
</modern:SimpleStackPanel>
</Border>
</Grid>
<Grid>
<Border Name="CaptureButton" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Left" Margin="20,0,0,0" Height="72" Width="72" CornerRadius="36" BorderBrush="#2563eb" BorderThickness="5">
<Border.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1"></ScaleTransform>
</Border.RenderTransform>
<Border Height="52" Width="52" CornerRadius="24" Background="#2563eb">
<Image Width="28" Height="28">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing Brush="White" Geometry="F1 M24,24z M0,0z M15,3C15.5046,2.99984 15.9906,3.19041 16.3605,3.5335 16.7305,3.87659 16.9572,4.34684 16.995,4.85L17,5C17,5.24493 17.09,5.48134 17.2527,5.66437 17.4155,5.84741 17.6397,5.96434 17.883,5.993L18,6 19,6C19.7652,5.99996 20.5015,6.29233 21.0583,6.81728 21.615,7.34224 21.9501,8.06011 21.995,8.824L22,9 22,18C22,18.7652 21.7077,19.5015 21.1827,20.0583 20.6578,20.615 19.9399,20.9501 19.176,20.995L19,21 5,21C4.23479,21 3.49849,20.7077 2.94174,20.1827 2.38499,19.6578 2.04989,18.9399 2.005,18.176L2,18 2,9C1.99996,8.23479 2.29233,7.49849 2.81728,6.94174 3.34224,6.38499 4.06011,6.04989 4.824,6.005L5,6 6,6C6.26522,6 6.51957,5.89464 6.70711,5.70711 6.89464,5.51957 7,5.26522 7,5 6.99984,4.49542 7.19041,4.00943 7.5335,3.63945 7.87659,3.26947 8.34685,3.04284 8.85,3.005L9,3 15,3z M12,10C11.2566,9.99994 10.5396,10.2759 9.98813,10.7744 9.43662,11.2729 9.08984,11.9584 9.015,12.698L9.004,12.85 9,13 9.004,13.15C9.03335,13.7362 9.23402,14.301 9.58117,14.7743 9.92832,15.2476 10.4067,15.6087 10.957,15.8128 11.5074,16.0169 12.1055,16.0551 12.6773,15.9226 13.2491,15.7901 13.7695,15.4928 14.174,15.0675 14.5786,14.6422 14.8494,14.1076 14.9531,13.5298 15.0568,12.9521 14.9887,12.3566 14.7572,11.8172 14.5258,11.2778 14.1412,10.8181 13.6511,10.4951 13.1611,10.1721 12.587,9.99995 12,10z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>
</Border>
<modern:SimpleStackPanel Orientation="Vertical" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,20,0">
<modern:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<CheckBox MinWidth="0" Name="ToggleSwitchAutoHideToolbar" IsChecked="True" FontWeight="Bold"/>
<TextBlock Foreground="#18181b" Text="截图时隐藏ICC" VerticalAlignment="Center"
FontSize="14" />
</modern:SimpleStackPanel>
<modern:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<CheckBox MinWidth="0" Name="ToggleSwitchAttachInk" IsChecked="True"
FontFamily="Microsoft YaHei UI" FontWeight="Bold"/>
<TextBlock Foreground="#18181b" Text="附带批注墨迹" VerticalAlignment="Center"
FontSize="14" />
</modern:SimpleStackPanel>
</modern:SimpleStackPanel>
</Grid>
</modern:SimpleStackPanel>
</Border>
<Border MouseDown="CloseButton_CloseWindow" BorderBrush="#2563eb" BorderThickness="1" Width="32" Height="32" CornerRadius="16" Background="#3b82f6" HorizontalAlignment="Right" VerticalAlignment="Top">
<Image Height="21" Width="21">
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V24 H24 V0 H0 Z">
<GeometryDrawing Brush="White" Geometry="F0 M24,24z M0,0z M18.7071,6.70711C19.0976,6.31658 19.0976,5.68342 18.7071,5.29289 18.3166,4.90237 17.6834,4.90237 17.2929,5.29289L12,10.5858 6.70711,5.29289C6.31658,4.90237 5.68342,4.90237 5.29289,5.29289 4.90237,5.68342 4.90237,6.31658 5.29289,6.70711L10.5858,12 5.29289,17.2929C4.90237,17.6834 4.90237,18.3166 5.29289,18.7071 5.68342,19.0976 6.31658,19.0976 6.70711,18.7071L12,13.4142 17.2929,18.7071C17.6834,19.0976 18.3166,19.0976 18.7071,18.7071 19.0976,18.3166 19.0976,17.6834 18.7071,17.2929L13.4142,12 18.7071,6.70711z" />
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Border>
</Grid>
</Window>

View File

@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
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.Imaging;
using System.Windows.Shapes;
using System.Xml.Linq;
using Vanara.PInvoke;
namespace Ink_Canvas.Popups
{
/// <summary>
/// ScreenshotWindow.xaml 的交互逻辑
/// </summary>
public partial class ScreenshotWindow : Window {
private MainWindow mainWindow;
public ScreenshotWindow(MainWindow mainWin) {
InitializeComponent();
mainWindow = mainWin;
iconList = new Border[] {
FullScreenIcon,
WindowIcon,
SelectionIcon
};
iconGeometryList = new GeometryDrawing[] {
FullScreenIconGeometry,
WindowIconsGeometry,
SelectionIconGeometry,
};
iconTextList = new TextBlock[] {
FullScreenIconText,
WindowIconText,
SelectionIconText,
};
foreach (var b in iconList) {
b.MouseLeave += IconMouseLeave;
b.MouseUp += IconMouseUp;
b.MouseDown += IconMouseDown;
}
CaptureButton.MouseUp += CaptureButton_MouseUp;
CaptureButton.MouseDown += CaptureButton_MouseDown;
CaptureButton.MouseLeave += CaptureButton_MouseLeave;
UpdateModeIconSelection();
ReArrangeWindowPosition();
mainWin.Hide();
}
private Border lastDownIcon;
private int selectedMode = 0;
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 void UpdateModeIconSelection() {
foreach (var b in iconList) b.Background = new SolidColorBrush(Colors.Transparent);
foreach (var g in iconGeometryList) g.Brush = new SolidColorBrush(Color.FromRgb(24, 24, 27));
foreach (var t in iconTextList) t.Foreground = new SolidColorBrush(Color.FromRgb(24, 24, 27));
iconList[selectedMode].Background = new SolidColorBrush(Color.FromRgb(37, 99, 235));
iconGeometryList[selectedMode].Brush = new SolidColorBrush(Colors.White);
iconTextList[selectedMode].Foreground = new SolidColorBrush(Colors.White);
}
private bool isCaptureButtonDown = false;
private void CaptureButton_MouseDown(object sender, MouseButtonEventArgs e) {
if (isCaptureButtonDown) return;
isCaptureButtonDown = true;
var sb = new Storyboard();
var animation = new DoubleAnimation {
From = 1,
To = 0.9,
Duration = TimeSpan.FromMilliseconds(200)
};
var animation2 = new DoubleAnimation {
From = 1,
To = 0.9,
Duration = TimeSpan.FromMilliseconds(200)
};
var animation3 = new ThicknessAnimation() {
From = new Thickness(5),
To = new Thickness(7),
Duration = TimeSpan.FromMilliseconds(200)
};
Storyboard.SetTargetProperty(animation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"));
Storyboard.SetTargetProperty(animation2, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));
Storyboard.SetTargetProperty(animation3, new PropertyPath(Border.BorderThicknessProperty));
animation.EasingFunction = new CubicEase();
animation2.EasingFunction = new CubicEase();
animation3.EasingFunction = new CubicEase();
sb.Children.Add(animation);
sb.Children.Add(animation2);
sb.Children.Add(animation3);
sb.Begin(CaptureButton);
}
private void CaptureButton_MouseUp(object sender, MouseButtonEventArgs e) {
if (isCaptureButtonDown != true) return;
CaptureButton_MouseLeave(sender, null);
if (selectedMode == 0) CaptureFullScreen();
}
private void CaptureFullScreen() {
mainWindow.SaveScreenshotToDesktopByMagnificationAPI(new HWND[] {
new WindowInteropHelper(mainWindow).Handle,
new WindowInteropHelper(this).Handle,
}, async bitmap => {
string savePath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
bitmap.Save(savePath + @"\" + DateTime.Now.ToString("u").Replace(':', '-') + ".bmp", ImageFormat.Bmp);
mainWindow.ShowNewToast("已保存截图到桌面!",MW_Toast.ToastType.Success,3000);
await Task.Delay(50);
Close();
});
}
private void CaptureButton_MouseLeave(object sender, MouseEventArgs e) {
if (isCaptureButtonDown != true) return;
var sb = new Storyboard();
var animation = new DoubleAnimation {
From = 0.9,
To = 1,
Duration = TimeSpan.FromMilliseconds(200)
};
var animation2 = new DoubleAnimation {
From = 0.9,
To = 1,
Duration = TimeSpan.FromMilliseconds(200)
};
var animation3 = new ThicknessAnimation() {
From = new Thickness(7),
To = new Thickness(5),
Duration = TimeSpan.FromMilliseconds(200)
};
Storyboard.SetTargetProperty(animation, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"));
Storyboard.SetTargetProperty(animation2, new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"));
Storyboard.SetTargetProperty(animation3, new PropertyPath(Border.BorderThicknessProperty));
animation.EasingFunction = new CubicEase();
animation2.EasingFunction = new CubicEase();
animation3.EasingFunction = new CubicEase();
sb.Children.Add(animation);
sb.Children.Add(animation2);
sb.Children.Add(animation3);
sb.Begin(CaptureButton);
isCaptureButtonDown = false;
}
private void IconMouseLeave(object sender, MouseEventArgs e) {
if (lastDownIcon == null) return;
lastDownIcon = null;
var b = (Border)sender;
if (Array.IndexOf(iconList,b)!=selectedMode)
b.Background = new SolidColorBrush(Colors.Transparent);
}
private void IconMouseDown(object sender, MouseButtonEventArgs e) {
if (lastDownIcon != null) return;
lastDownIcon = (Border)sender;
var b = (Border)sender;
if (Array.IndexOf(iconList,b)!=selectedMode)
b.Background = new SolidColorBrush(Color.FromArgb(22, 24, 24, 27));
}
private WindowScreenshotGridWindow _screenshotGridWindow = null;
private void IconMouseUp(object sender, MouseButtonEventArgs e) {
if (lastDownIcon == null) return;
IconMouseLeave(sender, null);
var index = Array.IndexOf(iconList, (Border)sender);
selectedMode = index;
UpdateModeIconSelection();
if (selectedMode == 1) {
_screenshotGridWindow = new WindowScreenshotGridWindow(mainWindow.GetAllWindows());
_screenshotGridWindow.Show();
} else if (_screenshotGridWindow != null) {
_screenshotGridWindow.Close();
_screenshotGridWindow = null;
}
}
private Border[] iconList = new Border[] { };
private GeometryDrawing[] iconGeometryList = new GeometryDrawing[] { };
private TextBlock[] iconTextList = new TextBlock[] { };
private void CloseButton_CloseWindow(object sender, MouseButtonEventArgs e) {
Close();
}
protected override void OnClosed(EventArgs e) {
mainWindow.Show();
base.OnClosed(e);
}
}
}

View File

@ -0,0 +1,29 @@
<Window x:Class="Ink_Canvas.Popups.WindowScreenshotGridWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Ink_Canvas.Popups"
xmlns:modern="http://schemas.inkore.net/lib/ui/wpf/modern"
mc:Ignorable="d" WindowStyle="None" Background="#18181b" WindowState="Maximized" ResizeMode="NoResize"
Title="WindowScreenshotGridWindow" Height="450" Width="800">
<Grid>
<WrapPanel Orientation="Horizontal">
<ItemsControl Name="WindowsItemControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<modern:SimpleStackPanel Width="164" Height="164">
<Image Width="148" Height="148" Source="{Binding Bitmap}"/>
<TextBlock FontSize="16" Foreground="White" Text="{Binding Title}"/>
</modern:SimpleStackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</WrapPanel>
</Grid>
</Window>

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
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.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Ink_Canvas.Popups
{
/// <summary>
/// WindowScreenshotGridWindow.xaml 的交互逻辑
/// </summary>
public partial class WindowScreenshotGridWindow : Window
{
private 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 class Win {
public string Title { get; set; }
public BitmapImage Bitmap { get; set; }
}
private ObservableCollection<Win> _windows = new ObservableCollection<Win>();
public WindowScreenshotGridWindow(MainWindow.WindowInformation[] wins) {
InitializeComponent();
_windows.Clear();
WindowsItemControl.ItemsSource = _windows;
foreach (var windowInformation in wins) {
_windows.Add(new Win() {
Title = windowInformation.Title,
Bitmap = BitmapToImageSource(windowInformation.WindowBitmap)
});
Trace.WriteLine(windowInformation.Title);
}
}
}
}