我想要一个相对简单的方法来做到这一点,有什么想法吗?例如,下面截取了不包括半透明窗口的屏幕截图:
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
要么我的 google-fu 真的很糟糕,要么这并不像听起来那么容易。我很确定为什么会发生这种情况,因为视频驱动程序必须分离内存才能使其正常工作,但我不在乎为什么它不起作用,我只是想在没有...的情况下进行
* 打印屏幕 key 黑客
* 第三方软件
* SDK 功能还可以,但我会投票支持用户拥有的每个可以在纯框架中向我展示它的对象(开玩笑,但它会很好)。
如果This是唯一的方法,我如何在 VB 中做到这一点?
1M 谢谢。
最佳答案
设置了 TransparencyKey 或 Opacity 属性的窗体是所谓的分层窗口。它们使用视频适配器的“覆盖”功能显示。这使它们能够产生透明效果。
捕获它们需要在接受 CopyPixelOperation 参数的 CopyFromScreen 重载中打开 CopyPixelOperation.CaptureBlt 选项。
不幸的是,这个重载有一个严重的错误,阻止它工作。它没有正确验证值。在 .NET 4.0 中仍未修复。没有其他好的解决办法,只能退回到使用 P/Invoke 来制作屏幕截图。这是一个例子:
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);
}
}
顺便说一句,后来的 Windows 版本为这个错误提供了解决方法。不确定是哪个,我认为是 Win7 SP1。如果您传递仅 CopyPixelOperation.CaptureBlt 选项,BitBlt() 函数现在将执行您想要的操作。但当然,该变通办法并没有追溯适用于早期的 Windows 版本,因此您不能真正依赖它。
关于c# - 在 .NET 中捕获包括半透明窗口的屏幕截图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3072349/