Question bitblt (GDI) Draws a Black Square

RealMT

New member
Joined
Jan 24, 2013
Messages
2
Programming Experience
3-5
Hello, I have a problem with bitblt, it draw a plain black square as described in the thread title. I haven't been able to find a problem and I hope that someone here can, thanks in advance. Below you can find my code.

Public Class frmMain
Dim recx As Integer = 0
Dim recy As Integer = 0
Dim angle As Integer = 0

Private Declare Auto Function BitBlt Lib "GDI32.DLL" (ByVal hdcDest As IntPtr, ByVal nXDest As Integer, _
ByVal nYDest As Integer, ByVal nWidth As Integer, _
ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, _
ByVal nXSrc As Integer, ByVal nYSrc As Integer, _
ByVal dwRop As Int32) As Boolean

Enum Raster As UInteger
'''dest = source
SRCCOPY = &HCC0020
'''dest = source OR dest
SRCPAINT = &HEE0086
'''dest = source AND dest
SRCAND = &H8800C6
'''dest = source XOR dest
SRCINVERT = &H660046
'''dest = source AND (NOT dest)
SRCERASE = &H440328
'''dest = (NOT source)
NOTSRCCOPY = &H330008
'''dest = (NOT src) AND (NOT dest)
NOTSRCERASE = &H1100A6
'''dest = (source AND pattern)
MERGECOPY = &HC000CA
'''dest = (NOT source) OR dest
MERGEPAINT = &HBB0226
'''dest = pattern
PATCOPY = &HF00021
'''dest = DPSnoo
PATPAINT = &HFB0A09
'''dest = pattern XOR dest
PATINVERT = &H5A0049
'''dest = (NOT dest)
DSTINVERT = &H550009
'''dest = BLACK
BLACKNESS = &H42
'''dest = WHITE
WHITENESS = &HFF0062
''' Capture window as seen on screen. This includes layered windows
''' such as WPF windows with AllowsTransparency="true"
CAPTUREBLT = &H40000000
End Enum

Private Sub frmMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
'MsgBox(e.KeyCode)
Select Case e.KeyCode
Case 37 'left
recx -= 5
Case 38 'top
recy -= 5
Case 39 'right
recx += 5
Case 40 'down
recy += 5
Case 32
angle += 1
If angle > 359 Then
angle -= 360
End If
End Select

End Sub

Private Sub frmMain_Shown(sender As Object, e As EventArgs) Handles Me.Shown
End Sub

Private Sub tmr_MainLoop_Tick(sender As Object, e As EventArgs) Handles tmr_MainLoop.Tick
Dim IMG As New Bitmap(Application.StartupPath & "\img.bmp")
Dim gIMG As Graphics = Graphics.FromImage(IMG)
Dim dcIMG As IntPtr = gIMG.GetHdc

Dim g As Graphics = Me.CreateGraphics()
Dim dcMainForm As IntPtr = g.GetHdc

BitBlt(dcMainForm, 0, 0, Me.Width, Me.Height, dcIMG, 0, 0, Raster.SRCCOPY)

'gIMG.TranslateTransform(CSng(tempIMG.Width) / 2, CSng(tempIMG.Height) / 2)
'gIMG.RotateTransform(angle)
'gIMG.TranslateTransform(-CSng(tempIMG.Width) / 2, -CSng(tempIMG.Height) / 2)

'gIMG.DrawImage(My.Resources.tankBar, 0, 0)
'g.FillRectangle(Brushes.White, 0, 0, Me.Width, Me.Height)
'g.DrawImage(IMG, New Point(recx, recy))

g.ReleaseHdc(dcMainForm)
g.Dispose()

gIMG.ReleaseHdc(dcIMG)
gIMG.Dispose()
IMG.Dispose()
End Sub


End Class
 
Ok, so the problem is quite simple, apparently you can't just simply bitblt an image that is stored in memory. In order to bitblt using a bitmap stored in memory you have to first select an object into a device context with SelectObject() API obviously if you're using this method you have to make sure that you are deleting your objects if you no longer need them using the DeleteObject() API.

Below is the code that I've used if someone else needs it

Can a moderator add [Resolved] to the title?

VB.NET:
Imports System.Threading

Public Class frmMain
    Dim recx As Integer = 0
    Dim recy As Integer = 0
    Dim angle As Integer = 0

    Private Declare Auto Function BitBlt Lib "GDI32.DLL" (ByVal hdcDest As IntPtr, ByVal nXDest As Integer, _
                                                        ByVal nYDest As Integer, ByVal nWidth As Integer, _
                                                        ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, _
                                                        ByVal nXSrc As Integer, ByVal nYSrc As Integer, _
                                                        ByVal dwRop As Int32) As Boolean

    Private Declare Function SelectObject Lib "gdi32" Alias "SelectObject" (ByVal hdc As IntPtr, ByVal hObject As IntPtr) As IntPtr
    Private Declare Function DeleteObject Lib "gdi32" Alias "DeleteObject" (ByVal hObject As IntPtr) As Integer

    Dim backBuffer As Bitmap
    Dim backBufferG As Graphics
    Dim backBufferH As IntPtr
    Dim backBufferDC As IntPtr
    Dim backBufferOBJ As IntPtr

    Dim frmWidth As Integer
    Dim frmHeight As Integer
    Dim lastFPS As Integer
    Dim currentFPS As Integer

    Enum Raster As UInteger
        SRCCOPY = &HCC0020      'dest = source
        SRCPAINT = &HEE0086     'dest = source OR dest
        SRCAND = &H8800C6       'dest = source AND dest
        SRCINVERT = &H660046    'dest = source XOR dest
        SRCERASE = &H440328     'dest = source AND (NOT dest)
        NOTSRCCOPY = &H330008   'dest = (NOT source)
        NOTSRCERASE = &H1100A6  'dest = (NOT src) AND (NOT dest)
        MERGECOPY = &HC000CA    'dest = (source AND pattern)
        MERGEPAINT = &HBB0226   'dest = (NOT source) OR dest
        PATCOPY = &HF00021      'dest = pattern
        PATPAINT = &HFB0A09     'dest = DPSnoo
        PATINVERT = &H5A0049    'dest = pattern XOR dest
        DSTINVERT = &H550009    'dest = (NOT dest)
        BLACKNESS = &H42        'dest = BLACK
        WHITENESS = &HFF0062    'dest = WHITE
        ' Capture window as seen on screen.  This includes layered windows
        ' such as WPF windows with AllowsTransparency="true"
        CAPTUREBLT = &H40000000
    End Enum

    Private Sub frmMain_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
        'MsgBox(e.KeyCode)
        Select Case e.KeyCode
            Case 37 'left
                recx -= 5
            Case 38 'top
                recy -= 5
            Case 39 'right
                recx += 5
            Case 40 'down
                recy += 5
            Case 32
                angle += 5
                If angle > 359 Then
                    angle -= 360
                End If
            Case 27
                End
        End Select
    End Sub

    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles Me.Load
        backBuffer = New Bitmap(frmWidth, frmHeight)
        backBufferG = Graphics.FromImage(backBuffer)
        backBufferDC = backBufferG.GetHdc
        backBufferH = backBuffer.GetHbitmap
        backBufferOBJ = SelectObject(backBufferDC, backBufferH)
        mainLoop()
    End Sub

    Sub Draw()
        Dim IMG As Bitmap = My.Resources.tankBar
        Dim gIMG As Graphics = Graphics.FromImage(IMG)

        Dim g As Graphics = Me.CreateGraphics()

        gIMG.TranslateTransform(CSng(IMG.Width) / 2, CSng(IMG.Height) / 2)
        gIMG.RotateTransform(angle)
        gIMG.TranslateTransform(-CSng(IMG.Width) / 2, -CSng(IMG.Height) / 2)
        gIMG.DrawImage(My.Resources.tankBar, 0, 0)

        DeleteObject(backBufferH)
        backBufferG.ReleaseHdc(backBufferDC)

        backBufferG.FillRectangle(Brushes.White, 0, 0, Me.Width, Me.Height)
        backBufferG.DrawImage(IMG, New Point(recx, recy))
        backBufferG.DrawString(lastFPS, SystemFonts.DefaultFont, Brushes.Black, New Point(50, 50))

        Dim dcMainForm As IntPtr = g.GetHdc

        backBufferDC = backBufferG.GetHdc
        backBufferH = backBuffer.GetHbitmap

        backBufferOBJ = SelectObject(backBufferDC, backBufferH)
        BitBlt(dcMainForm, 0, 0, frmWidth, frmHeight, backBufferDC, 0, 0, Raster.SRCCOPY)

        g.ReleaseHdc(dcMainForm)
        g.Dispose()
        gIMG.Dispose()
        IMG.Dispose()
    End Sub

    Sub mainLoop()
        Try
            Thread.Sleep(100)
            Dim iloop As Boolean = True
            Do While iloop = True
                Draw()
                currentFPS += 1
                Application.DoEvents()
            Loop
        Catch ex As Exception
            End
        End Try
    End Sub

    Private Sub frmMain_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged
        frmWidth = Me.Width
        frmHeight = Me.Height
    End Sub

    Private Sub tmr_MainLoop_Tick(sender As Object, e As EventArgs) Handles tmr_MainLoop.Tick
        lastFPS = currentFPS
        currentFPS = 0
        'TextBox1.Text = lastFPS
    End Sub
End Class
 
Back
Top