Frage

Ich versuche, eine Drittanbieter-Win32-Anwendung zu automatisieren, wo ich die Grafikinhalte eines bestimmten Fensters in definierten Zeitintervallen erfassen möchten. Ich bin in den frühen Phasen dieses, und ich versuche zur Zeit den Microsoft UI Automation API über C # die meisten der Interaktion zwischen meiner Client-Anwendung und dem externen App zu tun. Ich kann jetzt die externe App bekommen zu tun, was ich will es tun, aber jetzt mag ich die Grafik von einem bestimmten Fenster erfassen, die einige Drittanbieter Ownerdrawn-Kontrolle zu sein scheint. Wie kann ich das machen? Das Fenster I aufnehmen möchten, ist die von dem roten Rechteck in diesem Bild markiert:

Ich habe eine Implementierung dieser Art von Arbeiten, aber es ist abhängig von der externen App UI oben zu sein, und das ist für mich nicht garantiert, so würde ich etwas allgemeinere finden bevorzugen.

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);
    }
}

Die oben genannte Arbeiten gut genug, wenn die automatisierte App auf, aber es einfach blind kopiert der Bildschirm in dem Rechteck, so dass mein Code ist auf Gedeih und Verderb, was auch immer passiert, auf der Maschine zu laufen und könnte meine App-Fenster abzudecken.

Ich habe einige Vorschläge lesen Sie die WM_PRINT Nachricht an das Fenster zu senden. Diese Frage / Antwort von ein paar Monate zurück schien viel versprechend, aber wenn ich diesen Code verwenden, bekomme ich nur ein weißes Rechteck mit keinem eigentlichen Inhalt meiner Kontrolle.

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");
    }
}

Also, zunächst ist es sogar möglich, dass ich zuverlässig speichern Bitmap eines Inhalts des Fensters? Wenn ja, was ist der beste Weg, und was ist falsch mit meiner WM_PRINT mit SendMessage Versuch?

War es hilfreich?

Lösung

Diese Modifikation der PrintWindow API Beispiel auf dem pinvoke. netto-Website scheint den Trick getan zu haben.

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");

Dies funktioniert, wenn die App von einem anderen Fenster verdeckt wird, aber es funktioniert nicht, wenn die App minimiert wird. Ich glaube, ich kann damit leben.

Andere Tipps

Es gibt keine zuverlässig Art und Weise eine Bitmap aus einer anderen App zu bekommen, wenn die App nicht oben ist. Das ist, weil der App-Kontrollen machen nicht, auch wenn die App nicht sichtbar ist, und Windows muss nicht unbedingt auch daran erinnern, was die letzten bekannten Inhalte der Steuerung waren nach, dass die Kontrolle der obersten Position in der z-Ordnung verliert.

Am besten ist es das Ziel App auf die Vorderseite der Z-Reihenfolge zu der Zeit zu bewegen, dass Sie den Screenshot müssen, und dann wiederherstellen optional die ursprüngliche Z-Reihenfolge nach der Aufnahme des Bildes.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top