Hilfe Beim Optimieren Von Capture image aus IntPtr Function

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Hilfe Beim Optimieren Von Capture image aus IntPtr Function

    Hallo
    Ich habe Eine Function um eine Image vom Hwnd zu Capturen.

    Diese Functioniert soweit super. Jedoch Geht der speicher innerhalb 30sec.. Auf 2Gb und dann ist klar Error.

    Nun habe ich versucht BmpRect.Dispose() Aber klappt nicht auch nicht wen ich etwas warte bevor die Bitmap Löschen will.

    Vielleicht Gibt es jemand der Den Code auch etwas Optimieren kann oder dabei helfen kann.

    Api:

    VB.NET-Quellcode

    1. Friend Const SRCCOPY As Integer = 13369376
    2. Friend Structure RECT
    3. Friend left As Int32
    4. Friend top As Int32
    5. Friend right As Int32
    6. Friend bottom As Int32
    7. End Structure
    8. Friend Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Int32
    9. Friend Declare Function GetDC Lib "user32.dll" (ByVal hWnd As IntPtr) As IntPtr
    10. Friend Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hdc As IntPtr) As IntPtr
    11. Friend Declare Function CreateCompatibleBitmap Lib "gdi32.dll" (ByVal hdc As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
    12. Friend Declare Function DeleteDC Lib "gdi32.dll" (ByVal hDc As IntPtr) As IntPtr
    13. Friend Declare Function ReleaseDC Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hDc As IntPtr) As IntPtr
    14. Friend Declare Function BitBlt Lib "gdi32.dll" (ByVal hdcDest As IntPtr, ByVal xDest As Integer, ByVal yDest As Integer, ByVal wDest As Integer, ByVal hDest As Integer, ByVal hdcSource As IntPtr, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal RasterOp As Integer) As Boolean
    15. Friend Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As IntPtr, ByVal bmp As IntPtr) As IntPtr
    16. Friend Declare Function DeleteObject Lib "gdi32.dll" (ByVal hDc As IntPtr) As IntPtr


    Function:

    VB.NET-Quellcode

    1. Public Function createBitmap(ByVal hWnd As IntPtr) As Bitmap
    2. Dim WinRect As RECT
    3. GetWindowRect(hWnd, WinRect)
    4. Dim BmpRect As Bitmap = New Bitmap(WinRect.right - WinRect.left, WinRect.bottom - WinRect.top)
    5. Dim hdcFrom As IntPtr = GetDC(hWnd)
    6. Dim hdcTo As IntPtr = CreateCompatibleDC(hdcFrom)
    7. Dim hBitmap As IntPtr = CreateCompatibleBitmap(hdcFrom, BmpRect.Width, BmpRect.Height)
    8. If hBitmap <> IntPtr.Zero Then
    9. Dim hLocalBitmap As IntPtr = SelectObject(hdcTo, hBitmap)
    10. BitBlt(hdcTo, 0, 0, BmpRect.Width, BmpRect.Height, hdcFrom, 0, 0, SRCCOPY)
    11. SelectObject(hdcTo, hLocalBitmap)
    12. DeleteDC(hdcTo)
    13. ReleaseDC(hWnd, hdcFrom)
    14. BmpRect = Image.FromHbitmap(hBitmap)
    15. DeleteObject(hBitmap)
    16. 'BmpRect.Dispose()
    17. End If
    18. Return BmpRect
    19. End Function


    Lg :)
    @seby1302 Zunächst mal sollte auch der Aufrufer / Empfänger der Bitmap die alte Bitmap disposen, bevor die neue gehandelt wird:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. If Me.PictureBox1.Image IsNot Nothing Then
    3. Me.PictureBox1.Image.Dispose()
    4. End If
    5. Me.PictureBox1.Image = createBitmap(Me.Handle)
    6. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Jap das wahr soweit schon, Problem ist das läuft in einem schnellem Timer.

    VB.NET-Quellcode

    1. Public Sub SchreenTimer_tick(sender As Object, e As EventArgs) Handles SchreenTimer.Tick
    2. If Not hWndChild7 = IntPtr.Zero Then
    3. Dim screenshot As Bitmap = createBitmap(hWndChild7)
    4. If screenshot IsNot Nothing Then
    5. PictureBox1.Image = screenshot
    6. Application.DoEvents()
    7. screenshot.Dispose()
    8. End If
    9. End If
    10. End Sub


    Das selbe Problem hatte ich bereits mit eine andre Function.

    VB.NET-Quellcode

    1. Dim WinRect As RECT
    2. ' GetWindowRect(WindowHandle, WinRect)
    3. ' Dim bmp As Bitmap = New Bitmap(WinRect.right - WinRect.left, WinRect.bottom - WinRect.top)
    4. ' Dim g As Graphics = Graphics.FromImage(bmp)
    5. ' Dim hDC As IntPtr = g.GetHdc()
    6. ' Dim pwRet As Integer = PrintWindow(WindowHandle, hDC, 0)
    7. ' g.ReleaseHdc(hDC)
    8. ' g.Flush()
    9. ' g.Dispose()


    Mit ' g.Flush()' g.Dispose() hatte ich es behoben, leider Gibt mir diesen Funktion ein schwarzes Bild bei meinem vorhaben, Funzioniert nicht bei allen Anwendungen.

    Ich habe es geschafft liegt einfach da dran das der Timer zu schnell ist und somit nicht schafft die Bmp zu löschen nun schaut das so aus..

    VB.NET-Quellcode

    1. Public Sub SchreenTimer_tick(sender As Object, e As EventArgs) Handles SchreenTimer.Tick
    2. If Not hWndChild7 = IntPtr.Zero Then
    3. If PictureBox1.Image IsNot Nothing Then
    4. PictureBox1.Image.Dispose()
    5. wait(50)
    6. End If
    7. PictureBox1.Image = createBitmap(hWndChild7)
    8. End If
    9. End Sub


    Wait Funktion.. Im gegensatz zu sleep kann die application währenddessen weitere aufgaben ausführen.

    VB.NET-Quellcode

    1. Friend Sub wait(ByVal interval As Integer)
    2. Dim sw As New Stopwatch
    3. sw.Start()
    4. Do While sw.ElapsedMilliseconds < interval
    5. Application.DoEvents()
    6. Loop
    7. sw.Stop()
    8. End Sub


    Für weitere vorschläge und verbeserungen bitte melden :)

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

    seby1302 schrieb:

    das der Timer zu schnell ist
    Dann sorge dafür, dass der Timercode erst verlassen werden muss, bevor er erneut aufgerufen werden kann: SyncLock oder einfach ein niedrigerer Takt.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    funzioniert leider nicht oder ich mache es falsch?

    'So gehts rauf und runter Jedoch immer mehr bis 2 Gb erreicht und Error

    VB.NET-Quellcode

    1. Dim field As Object = New Object
    2. If Not hWndChild7 = IntPtr.Zero Then
    3. SyncLock field
    4. If PictureBox1.Image IsNot Nothing Then
    5. PictureBox1.Image.Dispose()
    6. End If
    7. End SyncLock
    8. PictureBox1.Image = CreateBitmap(HWndChild7)



    'Und so Bleibt etwa die ersten 30sec.. constant auf 280MB dann langsam rauf auf 2Gb Error

    VB.NET-Quellcode

    1. Dim field As Object = New Object
    2. If Not hWndChild7 = IntPtr.Zero Then
    3. SyncLock field
    4. If PictureBox1.Image IsNot Nothing Then
    5. PictureBox1.Image.Dispose()
    6. End If
    7. PictureBox1.Image = CreateBitmap(HWndChild7)
    8. End SyncLock


    Habe ich auch so versucht, leider funzioniert das nur solange der control den focus hat und man da zwischen dursch was macht, minimiere ich dem oder mache ich länger nix geht der speicher sofort rauf..

    VB.NET-Quellcode

    1. If PictureBox1.Image IsNot Nothing Then
    2. SyncLock field
    3. PictureBox1.Image.Dispose()
    4. 'Wait(50)
    5. End SyncLock
    6. End If


    Nidrigere tackt ist nicht machbar, steht schon auf 200ms und das ist schon recht an der grenze.
    Mit dem Wait lief es jedoch konstant auf 280Mb auch wenn mir Bewust das es nicht correct programmiert ist.

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

    seby1302 schrieb:

    VB.NET-Quellcode

    1. Dim field As Object = New Object
    Diesed Zeile muss in der Klasse, nicht aber in der Prozedur stehen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @seby1302 Machma das SyncLock so:

    VB.NET-Quellcode

    1. SyncLock field
    2. If PictureBox1.Image IsNot Nothing Then
    3. PictureBox1.Image.Dispose()
    4. PictureBox1.Image = Nothing
    5. 'Wait(50)
    6. End If
    7. End SyncLock
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    nix zu machen..

    habe auch so versucht, das einzige das bild blinkt warscheinlich wegen PictureBox1.Image = Nothing, die speicher ist dennoch nach ca.. 30 sec voll

    VB.NET-Quellcode

    1. SyncLock field
    2. If PictureBox1.Image IsNot Nothing Then
    3. PictureBox1.Image.Dispose()
    4. PictureBox1.Image = Nothing
    5. End If
    6. End SyncLock
    7. Application.DoEvents()
    8. PictureBox1.Image = CreateBitmap(HWndChild)


    Ohne Application.DoEvents() blinkt nix aber selbe effekt speicher 30 sec voll..
    @seby1302 Ich ahne.
    Deine Routine wird so schnell hintereinander aufgerufen, dass .NET nicht hinterher kommt, den Speicher glattzuziehen.
    Da könnte ein GC.Collect() Abhilfe schaffen, aber das ist die Brecheisen-Methode.
    Beschreib mal ganz genau, was Du ühaupt erreichen willst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Diesen Fehler habe ich nun behoben, läuft ganz ohne Wait etc..

    Ich trottel hatte das noch da rein gehauen klar das nicht Funzioniert.

    VB.NET-Quellcode

    1. If Not HWndChild7 = IntPtr.Zero Then
    2. If PictureBox1Acc1.Image IsNot Nothing Then
    3. Dim MausePositionX As Double = Cursor.Position.X - Me.Location.X
    4. Dim TolleranceW As Double = HWndChield7width / PictureBox1Acc1.Width


    Jetzt auf

    VB.NET-Quellcode

    1. If Not HWndChild7 = IntPtr.Zero Then
    2. Dim MausePositionX As Double = Cursor.Position.X - Me.Location.X
    3. Dim TolleranceW As Double = HWndChield7width / PictureBox1Acc1.Width
    4. If PictureBox1Acc1.Image IsNot Nothing Then


    Mir ist bekannt das die Deklarationen in dem Timer Garnicht gut sind und in der klasse gehören aber wegen HWndChield7width muss ich erstmal abfragen ob vorhanden :/

    seby1302 schrieb:

    VB.NET-Quellcode

    1. Dim MausePositionX As Double = Cursor.Position.X - Me.Location.X
    MausePositionX kannst Du als Integer deklarieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!