Drydo's Blog

Teenager of the Internet

This blog hosted by:
http://blogs.vbcity.com
  Home :: Syndication  :: Login   Community Forums   :: vbCity.com   :: DevCity.NET  

Eh up, Well, have I been busy as of late. Decorating bedrooms, mending roofs, training for the annual 100 mile cycle run and the new football season. However, oh wanderer of the internet - you do not bless my blog for pure merriment or concern about my person. Nope, you've come here for a reason - using me like some scabby medival whore.

Anyway, I digress....

Ok - this post I'm sure is going to produce an avalanche of comments - so as a precursor. This has merely been an experiment and whilst I consider myself reasonably savvy on the GDI+ side of things - DirectX (yes - Managed DirectX 9.0) is something else. The following code is based upon elements of this tutorial  on managed DirectX game in C#. However, as you probably have either a) found out or b) will find out - the number of Managed DirectX samples in VB.NET is extremely low. So - at the very least, here's something that works.

The code simply creates a DirectX surface (well, it creates two for the blitters among you) and draws a Bitmap object upon if based upon the size of the form. Its intention for me was to prove that I could use Managed DirectX as an alternative to GDI+ where the framework's drawing routine may not perform as fast as I would expect. Have fun...

Main Form Initialisation (Remember to add the Windows Generated Code)

Code Copy HideScrollFull


Public
Class frmMain
    Inherits System.Windows.Forms.Form

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        Me.Show()
        Dim DTest As New Controller(Me, New Rectangle(Me.Left, Me.Top, Me.ClientSize.Width, Me.ClientSize.Height))
    End Sub

    ' Snip

End
Class
. . .

Drawing Controller Class

Code Copy HideScrollFull
Public Class Controller

    ' Private
    Private _Target As Control
    Private _Graphics As GraphicsHandler
    Private _NativeRect As Rectangle

    ' Bitmap object to draw
    Private _TestImg As BitmapObject

    Public Sub New(ByVal RenderTarget As Control, ByVal NativeSize As Rectangle)
        Me._Target = RenderTarget

        ' Add handler for losing focus
        AddHandler Me._Target.GotFocus, AddressOf Restore

        ' Initialise a graphics handlers
        Me._Graphics = New GraphicsHandler(Me._Target)
        ' Obtain the native dimensions of the window
        Me._NativeRect = NativeSize

        ' Resize the bitmap using GDI
        Dim ImgToCopy As New Bitmap("C:\TestImage.jpg")
        Dim ImgToDraw As New Bitmap(Me._NativeRect.Width, Me._NativeRect.Height, Imaging.PixelFormat.Format32bppArgb)

        ' Resize the image
        Dim g As Graphics = Graphics.FromImage(ImgToDraw)
        g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.High
        g.DrawImage(ImgToCopy, New Rectangle(0, 0, Me._NativeRect.Width, Me._NativeRect.Height))

        ' Generate the bitmap obj and draw
        _TestImg = New BitmapObject(ImgToDraw, Me._Graphics.DDevice)
        Me._TestImg.DrawBitmap(_Graphics.RenderSurface, Me._NativeRect.X, Me._NativeRect.Y)

        ' Set main process loop (uses to copy the surfaces over)
        Me.ProcessLoop()
    End Sub

    Private Sub ProcessLoop()

        While Me._Target.Created
            If Not Me._Target.Focused Then
                System.Threading.Thread.Sleep(1000)
                Application.DoEvents()
            End If

            ' Perform the draw operation
            Me._Graphics.Flip()

            System.Threading.Thread.Sleep(100)
            Application.DoEvents()

        End While

    End Sub

    Private Sub Restore(ByVal sender As Object, ByVal e As System.EventArgs)
        ' Refresh
        Me._Graphics = New GraphicsHandler(Me._Target)
        _TestImg.RestoreSurface()
        Me._TestImg.DrawBitmap(_Graphics.RenderSurface)
    End Sub

End
Class
. . .

Graphics Handler

Code Copy HideScrollFull
Imports Microsoft.DirectX.DirectDraw
Imports
Microsoft.DirectX

Public
Class GraphicsHandler

    ' Private elements
    Private _Target As Control
    Private _GraphicsDevice As Device
    Private _GraphicsClipper As Clipper
    Private _SurfacePrimary As Surface
    Private _SurfaceSecondary As Surface

    Public ReadOnly Property DDevice() As Device
        Get
            Return Me._GraphicsDevice
        End Get
    End Property

    Public ReadOnly Property RenderSurface() As Surface
        Get
            Return Me._SurfaceSecondary
        End Get
    End Property

    Public Sub New(ByVal RenderControl As Control)
        ' Initialise
        Me._Target = RenderControl
        Me._GraphicsDevice = New Device
        Me._GraphicsDevice.SetCooperativeLevel(Me._Target, CooperativeLevelFlags.Normal)
        Me.CreateSurfaces()
    End Sub

    Private Sub CreateSurfaces()
        ' Create primary surface
        Dim desc As SurfaceDescription = New SurfaceDescription
        desc.SurfaceCaps.PrimarySurface = True
        Me._SurfacePrimary = New Surface(desc, Me._GraphicsDevice)
        ' Reconfigure for the secondary surface
        desc.Clear()
        With desc
            .Width = Me._SurfacePrimary.SurfaceDescription.Width
            .Height = Me._SurfacePrimary.SurfaceDescription.Height
            .SurfaceCaps.OffScreenPlain = True
        End With
        Me._SurfaceSecondary = New Surface(desc, Me._GraphicsDevice)

        Me._GraphicsClipper = New Clipper(Me._GraphicsDevice)
        Me._GraphicsClipper.Window = Me._Target
        Me._SurfacePrimary.Clipper = Me._GraphicsClipper

    End Sub

    Public Sub Flip()
        If Not Me._Target.Created Then
            Return
        End If

        If Me._SurfacePrimary Is Nothing Or Me._SurfaceSecondary Is Nothing Then
            Return
        End If

        Me._SurfacePrimary.Draw(Me._SurfaceSecondary, DrawFlags.Wait)

    End Sub

End
Class
. . .

Bitmap Object

Code Copy HideScrollFull
Imports Microsoft.DirectX.DirectDraw
Imports
Microsoft.DirectX

Public
Class BitmapObject

    ' Private
    Private _SourceBitmap As Bitmap
    Private _TargetDevice As Device
    Private _BitmapDim As Rectangle
    Private _SurfaceDesc As SurfaceDescription
    Private _BitmapSurface As Surface
    Private _DrawPos As Point

    Public Sub New(ByVal SourceBitmap As Bitmap, ByVal TargetDevice As Device)

        Me._SourceBitmap = SourceBitmap
        Me._TargetDevice = TargetDevice
        Me._BitmapDim = New Rectangle(0, 0, Me._SourceBitmap.Width, Me._SourceBitmap.Height)

        ' Initialise the bitmap surface
        Me.initializeSurfaceDescription()
        Me.initializeSurface()
    End Sub

    Private Sub initializeSurfaceDescription()
        _SurfaceDesc = New SurfaceDescription

        With _SurfaceDesc
            .SurfaceCaps.OffScreenPlain = True
            .Width = _BitmapDim.Width
            .Height = _BitmapDim.Height
        End With
    End Sub

    Private Sub initializeSurface()
        Me._BitmapSurface = New Surface(Me._SourceBitmap, Me._SurfaceDesc, Me._TargetDevice)
    End Sub

    Public Overloads Sub DrawBitmap(ByVal TargetSurface As Surface, ByVal TargetXPos As Integer, ByVal TargetYPos As Integer)
        ' Overloads
        _DrawPos = New Point(TargetXPos, TargetYPos)
        DrawBitmap(TargetSurface)
    End Sub

    Public Overloads Sub DrawBitmap(ByVal TargetSurface As Surface)
        ' Draw the image
        TargetSurface.DrawFast(_DrawPos.X, _DrawPos.Y, _
            Me._BitmapSurface, Me._BitmapDim, DrawFastFlags.NoColorKey Or DrawFastFlags.Wait)
    End Sub

    Public Sub RestoreSurface()
        Me.initializeSurfaceDescription()
        Me.initializeSurface()
    End Sub

End
Class
. . .

Oh yes - you'll need DirectX installed on your machine and it might be a good idea to get the DirectX 9.0 SDK for some different toilet reading.

M

posted on Friday, July 22, 2005 4:44 PM