Question GetDIBits & SetDIBits

bigfoot3d

Well-known member
Joined
Mar 11, 2007
Messages
56
Location
New Orleans, LA
Programming Experience
3-5
So I am trying to capture a screen and use GetDIBits to get the bytes of the screen capture for a network transfer. On the other side the bytes will be received and processed by SetDIBits for further processing.

Well maybe you can tell me what I am doing wrong here. The GetDIBits returns a result of 1050 which is the height of my screen. However SetDIBits returns 0 every time. What am I doing wrong?

Thanks!

VB.NET:
        'Bitblt to compare and get differences.
        BitBlt(IncompDC3, 0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, _
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, OrigScreen, 0, 0, &HCC0020)
        BitBlt(IncompDC3, 0, 0, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, _
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, IncompDC2, 0, 0, &H660046)
        
        CompDC3 = CreateCompatibleDC(IncompDC3)
        FW3 = GetDeviceCaps(IncompDC3, 8)
        FH3 = GetDeviceCaps(IncompDC3, 10)
        CompBMP3 = CreateCompatibleBitmap(IncompDC3, FW3, FH3)
        hBMPOld3 = SelectObject(CompDC3, CompBMP3)
        BitBlt(CompDC3, 0, 0, FW3, FH3, IncompDC3, 0, 0, &HCC0020)
        NewBMP3 = SelectObject(CompDC3, hBMPOld3)
        'See the result, is this what I want?
        PictureBox4.Image = Image.FromHbitmap(NewBMP3)

        Dim bi24BitInfo As New BITMAPINFO
        With bi24BitInfo.bmiHeader
            .biSize = 40 'System.Runtime.InteropServices.Marshal.SizeOf(GetType(BITMAPINFO))
            .biBitCount = 24
            .biCompression = 0 ' BI_RGB
            .biPlanes = 1
            .biWidth = FW3
            .biHeight = FH3
            .biXPelsPerMeter = 0
            .biYPelsPerMeter = 0
            .biSizeImage = FW3 * FH3 * 3
            .biClrUsed = 0
            .biClrImportant = 0
        End With

        Dim textureImg(FW3 * FH3 * 3 - 1) As Byte

        Dim gch As GCHandle = GCHandle.Alloc(textureImg, GCHandleType.Pinned)

        'Get the bits of the memory.
        Dim result As Integer = GetDIBits(IncompDC3, NewBMP3, 0, FH3, gch.AddrOfPinnedObject, bi24BitInfo, 0)
        ' Result should be > 0
        MsgBox("GetDIBits Result: " + result.ToString)
        'Testing without GCHandle
        'Dim result As Integer = GetDIBits(IncompDC3, NewBMP3, 0, FH3, textureImg, bi24BitInfo, 0)

        gch.Free()

        Dim filewriter As New System.IO.FileStream("C:\RemoteHandImages\imagetxtinfo.txt", IO.FileMode.Create)
        filewriter.Write(textureImg, 0, textureImg.Length)
        filewriter.Flush()
        filewriter.Close()

        'Setup new variables as if it was on the receiving computer of a network stream.
        Dim FW4, FH4, CompDC4, CompBMP4, hBMPOld4, NewBMP4 As Integer
        Dim IncompDC4 As Integer
        Dim Screen4 As Graphics
        Screen4 = Graphics.FromImage(New System.Drawing.Bitmap(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, _
 System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))
        IncompDC4 = Screen4.GetHdc
        CompBMP4 = CreateCompatibleBitmap(IncompDC4, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, _
 System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height)
        CompDC4 = CreateCompatibleDC(IncompDC4)
        
        Dim gch2 As GCHandle = GCHandle.Alloc(textureImg, GCHandleType.Pinned)

        result = SetDIBits(IncompDC4, CompBMP4, 0, bi24BitInfo.bmiHeader.biHeight, gch2.AddrOfPinnedObject, bi24BitInfo, 0)
        'Testing without GCHandle
        'SetDIBits(IncompDC4, NewBMP4, 0, bi24BitInfo.bmiHeader.biHeight, textureImg, bi24BitInfo, 0)
        'Result should be > 0 !  For some reason here is always now 0
        MsgBox("SetDIBits Result: " + result.ToString)

        gch2.Free()
        CompDC4 = CreateCompatibleDC(IncompDC4)
        FW4 = GetDeviceCaps(IncompDC4, 8)
        FH4 = GetDeviceCaps(IncompDC4, 10)
        CompBMP4 = CreateCompatibleBitmap(IncompDC4, FW4, FH4)
        hBMPOld4 = SelectObject(CompDC4, CompBMP4)
        BitBlt(CompDC4, 0, 0, FW4, FH4, IncompDC4, 0, 0, &HCC0020)
        NewBMP4 = SelectObject(CompDC4, hBMPOld4)

        'Save image to see if it worked
        Image.FromHbitmap(NewBMP4).Save("C:\RemoteHandImages\hmm69.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg)
        
        'Image saved for comparison.
PictureBox4.Image.Save("C:\RemoteHandImages\hmm3.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg)
        Screen3.Dispose()

If any more clarification is needed, please let me know!

Thanks for your help in advance!
 
Here is the entire class if this will help anyone spot my error with why SetDIBits continues to return a value of 0 meaning it fails.

Please excuse the lack of comments. This is the first time I am playing with GetDIBits and SetDIBits, so I opened an application to just play around with the methods and to see if I can get it working. Once I figure it out, I will put it into my other application where everything will be commented and this application will simply be discarded.

VB.NET:
Imports System.Runtime.InteropServices

Public Class Form11
    Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, _
ByVal lpOutput As String, ByVal lpInitData As String) As Integer
    Private Declare Function CreateCompatibleDC Lib "GDI32" (ByVal hDC As Integer) As Integer
    Private Declare Function GetDeviceCaps Lib "gdi32" Alias "GetDeviceCaps" (ByVal hdc As Integer, ByVal nIndex As Integer) As Integer
    Private Declare Function CreateCompatibleBitmap Lib "GDI32" (ByVal hDC As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer) As Integer
    Private Declare Function SelectObject Lib "GDI32" (ByVal hDC As Integer, ByVal hObject As Integer) As Integer
    Private Declare Function BitBlt Lib "GDI32" (ByVal deshDC As Integer, ByVal desX As Integer, ByVal desY As Integer, ByVal desW As Integer, _
ByVal desH As Integer, ByVal srchDC As Integer, ByVal srcX As Integer, ByVal srcY As Integer, ByVal op As Integer) As Integer
    Const SRCCOPY = &HCC0020    ' (DWORD) dest = source
    Const SRCINVERT = &H660046  ' (DWORD) dest = source XOR dest

    Public Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Integer, _
   ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, _
   ByVal nHeight As Integer, ByVal hSrcDC As Integer, ByVal xSrc As Integer, _
   ByVal ySrc As Integer, ByVal nSrcWidth As Integer, _
   ByVal nSrcHeight As Integer, ByVal dwRop As Integer) As Integer

    Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Integer, _
                                        ByVal hBitmap As Integer, _
                                        ByVal nStartScan As Integer, _
                                        ByVal nNumScans As Integer, _
                                        ByVal lpBits As Integer, _
                                        ByRef lpBI As BITMAPINFO, _
                                        ByVal wUsage As Integer) _
                                        As Integer

    Private Declare Function CreateDIBSection Lib "GDI32" (ByVal hdc As Integer, ByRef pbmi As BITMAPINFO, ByVal iUsage As Integer, _
ByRef ppvBits As Integer, ByVal hSection As Integer, ByVal dwOffset As Integer) As Integer

    Private Declare Function SetDIBits Lib "GDI32.dll" (ByVal hDC As Integer, _
    ByVal hBitmap As Integer, ByVal nStartScan As Integer, ByVal nNumScans As Integer, _
    ByRef lpBits As Integer, ByRef lpBI As BITMAPINFO, ByVal wUsage As Integer) As Integer


    Public Structure RGBTRIPLE
        Public rgbBlue As Byte
        Public rgbGreen As Byte
        Public rgbRed As Byte
    End Structure

    'Public Structure BITMAP
    '    Public biStructure As Integer
    '    Public biWidth As Integer
    '    Public biHeight As Integer
    '    Public biWidthBytes As Integer
    '    Public biPlanes As Short
    '    Public biBitsPixel As Short
    '    'Public biBits As IntPtr
    'End Structure

    Public Structure BITMAPINFOHEADER
        Public biSize As Integer
        Public biWidth As Integer
        Public biHeight As Integer
        Public biPlanes As Short
        Public biBitCount As Short
        Public biCompression As Integer
        Public biSizeImage As Integer
        Public biXPelsPerMeter As Integer
        Public biYPelsPerMeter As Integer
        Public biClrUsed As Integer
        Public biClrImportant As Integer
    End Structure

    Public Structure BITMAPINFO
        Public bmiHeader As BITMAPINFOHEADER
        Public bmColors() As RGBTRIPLE
    End Structure

    Public Const DIB_RGB_COLORS As Integer = 0


    Dim FW2, FH2, IncompDC2, CompDC2, CompBMP2, hBMPOld2, NewBMP2 As Integer

    Private Sub Form11_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        IncompDC2 = CreateDC("DISPLAY", "", "", "")
        CompDC2 = CreateCompatibleDC(IncompDC2)
        FW2 = GetDeviceCaps(IncompDC2, 8)
        FH2 = GetDeviceCaps(IncompDC2, 10)
        CompBMP2 = CreateCompatibleBitmap(IncompDC2, FW2, FH2)
        hBMPOld2 = SelectObject(CompDC2, CompBMP2)
        BitBlt(CompDC2, 0, 0, FW2, FH2, IncompDC2, 0, 0, &HCC0020)
        NewBMP2 = SelectObject(CompDC2, hBMPOld2)
        'PictureBox4.Image = Image.FromHbitmap(NewBMP2)

        Dim bi24BitInfo As New BITMAPINFO
        With bi24BitInfo.bmiHeader
            .biSize = 40 'System.Runtime.InteropServices.Marshal.SizeOf(GetType(BITMAPINFO))
            .biBitCount = 24
            .biCompression = 0 ' BI_RGB
            .biPlanes = 1
            .biWidth = FW2
            .biHeight = FH2
            .biXPelsPerMeter = 0
            .biYPelsPerMeter = 0
            .biSizeImage = FW2 * FH2 * 3
            .biClrUsed = 0
            .biClrImportant = 0
        End With

        Dim textureImg(FW2 * FH2 * 3 - 1) As Byte

        Dim gch As GCHandle = GCHandle.Alloc(textureImg, GCHandleType.Pinned)
        Dim result As Integer = GetDIBits(IncompDC2, NewBMP2, 0, FH2, gch.AddrOfPinnedObject, bi24BitInfo, 0)
        MsgBox("GetDIBits Result: " + result.ToString)
        gch.Free()

        Dim FW4, FH4, CompDC4, CompBMP4, hBMPOld4, NewBMP4 As Integer
        Dim IncompDC4 As Integer
        Dim Screen4 As Graphics
        Screen4 = Graphics.FromImage(New System.Drawing.Bitmap(FW2, FH2))
        IncompDC4 = Screen4.GetHdc
        CompBMP4 = CreateCompatibleBitmap(IncompDC4, FW2, FH2)
        CompDC4 = CreateCompatibleDC(IncompDC4)
        hBMPOld4 = SelectObject(CompDC4, CompBMP4)
        BitBlt(CompDC4, 0, 0, FW2, FH2, IncompDC4, 0, 0, &HCC0020)
        NewBMP4 = SelectObject(CompDC4, hBMPOld4)

        Dim gch2 As GCHandle = GCHandle.Alloc(textureImg, GCHandleType.Pinned)
        result = SetDIBits(IncompDC4, NewBMP4, 0, FH2, gch2.AddrOfPinnedObject, bi24BitInfo, 0)
        MsgBox("SetDIBits Result: " + result.ToString)
        gch2.Free()

        CompDC4 = CreateCompatibleDC(IncompDC4)
        FW4 = GetDeviceCaps(IncompDC4, 8)
        FH4 = GetDeviceCaps(IncompDC4, 10)
        CompBMP4 = CreateCompatibleBitmap(IncompDC4, FW4, FH4)
        hBMPOld4 = SelectObject(CompDC4, CompBMP4)
        BitBlt(CompDC4, 0, 0, FW4, FH4, IncompDC4, 0, 0, &HCC0020)
        NewBMP4 = SelectObject(CompDC4, hBMPOld4)

        Image.FromHbitmap(NewBMP4).Save("C:\RemoteHandImages\hmm69.jpeg", System.Drawing.Imaging.ImageFormat.Jpeg)
    End Sub
End Class
 
Last edited:
Back
Top