Click here to Skip to main content
11,414,561 members (69,884 online)
Click here to Skip to main content
Add your own
alternative version

Mole II for WPF

, , , 31 Dec 2007 CPOL
Introduces the second version of a very useful and educational debugger visualizer for WPF developers.
mole_visualizer_2_1_1_packages.zip
Mole_Visualizer_2_1_1_VS2008_SourceAndTestProject.zip
Mole_Visualizer_2_1_1_VS2005_SourceAndTestProject.zip
Mole_Visualizer_2_1_1_VS2005_Release.zip
Mole_Visualizer_2_1_1_VS2008_Release.zip
mole_visualizer_2_1_1_vs2005_release.zip
Mole.Visualizer.dll
mole_visualizer_2_1_1_vs2005_sourceandtestproject.zip
Mole.Visualizer
Custom Controls
Data Source
Image Processing
Data
Debugger Visualizer
Enums Constants
Event Args
Extended Controls
Images
MoleVisualUnavailable.gif
Mole.Visualizer.csi
Mole.Visualizer.suo
Mole.Visualizer.vbproj.user
My Project
Application.myapp
Settings.settings
Settings
Visualizer UI
XSLT
Mole.TestBench
bach.jpg
Mole.TestBench.csi
Mole.TestBench.suo
My Project
Settings.settings
mole_visualizer_2_1_1_vs2008_release.zip
Mole.Visualizer.dll
mole_visualizer_2_1_1_vs2008_sourceandtestproject.zip
bach.jpg
Mole.TestBench.csi
Mole.TestBench.suo
Settings.settings
MoleVisualUnavailable.gif
Mole.Visualizer.csi
Mole.Visualizer.suo
Mole.Visualizer.vbproj.user
Application.myapp
Settings.settings
mole_visualizer_2_1_vs2005_release.zip
Mole.Visualizer.dll
mole_visualizer_2_1_vs2005_sourceandtestproject.zip
MoleVisualUnavailable.gif
Mole.Visualizer.csi
Mole.Visualizer.suo
Mole.Visualizer.vbproj.user
Application.myapp
Settings.settings
bach.jpg
Mole.TestBench.csi
Mole.TestBench.suo
Settings.settings
mole_visualizer_2_1_vs2008_release.zip
Mole.Visualizer.dll
mole_visualizer_2_1_vs2008_sourceandtestproject.zip
MoleVisualUnavailable.gif
Mole.Visualizer.csi
Mole.Visualizer.suo
Mole.Visualizer.vbproj.user
Application.myapp
Settings.settings
bach.jpg
Mole.TestBench.csi
Mole.TestBench.suo
Settings.settings
mole_visualizer_vs2005_release.zip
Mole.Visualizer.dll
mole_visualizer_vs2005_sourceandtestproject.zip
MoleVisualUnavailable.gif
Mole.Visualizer.csi
Mole.Visualizer.suo
Mole.Visualizer.vbproj.user
Application.myapp
Settings.settings
bach.jpg
Mole.TestBench.csi
Mole.TestBench.suo
Settings.settings
mole_visualizer_vs2008_release.zip
Mole.Visualizer.dll
mole_visualizer_vs2008_sourceandtestproject.zip
MoleVisualUnavailable.gif
Mole.Visualizer.csi
Mole.Visualizer.suo
Mole.Visualizer.vbproj.user
Application.myapp
Settings.settings
bach.jpg
Mole.TestBench.csi
Mole.TestBench.suo
Settings.settings
Imports System.Drawing
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Runtime.InteropServices

Public Class VisualSnapshot

#Region " Methods "

    Private Shared Function BitmapSourceToGDIImage(ByVal bitmapSource As BitmapSource) As System.Drawing.Bitmap

        Dim intWidth As Integer = bitmapSource.PixelWidth
        Dim intHeight As Integer = bitmapSource.PixelHeight
        Dim intStride As Integer = CInt(intWidth * ((bitmapSource.Format.BitsPerPixel + 7) / 8))

        'this code ensures that the stride is a multiple of 4
        'learned a lot about stride here: http://www.bobpowell.net/lockingbits.htm
        Dim intStrideFixer As Integer = intStride Mod 4

        If intStrideFixer <> 0 Then
            intStride += 4 - intStrideFixer
        End If

        Dim bits As Byte() = New Byte(intHeight * intStride - 1) {}
        bitmapSource.CopyPixels(bits, intStride, 0)

        Dim bitmap As System.Drawing.Bitmap = Nothing

        'the following optimization was suggested by DrewS http://www.codeproject.com/script/profile/whos_who.asp?id=59807
        'Mole used to have to call a C# function becuase unsafe code had to be called.
        'With this code, Mole no longer requires a call to unsafe code.
        'Oh, VB.NET pointers in ACTION!
        'Thanks DrewS :-))
        Dim handle As GCHandle = GCHandle.Alloc(bits, GCHandleType.Pinned)

        Try

            Dim ptr As IntPtr = handle.AddrOfPinnedObject()
            bitmap = New System.Drawing.Bitmap(intWidth, intHeight, intStride, System.Drawing.Imaging.PixelFormat.Format32bppPArgb, ptr)

        Catch ex As Exception

            'this is our insurance policy
            ' if we get here, function will return Nothing which is OK
        Finally
            handle.Free()
        End Try

        Return bitmap

    End Function

    Private Shared Function CaptureVisual(ByVal target As Visual, ByVal intHeight As Integer, ByVal intWidth As Integer) As BitmapSource

        'learned a lot from this article
        'http://www.wiredprairie.us/downloads/GhostCursor.cs.txt
        Dim objRenderBitmap As New RenderTargetBitmap(intWidth, intHeight, 96, 96, PixelFormats.Pbgra32)
        Dim dv As New DrawingVisual()
        Using ctx As DrawingContext = dv.RenderOpen()
            ctx.DrawRectangle(New VisualBrush(target), Nothing, New Rect(New System.Windows.Point(), VisualTreeHelper.GetDescendantBounds(target).Size))
        End Using
        objRenderBitmap.Render(dv)
        Return objRenderBitmap

    End Function

    Public Shared Function TakeSnapshot(ByVal target As Object) As System.Drawing.Bitmap

        Dim objBitmap As System.Drawing.Bitmap = Nothing

        If TypeOf target Is BitmapSource Then
            'Convert.BitmapSourceToGDIImage is a function in the C# project Mole.ImageConverter
            'this is required to be C# since it makes an Unsafe call
            objBitmap = BitmapSourceToGDIImage(DirectCast(target, BitmapSource))

        ElseIf TypeOf target Is FrameworkElement Then

            Dim fe As FrameworkElement = DirectCast(target, FrameworkElement)

            'I know it looks strange, but a visual can have a height of 100 and a width of .4
            If 0 < fe.ActualHeight AndAlso 0 < fe.ActualWidth AndAlso TypeOf target Is Visual Then

                'so, if the visual has a width of .4, casting to an integer will result in size of 0
                'meaning, we won't see anything, so lets fudge so we can at least see one pixel
                'Math.Ceiling can't blow up here because we have checked the values above to ensure that they are numbers.
                Dim intHeight As Integer = CType(Math.Ceiling(fe.ActualHeight), Integer)

                'same as width
                Dim intWidth As Integer = CType(Math.Ceiling(fe.ActualWidth), Integer)
                'Convert.BitmapSourceToGDIImage is a function in the C# project Mole.ImageConverter
                'this is required to be C# since it makes an Unsafe call
                objBitmap = BitmapSourceToGDIImage(CaptureVisual(DirectCast(target, Visual), intHeight, intWidth))
            End If

        End If

        If objBitmap Is Nothing Then
            'if the above code did not create the image, then return the unavailable image from project resources
            'this typically occurs when the target has either an ActualHeight of 0 or an ActualWidth of 0
            objBitmap = New System.Drawing.Bitmap(My.Resources.MoleVisualUnavailable)
            Return objBitmap

        Else
            'this is required to prevent memory corruption
            Using objBitmap
                Return New System.Drawing.Bitmap(objBitmap)
            End Using
        End If

    End Function

#End Region

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Authors

Andrew Smith
Architect Infragistics, Inc.
United States United States
Andrew currently works as an architect for Infragistics working with windows forms and WPF. You can check out his blog here.

Josh Smith
Software Developer (Senior) Cynergy Systems
United States United States
Josh creates software, for iOS and Windows.

He works at Cynergy Systems as a Senior Experience Developer.

Read his iOS Programming for .NET Developers[^] book to learn how to write iPhone and iPad apps by leveraging your existing .NET skills.

Use his Master WPF[^] app on your iPhone to sharpen your WPF skills on the go.

Check out his Advanced MVVM[^] book.

Visit his WPF blog[^] or stop by his iOS blog[^].
Follow on   Twitter

Karl Shifflett
Architect Gayle Manufacturing Company
United States United States
Karl loves .NET, WPF, WCF, ASP.NET, VB.NET and C#.

Awards:

  • December 2008 VB.NET Code Project Article Award
  • 2009 Code Project MVP
  • 2008 Code Project MVP
  • 2008 Microsoft MVP - Client App Dev
  • December 2007 VB.NET Code Project Article Award
  • Gold Medal Winner at IBM's 1998 PROIV Programming Contest in Las Vegas
Click here to check out my Blog

Click here to learn about Mole 2010 debugging tool for Visual Studio 2010

Click here to read about XAML Power Toys

Just a grain of sand on the worlds beaches.

Follow on   Twitter

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150427.4 | Last Updated 31 Dec 2007
Article Copyright 2007 by Andrew Smith, Josh Smith, Karl Shifflett
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid