none
Screenshot erstellen von anderen Prozess erstellen RRS feed

  • Frage

  • Hi zusammen, ich (hatte ich schon mal gefragt) erstellen von meinem laufenden Programm (ich rufe jetzt noch ein neues Fenster auf) einen Screenshot von einem anderen Prozess.
    Das klappt alles schon recht gut. Nur wenn das neue Fenster sich mit dem Fenster vom neuen Prozess überlagert, denn ist immer ein Teil vom neuen Fenster auf dem Screenshot mit drauf.
    Ich habe schon SetForegroundWindow probiert. SetActiveWindow und SetFocus. Will aber nicht so recht.

     If (SetForegroundWindow(cls_Screenshot.m_pscreen_handle)) = True Then
    '                SetActiveWindow(cls_Screenshot.m_pscreen_handle)
     '               SetFocus(cls_Screenshot.m_pscreen_handle)
                    Image_Screen = cls_Screenshot.CaptureWindowRegion(cls_Screenshot.m_pscreen_handle) 'myProcess1.MainWindowHandle)

    Wie bekomme ich das am besten hin?
    Gruss

    Mittwoch, 2. April 2014 12:55

Antworten

  • Hallo,
    du solltest vielleicht versuchen das Fenster mit den TopMost-Attribut zu versehen. Dieses Attribut sorgt dafür, dass das Fenster nicht von einem anderen nicht-TopMost-Fenster überlagert werden kann.

    Zunächst rufen wir die aktuelle Position und Größe des Fensters ab. Das geht mit einer eigenen Struktur:

    <DllImport("user32.dll", SetLastError:=True)> _
    Public Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
    End Function
    
    Public Structure RECT
    'Unbedingt in dieser Reihenfolge belassen, die automatisch generierten Felder'
    'hinter den Eigenschaften entsprechen den 4*32 Byte die Windows erwartet' Public Property Left() As Integer Public Property Top() As Integer Public Property Right() As Integer Public Property Bottom() As Integer End Structure

    Den erhaltenen Wert können wir dann mit dem HWND_TOPMOST-Flag an SetWindowPos übergeben:

        Private HWND_TOPMOST As Integer = -1
        Private HWND_NOTOPMOST As Integer = -1
    
        <DllImport("user32.dll", SetLastError:=True)> _
        Public Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As Integer, X As Integer, Y As Integer, W As Integer, H As Integer, uFlags As UInteger) As Boolean
        End Function

    Die Konstante HWND_NOTOPMOST entfernt das TopMost-Attribut wieder.
    Nun der Aufruf der Methoden:

    Dim rect As RECT
    GetWindowRect(p.MainWindowHandle, rect)
    SetWindowPos(p.MainWindowHandle, HWND_TOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0)
    
    Thread.Sleep(5000) 'Screenshot machen simulieren'
    
    SetWindowPos(p.MainWindowHandle, HWND_NOTOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0)

    Zunächst wird also die Fensterposition- und die Größe ausgelesen. Anschließend werden die Grundeigenschaften des Fensters gesetzt. Hier müssen wir die Größe- und Position angeben, darum die vorherige Ermittlung.
    Anschließend wird der Screenshot gemacht (Thread.Sleep zum testen). Zum schluss wird das TopMost-Attribut wieder entfernt.

    In meinen Tests hat alles problemlos funktioniert (Mit Notepad.exe getestet).


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 2. April 2014 13:44
    Moderator

Alle Antworten

  • Hallo,
    du solltest vielleicht versuchen das Fenster mit den TopMost-Attribut zu versehen. Dieses Attribut sorgt dafür, dass das Fenster nicht von einem anderen nicht-TopMost-Fenster überlagert werden kann.

    Zunächst rufen wir die aktuelle Position und Größe des Fensters ab. Das geht mit einer eigenen Struktur:

    <DllImport("user32.dll", SetLastError:=True)> _
    Public Function GetWindowRect(hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
    End Function
    
    Public Structure RECT
    'Unbedingt in dieser Reihenfolge belassen, die automatisch generierten Felder'
    'hinter den Eigenschaften entsprechen den 4*32 Byte die Windows erwartet' Public Property Left() As Integer Public Property Top() As Integer Public Property Right() As Integer Public Property Bottom() As Integer End Structure

    Den erhaltenen Wert können wir dann mit dem HWND_TOPMOST-Flag an SetWindowPos übergeben:

        Private HWND_TOPMOST As Integer = -1
        Private HWND_NOTOPMOST As Integer = -1
    
        <DllImport("user32.dll", SetLastError:=True)> _
        Public Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As Integer, X As Integer, Y As Integer, W As Integer, H As Integer, uFlags As UInteger) As Boolean
        End Function

    Die Konstante HWND_NOTOPMOST entfernt das TopMost-Attribut wieder.
    Nun der Aufruf der Methoden:

    Dim rect As RECT
    GetWindowRect(p.MainWindowHandle, rect)
    SetWindowPos(p.MainWindowHandle, HWND_TOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0)
    
    Thread.Sleep(5000) 'Screenshot machen simulieren'
    
    SetWindowPos(p.MainWindowHandle, HWND_NOTOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0)

    Zunächst wird also die Fensterposition- und die Größe ausgelesen. Anschließend werden die Grundeigenschaften des Fensters gesetzt. Hier müssen wir die Größe- und Position angeben, darum die vorherige Ermittlung.
    Anschließend wird der Screenshot gemacht (Thread.Sleep zum testen). Zum schluss wird das TopMost-Attribut wieder entfernt.

    In meinen Tests hat alles problemlos funktioniert (Mit Notepad.exe getestet).


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 2. April 2014 13:44
    Moderator