Visualizzazione dei risultati da 1 a 10 su 10
  1. #1

    vb - immagine da handle

    ho letto e riletto tanto ... ma nn riesco proprio a fare ciò che voglio.
    immaginiamo che io voglia, al click del mouse, fare uno screenshot del desktop

    ecco il codice che ho scritto
    codice:
    Public Class Form1
        Private Declare Function GetDesktopWindow Lib "user32" () As Long
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            Dim intero As Long
            Dim temp as Bitmap
    
            intero = GetDesktopWindow()
    
            temp = temp = Image.FromHbitmap(intero)
    
    temp.save("c:\prova.bmp")
    
        End Sub
    End Class
    al click del mouse ottengo "errore generico gdi+" con evidenziata questa riga
    temp = temp = Image.FromHbitmap(intero)


    dove sbaglio ?

    PS: dimenticavo di dirvi che lavoro su visual studio 2005, e che sono un principiante (ma penso che si fosse capito :P )

  2. #2

    Re: vb - immagine da handle

    Al di là del fatto che
    codice:
    temp = temp = Image.FromHBitmap(intero)
    non ha un gran senso (ne avrebbe già di più se fosse
    codice:
    temp = Image.FromHBitmap(intero)
    ), devi tenere conto che stai passando ad una funzione che si aspetta un handle ad una bitmap un handle ad una finestra (due tipi di handle che rappresentano oggetti completamente differenti). Per poter fare quello che chiedi devi creare una bitmap, copiarci dentro il contenuto della finestra e quindi associare l'handle della bitmap ad un oggetto bitmap del .NET Framework. Tutto questo lavoro, se non conosci bene le GDI API di Windows, rischia di trasformarsi in un gran casino, per cui ti consiglio di usare questa classe già pronta, che fa proprio al caso tuo.
    P.S.: nel titolo bisogna indicare con precisione di che linguaggio si parla, nel tuo caso VB.NET.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    ciao,

    grazie per la risposta.

    si il codice originale era quello che hai scritto tu più sensato, ho sbagliato copiando

    ho già visto quella classe, e vorrei utilizzarla, solo che per importarla nel mio progetto dovrei creare la dll da quel file, e poi includerla nel mio progetto .. ma dopo vari tentativi nn ci sono riuscito

    se mi dici come ottenere la dll da quel file .cs e includerla nel mio progetto, a me va benissimo ugualmente

    ancora grazie

    kicko

  4. #4
    Non è necessario compilare una dll a parte, basta aggiungere quella classe al tuo progetto.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Come posso risolvere i numerosi errori che sono presenti nella classe?
    Uno dei tanti è dato sul segno di minore e mi dice è previsto un identificatore :
    codice:
      Public Shared<DllImport("gdi32.dll")>  _
             Function CreateCompatibleBitmap(hDC As IntPtr, nWidth As Integer, nHeight As Integer) As IntPtr

  6. #6
    In effetti la traduzione dal C# in VB.NET di quella classe è fatta con i piedi... be', modifica tutti i metodi che ti danno quell'errore da così:
    codice:
    Public Shared<DllImport("gdi32.dll")>  _
             Function CreateCompatibleBitmap(hDC As IntPtr, nWidth As Integer, nHeight As Integer) As IntPtr
    a così
    codice:
    <DllImport("gdi32.dll")> _
    Public Shared Function CreateCompatibleBitmap(hDC As IntPtr, nWidth As Integer, nHeight As Integer) As IntPtr
    .
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Grazie per la risposta. Ho apportato delle altre modifiche al codice perché continuava a dare errori e alla fine sono riuscito a farla funzionare! posto l'intera classe nel caso possa essere d'aiuto ad altri:
    Inserire in un file di classe nel progetto il seguente codice:
    codice:
    Imports System
    Imports System.Runtime.InteropServices
    Imports System.Drawing
    Imports System.Drawing.Imaging
    
    Namespace ScreenShotDemo
        _
        '/ <summary>
        '/ Provides functions to capture the entire screen, or a particular window, and save it to a file.
        '/ </summary>
        Public Class ScreenCapture
    
            '/ <summary>
            '/ Creates an Image object containing a screen shot of the entire desktop
            '/ </summary>
            '/ <returns></returns>
            Public Function CaptureScreen() As Image
                Return CaptureWindow(User32.GetDesktopWindow())
            End Function 'CaptureScreen
    
    
            '/ <summary>
            '/ Creates an Image object containing a screen shot of a specific window
            '/ </summary>
            '/ <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
            '/ <returns></returns>
            Public Function CaptureWindow(ByVal handle As IntPtr) As Image
                ' get te hDC of the target window
                Dim hdcSrc As IntPtr = User32.GetWindowDC(handle)
                ' get the size
                Dim windowRect As New User32.RECT()
                User32.GetWindowRect(handle, windowRect)
                Dim width As Integer = windowRect.right - windowRect.left
                Dim height As Integer = windowRect.bottom - windowRect.top
                ' create a device context we can copy to
                Dim hdcDest As IntPtr = GDI32.CreateCompatibleDC(hdcSrc)
                ' create a bitmap we can copy it to,
                ' using GetDeviceCaps to get the width/height
                Dim hBitmap As IntPtr = GDI32.CreateCompatibleBitmap(hdcSrc, width, height)
                ' select the bitmap object
                Dim hOld As IntPtr = GDI32.SelectObject(hdcDest, hBitmap)
                ' bitblt over
                GDI32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, GDI32.SRCCOPY)
                ' restore selection
                GDI32.SelectObject(hdcDest, hOld)
                ' clean up 
                GDI32.DeleteDC(hdcDest)
                User32.ReleaseDC(handle, hdcSrc)
    
                ' get a .NET image object for it
                Dim img As Image = Image.FromHbitmap(hBitmap)
                ' free up the Bitmap object
                GDI32.DeleteObject(hBitmap)
    
                Return img
            End Function 'CaptureWindow
    
    
            '/ <summary>
            '/ Captures a screen shot of a specific window, and saves it to a file
            '/ </summary>
            '/ <param name="handle"></param>
            '/ <param name="filename"></param>
            '/ <param name="format"></param>
            Public Sub CaptureWindowToFile(ByVal handle As IntPtr, ByVal filename As String, ByVal format As ImageFormat)
                Dim img As Image = CaptureWindow(handle)
                img.Save(filename, format)
            End Sub 'CaptureWindowToFile
    
    
            '/ <summary>
            '/ Captures a screen shot of the entire desktop, and saves it to a file
            '/ </summary>
            '/ <param name="filename"></param>
            '/ <param name="format"></param>
            Public Sub CaptureScreenToFile(ByVal filename As String, ByVal format As ImageFormat)
                Dim img As Image = CaptureScreen()
                img.Save(filename, format)
            End Sub 'CaptureScreenToFile
           _
    
            '/ <summary>
            '/ Helper class containing Gdi32 API functions
            '/ </summary>
            Private Class GDI32
    
                Public Shared SRCCOPY As Integer = &HCC0020
                ' BitBlt dwRop parameter
    
                <DllImport("gdi32.dll")> _
                Public Shared Function CreateCompatibleBitmap(ByVal hDC As IntPtr, ByVal nWidth As Integer, ByVal nHeight As Integer) As IntPtr
    
                End Function
    
                <DllImport("gdi32.dll")> _
                Public Shared Function BitBlt(ByVal hObject As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hObjectSource As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean
                End Function
    
                <DllImport("gdi32.dll")> _
                  Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr
                End Function
    
                <DllImport("gdi32.dll")> _
                 Public Shared Function DeleteDC(ByVal hDC As IntPtr) As Boolean
                End Function
    
                <DllImport("gdi32.dll")> _
                 Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean
                End Function
    
                <DllImport("gdi32.dll")> _
                 Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr
                End Function
    
            End Class 'GDI32
           _
    
            '/ <summary>
            '/ Helper class containing User32 API functions
            '/ </summary>
            Private Class User32
                <StructLayout(LayoutKind.Sequential)> _
                Public Structure RECT
                    Public left As Integer
                    Public top As Integer
                    Public right As Integer
                    Public bottom As Integer
                End Structure 'RECT
    
    
                <DllImport("user32.dll")> _
                Public Shared Function GetDesktopWindow() As IntPtr
                End Function
    
                <DllImport("user32.dll")> _
                Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
                End Function
    
                <DllImport("user32.dll")> _
                Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As IntPtr
                End Function
    
                <DllImport("user32.dll")> _
                Public Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef rect As RECT) As IntPtr
                End Function
    
            End Class 'User32
        End Class 'ScreenCapture 
    End Namespace 'ScreenShotDemo
    Un esempio dell'utilizzo della classe è:
    codice:
     Dim sc As New ScreenCapture()
     sc.CaptureScreenToFile("C:\temp2.gif", Imaging.ImageFormat.gif)
    Ps. cosa strana è che anche AspAlliance traduce il codice C# della classe originale nel codice Vb.Net che mi dava tanti errori. Sarà che anche la classe in c# abbia errori?
    Ciao e grazie tante a MItaly.

  8. #8
    Originariamente inviato da mardok30
    Ps. cosa strana è che anche AspAlliance traduce il codice C# della classe originale nel codice Vb.Net che mi dava tanti errori. Sarà che anche la classe in c# abbia errori?
    Non mi pare... ci ho dato un'occhiata e mi pare in ordine... anche perché, se fosse stata bacata sia la versione in VB.NET che quella in C# come avrebbero potuto collaudare quel codice? Probabilmente anche loro l'hanno tradotta con un traduttore automatico, che non ha fatto un buon lavoro con gli attributi.
    Ciao e grazie tante a MItaly.
    Ciao; alla prossima!
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    grazie a tutti dell'aiuto.

    ora la mia necessità però sarebbe salvare lo screen di una finestra (e nel particolare quella di google earth)

    per fare ciò ho scritto questo

    codice:
    Public Class Form1
    
        Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    
    
        Private Function GetWindowHandle(ByVal ps_WindowTitle As String) As Long
            GetWindowHandle = FindWindow(vbNullString, ps_WindowTitle)
        End Function
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
            Dim gea As ApplicationGE
    
            Dim sc As New ScreenCapture()
    
            gea = CreateObject("GoogleEarth.ApplicationGE")
    
            Dim lon As Long = GetWindowHandle("Google Earth")
    
            sc.CaptureWindowToFile(lon, "c:\poba.gif", Imaging.ImageFormat.Gif)
    
    
            MessageBox.Show("ok")
    
        End Sub
    
    
    End Class
    solo che ottengo "overflow di un operazione aritmetica in questa riga
    sc.CaptureWindowToFile(lon, "c:\poba.gif", Imaging.ImageFormat.Gif)

    penso che sia dovuto al fatto che l'handle che passo io nn è quello che la classe deve ricevere :P
    non ho tanto chiaro questo discorso, se mi aiutate a risolvere il problema e a capire concettualmente la differenza ve ne sarei molto grato (magari con qualche link dove vi siano chiarimenti ..)

    ancora grazie a tutti dell'aiuto

    kicko

  10. #10
    Prima regola con VB.NET: non riciclare mai le dichiarazioni delle API di VB6, perché i tipi di dati non corrispondono.
    codice:
    Byte (Bit)   VB6          VB.NET
    1 (8)        Byte         Byte (System.Byte)
    2 (16)       Integer      Short (System.Int16)
    4 (32)       Long         Integer (System.Int32)
    8 (64)       n.d.         Long (System.Int64)
    Tuttavia la dimensione in bit di molti tipi di handle (quelli di finestra compresi) varia a seconda della piattaforma, ossia è di 32 bit sotto Windows a 32 bit (e quindi corrisponderebbe ad un Integer di VB.NET) ed è di 64 bit sotto Windows a 64 bit (e quindi corrisponderebbe ad un Long di VB.NET). Per ovviare a questo problema è stata inventata la struttura System.IntPtr (INTeger PoinTeR, puntatore intero), le cui dimensioni variano correttamente a seconda della piattaforma su cui il codice IL viene jit-compilato (in effetti il suo unico campo privato, m_value, è un puntatore a void, che ha il genere di comportamento desiderato). Pertanto lavorando con gli handle si tende ad utilizzare tale struttura al posto dei normali tipi di dati Integer o Long.
    Ecco il codice corretto:
    codice:
    Private Declare Auto Function FindWindow Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    
    
        Private Function GetWindowHandle(ByVal ps_WindowTitle As String) As IntPtr
            Return FindWindow(vbNullString, ps_WindowTitle)
        End Function
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
            Dim gea As ApplicationGE
    
            Dim sc As New ScreenCapture()
    
            gea = CreateObject("GoogleEarth.ApplicationGE")
    
            Dim hwnd As IntPtr = GetWindowHandle("Google Earth")
    
            sc.CaptureWindowToFile(hwnd, "c:\poba.gif", Imaging.ImageFormat.Gif)
    
    
            MessageBox.Show("ok")
    
        End Sub
    
    
    End Class
    .
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.