欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

WPF調(diào)用WindowsAPI實(shí)現(xiàn)屏幕錄制

 更新時(shí)間:2023年05月31日 08:45:31   作者:WPF開發(fā)者  
這篇文章主要為大家詳細(xì)介紹了WPF如何調(diào)用WindowsAPI實(shí)現(xiàn)屏幕錄制,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下

WPF 實(shí)現(xiàn)調(diào)用 WindowsAPI 實(shí)現(xiàn)屏幕錄制

  • 框架使用.NET4
  • Visual Studio 2022
  • 接著上一篇做一個(gè)不依賴 ffmpeg 實(shí)現(xiàn)屏幕錄制
  • 1000 毫秒調(diào)用 WindowsAPI 進(jìn)行截取屏幕獲取圖像,并保存 jpg 文件到指定路徑(保存的文件從 0.jpg 至 n.jpg )。

實(shí)現(xiàn)代碼

1)獲取屏幕圖片并保存為 jpg 代碼如下:

????????private?static?BitmapSource?CaptureScreen()
????????{
????????????IntPtr?desk?=?GetDesktopWindow();
????????????IntPtr?dc?=?GetWindowDC(desk);
????????????IntPtr?memdc?=?CreateCompatibleDC(dc);
????????????IntPtr?bitmap?=?CreateCompatibleBitmap(dc,?screenWidth,?screenHeight);
????????????SelectObject(memdc,?bitmap);
????????????BitBlt(memdc,?0,?0,?screenWidth,?screenHeight,?dc,?0,?0,?0xCC0020);
????????????BitmapSource?source?=?Imaging.CreateBitmapSourceFromHBitmap(bitmap,?IntPtr.Zero,?Int32Rect.Empty,?BitmapSizeOptions.FromEmptyOptions());
????????????ReleaseDC(desk,?dc);
????????????return?source;
????????}
????????Task.Factory.StartNew(()?=>
????????????{
????????????????while?(IsRunning)
????????????????{
????????????????????Thread.Sleep(1000);
????????????????????num?+=?1;
????????????????????Application.Current.Dispatcher.Invoke(new?Action(()?=>
????????????????????{
????????????????????????var?drawingVisual?=?new?DrawingVisual();
????????????????????????POINT?mousePosition;
????????????????????????using?(DrawingContext?drawingContext?=?drawingVisual.RenderOpen())
????????????????????????{
????????????????????????????drawingContext.DrawImage(CaptureScreen(),
????????????????????????????????new?Rect(new?Point(),
????????????????????????????????new?Size(screenWidth,?screenHeight)));
????????????????????????????if?(GetCursorPos(out?mousePosition))
????????????????????????????{
????????????????????????????????var?cursorSize?=?30;
????????????????????????????????var?cursorHalfSize?=?cursorSize?/?2;
????????????????????????????????var?cursorCenterX?=?mousePosition.X?-?SystemParameters.VirtualScreenLeft;
????????????????????????????????var?cursorCenterY?=?mousePosition.Y?-?SystemParameters.VirtualScreenTop;
????????????????????????????????drawingContext.DrawImage(GetCursorIcon(),
????????????????????????????????????new?Rect(new?Point(cursorCenterX,?cursorCenterY),
????????????????????????????????????new?Size(cursorSize,?cursorSize)));
????????????????????????????}
????????????????????????}
????????????????????????var?png?=?Path.Combine(tempDir,?$"{num}.jpg");
????????????????????????using?(FileStream?stream?=?new?FileStream(png,?FileMode.Create))
????????????????????????{
????????????????????????????var?bitmap?=?new?RenderTargetBitmap((int)screenWidth,?(int)screenHeight,?96,?96,?PixelFormats.Pbgra32);
????????????????????????????bitmap.Render(drawingVisual);
????????????????????????????var?bitmapEncoder?=?BitmapFrame.Create(bitmap);
????????????????????????????bitmapEncoder.Freeze();
????????????????????????????var?encoder?=?new?JpegBitmapEncoder();
????????????????????????????encoder.QualityLevel?=?50;
????????????????????????????encoder.Frames.Add(bitmapEncoder);
????????????????????????????encoder.Save(stream);
????????????????????????????encoder.Frames.Clear();
????????????????????????????GC.Collect();
????????????????????????}
????????????????????}));
????????????????}
????????????});

當(dāng)點(diǎn)擊開始錄制按鈕時(shí)將窗體最小化,停止錄制時(shí)通過循環(huán)之前保存的文件夾地址排序循環(huán)添加每一幀圖像到 GifBitmapEncoder.Frames 中,但是在使用自帶的 GifBitmapEncoder 發(fā)現(xiàn)內(nèi)存占用很高,當(dāng)使用完成后沒有釋放 GC ,所以放棄了使用它。哪位大佬有好的方式歡迎分享

使用了GifEncoder 自己寫入 GIF 文件。

保存 gif 文件可以使用以下庫(kù)

  • FreeImage.NET
  • WpfAnimatedGif
  • ImageTools
  • Magick.NET
  • GifRenderer

2) MainWindow.xaml 代碼如下:

<wd:Window
????x:Class="DesktopRecord.View.MainWindow"
????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:vm="clr-namespace:DesktopRecord.ViewModel"
????xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
????Title="屏幕錄制"
????Width="525"
????Height="200"
????Icon="/screen.ico"
????ResizeMode="CanMinimize"
????WindowStartupLocation="CenterScreen"
????mc:Ignorable="d">
????<wd:Window.DataContext>
????????<vm:MainVM?/>
????</wd:Window.DataContext>
????<Grid>
????????<TabControl>
????????????<TabItem?Header="ffmpeg?錄制">
????????????????<StackPanel
????????????????????HorizontalAlignment="Center"
????????????????????VerticalAlignment="Center"
????????????????????Orientation="Horizontal">
????????????????????<Button
????????????????????????Margin="0,0,5,0"
????????????????????????Command="{Binding?MyStart}"
????????????????????????Content="{Binding?MyTime}"
????????????????????????Style="{StaticResource?WD.SuccessPrimaryButton}"?/>
????????????????????<Button
????????????????????????Margin="5,0,0,0"
????????????????????????Command="{Binding?MyStop}"
????????????????????????Content="停止錄制"
????????????????????????Style="{StaticResource?WD.DangerPrimaryButton}"?/>
????????????????</StackPanel>
????????????</TabItem>
????????????<TabItem?Header="WindowsAPI?錄制">
????????????????<StackPanel
????????????????????HorizontalAlignment="Center"
????????????????????VerticalAlignment="Center"
????????????????????Orientation="Horizontal">
????????????????????<Button
????????????????????????Margin="0,0,5,0"
????????????????????????Command="{Binding?RecordCommand}"
????????????????????????Content="開始錄制"
????????????????????????Style="{StaticResource?WD.SuccessPrimaryButton}"?/>
????????????????????<Button
????????????????????????Margin="5,0,0,0"
????????????????????????wd:Loading.Child="{x:Static?wd:NormalLoading.Default}"
????????????????????????wd:Loading.IsShow="{Binding?IsShow}"
????????????????????????Command="{Binding?RecordStopCommand}"
????????????????????????Content="停止錄制"
????????????????????????Style="{StaticResource?WD.DangerPrimaryButton}"?/>
????????????????</StackPanel>
????????????</TabItem>
????????</TabControl>
????</Grid>
</wd:Window>

3)創(chuàng)建 MainVM.cs 代碼如下:

using?DesktopRecord.Helper;
using?System;
using?System.Diagnostics;
using?System.Threading.Tasks;
using?System.Windows.Input;
using?System.Windows.Threading;
using?WPFDevelopers.Controls;
using?WPFDevelopers.Helpers;
namespace?DesktopRecord.ViewModel
{
????public?class?MainVM?:?ViewModelBase
????{
????????private?DispatcherTimer?tm?=?new?DispatcherTimer();
????????public?int?currentCount?=?0;
????????private?string?myTime?=?"開始錄制";
????????public?string?MyTime
????????{
????????????get?{?return?myTime;?}
????????????set
????????????{
????????????????myTime?=?value;
????????????????NotifyPropertyChange("MyTime");
????????????}
????????}
????????private?bool?isStart?=?true;
????????public?bool?IsStart
????????{
????????????get?{?return?isStart;?}
????????????set
????????????{
????????????????isStart?=?value;
????????????????NotifyPropertyChange("IsStart");
????????????}
????????}
????????private?bool?_isShow;
????????public?bool?IsShow
????????{
????????????get?{?return?_isShow;?}
????????????set
????????????{
????????????????_isShow?=?value;
????????????????NotifyPropertyChange("IsShow");
????????????}
????????}
????????private?ICommand?myStart;
????????public?ICommand?MyStart
????????{
????????????get
????????????{
????????????????return?myStart????(myStart?=?new?RelayCommand(p?=>
????????????????{
????????????????????App.Current.MainWindow.WindowState?=?System.Windows.WindowState.Minimized;
????????????????????if?(!FFmpegHelper.Start())
????????????????????{
????????????????????????App.Current.MainWindow.WindowState?=?System.Windows.WindowState.Normal;
????????????????????????MessageBox.Show("未找到?【ffmpeg.exe】,請(qǐng)下載",?"錯(cuò)誤",?System.Windows.MessageBoxButton.OK,?System.Windows.MessageBoxImage.Error);
????????????????????????return;
????????????????????}
????????????????????tm.Tick?+=?tm_Tick;
????????????????????tm.Interval?=?TimeSpan.FromSeconds(1);
????????????????????tm.Start();
????????????????????IsStart?=?false;
???????????????},?a?=>
????????????????{
????????????????return?IsStart;
????????????????}));
????????????}
????????}
????????private?void?tm_Tick(object?sender,?EventArgs?e)
????????{
????????????currentCount++;
????????????MyTime?=?"錄制中("?+?currentCount?+?"s)";
????????}
????????///?<summary>
????????///?獲取或設(shè)置
????????///?</summary>
????????private?ICommand?myStop;
????????///?<summary>
????????///?獲取或設(shè)置
????????///?</summary>
????????public?ICommand?MyStop
????????{
????????????get
????????????{
????????????????return?myStop????(myStop?=?new?RelayCommand(p?=>
???????????????????????????{
???????????????????????????????var?task?=?new?Task(()?=>
???????????????????????????????{
???????????????????????????????????FFmpegHelper.Stop();
???????????????????????????????????MyTime?=?"開始錄制";
???????????????????????????????????tm.Stop();
???????????????????????????????????currentCount?=?0;
???????????????????????????????????IsShow?=?true;
???????????????????????????????});
???????????????????????????????task.ContinueWith(previousTask?=>
???????????????????????????????{
???????????????????????????????????IsShow?=?false;
???????????????????????????????????IsStart?=?true;
???????????????????????????????????Process.Start(AppDomain.CurrentDomain.BaseDirectory);
???????????????????????????????},?TaskScheduler.FromCurrentSynchronizationContext());
???????????????????????????????task.Start();
???????????????????????????},?a?=>
????????????{
????????????????return?!IsStart;
????????????}));
????????????}
????????}
????????public?ICommand?RecordCommand?{?get;?}
????????public?ICommand?RecordStopCommand?{?get;?}
????????public?MainVM()
????????{
????????????RecordCommand?=?new?RelayCommand(Record,?CanExecuteRecordCommand);
????????????RecordStopCommand?=?new?RelayCommand(RecordStop);
????????}
????????void?Record(object?parameter)
????????{
????????????App.Current.MainWindow.WindowState?=?System.Windows.WindowState.Minimized;
????????????Win32.Start();
????????????IsStart?=?false;
????????}
????????private?bool?CanExecuteRecordCommand(object?parameter)
????????{
????????????return?IsStart;
????????}
????????void?RecordStop(object?parameter)
????????{
????????????var?task?=?new?Task(()?=>
????????????{
????????????????Win32.Stop();
????????????????IsShow?=?true;
????????????????Win32.Save($"DesktopRecord_{DateTime.Now.ToString("yyyyMMddHHmmss")}.gif");
????????????});
????????????task.ContinueWith(previousTask?=>
????????????{
????????????????IsShow?=?false;
????????????????IsStart?=?true;
????????????????Process.Start(AppDomain.CurrentDomain.BaseDirectory);
????????????},?TaskScheduler.FromCurrentSynchronizationContext());
????????????task.Start();
????????}
????}
}

4)創(chuàng)建 Win32.cs 代碼如下:

using?System;
using?System.Collections.Generic;
using?System.IO;
using?System.Runtime.InteropServices;
using?System.Threading;
using?System.Threading.Tasks;
using?System.Windows;
using?System.Windows.Interop;
using?System.Windows.Media;
using?System.Windows.Media.Imaging;
namespace?DesktopRecord.Helper
{
????public?class?Win32
????{
????????[DllImport("user32.dll")]
????????public?static?extern?IntPtr?GetDesktopWindow();
????????[DllImport("user32.dll")]
????????public?static?extern?IntPtr?GetWindowDC(IntPtr?hwnd);
????????[DllImport("user32.dll")]
????????public?static?extern?IntPtr?ReleaseDC(IntPtr?hwnd,?IntPtr?hdc);
????????[DllImport("gdi32.dll")]
????????public?static?extern?IntPtr?CreateCompatibleDC(IntPtr?hdc);
????????[DllImport("gdi32.dll")]
????????public?static?extern?IntPtr?CreateCompatibleBitmap(IntPtr?hdc,?int?nWidth,?int?nHeight);
????????[DllImport("gdi32.dll")]
????????public?static?extern?IntPtr?SelectObject(IntPtr?hdc,?IntPtr?hgdiobj);
????????[DllImport("gdi32.dll")]
????????public?static?extern?bool?BitBlt(IntPtr?hdcDest,?int?nXDest,?int?nYDest,?int?nWidth,?int?nHeight,?IntPtr?hdcSrc,?int?nXSrc,?int?nYSrc,?System.Int32?dwRop);
????????[DllImport("user32.dll")]
????????private?static?extern?bool?GetCursorInfo(out?CURSORINFO?pci);
????????[StructLayout(LayoutKind.Sequential)]
????????public?struct?POINT
????????{
????????????public?int?X;
????????????public?int?Y;
????????}
????????[StructLayout(LayoutKind.Sequential)]
????????public?struct?CURSORINFO
????????{
????????????public?Int32?cbSize;
????????????public?Int32?flags;
????????????public?IntPtr?hCursor;
????????????public?POINT?ptScreenPos;
????????}
????????[DllImport("user32.dll")]
????????public?static?extern?bool?GetCursorPos(out?POINT?lpPoint);
????????[DllImport("user32.dll")]
????????public?static?extern?bool?DestroyIcon(IntPtr?handle);
????????private?static?string?basePath?=?AppDomain.CurrentDomain.BaseDirectory;
????????private?static?string?tempDir?=?Path.Combine(Path.GetTempPath(),?"DesktopRecord");
????????private?static?Thread?_thread?=?null;
????????public?static?bool?IsRunning?=?false;
????????static?int?screenWidth?=?Convert.ToInt32(SystemParameters.PrimaryScreenWidth);
????????static?int?screenHeight?=?Convert.ToInt32(SystemParameters.PrimaryScreenHeight);
????????private?static?BitmapSource?GetCursorIcon()
????????{
????????????var?cursorInfo?=?new?CURSORINFO?{?cbSize?=?Marshal.SizeOf(typeof(CURSORINFO))?};
????????????if?(GetCursorInfo(out?cursorInfo)?&&?cursorInfo.hCursor?!=?IntPtr.Zero)
????????????{
????????????????try
????????????????{
????????????????????return?Imaging.CreateBitmapSourceFromHIcon(cursorInfo.hCursor,?Int32Rect.Empty,?BitmapSizeOptions.FromEmptyOptions());
????????????????}
????????????????finally
????????????????{
????????????????????DestroyIcon(cursorInfo.hCursor);
????????????????}
????????????}
????????????return?null;
????????}
????????private?static?BitmapSource?CaptureScreen()
????????{
????????????IntPtr?desk?=?GetDesktopWindow();
????????????IntPtr?dc?=?GetWindowDC(desk);
????????????IntPtr?memdc?=?CreateCompatibleDC(dc);
????????????IntPtr?bitmap?=?CreateCompatibleBitmap(dc,?screenWidth,?screenHeight);
????????????SelectObject(memdc,?bitmap);
????????????BitBlt(memdc,?0,?0,?screenWidth,?screenHeight,?dc,?0,?0,?0xCC0020);
????????????BitmapSource?source?=?Imaging.CreateBitmapSourceFromHBitmap(bitmap,?IntPtr.Zero,?Int32Rect.Empty,?BitmapSizeOptions.FromEmptyOptions());
????????????ReleaseDC(desk,?dc);
????????????return?source;
????????}
????????public?static?void?Start()
????????{
????????????if?(_thread?==?null)
????????????{
????????????????IsRunning?=?true;
????????????????_thread?=?new?Thread(Record);
????????????????_thread.Start();
????????????}
????????}
????????public?static?void?Stop()
????????{
????????????if?(_thread?!=?null)
????????????{
????????????????IsRunning?=?false;
????????????????_thread?=?null;
????????????}
????????}
????????private?static?void?Record()
????????{
????????????if?(!Directory.Exists(tempDir))
????????????????Directory.CreateDirectory(tempDir);
????????????else
????????????{
????????????????foreach?(string?file?in?Directory.GetFiles(tempDir))
????????????????????File.Delete(file);
????????????}
????????????int?num?=?0;
????????????Task.Factory.StartNew(()?=>?
????????????{
????????????????while?(IsRunning)
????????????????{
????????????????????Thread.Sleep(20);
????????????????????num?+=?1;
????????????????????Application.Current.Dispatcher.Invoke(new?Action(()?=>
????????????????????{
????????????????????????var?drawingVisual?=?new?DrawingVisual();
????????????????????????POINT?mousePosition;
????????????????????????using?(DrawingContext?drawingContext?=?drawingVisual.RenderOpen())
????????????????????????{
????????????????????????????drawingContext.DrawImage(CaptureScreen(),
????????????????????????????????new?Rect(new?Point(),
????????????????????????????????new?Size(screenWidth,?screenHeight)));
????????????????????????????if?(GetCursorPos(out?mousePosition))
????????????????????????????{
????????????????????????????????var?cursorSize?=?30;
????????????????????????????????var?cursorHalfSize?=?cursorSize?/?2;
????????????????????????????????var?cursorCenterX?=?mousePosition.X?-?SystemParameters.VirtualScreenLeft;
????????????????????????????????var?cursorCenterY?=?mousePosition.Y?-?SystemParameters.VirtualScreenTop;
????????????????????????????????drawingContext.DrawImage(GetCursorIcon(),
????????????????????????????????????new?Rect(new?Point(cursorCenterX,?cursorCenterY),
????????????????????????????????????new?Size(cursorSize,?cursorSize)));
????????????????????????????}
????????????????????????}
????????????????????????var?png?=?Path.Combine(tempDir,?$"{num}.jpg");
????????????????????????using?(FileStream?stream?=?new?FileStream(png,?FileMode.Create))
????????????????????????{
????????????????????????????var?bitmap?=?new?RenderTargetBitmap((int)screenWidth,?(int)screenHeight,?96,?96,?PixelFormats.Pbgra32);
????????????????????????????bitmap.Render(drawingVisual);
????????????????????????????var?bitmapEncoder?=?BitmapFrame.Create(bitmap);
????????????????????????????bitmapEncoder.Freeze();
????????????????????????????var?encoder?=?new?JpegBitmapEncoder();
????????????????????????????encoder.QualityLevel?=?50;
????????????????????????????encoder.Frames.Add(bitmapEncoder);
????????????????????????????encoder.Save(stream);
????????????????????????????encoder.Frames.Clear();
????????????????????????????GC.Collect();
????????????????????????}
????????????????????}));
????????????????}
????????????});
????????}
????????public?static?void?ClearRecording()
????????{
????????????if?(Directory.Exists(tempDir))
????????????????Directory.Delete(tempDir,?true);
????????????Directory.CreateDirectory(tempDir);
????????}
????????public?static?void?Save(string?output)
????????{
????????????try
????????????{
????????????????output?=?Path.Combine(basePath,?output);
????????????????var?imagePaths?=?Directory.GetFiles(tempDir,?"*.jpg",?SearchOption.TopDirectoryOnly);
????????????????if?(imagePaths.Length?==?0)?return;
????????????????#region?GC不釋放,暫時(shí)棄用
????????????????//using?(var?gifFileStream?=?new?FileStream(Output,?FileMode.Create))
????????????????//{
????????????????//????var?gifBitmapEncoder?=?new?GifBitmapEncoder();
????????????????//????var?jpgs?=?Directory.GetFiles(tempDir,?"*.jpg",?SearchOption.TopDirectoryOnly);
????????????????//????if?(jpgs.Length?==?0)?return;
????????????????//????foreach?(string?file?in?jpgs)
????????????????//????{
????????????????//????????using?(var?stream?=?new?FileStream(file,?FileMode.Open,?FileAccess.Read))
????????????????//????????{
????????????????//????????????var?bitmapDecoder?=?new?JpegBitmapDecoder(stream,?BitmapCreateOptions.None,?BitmapCacheOption.OnLoad);
????????????????//????????????var?bitmapFrame?=?bitmapDecoder.Frames[0];
????????????????//????????????bitmapDecoder.Frames[0].Freeze();
????????????????//????????????gifBitmapEncoder.Frames.Add(bitmapFrame);
????????????????//????????????bitmapFrame?=?null;
????????????????//????????????bitmapDecoder?=?null;
????????????????//????????????GC.Collect();
????????????????//????????????stream.Dispose();
????????????????//????????}
????????????????//????}
????????????????//????gifBitmapEncoder.Save(gifFileStream);
????????????????//????gifBitmapEncoder.Frames.Clear();
????????????????//????gifBitmapEncoder?=?null;
????????????????//????GC.Collect();
????????????????//????GC.WaitForPendingFinalizers();
????????????????//}?
????????????????#endregion
????????????????var?bitmapFrames?=?new?List<BitmapFrame>();
????????????????foreach?(string?imagePath?in?imagePaths)
????????????????{
????????????????????var?frame?=?BitmapFrame.Create(new?Uri(imagePath,?UriKind.RelativeOrAbsolute));
????????????????????bitmapFrames.Add(frame);
????????????????}
????????????????using?(var?gifStream?=?new?MemoryStream())
????????????????{
????????????????????using?(var?encoder?=?new?GifEncoder(gifStream))
????????????????????{
????????????????????????foreach?(var?imagePath?in?imagePaths)
????????????????????????{
????????????????????????????var?image?=?System.Drawing.Image.FromFile(imagePath);
????????????????????????????encoder.AddFrame(image,?0,?0,?TimeSpan.FromSeconds(0));
????????????????????????}
????????????????????}
????????????????????gifStream.Position?=?0;
????????????????????using?(var?fileStream?=?new?FileStream(output,?FileMode.Create))
????????????????????{
????????????????????????fileStream.Write(gifStream.ToArray(),?0,?gifStream.ToArray().Length);
????????????????????}
????????????????}
????????????}
????????????catch
????????????{
????????????????throw;
????????????}
????????}
????}
}

5)創(chuàng)建 GifEncoder.cs 代碼如下:

using?System;
using?System.Drawing;
using?System.Drawing.Imaging;
using?System.IO;
using?System.Linq;
namespace?DesktopRecord.Helper
{
????public?class?GifEncoder?:?IDisposable
????{
????????#region?Header?Constants
????????private?const?string?FileType?=?"GIF";
????????private?const?string?FileVersion?=?"89a";
????????private?const?byte?FileTrailer?=?0x3b;
????????private?const?int?ApplicationExtensionBlockIdentifier?=?0xff21;
????????private?const?byte?ApplicationBlockSize?=?0x0b;
????????private?const?string?ApplicationIdentification?=?"NETSCAPE2.0";
????????private?const?int?GraphicControlExtensionBlockIdentifier?=?0xf921;
????????private?const?byte?GraphicControlExtensionBlockSize?=?0x04;
????????private?const?long?SourceGlobalColorInfoPosition?=?10;
????????private?const?long?SourceGraphicControlExtensionPosition?=?781;
????????private?const?long?SourceGraphicControlExtensionLength?=?8;
????????private?const?long?SourceImageBlockPosition?=?789;
????????private?const?long?SourceImageBlockHeaderLength?=?11;
????????private?const?long?SourceColorBlockPosition?=?13;
????????private?const?long?SourceColorBlockLength?=?768;
????????#endregion
????????private?bool?_isFirstImage?=?true;
????????private?int??_width;
????????private?int??_height;
????????private?int??_repeatCount;
????????private?readonly?Stream?_stream;
????????public?TimeSpan?FrameDelay?{?get;?set;?}
????????///?<summary>
????????///?Encodes?multiple?images?as?an?animated?gif?to?a?stream.?<br?/>
????????///?ALWAYS?ALWAYS?ALWAYS?wire?this?in?a?using?block?<br?/>
????????///?Disposing?the?encoder?will?complete?the?file.?<br?/>
????????///?Uses?default?.net?GIF?encoding?and?adds?animation?headers.
????????///?</summary>
????????///?<param?name="stream">The?stream?that?will?be?written?to.</param>
????????///?<param?name="width">Sets?the?width?for?this?gif?or?null?to?use?the?first?frame's?width.</param>
????????///?<param?name="height">Sets?the?height?for?this?gif?or?null?to?use?the?first?frame's?height.</param>
????????public?GifEncoder(Stream?stream,?int??width?=?null,?int??height?=?null,?int??repeatCount?=?null)
????????{
????????????_stream?=?stream;
????????????_width?=?width;
????????????_height?=?height;
????????????_repeatCount?=?repeatCount;
????????}
????????///?<summary>
????????///?Adds?a?frame?to?this?animation.
????????///?</summary>
????????///?<param?name="img">The?image?to?add</param>
????????///?<param?name="x">The?positioning?x?offset?this?image?should?be?displayed?at.</param>
????????///?<param?name="y">The?positioning?y?offset?this?image?should?be?displayed?at.</param>
????????public?void?AddFrame(Image?img,?int?x?=?0,?int?y?=?0,?TimeSpan??frameDelay?=?null)
????????{
????????????using?(var?gifStream?=?new?MemoryStream())
????????????{
????????????????img.Save(gifStream,?ImageFormat.Gif);
????????????????if?(_isFirstImage)?//?Steal?the?global?color?table?info
????????????????{
????????????????????InitHeader(gifStream,?img.Width,?img.Height);
????????????????}
????????????????WriteGraphicControlBlock(gifStream,?frameDelay.GetValueOrDefault(FrameDelay));
????????????????WriteImageBlock(gifStream,?!_isFirstImage,?x,?y,?img.Width,?img.Height);
????????????}
????????????_isFirstImage?=?false;
????????}
????????private?void?InitHeader(Stream?sourceGif,?int?w,?int?h)
????????{
????????????//?File?Header
????????????WriteString(FileType);
????????????WriteString(FileVersion);
????????????WriteShort(_width.GetValueOrDefault(w));?//?Initial?Logical?Width
????????????WriteShort(_height.GetValueOrDefault(h));?//?Initial?Logical?Height
????????????sourceGif.Position?=?SourceGlobalColorInfoPosition;
????????????WriteByte(sourceGif.ReadByte());?//?Global?Color?Table?Info
????????????WriteByte(0);?//?Background?Color?Index
????????????WriteByte(0);?//?Pixel?aspect?ratio
????????????WriteColorTable(sourceGif);
????????????//?App?Extension?Header
????????????WriteShort(ApplicationExtensionBlockIdentifier);
????????????WriteByte(ApplicationBlockSize);
????????????WriteString(ApplicationIdentification);
????????????WriteByte(3);?//?Application?block?length
????????????WriteByte(1);
????????????WriteShort(_repeatCount.GetValueOrDefault(0));?//?Repeat?count?for?images.
????????????WriteByte(0);?//?terminator
????????}
????????private?void?WriteColorTable(Stream?sourceGif)
????????{
????????????sourceGif.Position?=?SourceColorBlockPosition;?//?Locating?the?image?color?table
????????????var?colorTable?=?new?byte[SourceColorBlockLength];
????????????sourceGif.Read(colorTable,?0,?colorTable.Length);
????????????_stream.Write(colorTable,?0,?colorTable.Length);
????????}
????????private?void?WriteGraphicControlBlock(Stream?sourceGif,?TimeSpan?frameDelay)
????????{
????????????sourceGif.Position?=?SourceGraphicControlExtensionPosition;?//?Locating?the?source?GCE
????????????var?blockhead?=?new?byte[SourceGraphicControlExtensionLength];
????????????sourceGif.Read(blockhead,?0,?blockhead.Length);?//?Reading?source?GCE
????????????WriteShort(GraphicControlExtensionBlockIdentifier);?//?Identifier
????????????WriteByte(GraphicControlExtensionBlockSize);?//?Block?Size
????????????WriteByte(blockhead[3]?&?0xf7?|?0x08);?//?Setting?disposal?flag
????????????WriteShort(Convert.ToInt32(frameDelay.TotalMilliseconds?/?10));?//?Setting?frame?delay
????????????WriteByte(blockhead[6]);?//?Transparent?color?index
????????????WriteByte(0);?//?Terminator
????????}
????????private?void?WriteImageBlock(Stream?sourceGif,?bool?includeColorTable,?int?x,?int?y,?int?h,?int?w)
????????{
????????????sourceGif.Position?=?SourceImageBlockPosition;?//?Locating?the?image?block
????????????var?header?=?new?byte[SourceImageBlockHeaderLength];
????????????sourceGif.Read(header,?0,?header.Length);
????????????WriteByte(header[0]);?//?Separator
????????????WriteShort(x);?//?Position?X
????????????WriteShort(y);?//?Position?Y
????????????WriteShort(h);?//?Height
????????????WriteShort(w);?//?Width
????????????if?(includeColorTable)?//?If?first?frame,?use?global?color?table?-?else?use?local
????????????{
????????????????sourceGif.Position?=?SourceGlobalColorInfoPosition;
????????????????WriteByte(sourceGif.ReadByte()?&?0x3f?|?0x80);?//?Enabling?local?color?table
????????????????WriteColorTable(sourceGif);
????????????}
????????????else
????????????{
????????????????WriteByte(header[9]?&?0x07?|?0x07);?//?Disabling?local?color?table
????????????}
????????????WriteByte(header[10]);?//?LZW?Min?Code?Size
????????????//?Read/Write?image?data
????????????sourceGif.Position?=?SourceImageBlockPosition?+?SourceImageBlockHeaderLength;
????????????var?dataLength?=?sourceGif.ReadByte();
????????????while?(dataLength?>?0)
????????????{
????????????????var?imgData?=?new?byte[dataLength];
????????????????sourceGif.Read(imgData,?0,?dataLength);
????????????????_stream.WriteByte(Convert.ToByte(dataLength));
????????????????_stream.Write(imgData,?0,?dataLength);
????????????????dataLength?=?sourceGif.ReadByte();
????????????}
????????????_stream.WriteByte(0);?//?Terminator
????????}
????????private?void?WriteByte(int?value)
????????{
????????????_stream.WriteByte(Convert.ToByte(value));
????????}
????????private?void?WriteShort(int?value)
????????{
????????????_stream.WriteByte(Convert.ToByte(value?&?0xff));
????????????_stream.WriteByte(Convert.ToByte((value?>>?8)?&?0xff));
????????}
????????private?void?WriteString(string?value)
????????{
????????????_stream.Write(value.ToArray().Select(c?=>?(byte)c).ToArray(),?0,?value.Length);
????????}
????????public?void?Dispose()
????????{
????????????//?Complete?File
????????????WriteByte(FileTrailer);
????????????//?Pushing?data
????????????_stream.Flush();
????????}
????}
}

效果圖

以上就是WPF調(diào)用WindowsAPI實(shí)現(xiàn)屏幕錄制的詳細(xì)內(nèi)容,更多關(guān)于WPF WindowsAPI屏幕錄制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#中實(shí)現(xiàn)插入、刪除Excel分頁符的方法

    C#中實(shí)現(xiàn)插入、刪除Excel分頁符的方法

    這篇文章主要給大家介紹了關(guān)于在C#中實(shí)現(xiàn)插入、刪除Excel分頁符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • 一文搞懂C#實(shí)現(xiàn)讀寫文本文件中的數(shù)據(jù)

    一文搞懂C#實(shí)現(xiàn)讀寫文本文件中的數(shù)據(jù)

    這篇文章重點(diǎn)給大家介紹C#實(shí)現(xiàn)讀寫文本文件中的數(shù)據(jù)的一些知識(shí),讀取.txt文件數(shù)據(jù)的實(shí)例代碼及寫入讀取過程完整代碼,感興趣的朋友跟隨小編一起看看吧
    2021-06-06
  • C#制作二維柱狀圖方法

    C#制作二維柱狀圖方法

    在本文里小編為各位分享的是關(guān)于C#制作二維柱狀圖方法和步驟,需要的讀者們學(xué)習(xí)下。
    2018-12-12
  • C#編寫的Base64加密和解密類

    C#編寫的Base64加密和解密類

    本文給大家匯總介紹了幾種C#編寫的Base64加密和解密類的代碼,從簡(jiǎn)單到復(fù)雜,都能夠?qū)崿F(xiàn)功能,有需要的小伙伴根據(jù)自己的項(xiàng)目需求參考下吧。
    2015-05-05
  • 基于Json序列化和反序列化通用的封裝完整代碼

    基于Json序列化和反序列化通用的封裝完整代碼

    JSON 是存儲(chǔ)和交換文本信息的語法。類似 XML。JSON 比 XML 更小、更快,更易解析。下面通過實(shí)例代碼給大家分享Json序列化和反序列化通用的封裝,需要的的朋友參考下吧
    2017-07-07
  • 淺談C#中堆和棧的區(qū)別(附上圖解)

    淺談C#中堆和棧的區(qū)別(附上圖解)

    C#中棧是編譯期間就分配好的內(nèi)存空間,因此你的代碼中必須就棧的大小有明確的定義;堆是程序運(yùn)行期間動(dòng)態(tài)分配的內(nèi)存空間,你可以根據(jù)程序的運(yùn)行情況確定要分配的堆內(nèi)存的大小
    2014-09-09
  • 大白話講解C# 中的委托

    大白話講解C# 中的委托

    這篇文章主要介紹了C# 中的委托的相關(guān)資料,幫助初學(xué)者更好的理解和使用c#,感興趣的朋友可以了解下
    2020-11-11
  • C# 獲取系統(tǒng)進(jìn)程的用戶名

    C# 獲取系統(tǒng)進(jìn)程的用戶名

    這也是應(yīng)一位網(wǎng)友的要求寫的,寫的比較倉(cāng)促,湊合吧
    2009-06-06
  • C#獲取微信小程序的云數(shù)據(jù)庫(kù)中數(shù)據(jù)的示例代碼

    C#獲取微信小程序的云數(shù)據(jù)庫(kù)中數(shù)據(jù)的示例代碼

    本文主要介紹了C#獲取微信小程序的云數(shù)據(jù)庫(kù)中數(shù)據(jù)的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C#實(shí)現(xiàn)Xml序列化與反序列化的方法

    C#實(shí)現(xiàn)Xml序列化與反序列化的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)Xml序列化與反序列化的方法,將序列化與反序列化的方法封裝入一個(gè)類文件中,包含了較為詳盡的注釋說明,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-12-12

最新評(píng)論