我正在尝试自动化第三方Win32应用程序,在该应用程序中,我希望以定义的时间间隔捕获特定窗口的图形内容。我正处于这方面的早期阶段,目前正在尝试使用
Microsoft UI Automation
API通过C在我的客户端应用程序和外部应用程序之间进行大部分交互。我现在可以让外部应用程序做我想做的事情,但现在我想从一个特定的窗口捕获图形,这个窗口似乎是第三方所有者绘制的控件。我该怎么做?我要捕获的窗口是由该图像中的红色矩形标记的窗口:
I need what's in the red rectangle http://img168.imageshack.us/img168/8169/5142010110014am.png
我有一个可以工作的实现,但是它依赖于外部应用程序的用户界面,这对我来说是不保证的,所以我更愿意找到更一般的东西。
var p = Process.Start("c:\myapp.exe");
var mainForm = AutomationElement.FromHandle(p.MainWindowHandle);
var workspace = mainForm.FindFirst(TreeScope.Descendents,
new PropertyCondition(AutomationElement.ClassNameProperty, "AfxFrameOrView70u"));
var rect = (Rect) workspace.GetCurrentPropertyValue(AutomationElement.BoundingRectangleProperty);
using (var bmp = new Bitmap((int)rect.Width, (int)rect.Height))
{
using (var g = Graphics.FromImage(bmp))
{
g.CopyFromScreen((int)rect.Left, (int)rect.Top, 0, 0, new Size((int)rect.Width, (int)rect.Height));
bmp.Save(@"c:\screenshot.png", ImageFormat.Png);
}
}
当自动应用程序在顶部时,上面的功能就足够好了,但是它只是盲目地复制矩形中的屏幕,所以我的代码取决于机器上运行的任何东西,可能会覆盖我的应用程序窗口。
我已经阅读了一些发送
WM_PRINT
向窗口发送消息。这个
question/answer
从几个月前开始似乎很有希望,但当我使用此代码时,我得到了一个白色矩形,没有控件的实际内容。
var prop = (int)workspace.GetCurrentPropertyValue(AutomationElement.NativeWindowHandleProperty);
var hwnd = new IntPtr(prop);
using ( var bmp2 = new Bitmap((int)rect.Width, (int)rect.Height))
{
using (Graphics g = Graphics.FromImage(bmp2))
{
g.FillRectangle(SystemBrushes.Control, 0, 0, (int)rect.Width, (int)rect.Height);
try
{
SendMessage(hwnd, WM_PRINT, g.GetHdc().ToInt32(), (int)(DrawingOptions.PRF_CHILDREN | DrawingOptions.PRF_CLIENT | DrawingOptions.PRF_OWNED));
}
finally
{
g.ReleaseHdc();
}
bmp2.Save(@"c:\screenshot.bmp");
}
}
所以,首先,是否可以可靠地保存窗口内容的位图?如果是这样,最好的方法是什么?我的
WMX打印
具有
SendMessage
尝试?