定義された時間間隔で特定のウィンドウのグラフィックスコンテンツをキャプチャしたいサードパーティのWin32アプリケーションを自動化しようとしています。私はこれの初期段階にあり、現在、C#を介してMicrosoft UI Automation APIを使用して、クライアントアプリと外部アプリ間のほとんどのやり取りを実行しようとしています。これで、外部アプリにやりたいことを実行させることができますが、サードパーティの所有者が作成したコントロールのように見える特定のウィンドウからグラフィックをキャプチャしたいと思います。これどうやってするの?キャプチャしたいウィンドウは、この画像の赤い長方形でマークされたウィンドウです。
私はそのような動作をする実装を持っていますが、それは外部アプリのUIが一番上にあることに依存しており、それは私にとって保証されていないので、もっと一般的なものを見つけたいと思います。
var p = Process.Start("c:\myapp.exe");
var mainForm = AutomationElement.FromHandle(p.MainWindowHandle);
// "workspace" below is the window whose content I want to capture.
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
メッセージをウィンドウに送信するためのいくつかの提案を読みました。数か月前のこの質問/回答は有望に思えましたが、このコードを使用すると、コントロールの実際の内容がまったく含まれていない白い長方形が表示されます。
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");
}
}
それで、最初に、ウィンドウのコンテンツのビットマップを確実に保存することさえ可能ですか?もしそうなら、最善の方法は何ですか、そして私WM_PRINT
のSendMessage
試みの何が悪いのですか?