vbAccelerator - Contents of code file: DataCDWriterVB\frmDataCDCreator.vb

This file is part of the download Data CD Writer, which is described in the article Writing Data CDs.

Imports vbAccelerator.Components.ImapiWrapper
Imports System.Threading
Imports System.IO
Imports System.Windows.Forms.Design

Public Class frmDataCDCreator
    Inherits System.Windows.Forms.Form

    Private WithEvents discMaster As discMaster = Nothing
    Private jolietDiscMaster As JolietDiscMaster = Nothing
    Private cancel As Boolean = False
    Private burnInProgress As Boolean = False
    Private creator As DataCDCreator = Nothing
    Private createCDHandler As CreateCDDelegate = Nothing


#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

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

        'Add any initialization after the InitializeComponent() call
        AddHandler Application.ThreadException, AddressOf
         application_ThreadException

        Show()
        Refresh()

        '// Create the disc master object and initialse the recorder list:
        GetRecorders()

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents label1 As System.Windows.Forms.Label
    Friend WithEvents btnBrowse As System.Windows.Forms.Button
    Friend WithEvents txtFolder As System.Windows.Forms.TextBox
    Friend WithEvents lblFolder As System.Windows.Forms.Label
    Friend WithEvents chkOverwrite As System.Windows.Forms.CheckBox
    Friend WithEvents chkEjectWhenComplete As System.Windows.Forms.CheckBox
    Friend WithEvents chkSimulate As System.Windows.Forms.CheckBox
    Friend WithEvents btnBurn As System.Windows.Forms.Button
    Friend WithEvents cboRecorder As System.Windows.Forms.ComboBox
    Friend WithEvents lblRecorder As System.Windows.Forms.Label
    Friend WithEvents sbrMain As System.Windows.Forms.StatusBar
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Dim resources As System.Resources.ResourceManager = New
         System.Resources.ResourceManager(GetType(frmDataCDCreator))
        Me.label1 = New System.Windows.Forms.Label()
        Me.btnBrowse = New System.Windows.Forms.Button()
        Me.txtFolder = New System.Windows.Forms.TextBox()
        Me.lblFolder = New System.Windows.Forms.Label()
        Me.chkOverwrite = New System.Windows.Forms.CheckBox()
        Me.chkEjectWhenComplete = New System.Windows.Forms.CheckBox()
        Me.chkSimulate = New System.Windows.Forms.CheckBox()
        Me.btnBurn = New System.Windows.Forms.Button()
        Me.cboRecorder = New System.Windows.Forms.ComboBox()
        Me.lblRecorder = New System.Windows.Forms.Label()
        Me.sbrMain = New System.Windows.Forms.StatusBar()
        Me.SuspendLayout()
        '
        'label1
        '
        Me.label1.Location = New System.Drawing.Point(88, 32)
        Me.label1.Name = "label1"
        Me.label1.Size = New System.Drawing.Size(396, 44)
        Me.label1.TabIndex = 34
        Me.label1.Text = "Note: this simple demo only allows you to burn a
         single folder (and all subfolder" & _
        "s) from disc.  The IMAPI library allows you to burn any source file to
         any desti" & _
        "nation on the disc."
        '
        'btnBrowse
        '
        Me.btnBrowse.Location = New System.Drawing.Point(88, 108)
        Me.btnBrowse.Name = "btnBrowse"
        Me.btnBrowse.Size = New System.Drawing.Size(92, 24)
        Me.btnBrowse.TabIndex = 33
        Me.btnBrowse.Text = "&Browse..."
        '
        'txtFolder
        '
        Me.txtFolder.Location = New System.Drawing.Point(84, 76)
        Me.txtFolder.Name = "txtFolder"
        Me.txtFolder.Size = New System.Drawing.Size(400, 21)
        Me.txtFolder.TabIndex = 32
        Me.txtFolder.Text = ""
        '
        'lblFolder
        '
        Me.lblFolder.Font = New System.Drawing.Font("Tahoma", 8.25!,
         System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
         CType(0, Byte))
        Me.lblFolder.Location = New System.Drawing.Point(4, 80)
        Me.lblFolder.Name = "lblFolder"
        Me.lblFolder.Size = New System.Drawing.Size(76, 16)
        Me.lblFolder.TabIndex = 31
        Me.lblFolder.Text = "&Folder:"
        '
        'chkOverwrite
        '
        Me.chkOverwrite.Checked = True
        Me.chkOverwrite.CheckState = System.Windows.Forms.CheckState.Checked
        Me.chkOverwrite.FlatStyle = System.Windows.Forms.FlatStyle.System
        Me.chkOverwrite.Location = New System.Drawing.Point(184, 224)
        Me.chkOverwrite.Name = "chkOverwrite"
        Me.chkOverwrite.Size = New System.Drawing.Size(236, 16)
        Me.chkOverwrite.TabIndex = 30
        Me.chkOverwrite.Text = "&Overwrite files on CDRW disc"
        '
        'chkEjectWhenComplete
        '
        Me.chkEjectWhenComplete.Checked = True
        Me.chkEjectWhenComplete.CheckState =
         System.Windows.Forms.CheckState.Checked
        Me.chkEjectWhenComplete.FlatStyle =
         System.Windows.Forms.FlatStyle.System
        Me.chkEjectWhenComplete.Location = New System.Drawing.Point(184, 204)
        Me.chkEjectWhenComplete.Name = "chkEjectWhenComplete"
        Me.chkEjectWhenComplete.Size = New System.Drawing.Size(236, 16)
        Me.chkEjectWhenComplete.TabIndex = 29
        Me.chkEjectWhenComplete.Text = "&Eject When Complete"
        '
        'chkSimulate
        '
        Me.chkSimulate.Checked = True
        Me.chkSimulate.CheckState = System.Windows.Forms.CheckState.Checked
        Me.chkSimulate.FlatStyle = System.Windows.Forms.FlatStyle.System
        Me.chkSimulate.Location = New System.Drawing.Point(184, 184)
        Me.chkSimulate.Name = "chkSimulate"
        Me.chkSimulate.Size = New System.Drawing.Size(236, 16)
        Me.chkSimulate.TabIndex = 28
        Me.chkSimulate.Text = "&Simulate"
        '
        'btnBurn
        '
        Me.btnBurn.FlatStyle = System.Windows.Forms.FlatStyle.System
        Me.btnBurn.Location = New System.Drawing.Point(92, 184)
        Me.btnBurn.Name = "btnBurn"
        Me.btnBurn.Size = New System.Drawing.Size(88, 24)
        Me.btnBurn.TabIndex = 27
        Me.btnBurn.Text = "&Burn"
        '
        'cboRecorder
        '
        Me.cboRecorder.DropDownStyle =
         System.Windows.Forms.ComboBoxStyle.DropDownList
        Me.cboRecorder.Location = New System.Drawing.Point(88, 4)
        Me.cboRecorder.Name = "cboRecorder"
        Me.cboRecorder.Size = New System.Drawing.Size(404, 21)
        Me.cboRecorder.TabIndex = 26
        '
        'lblRecorder
        '
        Me.lblRecorder.Font = New System.Drawing.Font("Tahoma", 8.25!,
         System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
         CType(0, Byte))
        Me.lblRecorder.Location = New System.Drawing.Point(8, 8)
        Me.lblRecorder.Name = "lblRecorder"
        Me.lblRecorder.Size = New System.Drawing.Size(76, 16)
        Me.lblRecorder.TabIndex = 25
        Me.lblRecorder.Text = "&Recorder:"
        '
        'sbrMain
        '
        Me.sbrMain.Location = New System.Drawing.Point(0, 254)
        Me.sbrMain.Name = "sbrMain"
        Me.sbrMain.Size = New System.Drawing.Size(492, 20)
        Me.sbrMain.TabIndex = 24
        '
        'frmDataCDCreator
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 14)
        Me.ClientSize = New System.Drawing.Size(492, 274)
        Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.label1,
         Me.btnBrowse, Me.txtFolder, Me.lblFolder, Me.chkOverwrite,
         Me.chkEjectWhenComplete, Me.chkSimulate, Me.btnBurn, Me.cboRecorder,
         Me.lblRecorder, Me.sbrMain})
        Me.Font = New System.Drawing.Font("Tahoma", 8.25!,
         System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
         CType(0, Byte))
        Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
        Me.Name = "frmDataCDCreator"
        Me.Text = "vbAccelerator Data CD Creator"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Sub application_ThreadException(ByVal sender As Object, ByVal e As
     ThreadExceptionEventArgs)
        MessageBox.Show(Me, String.Format("An untrapped exception occurred:
         {0}.  The application will now close.", e.Exception), _
             Text, MessageBoxButtons.OK, MessageBoxIcon.Error)
        Close()
    End Sub


    Protected Overrides Sub OnClosing(ByVal e As
     System.ComponentModel.CancelEventArgs)

        '// Don't close if burn in progress
        If (burnInProgress) Then
            e.Cancel = True
         MessageBox.Show(Me, "A CD burn is currently in progress.  Cancel the
          burn before closing this application.",  _
               Text, MessageBoxButtons.OK, MessageBoxIcon.Information)
            Exit Sub
        End If

        '// Clear up:
        MyBase.OnClosing(e)
        Cursor.Current = Cursors.WaitCursor
        sbrMain.Text = "Closing IMAPI interface..."
        jolietDiscMaster.Dispose()
        discMaster.Dispose()
        Cursor.Current = Cursors.Default

    End Sub

    Private Sub GetRecorders()
        Dim ex As Exception
        Try
            discMaster = New DiscMaster()
            jolietDiscMaster = discMaster.JolietDiscMaster()
            Dim recorder As DiscRecorder
            For Each recorder In discMaster.DiscRecorders
                cboRecorder.Items.Add( _
                 New ComboRecorderWrapper(recorder))
            Next

            If (cboRecorder.Items.Count > 0) Then
                cboRecorder.SelectedIndex = 0
            End If
        Catch ex
            MessageBox.Show(Me, String.Format("Unable to initialise the IMAPI
             library {0}", ex), _
              Text, MessageBoxButtons.OK, MessageBoxIcon.Stop)
            If Not (discMaster Is Nothing) Then
                discMaster.Dispose()
            End If
        End Try
    End Sub




    Private Sub discMaster_AddProgress(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.ProgressEventArgs) Handles
     discMaster.AddProgress
        sbrMain.Text = String.Format("Adding {0} of {1}", args.Completed,
         args.Total)
    End Sub

    Private Sub discMaster_BlockProgress(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.ProgressEventArgs) Handles
     discMaster.BlockProgress
        sbrMain.Text = String.Format("Block {0} of {1}", args.Completed,
         args.Total)
    End Sub

    Private Sub discMaster_BurnComplete(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.CompletionStatusEventArgs) Handles
     discMaster.BurnComplete
        sbrMain.Text = String.Format("Burn Complete!")
    End Sub

    Private Sub discMaster_ClosingDisc(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.EstimatedTimeOperationEventArgs)
     Handles discMaster.ClosingDisc
        sbrMain.Text = String.Format("Closing disc (estimated time {0}s)...", _
            args.EstimatedSeconds)
    End Sub

    Private Sub discMaster_EraseComplete(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.CompletionStatusEventArgs) Handles
     discMaster.EraseComplete
        sbrMain.Text = String.Format("Erase Complete!")
    End Sub

    Private Sub discMaster_PnPActivity(ByVal sender As Object, ByVal e As
     System.EventArgs) Handles discMaster.PnPActivity

    End Sub

    Private Sub discMaster_PreparingBurn(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.EstimatedTimeOperationEventArgs)
     Handles discMaster.PreparingBurn
        sbrMain.Text = String.Format("Preparing to burn disc (estimated time
         {0}s)...", _
         args.EstimatedSeconds)
    End Sub

    Private Sub discMaster_QueryCancel(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.QueryCancelEventArgs) Handles
     discMaster.QueryCancel
        args.Cancel = cancel
    End Sub

    Private Sub discMaster_TrackProgress(ByVal sender As Object, ByVal args As
     vbAccelerator.Components.ImapiWrapper.ProgressEventArgs) Handles
     discMaster.TrackProgress
        If (args.Completed < args.Total) Then
            sbrMain.Text = String.Format("Track {0} of {1}", args.Completed +
             1, args.Total)
        Else
            sbrMain.Text = String.Format("Completed adding last track")
        End If
    End Sub

    Private Sub cboRecorder_SelectedIndexChanged(ByVal sender As Object, ByVal
     e As System.EventArgs) Handles cboRecorder.SelectedIndexChanged
        If (cboRecorder.SelectedIndex > -1) Then
            Dim wrapper As ComboRecorderWrapper = cboRecorder.SelectedItem
            discMaster.DiscRecorders.ActiveDiscRecorder = wrapper.DiscRecorder
        End If
    End Sub

    Private Sub btnBurn_Click(ByVal sender As Object, ByVal e As
     System.EventArgs) Handles btnBurn.Click
        If (burnInProgress) Then
            cancel = True
        Else
            BurnCd(chkSimulate.Checked, chkEjectWhenComplete.Checked,
             chkOverwrite.Checked)
        End If
    End Sub

    Private Function ValidateFolder() As Boolean
        Dim folder As String = txtFolder.Text
        If (Directory.Exists(folder)) Then
            Return True
        Else
            MessageBox.Show(Me, "Please choose a valid folder on the file
             system to copy from.", _
              Text, MessageBoxButtons.OK, MessageBoxIcon.Information)
            Return False
        End If
    End Function

    '/// <summary>
    '/// Burns the CD asynchronously
    '/// </summary>
    '/// <param name="simulate"><c>true</c> to simulate, <c>false</c> to really
     burn</param>
    '/// <param name="ejectWhenComplete"><c>true</c> if the tray should be
     ejected once
    '/// burn has finished.</param>
    '/// <param name="overwrite"><c>true</c> to overwrite existing files on the
     disc.</param>
    Private Sub BurnCd(ByVal simulate As Boolean, ByVal ejectWhenComplete As
     Boolean, ByVal overwrite As Boolean)
        '// If the folder is good
        If (ValidateFolder()) Then
            '// Check that we have media:
            If (CheckMedia()) Then
                '// Asynchronously invoke the creator
                creator = New DataCDCreator(discMaster, jolietDiscMaster)
                creator.AddDirectory(txtFolder.Text, True)

                createCDHandler = AddressOf creator.CreateCD
                Dim callback As AsyncCallback = AddressOf createCD_Complete
                Dim ar As IAsyncResult = createCDHandler.BeginInvoke( _
                    simulate, ejectWhenComplete, overwrite, callback, Nothing)

                SetApplicationMode(True)

            End If
        End If
    End Sub

    '/// <summary>
    '/// Called when CD creation completes
    '/// </summary>
    '/// <param name="ar">Result of method call (none)</param>
    Private Sub createCD_Complete(ByVal ar As IAsyncResult)
        SetApplicationMode(False)
        createCDHandler.EndInvoke(ar)
    End Sub

    '/// <summary>
    '/// Sets the application's mode
    '/// </summary>
    '/// <param name="burning"><c>true</c> if a burn is in progress</param>
    Private Sub SetApplicationMode(ByVal burning As Boolean)
        If (burning) Then
            burnInProgress = True
            cancel = False
            btnBurn.Text = "Cancel"

            cboRecorder.Enabled = False
        Else
            burnInProgress = False
            btnBurn.Text = "&Burn"

            cboRecorder.Enabled = True
        End If
    End Sub

    '/// <summary>
    '/// Checks the media in the drive.
    '/// </summary>
    '/// <returns></returns>
    Private Function CheckMedia() As Boolean
        Dim mediaOk As Boolean = False

        sbrMain.Text = "Checking media in recorder..."
        Cursor.Current = Cursors.WaitCursor
        Dim recorder As DiscRecorder = cboRecorder.SelectedItem.DiscRecorder
        recorder.OpenExclusive()
        Dim media As MediaDetails = recorder.GetMediaDetails()
        recorder.CloseExclusive()

        Cursor.Current = Cursors.Default
        If (media.MediaPresent) Then
            If ((media.MediaFlags And MEDIA_FLAGS.MEDIA_WRITABLE) =
             MEDIA_FLAGS.MEDIA_WRITABLE) Then
                sbrMain.Text = "Preparing to burn CD."
                mediaOk = True
            Else
                sbrMain.Text = "Media cannot be written to."
                MessageBox.Show(Me, _
                 String.Format("The disc in drive {0} ({1}) is either not blank
                  or cannot be written to.", recorder.DriveLetter,
                  recorder.PnPID), _
                 Text, MessageBoxButtons.OK, MessageBoxIcon.Information)

            End If
        Else
            sbrMain.Text = "No media in drive."
            MessageBox.Show(Me, _
             String.Format("Please insert blank, writable media into drive {0}
              ({1})", recorder.DriveLetter, recorder.PnPID), _
             Text, MessageBoxButtons.OK, MessageBoxIcon.Information)

        End If
        Return mediaOk
    End Function


    Private Sub btnBrowse_Click(ByVal sender As Object, ByVal e As
     System.EventArgs) Handles btnBrowse.Click
        '
        '''TODO
        '
    End Sub

    '/// <summary>
    '/// Slight class to wrap a DiscRecorder allowing it to be associated
    '/// with a combo box.
    '/// </summary>
    Class ComboRecorderWrapper
        Private ReadOnly recorder As DiscRecorder

        Public Sub New(ByVal recorderParam As DiscRecorder)
            recorder = recorderParam
        End Sub

        Public ReadOnly Property DiscRecorder() As DiscRecorder
            Get
                Return recorder
            End Get
        End Property

        Public Overrides Function ToString() As String
            Return String.Format("{0} ({1} {2} {3})", _
              recorder.DriveLetter, recorder.Vendor, recorder.Product,
               recorder.Revision)
        End Function
    End Class

End Class