usingSystem;usingSystem.Diagnostics;usingSystem.Drawing;usingSystem.Drawing.Imaging;usingSystem.IO;usingSystem.Linq;usingSystem.Runtime.InteropServices;usingSystem.Windows;usingSystem.Windows.Interop;usingSystem.Windows.Media.Imaging;usingForms=System.Windows.Forms;usingWpfClipboard=System.Windows.Clipboard;namespace ScreenShotApp;publicpartialclassMainWindow : Window{privatebyte[]?_latestPng;privatestring_saveFolder;publicMainWindow(){InitializeComponent();_saveFolder=Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),"ScreenShots"); Directory.CreateDirectory(_saveFolder); SaveFolderTextBox.Text=_saveFolder; IncludeCursorCheckBox.IsChecked=true; StatusTextBlock.Text="準備完了。";}privatevoidCaptureButton_Click(objectsender,RoutedEventArgse){try{SetUiEnabled(false);varincludeCursor=IncludeCursorCheckBox.IsChecked==true;var (pngBytes,bitmapSource,size) =CaptureScreen(includeCursor);_latestPng=pngBytes;PreviewImage.Source=bitmapSource;if (CopyClipboardCheckBox.IsChecked==true){WpfClipboard.SetImage(bitmapSource);}StatusTextBlock.Text=$"キャプチャ完了: {size.Width}x{size.Height} ({DateTime.Now:HH:mm:ss})";}catch(Exceptionex){StatusTextBlock.Text=$"失敗: {ex.Message}";}finally{SetUiEnabled(true);}}privatevoidRangeCaptureButton_Click(objectsender,RoutedEventArgse){try{SetUiEnabled(false);varselector=newSelectionOverlay{Owner=this};if (selector.ShowDialog() !=true||selector.SelectedBoundsisnull){StatusTextBlock.Text="範囲選択をキャンセルしました。";return;}varincludeCursor=IncludeCursorCheckBox.IsChecked==true;var (pngBytes,bitmapSource,size) =CaptureBounds(selector.SelectedBounds.Value,includeCursor);_latestPng=pngBytes;PreviewImage.Source=bitmapSource;if (CopyClipboardCheckBox.IsChecked==true){WpfClipboard.SetImage(bitmapSource);}StatusTextBlock.Text=$"範囲キャプチャ完了: {size.Width}x{size.Height} ({DateTime.Now:HH:mm:ss})";}catch(Exceptionex){StatusTextBlock.Text=$"失敗: {ex.Message}";}finally{SetUiEnabled(true);}}privatevoidSaveButton_Click(objectsender,RoutedEventArgse){if(_latestPngisnull){StatusTextBlock.Text="保存するスクリーンショットがありません。";return;} Directory.CreateDirectory(_saveFolder); var fileName=$"Screenshot_{DateTime.Now:yyyyMMdd_HHmmss_fff}.png"; var path=Path.Combine(_saveFolder,fileName); File.WriteAllBytes(path, _latestPng); StatusTextBlock.Text=$"保存しました: {path}";}privatevoidOpenFolderButton_Click(objectsender,RoutedEventArgse){if(!Directory.Exists(_saveFolder)){StatusTextBlock.Text="保存先フォルダが見つかりません。";return;} Process.Start(new ProcessStartInfo{FileName=_saveFolder,UseShellExecute=true});}privatevoidChangeFolderButton_Click(objectsender,RoutedEventArgse){ using var dialog=newForms.FolderBrowserDialog{Description="保存先フォルダを選択",SelectedPath=_saveFolder,ShowNewFolderButton=true};if(dialog.ShowDialog() == Forms.DialogResult.OK && !string.IsNullOrWhiteSpace(dialog.SelectedPath)){_saveFolder=dialog.SelectedPath;SaveFolderTextBox.Text=_saveFolder;StatusTextBlock.Text=$"保存先を変更しました: {_saveFolder}";}}privatevoidSetUiEnabled(boolenabled){ CaptureButton.IsEnabled=enabled; RangeCaptureButton.IsEnabled=enabled; SaveButton.IsEnabled=enabled; OpenFolderButton.IsEnabled=enabled;}privatestatic (byte[] PngBytes,BitmapSourceImage,System.Drawing.SizeSize) CaptureScreen(boolincludeCursor){ var screens=Forms.Screen.AllScreens; var left=screens.Min(screen=>screen.Bounds.Left); var top=screens.Min(screen=>screen.Bounds.Top); var right=screens.Max(screen=>screen.Bounds.Right); var bottom=screens.Max(screen=>screen.Bounds.Bottom); var bounds=Rectangle.FromLTRB(left,top,right,bottom); return CaptureBounds(bounds,includeCursor);}privatestatic (byte[] PngBytes,BitmapSourceImage,System.Drawing.SizeSize) CaptureBounds(Rectanglebounds,boolincludeCursor){ using var bitmap=newBitmap(bounds.Width,bounds.Height,PixelFormat.Format32bppArgb);using(vargraphics=Graphics.FromImage(bitmap)){graphics.CopyFromScreen(bounds.Left,bounds.Top,0,0,bounds.Size,CopyPixelOperation.SourceCopy);if (includeCursor){DrawCursor(graphics,bounds);}} var hBitmap=bitmap.GetHbitmap();try{varbitmapSource=Imaging.CreateBitmapSourceFromHBitmap(hBitmap,IntPtr.Zero,Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());bitmapSource.Freeze();usingvar stream =newMemoryStream();bitmap.Save(stream,ImageFormat.Png);return (stream.ToArray(),bitmapSource,bitmap.Size);}finally{DeleteObject(hBitmap);}}privatestaticvoidDrawCursor(Graphicsgraphics,Rectanglebounds){ var cursorInfo=newCURSORINFO{cbSize=Marshal.SizeOf<CURSORINFO>() };if(!GetCursorInfo(refcursorInfo) || cursorInfo.flags != CURSOR_SHOWING){return;}if(!GetIconInfo(cursorInfo.hCursor,outvariconInfo)){return;}if(cursorInfo.ptScreenPos.x < bounds.Left || cursorInfo.ptScreenPos.x > bounds.Right || cursorInfo.ptScreenPos.y < bounds.Top || cursorInfo.ptScreenPos.y > bounds.Bottom){return;} var x=cursorInfo.ptScreenPos.x-bounds.Left; var y=cursorInfo.ptScreenPos.y-bounds.Top;if(!iconInfo.fIcon){x-=iconInfo.xHotspot;y-=iconInfo.yHotspot;} var hdc=graphics.GetHdc();try{DrawIconEx(hdc,x,y,cursorInfo.hCursor,0,0,0,IntPtr.Zero,DI_NORMAL);}finally{graphics.ReleaseHdc(hdc);if (iconInfo.hbmColor!=IntPtr.Zero){DeleteObject(iconInfo.hbmColor);}if (iconInfo.hbmMask!=IntPtr.Zero){DeleteObject(iconInfo.hbmMask);}}}privateconstintCURSOR_SHOWING=0x00000001;privateconstintDI_NORMAL=0x0003; [StructLayout(LayoutKind.Sequential)]privatestructPOINT{ public int x; public int y;} [StructLayout(LayoutKind.Sequential)]privatestructCURSORINFO{ public int cbSize; public int flags; public IntPtr hCursor; public POINT ptScreenPos;} [StructLayout(LayoutKind.Sequential)]privatestructICONINFO{[MarshalAs(UnmanagedType.Bool)] public bool fIcon; public int xHotspot; public int yHotspot; public IntPtr hbmMask; public IntPtr hbmColor; } [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetCursorInfo(ref CURSORINFO pci); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DrawIconEx( IntPtr hdc, int xLeft, int yTop, IntPtr hIcon, int cxWidth, int cyWidth, int istepIfAniCur, IntPtr hbrFlickerFreeDraw, int diFlags); [DllImport("gdi32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool DeleteObject(IntPtr hObject);}
usingSystem;usingSystem.Linq;usingSystem.Windows;usingSystem.Windows.Input;usingSystem.Windows.Controls;usingSystem.Windows.Shapes;usingForms=System.Windows.Forms;usingDrawingRect=System.Drawing.Rectangle;usingWpfPoint=System.Windows.Point;namespace ScreenShotApp;publicpartialclassSelectionOverlay : Window{privateWpfPoint?_startPoint;privateDrawingRect_virtualBounds;publicDrawingRect?SelectedBounds{ get; private set; }publicSelectionOverlay(){InitializeComponent(); Loaded += OnLoaded;}privatevoidOnLoaded(objectsender,RoutedEventArgse){ var screens=Forms.Screen.AllScreens; var left=screens.Min(screen=>screen.Bounds.Left); var top=screens.Min(screen=>screen.Bounds.Top); var right=screens.Max(screen=>screen.Bounds.Right); var bottom=screens.Max(screen=>screen.Bounds.Bottom);_virtualBounds=DrawingRect.FromLTRB(left,top,right,bottom);Left=_virtualBounds.Left;Top=_virtualBounds.Top;Width=_virtualBounds.Width;Height=_virtualBounds.Height;}privatevoidWindow_MouseLeftButtonDown(objectsender,System.Windows.Input.MouseButtonEventArgse){_startPoint=e.GetPosition(RootCanvas); SelectionRect.Visibility=Visibility.Visible;CaptureMouse();}privatevoidWindow_MouseMove(objectsender,System.Windows.Input.MouseEventArgse){if(_startPointisnull || e.LeftButton != MouseButtonState.Pressed){return;} var current=e.GetPosition(RootCanvas); var x=Math.Min(_startPoint.Value.X,current.X); var y=Math.Min(_startPoint.Value.Y,current.Y); var width=Math.Abs(_startPoint.Value.X-current.X); var height=Math.Abs(_startPoint.Value.Y-current.Y); Canvas.SetLeft(SelectionRect, x); Canvas.SetTop(SelectionRect, y); SelectionRect.Width=width; SelectionRect.Height=height;}privatevoidWindow_MouseLeftButtonUp(objectsender,System.Windows.Input.MouseButtonEventArgse){if(_startPointisnull){return;} var end=e.GetPosition(RootCanvas);ReleaseMouseCapture(); var x=Math.Min(_startPoint.Value.X,end.X); var y=Math.Min(_startPoint.Value.Y,end.Y); var width=Math.Abs(_startPoint.Value.X-end.X); var height=Math.Abs(_startPoint.Value.Y-end.Y);if(width < 2 || height < 2){SelectedBounds=null;DialogResult=false;Close();return;} var left= (int)Math.Round(_virtualBounds.Left+x); var top= (int)Math.Round(_virtualBounds.Top+y); var right= (int)Math.Round(left+width); var bottom= (int)Math.Round(top+height);SelectedBounds=DrawingRect.FromLTRB(left,top,right,bottom);DialogResult=true;Close();}privatevoidWindow_KeyDown(objectsender,System.Windows.Input.KeyEventArgse){if(e.Key == Key.Escape){SelectedBounds=null;DialogResult=false;Close();}}}