Computer Science Canada

Double Buffering in VB6

Author:  CodeMonkey2000 [ Tue Sep 11, 2007 4:01 pm ]
Post subject:  Double Buffering in VB6

Is there any way of getting rid of the screen flicker? Also is there a way to take a screen shot of your VB form (similar to turing's pic.new)?

Author:  CodeMonkey2000 [ Thu Sep 13, 2007 2:58 pm ]
Post subject:  RE:Double Buffering in VB6

No suggestions? Sad

Author:  Nick [ Thu Sep 13, 2007 3:03 pm ]
Post subject:  RE:Double Buffering in VB6

no idea did u try using the search feature or looking at some tuturials?

Author:  cpu_hacker4.0 [ Tue Oct 09, 2007 7:17 pm ]
Post subject:  Re: Double Buffering in VB6

yeah ive always wondered about double buffering in vb

Author:  CodeMonkey2000 [ Tue Oct 09, 2007 7:27 pm ]
Post subject:  RE:Double Buffering in VB6

Apparently you can't, not in VB6 anyway.

Author:  Euphoracle [ Tue Oct 09, 2007 11:22 pm ]
Post subject:  RE:Double Buffering in VB6

DoubleBuffering is just drawing to an offscreen image and then drawing that image to the screen at one time, so it's not drawing bit-by-bit, but instead as a whole. I KNOW this is possible because I friend made a "3D" 2D tunnel in VB6 and sent it to me. It's just not given to you like in .Net (You can set Control.DoubleBuffered, which just wraps an offscreen image and sends that to paint instead of the plain Graphics object).

Here, I did it in Java (because that's what I'm learning for school) to demonstrate how it can be done manually.

Java:
/*
 * Drawable Base Frame :D
 * */


// Imports
import java.awt.*;

// Application
class DrawableFrame2D extends Frame
{
   
    // Buffers, fixes flickering
    private Graphics gBuffer;
    private Image iBuffer;
   
    // Defaults
    private final Point DEFAULT_POS = new Point( 200, 200 );
    private final Point DEFAULT_SIZE = new Point( 640, 480 );
    private final Color DEFAULT_BACK_COLOR = Color.WHITE;
   
    public static void main( String[] arg )
    {
       
        // DrawableFrame2D App = new DrawableFrame2D( "Drawable Base Test!", true );
       
    }
   
    public DrawableFrame2D( String title, boolean max )
    {
       
        // Title bar
        setUndecorated( true );
       
        // Perform the form init requirements
        setTitle( title );
        setVisible( true );
       
        // Size based on maximized
        if ( max )
        {
           
            // Get the current resolution
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            setBounds( 0, 0, screenSize.width, screenSize.height - 20 );
           
        }
        else
            setBounds( DEFAULT_POS.x, DEFAULT_POS.y, DEFAULT_SIZE.x, DEFAULT_SIZE.y );
       
        setBackground( DEFAULT_BACK_COLOR );
       
        // Stuff we don't mess with
        setLocationRelativeTo( null );
       
    }
   
    // Fixes the flicker bug, I hope :)
    public void update( Graphics g )
    {
       
        // Recreate our buffers
        if ( iBuffer == null )
            iBuffer = createImage( getSize( ).width, getSize( ).height );
       
        gBuffer = iBuffer.getGraphics( );
       
        // Call paint with our buffer
        paint( gBuffer );
       
        // Paint our buffer
        g.drawImage( iBuffer, 0, 0, this );
       
        // Kill us, so we can be recreated later
        gBuffer.dispose( );
       
    }
   
}


As you can see, this is a very crude example that bases itself off a Panel. paint is an abstract method that is forced to be call. Essentially, all you'd have to do is make a class based on Form, override update to use your doublebuffer, call the base, just to make sure you didn't forget anything, and then draw your image, unless, of course, you can't do any of that in VB6 (the way I described it) in which case: ( X _ x )

Find your equivalent VB6 classes, and code away :V

Author:  Brightguy [ Sat Oct 13, 2007 7:03 pm ]
Post subject:  Re: Double Buffering in VB6

Well how about that, I never knew "Double Buffering" had a name... but here's an example of how to do it in classic VB, just change the filename variable to point to a picture.

VisualBASIC:
Option Explicit

Private Const filename = "C:\picture.jpg"
Private backDC As Long, picDC As Long, picInfo As BITMAP

Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetObject Lib "gdi32.dll" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, ByRef lpObject As Any) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long

Private Type BITMAP
    bmType As Long
    bmWidth As Long
    bmHeight As Long
    bmWidthBytes As Long
    bmPlanes As Integer
    bmBitsPixel As Integer
    bmBits As Long
End Type

Private Sub Form_Load()
    'Damn twips
    Me.ScaleMode = vbPixels

    'Load the picture into the device context and retrieve info
    picDC = CreateCompatibleDC(GetDC(0))
    SelectObject picDC, LoadPicture(filename)
    GetObject LoadPicture(filename), Len(picInfo), picInfo
   
    'Create device context for the background
    backDC = CreateCompatibleDC(GetDC(0))
End Sub

Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    'Draw picture on background
    BitBlt backDC, X - Int(picInfo.bmWidth / 2), Y - Int(picInfo.bmHeight / 2), picInfo.bmWidth, picInfo.bmHeight, picDC, 0, 0, vbSrcCopy
    Form_Paint
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Button > 0 Then
        'Draw picture on background
        BitBlt backDC, X - Int(picInfo.bmWidth / 2), Y - Int(picInfo.bmHeight / 2), picInfo.bmWidth, picInfo.bmHeight, picDC, 0, 0, vbSrcCopy
        Form_Paint
    End If
End Sub

Private Sub Form_Paint()
    'Draw background on form
    BitBlt Me.hdc, 0, 0, Me.ScaleWidth, Me.ScaleHeight, backDC, 0, 0, vbSrcCopy
End Sub

Private Sub Form_Resize()
    'Create bitmap of proper size for the background
    Dim backBitmap As Long
    backBitmap = CreateCompatibleBitmap(GetDC(0), Me.ScaleWidth, Me.ScaleHeight)
    SelectObject backDC, backBitmap
    DeleteObject backBitmap
   
    'Draw picture in the middle of background
    BitBlt backDC, Int((Me.ScaleWidth - picInfo.bmWidth) / 2), Int((Me.ScaleHeight - picInfo.bmHeight) / 2), picInfo.bmWidth, picInfo.bmHeight, picDC, 0, 0, vbSrcCopy
    Form_Paint
End Sub

Private Sub Form_Unload(Cancel As Integer)
    'Cleanup memory
    DeleteDC backDC
    DeleteDC picDC
End Sub

Author:  CodeMonkey2000 [ Sat Oct 13, 2007 8:21 pm ]
Post subject:  RE:Double Buffering in VB6

Wow thanks Brightguy. What's gdi32? Is that like SDL? Can I use SDL instead?

Author:  rdrake [ Sat Oct 13, 2007 8:28 pm ]
Post subject:  Re: RE:Double Buffering in VB6

CodeMonkey2000 @ Sat Oct 13, 2007 8:21 pm wrote:
Wow thanks Brightguy. What's gdi32? Is that like SDL? Can I use SDL instead?
Graphical Device Interface. It's used by Windows to draw graphics on the monitor and to output graphics to printers and such.

Author:  CodeMonkey2000 [ Sat Oct 13, 2007 9:17 pm ]
Post subject:  RE:Double Buffering in VB6

Why doesn't this work?

VisualBASIC:

Option Explicit
Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, lpPoint As Any) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreatePen Lib "gdi32" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
Dim redPen As Long
Dim mousePress As Boolean
Private Sub Form_Load()
   redPen = CreatePen(0, 15, vbRed)
   DeleteObject SelectObject(hdc, redPen)
   mousePress = False
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
   If Button > 1 And Not mousePress Then
      MoveToEx hdc, X, Y, 0
      LineTo hdc, X, Y
   ElseIf Button > 1 And mousePress Then
      LineTo hdc, X, Y
   Else
      mousePress = False
   End If
   Refresh
End Sub

Author:  Brightguy [ Sun Oct 14, 2007 1:43 am ]
Post subject:  Re: Double Buffering in VB6

A few things:

-Make sure ScaleMode is in pixels
-Don't use Refresh unless AutoRedraw is true
-Button > 1 doesn't recognize left clicks
-mousePress will never be true

Author:  CodeMonkey2000 [ Sun Oct 14, 2007 7:35 am ]
Post subject:  Re: Double Buffering in VB6

Thanks. For those interested, here is a decent reference for gdi32 commands.


: