Screenshot vom Desktop machen auch wenn Fenster Überdeckt

  • VB.NET

Es gibt 24 Antworten in diesem Thema. Der letzte Beitrag () ist von Tsuyo.

    Screenshot vom Desktop machen auch wenn Fenster Überdeckt

    Hi, wie könnte man ein Screenshot von einem Desktop machen, wenn ein Fenster (z.b Firefox) Den Desktop komplett überdeckt?
    Kann ich .Net funktionen nutzen? Muss ich WMI nutzen?

    Grüße
    Hi, ich habs mit Explorer versucht.
    Jedoch wird mir dann ein Ordner gezeigt und kein Desktop.
    Falls kein ordner auf ist, gibts 'nen crash.
    Liegt's vieleicht an Windows 7?

    /Edit:
    Nun wird mir nur die Taskleiste gezeigt. Warum auch immer.

    /reedit:
    Ich hab mir mal alle Prozesse auflisten lassen und dann jedesmal ein screen abrufen lassen.
    Kein Prozess bringt mir den Desktop

    /rereedit:
    Es würde auch schon was bringen alles hinter einem Fenster zu screenshotten.
    Ich möchte wissen was hinter meinem Firefox passiert. Egal ob dahinter ein programm etc läuft

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Tsuyo“ ()

    Nene, ich möchte einfach nur ein Screenshot machen. Dieser soll alles anzeigen was hinter dem Firefox ist.

    Was mir auch Helfen würde wäre einfach nur die Position und das Iconbild der Icons auf dem Desktop herauszufinden.
    Dann könnte man einfach mit GDI arbeiten.
    Ich hab diesen Post hier gefunden:
    social.msdn.microsoft.com/Foru…0f-4b62-80c9-7768756456e6
    Und da macht selbst der C# VB converter schlapp

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Tsuyo“ ()

    Das wäre auch eine Idee, aber so schwer ist der Code doch nicht, ist doch recht übersichtlich, lediglich paar API Deklarationen und bischel Code dazu. Entweder sofern nicht hast die c# Express IDE laden oder eben per Hand übersetzten, ist eigentlich nicht so schwer.
    Nun, ich hab mir den Code mal in C# angesehen. Bin ja nicht auf den kopf gefallen.^^
    Jedoch bietet es mir nur den namen. Nicht die Position, geschweige denn das Icon des Icon's.

    /Edit:
    Ich werd nochmal alles per Hand auf Vb übersetzen, mal sehn was dabei rauskommt.

    grüße

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Tsuyo“ ()

    Da stand doch was das die System Icons aus der shell32.dll holen kannst und die Icons eines Programms aus der Exe extrahieren kannst, meine ich gelesen zu haben als ichs ma schnell überflogen habe.
    Die Positionen müsste man aber auch irgendwie bekommen, kann das sein das die sogar in der Registry stehen?
    Also ich habe aufjedenfall so ein Programm was sich Icon Saver nennt, das speichert die Positionen der Icons und wenn man mal so nen Spiel oder Programm ausführt welches die Auflösung ändert und somit alle Icons wirr durcheinander würfelt kann man mit dem Icon Saver die Icons über Restore an ihre urspürngliche Position zurücksetzten.
    Also prinzipiell muss sowas möglich sein.
    Hi, also ich habs jetzt komplett in Vb Übersetzt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. ListBox1.Items.Clear()
    3. Dim vhandle As IntPtr = FindWindow("Progman", "Program Manager")
    4. vhandle = FindWindowEx(vhandle, IntPtr.Zero, "SHELLDLL_DefView", Nothing)
    5. vhandle = FindWindowEx(vhandle, IntPtr.Zero, "SysListView32", "FolderView")
    6. ' Find correct Windows
    7. Dim iconcount As Integer = SendMessage(vhandle, LVM_GETITEMCOUNT, 0, 0) 'Get all Icons
    8. Button1.Text = iconcount.ToString
    9. ' -----
    10. Dim vprocessid As UInteger = 0
    11. GetWindowThreadProcessId(vhandle, vprocessid)
    12. Dim vProcess As IntPtr = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, vprocessid)
    13. Dim vPointer As IntPtr = VirtualAllocEx(vProcess, IntPtr.Zero, 4096, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
    14. Try
    15. For i As Integer = 0 To iconcount - 1
    16. Dim Buffer As Byte() = New Byte(255) {}
    17. Dim vItem As LVITEM() = New LVITEM(0) {}
    18. vItem(0).mask = LVIF_TEXT
    19. vItem(0).iItem = i
    20. vItem(0).iSubItem = 0
    21. vItem(0).cchTextMax = Buffer.Length
    22. vItem(0).pszText = CType(CInt(vPointer) + Marshal.SizeOf(GetType(LVITEM)), IntPtr)
    23. Dim vbytesread As UInteger = 0
    24. WriteProcessMemory(vProcess, vPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0), Marshal.SizeOf(GetType(LVITEM)), vbytesread)
    25. SendMessage(vhandle, LVM_GETITEMW, i, vPointer.ToInt32)
    26. ReadProcessMemory(vProcess, CType(CInt(vPointer) + Marshal.SizeOf(GetType(LVITEM)), IntPtr) _
    27. , Marshal.UnsafeAddrOfPinnedArrayElement(Buffer, 0), Buffer.Length, vbytesread)
    28. Dim vText As String = Encoding.Unicode.GetString(Buffer, 0, CInt(vbytesread))
    29. Dim iconname As String = vText
    30. SendMessage(vhandle, LVM_GETITEMPOSITION, i, vPointer.ToInt32())
    31. Dim vpoint As Point() = New Point(1) {}
    32. ReadProcessMemory(vProcess, vPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vpoint, 0), Marshal.SizeOf(GetType(LVITEM)), vbytesread)
    33. Dim iconlocy As Integer = vpoint(0).Y
    34. Dim iconlocx As Integer = vpoint(0).X
    35. ListBox1.Items.Add(iconname + " " + iconlocx.ToString + " " + iconlocy.ToString)
    36. Next
    37. Catch ex As Exception
    38. Finally
    39. VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE)
    40. CloseHandle(vProcess)
    41. End Try
    42. End Sub



    Die Functionen und Constanten hab ich mal nicht mit reingefügt. Ist ja nur zur veranschaulichung da.
    Das mit dem Extrahieren ha ich gelesen, jedoch dachte ich das man das direkt mit dem code machen könnte, was wohl nicht zutrifft.
    Anyway. Ich versuch jetzt mal die Positionen herauszufinden.

    Grüße
    Was den hiermit

    VB.NET-Quellcode

    1. SendMessage(vhandle, LVM_GETITEMPOSITION, i, vPointer.ToInt32())
    2. Dim vpoint As Point() = New Point(1) {}
    3. ReadProcessMemory(vProcess, vPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vpoint, 0), Marshal.SizeOf(GetType(LVITEM)), vbytesread)
    4. Dim iconlocy As Integer = vpoint(0).Y
    5. Dim iconlocx As Integer = vpoint(0).X


    Da wird doch die Position ausgelesen oder etwa nicht? Bzw. ist die Variable Leer?
    Nun ich habe es Fixen können.

    VB.NET-Quellcode

    1. Dim vText As String = Encoding.Unicode.GetString(Buffer, 0, CInt(vbytesread))
    2. SendMessage(vhandle, LVM_GETITEMPOSITION, i, vPointer.ToInt32)
    3. Dim vPoint As Point() = New Point(i) {}
    4. ReadProcessMemory(vProcess, vPointer, Marshal.UnsafeAddrOfPinnedArrayElement(vPoint, i), Marshal.SizeOf(GetType(Point)), vbytesread)
    5. Dim iconloc As String = vPoint(i).ToString
    6. Dim iconlocy As Integer = vPoint(i).Y
    7. Dim iconlocx As Integer = vPoint(i).X


    Das Problem ist (war auch bei anderen Projekten so wo ich mit Sendmessages gearbeitet hab) das wenn ich in z.b ner listbox vText und ne andere Variable mit dranhänge, das die andere Variable nicht angezeigt wird.
    Anderes Beispiel, ich nutze die Variable als Pfad. Dann wird mir gesagt das das kein richtiger Pfad ist. Wenn ich aber einer Textbox diese Variable als Text zuweise, eine zweite Variable erstelle die gleich der Textbox ist.
    Funktionierts.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Tsuyo“ ()

    Da ich momentan viel mit API mache bin ich nun doch darauf gestoßen wie du ein Screenshot NUR vom Destktop machen kannst, im prinzip war meine Idee mit PrintWindow schon richtig nur das Handle nicht, ich habe mal hier für dich einen Code

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function PrintWindow(ByVal hwnd As IntPtr, ByVal hdcBlt As IntPtr, ByVal nFlags As UInteger) As Boolean
    3. End Function
    4. <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function GetWindowRect(ByVal hwnd As IntPtr, ByRef rc As RECT) As Integer
    5. End Function
    6. <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindowEx(ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    7. End Function
    8. Public Class Screenshot
    9. Public Shared Function FromDesktop() As Bitmap
    10. Dim hwnd As IntPtr = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Progman", Nothing)
    11. Dim rc As RECT
    12. GetWindowRect(hwnd, rc)
    13. Dim bm As New Bitmap(rc.Right - rc.Left, rc.Bottom - rc.Top)
    14. Dim g As Graphics = Graphics.FromImage(bm)
    15. Dim hdc As IntPtr = g.GetHdc()
    16. PrintWindow(hwnd, hdc, 0)
    17. g.ReleaseHdc(hdc)
    18. g.Flush()
    19. g.Dispose()
    20. Return bm
    21. End Function
    22. <StructLayout(LayoutKind.Sequential)> _
    23. Public Structure RECT
    24. Public Left As Integer
    25. Public Top As Integer
    26. Public Right As Integer
    27. Public Bottom As Integer
    28. End Structure
    29. End Class


    Edit: Ich hatte die RECT Structure vergessen gehabt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Dodo“ ()

    Wow!
    Super, vielen Dank.
    Ich hatte mir schon zwar ne Lösung gesucht, aber das macht mich baff :D
    Ich hab nämlich über Sendmessages jedes Icon vom Desktop abgesucht, und dann mit Gdi Poistioniert.
    das es soo einfach geht. Woah.
    Danke!
    wenn du direkt speicherst ist das was anderes, wie wenn du es nur bis in den Speicher kopierst(auf die Platte kannst du es dann in einem extra Thread speichern...)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Selbst dann. Was ich erreichen möchte, ist ein DirectX Handle zu bekommen. Video oder InGame.
    Dann möchte ich die Farbe ausrechnen die am meißten genutzt wird, und dann die Farbe meiner Tastatur ändern. Aber da geht mein Programm schon fast in die Hose.
    Nicht wegen dem ausrechnen, das alleinige in den Speicher kopieren dauert fast ne Halbe Sec. Dann kommt noch das ausrechnen dazu usw.