C# 抓图服务的实现

yizhihongxing

下面是详细的讲解。

C# 抓图服务的实现

用 C# 实现一个抓图服务是一个非常实用的功能。在一些需要截屏或者截图的场景中,它可以自动化这个过程,非常方便。这里将介绍用 C# 实现一个简单的抓图服务的过程,并提供两个示例说明。

准备工作

在 C# 中通过 System.Windows.Forms 命名空间中的 Screen 类可以实现抓屏功能。在实现抓图服务之前,需要安装一个服务制作工具,用于制作服务程序。

这里以 Topshelf 为例进行制作,Topshelf 是一个轻量级的开源服务框架,提供了非常便捷的服务构建功能。使用 Topshelf 制作服务非常简单,在 Visual Studio 中新建一个控制台应用程序,使用 NuGet 安装 Topshelf 包即可。NuGet 安装命令为:Install-Package Topshelf

实现抓图服务

下面是实现抓图服务的步骤:

  1. 创建服务类和服务主程序

在 Visual Studio 中添加一个服务类和一个服务主程序。服务类中定义了服务的具体实现逻辑,而服务主程序用于启动和停止服务。

  1. 配置服务

使用 Topshelf 提供的 HostFactory 类来配置服务。配置主要包括服务名称服务描述服务启动账户服务依赖项等内容。示例代码如下:

csharp
static void Main(string[] args)
{
HostFactory.Run(x =>
{
x.Service<ScreenshotService>();
x.SetServiceName("ScreenshotService");
x.SetDisplayName("ScreenshotService");
x.SetDescription("A service for automatically taking screenshots");
x.StartAutomatically();
x.RunAsLocalSystem();
});
}

其中,x.Service() 方法用于指定服务实现类,x.SetServiceName() 方法用于指定服务名称,x.SetDisplayName() 方法用于指定服务显示名称,x.SetDescription() 方法用于指定服务描述,x.StartAutomatically() 方法用于指定服务自动启动,x.RunAsLocalSystem() 方法用于指定服务启动账户为本地系统账户。

  1. 实现服务逻辑

在服务类中实现具体的抓图服务逻辑:

```csharp
public class ScreenshotService
{
private readonly Timer _timer;
private readonly string _savePath;

    public ScreenshotService()
    {
        _timer = new Timer(10000);
        _timer.Elapsed += OnTimerElapsed;
        _savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Screenshots");
    }

    public void Start()
    {
        _timer.Start();
    }

    public void Stop()
    {
        _timer.Stop();
    }

    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        var fileName = $"{DateTime.Now:yyyyMMddHHmmss}.png";
        var filePath = Path.Combine(_savePath, fileName);
        if (!Directory.Exists(_savePath))
        {
            Directory.CreateDirectory(_savePath);
        }

        var screenBounds = Screen.PrimaryScreen.Bounds;
        using (var bmp = new Bitmap(screenBounds.Width, screenBounds.Height))
        {
            using (var graphics = Graphics.FromImage(bmp))
            {
                graphics.CopyFromScreen(Point.Empty, Point.Empty, screenBounds.Size);
            }
            bmp.Save(filePath, ImageFormat.Png);
        }
    }
}

```

服务每隔10秒执行一次,在指定的路径下保存当前屏幕的截图。

  1. 安装服务

使用管理员身份打开命令提示符,进入服务主程序所在文件夹,在命令行中输入 service.exe install 命令即可安装服务。

到此为止,一个简单的抓图服务就实现了。接下来我们来看两条示例。

示例一:抓取窗口截图

这个示例演示如何抓取一个窗口的截图。通过指定窗口的标题,可以在服务启动时获取窗口句柄,然后对该窗口进行截图。

private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
    var fileName = $"{DateTime.Now:yyyyMMddHHmmss}.png";
    var filePath = Path.Combine(_savePath, fileName);
    if (!Directory.Exists(_savePath))
    {
        Directory.CreateDirectory(_savePath);
    }

    var windowTitle = "Google Chrome";
    var windowHandle = FindWindow(null, windowTitle);
    if (windowHandle == IntPtr.Zero)
    {
        return;
    }

    var rect = new Rect();
    GetWindowRect(windowHandle, ref rect);

    var width = rect.right - rect.left;
    var height = rect.bottom - rect.top;
    var bmp = new Bitmap(width, height);
    using (var graphics = Graphics.FromImage(bmp))
    {
        var hdcBmp = graphics.GetHdc();
        var hdcSrc = GetDC(windowHandle);
        BitBlt(hdcBmp, 0, 0, width, height, hdcSrc, 0, 0, CopyPixelOperation.SourceCopy);
        graphics.ReleaseHdc(hdcBmp);
        ReleaseDC(windowHandle, hdcSrc);
    }

    bmp.Save(filePath, ImageFormat.Png);
    bmp.Dispose();
}

OnTimerElapsed 方法中,通过 FindWindow 函数获取窗口句柄,然后通过 GetDC 函数获取设备上下文,再通过 BitBlt 函数将窗口图像绘制到位图上,最后保存位图到指定路径。

示例二:抓取多个窗口截图

这个示例演示如何抓取多个窗口的截图。通过维护一个窗口列表,可以轮流对窗口进行截图。

public class ScreenshotService
{
    private readonly Timer _timer;
    private readonly List<string> _windowTitles;
    private readonly string _savePath;

    private int _currentIndex;

    public ScreenshotService()
    {
        _timer = new Timer(10000);
        _timer.Elapsed += OnTimerElapsed;
        _savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "Screenshots");

        _currentIndex = 0;
        _windowTitles = new List<string>
        {
            "Google Chrome",
            "Microsoft Edge"
        };
    }

    public void Start()
    {
        _timer.Start();
    }

    public void Stop()
    {
        _timer.Stop();
    }

    private void OnTimerElapsed(object sender, ElapsedEventArgs e)
    {
        var windowTitle = _windowTitles[_currentIndex];
        _currentIndex = (_currentIndex + 1) % _windowTitles.Count;

        var fileName = $"{windowTitle} - {DateTime.Now:yyyyMMddHHmmss}.png";
        var filePath = Path.Combine(_savePath, fileName);
        if (!Directory.Exists(_savePath))
        {
            Directory.CreateDirectory(_savePath);
        }

        var windowHandle = FindWindow(null, windowTitle);
        if (windowHandle == IntPtr.Zero)
        {
            return;
        }

        var rect = new Rect();
        GetWindowRect(windowHandle, ref rect);

        var width = rect.right - rect.left;
        var height = rect.bottom - rect.top;
        var bmp = new Bitmap(width, height);
        using (var graphics = Graphics.FromImage(bmp))
        {
            var hdcBmp = graphics.GetHdc();
            var hdcSrc = GetDC(windowHandle);
            BitBlt(hdcBmp, 0, 0, width, height, hdcSrc, 0, 0, CopyPixelOperation.SourceCopy);
            graphics.ReleaseHdc(hdcBmp);
            ReleaseDC(windowHandle, hdcSrc);
        }

        bmp.Save(filePath, ImageFormat.Png);
        bmp.Dispose();
    }
}

ScreenshotService 类的构造函数中维护了一个窗口列表。在 OnTimerElapsed 方法中,按照列表顺序轮流对窗口进行截图。

总结

本文介绍了用 C# 实现抓图服务的方法,并提供了两个示例说明,分别演示了如何抓取窗口截图和如何抓取多个窗口截图。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 抓图服务的实现 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • C#创建安全的栈(Stack)存储结构

    下面是关于C#创建安全的栈(Stack)存储结构的完整攻略: 1. Stack的概念 Stack是一种线性的数据结构,可以通过’栈顶’进行插入、删除和访问元素。栈的特殊性在于它是LIFO(后进先出)模型,就像一叠盘子,最后放上去的盘子将会最先被取走。 2. C#的Stack类 在C#中,Stack类封装了栈的逻辑,可以使用其提供的方法来创建、push(添加)…

    C# 2023年5月15日
    00
  • C#的winform控件命名规范

    C#的WinForm控件命名规范是指在WinForm应用程序中对各种控件进行命名的规范化约定,这能够使命名更加规范、易于理解和维护。接下来,我将介绍一些命名规范和示例说明: 命名规范 控件的名称应该以小写字母开头,其后可以跟着一个或多个单词,每个单词首字母大写,这些单词应当准确地描述该控件的用途。例如,如果你有一个按钮控件用于保存数据,那么这个按钮应当被命名…

    C# 2023年6月1日
    00
  • c# wpf如何附加依赖项属性

    附加依赖属性是WPF中使用频率较高的一种技术,可以用于从外部控制控件样式等外观相关内容。先将WPF中的依赖属性及其结构回顾一下。 依赖属性的类型全部都是静态成员 DependencyProperty,包含了名称、数据类型、属性所有者等信息。每个依赖属性还有一个名称以“XXXProperty”形式命名的静态实例,相当于依赖属性的标识符,用于设置、读取此属性值。…

    C# 2023年5月31日
    00
  • 详解Winform里面的缓存使用

    在Winform中,缓存是一种常用的技术,用于提高应用程序的性能和响应速度。本文将提供详细的“详解Winform里面的缓存使用”的完整攻略,包括什么是缓存、为什么要使用缓存、如何使用缓存以及两个示例。 什么是缓存? 缓存是一种将数据存储在内存中的技术,以便在需要时快速访问数据。缓存可以提高应用程序的性能和响应速度,因为从内存中读取数据比从磁盘或网络中读取数据…

    C# 2023年5月15日
    00
  • UGUI ScrollRect滑动定位优化详解

    UGUI ScrollRect滑动定位优化详解 前言 UGUI ScrollRect是Unity提供的一个用于制作滚动效果的UI组件,使用它可以比较方便地实现高效的滚动效果。但是在实际使用中,我们可能会遇到滑动定位的问题,即当我们滑动到一个特定位置后,需要把这个位置对应的item定位到屏幕中央或者其他位置。这时候,我们就需要对ScrollRect进行优化。 …

    C# 2023年6月3日
    00
  • C#实现Ping的方法小结

    C#实现Ping的方法小结 1. 简介 Ping是一种常用的测试网络连接的工具,可以测试网络延迟和连接状况,以及判断网络是否可用。在C#中也可以通过系统自带的Ping类来实现Ping功能。 2. Ping的基础使用 2.1 创建Ping实例 在使用Ping功能之前,需要创建一个Ping实例。使用如下代码可创建一个实例: Ping pingSender = n…

    C# 2023年6月7日
    00
  • 在winform下实现左右布局多窗口界面的方法

    在WinForm下实现左右布局多窗口界面的方法 1. 思路 在WinForm下实现左右布局多窗口界面,主要的思路是使用SplitContainer控件。SplitContainer控件可分裂成两个窗格,一个在左侧,一个在右侧,可以用来容纳两个不同的控件,以实现布局。 2. 实现步骤 2.1 创建SplitContainer 在VS中创建WinForm窗口,从…

    C# 2023年6月7日
    00
  • asp.net输出重写压缩页面文件实例代码

    ASP.NET是一款常用的Web应用程序开发框架,提供了很多优秀的功能。其中,输出重写和压缩页面文件也是ASP.NET的一个很重要的功能。下面,我将向大家详细讲解“asp.net输出重写压缩页面文件实例代码”的完整攻略。 一、什么是输出重写 ASP.NET中,输出重写是一种技术,可以动态地修改应用程序输出的HTML代码。当ASP.NET处理应用程序时,会生成…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部