捕获截图包括.NET半透明窗口 [英] Capture screenshot Including Semitransparent windows in .NET

查看:234
本文介绍了捕获截图包括.NET半透明窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想一个比较下锅免费的方式做到这一点,任何想法?例如,以下取截图不包括半透明窗口:

I would like a relatively hack-free way to do this, any ideas? For example, the following takes a screenshot that doesn't include the semi-transparent window:

Public Class Form1
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
        Text = "Opaque Window"
        Dim win2 As New Form
        win2.Opacity = 0.5
        win2.Text = "Tranparent Window"
        win2.Show()
        win2.Top = Top + 50
        win2.Left = Left() + 50
        Dim bounds As Rectangle = System.Windows.Forms.Screen.GetBounds(Point.Empty)
        Using bmp As Bitmap = New Bitmap(bounds.Width, bounds.Height)
            Using g As Graphics = Graphics.FromImage(bmp)
                g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size)
            End Using
            bmp.Save("c:\temp\scn.gif")
        End Using
        Process.Start(New Diagnostics.ProcessStartInfo("c:\temp\scn.gif") With {.UseShellExecute = True})
    End Sub
End Class

无论是我的谷歌福真的很烂或者这并不像听起来那么容易。我是pretty的知道为什么发生这种情况,因为这样的视频驱动程序必须将内存,使这项工作,但我不在乎,为什么它不工作,我只想做没有...
  *打印屏幕键黑客
  *第三方软件 -   * SDK功能都OK,但我会upvote由能告诉我它在纯框架用户所拥有的每一个对象(开个玩笑,但是这将是很好)。

Either my google-fu really sucks or this is not as easy as it sounds. I'm pretty sure why this is happening because of the way the video driver would have to separate the memory to make this work, but I don't care why it doesn't work, I just want to do it without...
* print-screen key hacks
* 3rd party software
* SDK functions are OK but I'll upvote every object owned by the user that can show me it in pure framework (Just kidding but it would be nice).

如果是做的唯一途径它,怎么我这样做,在VB?
1M的感谢。

If This is the only way to do it, how to I do that in VB?
1M thanks.

推荐答案

形式具有TransparencyKey和Opacity属性设置是所谓的分层的窗口。他们所使用的视频适配器的叠加功能,如图所示。这使他们能够有自己的透明效果。

Forms that have the TransparencyKey or Opacity property set are so-called layered windows. They are shown using the "overlay" feature of the video adapter. Which make them being able to have their transparency effects.

捕捉他们需要打开一个接受CopyPixelOperation参数在CopyFromScreen超载CopyPixelOperation.CaptureBlt选项。

Capturing them requires turning on the CopyPixelOperation.CaptureBlt option in the CopyFromScreen overload that accepts the CopyPixelOperation argument.

不幸的是,这种超载具有起价工作p $ pvents这是一个严重错误。它不验证值正常。还是不固定在.NET 4.0中。有没有其他好的修复,但回落到使用P / Invoke,使拍摄的画面。这里有一个例子:

Unfortunately, this overload has a critical bug that prevents this from working. It doesn't validate the value properly. Still not fixed in .NET 4.0. There is no other good fix but fall back to using P/Invoke to make the screen shot. Here's an example:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication1 {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e) {
      Size sz = Screen.PrimaryScreen.Bounds.Size;
      IntPtr hDesk = GetDesktopWindow();
      IntPtr hSrce = GetWindowDC(hDesk);
      IntPtr hDest = CreateCompatibleDC(hSrce);
      IntPtr hBmp = CreateCompatibleBitmap(hSrce, sz.Width, sz.Height);
      IntPtr hOldBmp = SelectObject(hDest, hBmp);
      bool b = BitBlt(hDest, 0, 0, sz.Width, sz.Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
      Bitmap bmp = Bitmap.FromHbitmap(hBmp);
      SelectObject(hDest, hOldBmp);
      DeleteObject(hBmp);
      DeleteDC(hDest);
      ReleaseDC(hDesk, hSrce);
      bmp.Save(@"c:\temp\test.png");
      bmp.Dispose();
    }

    // P/Invoke declarations
    [DllImport("gdi32.dll")]
    static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int
    wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
    [DllImport("user32.dll")]
    static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
    [DllImport("gdi32.dll")]
    static extern IntPtr DeleteDC(IntPtr hDc);
    [DllImport("gdi32.dll")]
    static extern IntPtr DeleteObject(IntPtr hDc);
    [DllImport("gdi32.dll")]
    static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
    [DllImport("gdi32.dll")]
    static extern IntPtr CreateCompatibleDC(IntPtr hdc);
    [DllImport("gdi32.dll")]
    static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
    [DllImport("user32.dll")]
    public static extern IntPtr GetDesktopWindow();
    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowDC(IntPtr ptr);
  }
}

FWIW,以后的Windows版本提供了解决此问题。不完全相信它,我认为这是Win7的SP1。该的BitBlt()函数现在你想,如果你通过的只有的的CopyPixelOperation.CaptureBlt选项是什么。但是,当然了解决方法并没有采用复古积极早期的Windows版本,所以你不能真正依赖于它。

Fwiw, a later Windows version provided a workaround for this bug. Not exactly sure which, I think it was Win7 SP1. The BitBlt() function will now do what you want if you pass only the CopyPixelOperation.CaptureBlt option. But of course that workaround wasn't applied retro-actively to earlier Windows versions so you can't really depend on it.

这篇关于捕获截图包括.NET半透明窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆