C# 有没有办法截取用户的 Windows 桌面?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/880878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 05:12:11  来源:igfitidea点击:

Is there a way to take a screenshot of the user's Windows desktop?

c#windowsdesktopscreenshot

提问by Damovisa

I want to provide the user with a scaled-down screenshot of their desktop in my application.

我想在我的应用程序中为用户提供他们桌面的缩小屏幕截图。

Is there a way to take a screenshot of the current user's Windows desktop?

有没有办法截取当前用户的 Windows 桌面?

I'm writing in C#, but if there's a better solution in another language, I'm open to it.

我正在用 C# 编写代码,但如果有其他语言的更好解决方案,我愿意接受。

To clarify, I need a screenshot of the Windows Desktop - that's the wallpaper and icons only; no applications or anything that's got focus.

澄清一下,我需要一张 Windows 桌面的屏幕截图——那只是壁纸和图标;没有应用程序或任何重点。

采纳答案by lc.

You're looking for Graphics.CopyFromScreen. Create a new Bitmap of the right size and pass the Bitmap's Graphics object screen coordinates of the region to copy.

您正在寻找Graphics.CopyFromScreen。创建一个新的大小合适的 Bitmap 并传递 Bitmap 的 Graphics 对象屏幕坐标要复制的区域。

There's also an articledescribing how to programmatically take snapshots.

还有一篇文章描述了如何以编程方式拍摄快照。

Response to edit: I misunderstood what you meant by "desktop". If you want to take a picture of the desktop, you'll have to:

对编辑的回应:我误解了您所说的“桌面”是什么意思。如果你想给桌面拍照,你必须:

  1. Minimize all windows using the Win32API(send a MIN_ALLmessage) first
  2. Take the snapshot
  3. Then undo the minimize all (send a MIN_ALL_UNDOmessage).
  1. 首先使用Win32API(发送MIN_ALL消息)最小化所有窗口
  2. 拍摄快照
  3. 然后撤消全部最小化(发送MIN_ALL_UNDO消息)。


A better way to do thiswould be not to disturb the other windows, but to copy the image directly from the desktop window. GetDesktopWindow in User32will return a handle to the desktop. Once you have the window handle, get it's device context and copy the image to a new Bitmap.

更好的方法是不要打扰其他窗口,而是直接从桌面窗口复制图像。User32 中的 GetDesktopWindow将返回桌面的句柄。获得窗口句柄后,获取它的设备上下文并将图像复制到新的位图。

There's an excellent example on CodeProjectof how to copy the image from it. Look for the sample code about getting and creating the device context in the "Capturing the window content" section.

CodeProject上有一个很好的例子,说明如何从中复制图像。在“捕获窗口内容”部分中查找有关获取和创建设备上下文的示例代码。

回答by Robert Venables

I get the impression that you are shooting for taking a picture of the actual desktop (with wallpaper and icons), and nothing else.

我的印象是您拍摄的是实际桌面(带有墙纸和图标)的照片,仅此而已。

1) Call ToggleDesktop() in Shell32 using COM
2) Use Graphics.CopyFromScreen to copy the current desktop area
3) Call ToggleDesktop() to restore previous desktop state

1) 在 Shell32 中使用 COM 调用 ToggleDesktop()
2) 使用 Graphics.CopyFromScreen 复制当前桌面区域
3) 调用 ToggleDesktop() 恢复以前的桌面状态

Edit: Yes, calling MinimizeAll() is belligerent.

编辑:是的,调用 MinimizeAll() 是好战的。

Here's an updated version that I whipped together:

这是我拼凑的更新版本:

    /// <summary>
    /// Minimizes all running applications and captures desktop as image
    /// Note: Requires reference to "Microsoft Shell Controls and Automation"
    /// </summary>
    /// <returns>Image of desktop</returns>
    private Image CaptureDesktopImage() {

        //May want to play around with the delay.
        TimeSpan ToggleDesktopDelay = new TimeSpan(0, 0, 0, 0, 150);

        Shell32.ShellClass ShellReference = null;

        Bitmap WorkingImage = null;
        Graphics WorkingGraphics = null;
        Rectangle TargetArea = Screen.PrimaryScreen.WorkingArea;
        Image ReturnImage = null;

        try
        {

            ShellReference = new Shell32.ShellClass();
            ShellReference.ToggleDesktop();

            System.Threading.Thread.Sleep(ToggleDesktopDelay);

            WorkingImage = new Bitmap(TargetArea.Width,
                TargetArea.Height);

            WorkingGraphics = Graphics.FromImage(WorkingImage);
            WorkingGraphics.CopyFromScreen(TargetArea.X, TargetArea.X, 0, 0, TargetArea.Size);

            System.Threading.Thread.Sleep(ToggleDesktopDelay);
            ShellReference.ToggleDesktop();

            ReturnImage = (Image)WorkingImage.Clone();

        }
        catch
        {
            System.Diagnostics.Debugger.Break();
            //...
        }
        finally
        {
            WorkingGraphics.Dispose();
            WorkingImage.Dispose();
        }

        return ReturnImage;

    }

Adjust to taste for multiple monitor scenarios (although it sounds like this should work just fine for your application).

调整以适应多个监视器场景(尽管听起来这对您的应用程序来说应该很好用)。

回答by JP Alioto

You might look at using GetDesktopWindowthrough p/invoke, then get the device context and take your snapshot. There is a very detailed tutorial here. It might be better than perturbing the existing windows.

您可能会考虑通过 p/invoke使用GetDesktopWindow,然后获取设备上下文并拍摄快照。有一个非常详细的教程在这里。这可能比扰乱现有的窗口要好。

回答by JP Alioto

All former answers are completely wrong (minimizing apps is absurd)
Simply use SHW api : one lineof code (the desktop bitmap being cached, the api simply blits it to your HDC...)

所有以前的答案都是完全错误的(最小化应用程序是荒谬的
只需使用 SHW api:一行代码(桌面位图被缓存,api 只是简单地将它传输到您的 HDC ......)

回答by user1692494

You can always catch screenshot on windows startup before applications run or use other desktop by using desktop switching. Take a look here: http://www.codeproject.com/Articles/7666/Desktop-SwitchingSwitch to other desktop, take picture and remember you dont need to show it just create it "DESKTOP"

您可以在应用程序运行或使用其他桌面之前通过桌面切换在 Windows 启动时捕获屏幕截图。看看这里:http: //www.codeproject.com/Articles/7666/Desktop-Switching切换到其他桌面,拍照并记住你不需要显示它只需创建它“桌面”