有没有一种方法可以截取用户Windows桌面的屏幕截图?

15

我希望在我的应用程序中向用户提供一个缩小的桌面屏幕截图。

有没有一种方法可以截取当前用户Windows桌面的屏幕截图?

我正在使用C#编写,但如果有其他语言的更好解决方案,我也愿意尝试。

需要澄清的是,我需要的是Windows桌面的屏幕截图 - 只包括壁纸和图标; 没有应用程序或任何被聚焦的东西。

5个回答

16
您需要使用Graphics.CopyFromScreen。创建一个具有正确大小的新位图,并将该位图的Graphics对象屏幕坐标传递给要复制的区域。
还有一篇文章描述了如何以编程方式进行快照。 编辑回复:我误解了您所说的“桌面”。如果您想拍摄桌面的图片,您需要:
  1. 使用Win32API最小化所有窗口(发送MIN_ALL消息)
  2. 进行快照
  3. 然后撤消最小化所有窗口(发送MIN_ALL_UNDO消息)。

更好的方法是不要干扰其他窗口,而是直接从桌面窗口复制图像。在User32中GetDesktopWindow将返回一个指向桌面的句柄。一旦您拥有窗口句柄,请获取它的设备上下文并将图像复制到新位图中。 CodeProject上有一个非常好的例子,介绍了从其中复制图像的示例代码。在“捕获窗口内容”部分查找有关获取和创建设备上下文的示例代码即可。

1
如果我的应用程序在焦点中,我可以这样做吗?如果它们在桌面前面,它不会捕获我的应用程序窗口(和其他窗口)吗? - Damovisa
1
我尝试了 GetDesktopWindow,但它捕获了在桌面前面的窗口。 - Aivan Monceller
有没有完整的源代码示例,可以作为最终解决方案? - Kiquenet

10

我认为你的目标是拍摄实际桌面(包括壁纸和图标),而不是其他任何内容。

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

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

下面是我快速修改的更新版本:

    /// <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;

    }

根据不同的多显示器情况进行调整(虽然听起来对于你的应用程序应该可以正常工作)。


很棒的答案!它详细说明了所需内容,而不是简单地复制粘贴。我希望更多的SO答案都像这样。 - Refracted Paladin
谢谢,这正是我想要的。我假设在Shell32中有一个类似的方法,我可以调用它来恢复我的应用程序的焦点。 - Damovisa
@Damovisa - 不仅仅是你的应用程序需要恢复。随机最小化所有用户的应用程序并不是一个好的做法... - Tal Pressman
@Damovisa:我完全同意。 @Mr_Mom:谢谢。 - Robert Venables

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

0

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


-2
所有先前的答案都是完全错误的(最小化应用程序是荒谬的)
只需使用SHW API:一行代码(桌面位图被缓存,API将其简单地合并到您的HDC中...)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接