我对 Vista 的理解是,每个窗口都有自己的屏幕缓冲区,然后将其进行 alpha 混合等以创建屏幕。
那么,有没有办法通过直接读取这些缓冲区来截取一个被遮挡或部分不在屏幕上的窗口?当您 alt-tab 或将鼠标悬停在任务栏上时,Vista 会执行此操作。
我在 Delphi 中这样做,但任何语言的代码都足够了。
我对 Vista 的理解是,每个窗口都有自己的屏幕缓冲区,然后将其进行 alpha 混合等以创建屏幕。
那么,有没有办法通过直接读取这些缓冲区来截取一个被遮挡或部分不在屏幕上的窗口?当您 alt-tab 或将鼠标悬停在任务栏上时,Vista 会执行此操作。
我在 Delphi 中这样做,但任何语言的代码都足够了。
我相信当这些窗口不在屏幕上时,这些缓冲区不存在。或者在部分离屏时仅部分存在。
如果您注意窗口缩略图,您会发现当这些窗口最小化或离屏时它不会更新。WM_PAINT 将在窗口从屏幕外拖动到打开时触发,再次表明此数据尚未缓冲在某处。
你考虑过挂钩 wm_paint 消息吗?《Windows图形编程:Win32 GDI与DirectDraw》作者冯远为此制作了示例dll。我认为通过这种方式也可以捕获 DirectXed 窗口(随时都有缓冲屏幕)。请参考http://www.fengyuan.com/article/wmprint.html 你可以通过谷歌找到工作的德尔福例子。还要检查 expterts-exchange.com
我认为新的 DWM APi(桌面 Windows 管理器)中可能有一些东西,它可以让您编写和安装自定义桌面管理器,并可以访问您在 Flip3d 和其他视图中看到的相同缩略图。
这是我很久以前用 C# 为屏幕捕获应用程序编写的一些代码。它使用 Win32 函数 GetWindowRect 来获取要捕获的窗口的边界,创建具有该大小的位图,然后使用 Win32 函数 PrintWindow 要求窗口将自身打印到该位图:
RECT lRectangle = new RECT();
if (!GetWindowRect(lWindow.HWnd, ref lRectangle))
{
MessageBox.Show(this, "An error occured while measuring the selected window.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
fCapturedImage = new Bitmap(lRectangle.Right - lRectangle.Left, lRectangle.Bottom - lRectangle.Top, PixelFormat.Format32bppArgb);
using (Graphics lGraphics = Graphics.FromImage(fCapturedImage))
{
HDC lHdc = lGraphics.GetHdc();
PrintWindow(lWindow.HWnd, lHdc, 0);
lGraphics.ReleaseHdc(lHdc);
}
这样做 (C#)
public static Bitmap PrintWindow(IntPtr hwnd)
{
RECT rc;
WinUserApi.GetWindowRect(hwnd, out rc);
Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
bool succeeded = WinUserApi.PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
if (!succeeded)
{
gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
}
IntPtr hRgn = WinGdiApi.CreateRectRgn(0, 0, 0, 0);
WinUserApi.GetWindowRgn(hwnd, hRgn);
Region region = Region.FromHrgn(hRgn);
if (!region.IsEmpty(gfxBmp))
{
gfxBmp.ExcludeClip(region);
gfxBmp.Clear(Color.Transparent);
}
gfxBmp.Dispose();
return bmp;
}