构建屏幕截图
Building a screen capture
我正在尝试通过每隔 x
毫秒截取 window 的屏幕截图来构建特定 window 的简单视频记录(然后将所有这些图像组合成 AVI文件),但我不知道如何定义 x
的值。我该如何定义它?用于此的共同价值是什么?我读到一些关于 24fps 的东西。
我也不确定是否使用 Timer
,在 Tick
事件中进行捕获是个好主意。我会不会有任何不准确的地方,我应该用别的东西?例如,出于任何原因,截屏时间比预期的要长。
我目前的实现是这样的:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT r);
public Bitmap GetScreenshot(IntPtr hwnd)
{
RECT rc;
if (!GetWindowRect(hwnd, out rc))
throw new Win32Exception(Marshal.GetLastWin32Error());
Bitmap bmp = new Bitmap(rc.right - rc.left, rc.bottom - rc.top, PixelFormat.Format32bppArgb);
using (var gfxBmp = Graphics.FromImage(bmp))
{
IntPtr hdcBitmap = gfxBmp.GetHdc();
bool succeeded = PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
if (!succeeded)
{
gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
}
IntPtr hRgn = CreateRectRgn(0, 0, 0, 0);
GetWindowRgn(hwnd, hRgn);
Region region = Region.FromHrgn(hRgn);
if (!region.IsEmpty(gfxBmp))
{
gfxBmp.ExcludeClip(region);
gfxBmp.Clear(Color.Transparent);
}
return bmp;
}
}
和
int i = 0;
const string dest_path = @"C:\Users\pc2\Desktop\images";
void doRecord()
{
string filename = Path.Combine(dest_path, string.Format("{0}.png", ++i));
// yeah, I'll add some error checking here soon as it gets working.
GetScreenshot(handle).Save(filename, ImageFormat.Png);
}
在计时器的滴答事件中我称之为:
private void timer1_Tick(object sender, EventArgs e)
{
doRecord();
}
还有如何正确定义 x
的值,我是不是遗漏了什么?
您必须为正在使用的计时器设置 'Interval' 参数。 'Interval' 以毫秒为单位设置,因此如果您想要 ~24 FPS,请将 'Interval' 设置为 42(1000(每秒毫秒数)/ 24(所需 FPS)= 42)。
我正在尝试通过每隔 x
毫秒截取 window 的屏幕截图来构建特定 window 的简单视频记录(然后将所有这些图像组合成 AVI文件),但我不知道如何定义 x
的值。我该如何定义它?用于此的共同价值是什么?我读到一些关于 24fps 的东西。
我也不确定是否使用 Timer
,在 Tick
事件中进行捕获是个好主意。我会不会有任何不准确的地方,我应该用别的东西?例如,出于任何原因,截屏时间比预期的要长。
我目前的实现是这样的:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT r);
public Bitmap GetScreenshot(IntPtr hwnd)
{
RECT rc;
if (!GetWindowRect(hwnd, out rc))
throw new Win32Exception(Marshal.GetLastWin32Error());
Bitmap bmp = new Bitmap(rc.right - rc.left, rc.bottom - rc.top, PixelFormat.Format32bppArgb);
using (var gfxBmp = Graphics.FromImage(bmp))
{
IntPtr hdcBitmap = gfxBmp.GetHdc();
bool succeeded = PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
if (!succeeded)
{
gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
}
IntPtr hRgn = CreateRectRgn(0, 0, 0, 0);
GetWindowRgn(hwnd, hRgn);
Region region = Region.FromHrgn(hRgn);
if (!region.IsEmpty(gfxBmp))
{
gfxBmp.ExcludeClip(region);
gfxBmp.Clear(Color.Transparent);
}
return bmp;
}
}
和
int i = 0;
const string dest_path = @"C:\Users\pc2\Desktop\images";
void doRecord()
{
string filename = Path.Combine(dest_path, string.Format("{0}.png", ++i));
// yeah, I'll add some error checking here soon as it gets working.
GetScreenshot(handle).Save(filename, ImageFormat.Png);
}
在计时器的滴答事件中我称之为:
private void timer1_Tick(object sender, EventArgs e)
{
doRecord();
}
还有如何正确定义 x
的值,我是不是遗漏了什么?
您必须为正在使用的计时器设置 'Interval' 参数。 'Interval' 以毫秒为单位设置,因此如果您想要 ~24 FPS,请将 'Interval' 设置为 42(1000(每秒毫秒数)/ 24(所需 FPS)= 42)。