2010-05-14 6 views
2

Я пытаюсь автоматизировать стороннее приложение Win32, где я хочу захватить графическое содержимое определенного окна через определенные промежутки времени. Я нахожусь на ранних этапах этого, и в настоящее время я пытаюсь использовать API Microsoft UI Automation через 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); 
// "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 в окно. Это 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"); 
    } 
} 

Итак, во-первых, возможно ли даже надежно сохранить растровое изображение содержимого окна? Если да, то какой лучший способ, и что не так с моим WM_PRINT с попыткой SendMessage?

ответ

4

Эта модификация PrintWindow API example на сайте pinvoke.net, похоже, сделала трюк.

Bitmap bmp = new Bitmap((int)rect.Width, (int)rect.Height); 
Graphics memoryGraphics = Graphics.FromImage(bmp); 
IntPtr dc = memoryGraphics.GetHdc(); 
bool success = PrintWindow(hwnd, dc, 0); 
memoryGraphics.ReleaseHdc(dc); 
bmp.Save(@"c:\screenshot.bmp"); 

Это работает, если приложение закрыто другим окном, но оно не работает, если приложение сведено к минимуму. Я думаю, что смогу жить с этим.

1

надежный способ получить растровое изображение из другого приложения, если это приложение не сверху. Это связано с тем, что элементы управления приложения даже не отображают, если приложение не видно, и Windows не обязательно даже помнит, какое последнее известное содержимое элемента управления было после того, как этот элемент управления потерял самую верхнюю позицию в z-порядке.

Лучше всего переместить целевое приложение на передний план z-порядка в то время, когда вам нужно сделать снимок экрана, а затем дополнительно восстановить исходный z-порядок после захвата изображения.