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)
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
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
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
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