我有一个运行良好的代码。但我想传递默认参数,以防ByRef没有使用Optional。。。。。。请忽略这些乱七八糟的评论,因为很多都是不正确的,甚至是不相关的。我下一步要做评论了=]
Private Function openInBrowse(ByRef bgwargs As bgwargs)
' Example I want to do: Optional ByRef bgwargs As bgwargs = ?????
这是没有学员的整个课程。
Imports System
Imports System.IO
Imports System.Xml
Imports iTextSharp
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports iTextSharp.text.xml
Imports System.Security
Imports System.Reflection
Imports System.Data.Odbc
Imports System.Collections.Generic
Imports System.Windows
Imports System.ComponentModel
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms
Public Class Form1
Public Sub New()
InitializeComponent()
Dim bgwargs As bgwargs = New bgwargs()
bgwargs._browserReadyState = Me.PDFWebBrowser.ReadyState
bgwargs._browserObject = Me.PDFWebBrowser
bgwargs._progressObject = Me.ProgressBar1
End Sub
Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Try
MsgBox(ListBox1.SelectedItem.ToString)
Catch ex As Exception
End Try
End Sub
Private Function BlankBrowser(ByRef bgwargs As bgwargs)
' Get argument.
'Dim args As bgwargs = New bgwargs()
' bgwargs._browserObject = Browser
If bgwargs._browserObject.IsDisposed = False Then
bgwargs._browserObject.Navigate("about:blank")
' MsgBox("after navigate")
While Not bgwargs._browserReadyState <> WebBrowserReadyState.Complete
' MsgBox("looping")
Application.DoEvents()
System.Threading.Thread.Sleep(100)
Return 1
End While
Else
' MsgBox("exiting loop")
'TODO: Create New PDF WebBrowser
Return 0
End If
' MsgBox("after end if")
Return 0
End Function
Private Function openInBrowse(Optional ByRef bgwargs As bgwargs = )
' Get argument.
'Dim args As bgwargs = New bgwargs()
' bgwargs._browserObject = Browser
' MsgBox("called")
If bgwargs._browserObject.IsDisposed = False Then
' MsgBox("not disposed")
bgwargs._browserObject.Navigate("file:\" + bgwargs._TempPDF + "#toolbar=0&navpanes=0")
' MsgBox("after navigate")
While Not bgwargs._browserReadyState <> WebBrowserReadyState.Complete
' MsgBox("while looping")
Application.DoEvents()
System.Threading.Thread.Sleep(100)
Return 1
End While
' MsgBox("not in loop")
Else
'TODO: Create New PDF WebBrowser
Return 0
End If
Return 0
End Function
Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveButton.Click
' Create the argument object.
Dim bgwargs As bgwargs = New bgwargs()
Dim location = Assembly.GetExecutingAssembly().Location
Dim appPath = Path.GetDirectoryName(location) ' C:SomeDirectory
Dim TempPDF As String = (appPath + "tmp" + ComboTemplates.SelectedItem + ".pdf")
Dim TemplatePDF As String = (appPath + "Templates" + ComboTemplates.SelectedItem + ".pdf")
Dim NewPDF As String = (appPath + "Saved Invoices" + ComboTemplates.SelectedItem + ".pdf")
Dim ComboSelected As String = ComboTemplates.SelectedItem
' args._a = 5
' args._b = 6
' Start up the BackgroundWorker1.
' ... Pass argument object to it.
bgwargs._browserReadyState = PDFWebBrowser.ReadyState
bgwargs._browserObject = PDFWebBrowser
bgwargs._progressObject = ProgressBar1
bgwargs._TempPDF = TempPDF
bgwargs._NewPDF = NewPDF
bgwargs._TemplatePDF = TemplatePDF
bgwargs._ComboSelectedItem = ComboSelected
bgwargs._appPath = appPath
' MsgBox(NewPDF, TempPDF, TemplatePDF)
' Start up the BackgroundWorker1. xmltopdf etc.
Me.BackgroundWorker1.RunWorkerAsync(bgwargs)
' Dim arg As Object = bgwargs._TempPDF(4)
'Me.BackgroundWorker1_DoWork(arg, ).RunWorkerAsync(bgwargs)
'MsgBox(PDFWebBrowser.Url.AbsolutePath)
End Sub
' Private Sub createNode(ByVal fName As String, ByVal lName As String, ByVal writer As XmlTextWriter)
Private Sub createNode(ByVal writer As XmlTextWriter)
'Global Declarations
Dim colList As New List(Of String)
Dim rowList As New List(Of String)
' Dim appLocation = Assembly.GetExecutingAssembly().Location
' Dim appPath = Path.GetDirectoryName(appLocation) ' C:SomeDirectory
' GetDataTable()
If Me.DataGridView.Columns.Count > 0 Then
For i As Integer = 0 To Me.DataGridView.Columns.Count - 1
' Dim dataColumn_1 As New DataColumn(DataGridView.Columns(i).HeaderText.ToString(), GetType(String))
' dataTable.Columns.Add(dataColumn_1)
'Now Add some row to newly created dataTable
' Dim ivalue As String = i
' MsgBox("ivalue: " + ivalue)
' MsgBox(Me.DataGridView.Columns(i).HeaderText)
Console.WriteLine("Simulating PDF Write...")
Dim colText As String = Me.DataGridView.Columns(i).HeaderText
Console.WriteLine("Writing Parent...")
Console.WriteLine(colText)
writer.WriteStartElement(colText)
For r As Integer = 0 To Me.DataGridView.Rows.Count - 1
' Dim rvalue As String = i
' MsgBox("rvalue: " + rvalue)
' MsgBox(Me.DataGridView.Rows(r).Cells(i).Value)
Dim rowText As String = Me.DataGridView.Rows(r).Cells(i).Value
Console.WriteLine("Writing Child...")
Console.WriteLine(rowText)
writer.WriteString(rowText)
Console.WriteLine("Writing End Element...")
writer.WriteEndElement()
rowList.Add(rowText)
r = r + 1
Next r
Next i
End If
' Console.WriteLine("Simulating PDF Write...")
' For Each col As String In colList
' Console.WriteLine("Writing Parent...")
'Console.WriteLine(col)
' writer.WriteStartElement(col)
' For Each row As String In rowList
'Console.WriteLine("Writing Child...")
' Console.WriteLine(row)
' writer.WriteString(row)
' Next row
' writer.WriteEndElement()
' Next col
'''' writer.WriteStartElement("FirstName")
' writer.WriteString(fName)
'''' ' writer.WriteStartElement("LastName")
' writer.WriteString(lName)
' writer.WriteEndElement()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Global Declarations
Dim colList As New List(Of String)
Dim rowList As New List(Of String)
Dim appLocation = Assembly.GetExecutingAssembly().Location
Dim appPath = Path.GetDirectoryName(appLocation) ' C:SomeDirectory
Dim doc As XmlDocument = New XmlDocument()
'Populate Template Files ComboBox
ComboTemplates.Items.Clear()
ComboTemplates.Text = Nothing
Dim dir As New DirectoryInfo(appPath + "Templates")
' ComboTemplates.Items.Add(System.IO.Path.GetFileNameWithoutExtension(myItem))
'get all files in folder with .xml extension
Dim strFiles() As FileInfo = dir.GetFiles("*.pdf")
'for each file add to combobox
For Each pdfItem In strFiles
'ComboTemplates.Items.Add(pdfItem.ToString)
ComboTemplates.Items.Add(System.IO.Path.GetFileNameWithoutExtension(pdfItem.ToString))
Next
If ComboTemplates.Items.Count > 0 Then
ComboTemplates.SelectedIndex = 0 ' The first item has index 0 '
End If
'Load Selected Template XML in Combo Box
doc.Load(appPath + "xml" + ComboTemplates.SelectedItem + ".xml")
ListBox1.Items.Clear()
For Each node As XmlNode In doc.DocumentElement.SelectNodes("*")
' MsgBox(node.Name)
ListBox1.Items.Add(node.Name)
Next
Dim ds As New DataSet
ds.ReadXml(appPath + "xml" + ComboTemplates.SelectedItem + ".xml")
DataGridView.DataSource = ds.Tables(0)
Dim pdfTempURL As String = appPath + "Templates" + "BlankInvoice.pdf#toolbar=0&navpanes=0"
PDFWebBrowser.Navigate("about:blank")
Do Until PDFWebBrowser.ReadyState = WebBrowserReadyState.Complete
Application.DoEvents()
System.Threading.Thread.Sleep(100)
Loop
PDFWebBrowser.Navigate(pdfTempURL)
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim location = Assembly.GetExecutingAssembly().Location
Dim appPath = Path.GetDirectoryName(location) ' C:SomeDirectory
'Populate Template Files ComboBox
ComboTemplates.Items.Clear()
ComboTemplates.Text = Nothing
Dim dir As New DirectoryInfo(appPath + "Templates")
' ComboTemplates.Items.Add(System.IO.Path.GetFileNameWithoutExtension(myItem))
'get all files in folder with .xml extension
Dim strFiles() As FileInfo = dir.GetFiles("*.pdf")
'for each file add to combobox
For Each pdfItem In strFiles
'ComboTemplates.Items.Add(pdfItem.ToString)
ComboTemplates.Items.Add(System.IO.Path.GetFileNameWithoutExtension(pdfItem.ToString))
Next
If ComboTemplates.Items.Count > 0 Then
ComboTemplates.SelectedIndex = 0 ' The first item has index 0 '
End If
'Load First Template in Combo Box
Dim doc As New XmlDocument()
doc.Load(appPath + "xml" + ComboTemplates.SelectedItem + ".xml")
For Each node As XmlNode In doc.DocumentElement.SelectNodes("*")
' MsgBox(node.Name)
ListBox1.Items.Add(node.Name)
Next
Dim ds As New DataSet
ds.ReadXml(appPath + "xml" + ComboTemplates.SelectedItem + ".xml")
Me.DataGridView.DataSource = ds.Tables(0)
Dim pdfTempURL As String = appPath + "Templates" + "BlankInvoice.pdf#toolbar=0&navpanes=0"
Me.PDFWebBrowser.Navigate(pdfTempURL)
End Sub
' Navigates to the given URL if it is valid.
Private Sub Navigate(ByVal address As String)
If String.IsNullOrEmpty(address) Then Return
If address.Equals("about:blank") Then Return
If Not address.StartsWith("http://") And _
Not address.StartsWith("https://") Then
address = "http://" & address
End If
Try
PDFWebBrowser.Navigate(New Uri(address))
Catch ex As System.UriFormatException
Return
End Try
End Sub
Private Function ShellExecute(ByVal File As String) As Boolean
Dim myProcess As New Process
myProcess.StartInfo.FileName = File
myProcess.StartInfo.UseShellExecute = True
myProcess.StartInfo.RedirectStandardOutput = False
myProcess.Start()
myProcess.Dispose()
Return True
End Function
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _
ByVal bgwargs As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
Dim bw As BackgroundWorker = New BackgroundWorker()
' Do not access the form's BackgroundWorker reference directly.
' Instead, use the reference provided by the sender parameter.
' Dim bw As BackgroundWorker = New CType(sender, BackgroundWorker)
' Extract the argument.
Dim arg As bgwargs = bgwargs.Argument
bgwargs.Result() = {arg._browserObject, arg._browserReadyState, arg._progressObject, arg._TempPDF, arg._NewPDF, arg._TemplatePDF, arg._ComboSelectedItem, arg._appPath}
SavePDF(bw, arg)
' If the operation was canceled by the user,
' set the DoWorkEventArgs.Cancel property to true.
If bw.CancellationPending Then
bgwargs.Cancel = True
End If
End Sub
' This event handler demonstrates how to interpret
' the outcome of the asynchronous operation implemented
' in the DoWork event handler.
Private Sub backgroundWorker1_RunWorkerCompleted( _
ByVal sender As Object, ByVal bgwargsEvents As RunWorkerCompletedEventArgs) _
Handles BackgroundWorker1.RunWorkerCompleted
If bgwargsEvents.Cancelled Then
' The user canceled the operation.
MessageBox.Show("Operation was canceled")
ElseIf (bgwargsEvents.Error IsNot Nothing) Then
' There was an error during the operation.
Dim msg As String = String.Format("An error occurred: {0}", bgwargsEvents.Error.Message)
MessageBox.Show(msg)
Else
' The operation completed normally.
' Dim msg As String = String.Format("Result = {0}", bgwargsEvents.Result)
' Called when the BackgroundWorker is completed.
Dim TempPDF As Object = bgwargsEvents.Result(5)
openInBrowser(bgwargsEvents.Result)
SetSaveButton(True)
End If
End Sub
Private Sub SavePDF(ByVal bw As BackgroundWorker, ByRef bgwargs As bgwargs)
' Do some time-consuming work on this thread.
' Dim bgwargs As bgwargs = New bgwargs()
' bgwargs = args
SetSaveButton(False)
' Me.PDFWebBrowser.Hide()
' Me.PDFWebBrowser.dis()
BlankBrowser(bgwargs)
' MsgBox(bgwargs._browserReadyState)
Do Until bgwargs._browserReadyState <> WebBrowserReadyState.Complete
Application.DoEvents()
System.Threading.Thread.Sleep(100)
Loop
' MsgBox(bgwargs._browserReadyState)
Dim colList As New List(Of String)
Dim rowList As New List(Of String)
' Get argument.
' Dim args As ArgumentType = New ArgumentType()
' args._browserObject = PDFWebBrowser
'args._progressObject = ProgressBar1
'DO MORE WORK
' Dim pdfTemp As String = appPath + "Templates" + "BlankInvoice.pdf" ' ---> It's the original pdf form you want to fill
' Dim newFile As String = appPath + "Saved Invoices" + "NewInvoice.pdf" ' ---> It will generate new pdf that you have filled from your program
Dim xmlForm As String = bgwargs._appPath + "xml" + bgwargs._ComboSelectedItem + ".xml"
' Dim tempPDF As String = bgwargs._TempPDF
SetProgress_instanceSafe(0, 100)
Try
'Write the XML XFA File
Dim writer As New XmlTextWriter(xmlForm, System.Text.Encoding.UTF8)
writer.WriteStartDocument(True)
writer.Formatting = Formatting.Indented
writer.Indentation = 2
writer.WriteStartElement("form1")
' createNode(tBoxFirstname.Text, tBoxLastname.Text, writer)
createNode(writer)
writer.WriteEndDocument()
writer.Close()
'Use the XML File and Create the PDF Fillables
Dim pdfReader As New PdfReader(bgwargs._TemplatePDF)
Dim pdfStamper As New PdfStamper(pdfReader, New FileStream(
bgwargs._NewPDF, FileMode.Create))
Dim D As Integer
Dim len As Long = pdfReader.EofPos - 1
' MsgBox(len)
' MsgBox(pdfReader.FileLength)
' ProgressBar1.Minimum = 0
' ProgressBar1.Maximum = 100
Do Until len >= bgwargs._NewPDF.Length
' MsgBox(newFile.Length)
D = bgwargs._NewPDF.Length / len * 50
' ProgressBar1.Value = D
SetProgress_instanceSafe(D - 1, 50)
Loop
pdfStamper.AcroFields.Xfa.FillXfaForm(xmlForm)
pdfStamper.FormFlattening = False
pdfStamper.Close()
pdfReader.Close()
' Try
BlankBrowser(bgwargs)
While Not bgwargs._browserReadyState <> WebBrowserReadyState.Complete
' MsgBox(e.Result.ToString() + " 4th")
'
Application.DoEvents()
System.Threading.Thread.Sleep(100)
End While
' MsgBox("File Open 1?:" + IsFileOpen(bgwargs._NewPDF, bgwargs).ToString())
' MsgBox("2? File Open 2?:" + IsFileOpen(bgwargs._TempPDF, bgwargs).ToString())
Do While (IsFileOpen(bgwargs._NewPDF, bgwargs) = False AndAlso IsFileOpen(bgwargs._TempPDF, bgwargs) = False)
' MsgBox("b4 copy")
Console.WriteLine("Attempting to copy file...")
BeginCopy(Path.Combine(bgwargs._NewPDF), Path.Combine(bgwargs._TempPDF), bgwargs)
' Will overwrite if the destination file already exists.
' MsgBox("after copy")
Loop
'MsgBox("after copy file while loop")
Catch ex As IOException
MsgBox("File write Error!" + Environment.NewLine + bgwargs._NewPDF)
End Try
Dim Message As String = "File Saved to: " + Environment.NewLine + bgwargs._NewPDF + Environment.NewLine + Environment.NewLine + "Open the file Now?"
Dim Caption As String = "Invoice Save Complete"
Dim Buttons As MessageBoxButtons = MessageBoxButtons.YesNo
Dim Result As DialogResult
'Displays the MessageBox
Result = MessageBox.Show(Message, Caption, Buttons)
' Gets the result of the MessageBox display.
If Result = System.Windows.Forms.DialogResult.Yes Then
Console.WriteLine("UserChose Chose YES")
' openInBrowser(bgwargs)
System.Threading.Thread.Sleep(200)
ShellExecute(bgwargs._NewPDF)
System.Threading.Thread.Sleep(100)
SetProgress_instanceSafe(0, 100)
ReportProgress(bgwargs, BackgroundWorker1)
Else
Console.WriteLine("UserChose Chose NO")
' openInBrowser(bgwargs)
' System.Threading.Thread.Sleep(100)
SetProgress_instanceSafe(0, 100)
ReportProgress(bgwargs, BackgroundWorker1)
End If
Try
Catch ex As Exception
If TypeOf ex Is Exception Then
Console.WriteLine(ex)
If PDFWebBrowser.IsDisposed = False Then
' MsgBox(e.Result.ToString() + " 3rd")
While Not bgwargs._browserReadyState <> WebBrowserReadyState.Complete
' MsgBox(e.Result.ToString() + " 4th")
'
Application.DoEvents()
System.Threading.Thread.Sleep(100)
End While
Else
'TODO: Create New PDF WebBrowser
End If
End If
End Try
End Sub
' This method demonstrates a pattern for making thread-safe
' calls on a Windows Forms control.
'
' If the calling thread is different from the thread that
' created the TextBox control, this method creates a
' SetTextCallback and calls itself asynchronously using the
' Invoke method.
'
' If the calling thread is the same as the thread that created
' the TextBox control, the Text property is set directly.
Private Sub SetText(ByVal [text] As String)
' InvokeRequired required compares the thread ID of the
' calling thread to the thread ID of the creating thread.
' If these threads are different, it returns true.
If Me.textBox1.InvokeRequired Then
Dim d As New SetTextCallback(AddressOf SetText)
Me.Invoke(d, New Object() {[text]})
Else
Me.textBox1.Text = [text]
End If
End Sub
' This method demonstrates a pattern for making thread-safe
' calls on a Windows Forms control.
'
' If the calling thread is different from the thread that
' created the TextBox control, this method creates a
' SetTextCallback and calls itself asynchronously using the
' Invoke method.
'
' If the calling thread is the same as the thread that created
' the TextBox control, the Text property is set directly.
Private Sub SetSaveButton(ByVal [enabled] As Boolean)
' InvokeRequired required compares the thread ID of the
' calling thread to the thread ID of the creating thread.
' If these threads are different, it returns true.
If Me.SaveButton.InvokeRequired Then
Dim d As New SetSaveButtonCallback(AddressOf SetSaveButton)
Me.Invoke(d, New Object() {[enabled]})
Else
Me.SaveButton.Enabled = [enabled]
End If
End Sub
Public Function SetProgress_instanceSafe(ByVal paramValue As Integer, ByVal paramMaximum As Integer) As Integer
If Me.ProgressBar1.InvokeRequired Then
Me.ProgressBar1.Invoke(New delegate_ProgressUpdate(AddressOf Me.SetProgress_instanceSafe), paramValue, paramMaximum)
Else
Me.ProgressBar1.Maximum = paramMaximum
Me.ProgressBar1.Value = paramValue
' Me.ProgressBar1.PerformStep()
Me.ProgressBar1.Update()
End If
Return paramValue
End Function
' This method models an operation that may take a long time
' to run. It can be cancelled, it can raise an exception,
' or it can exit normally and return a result. These outcomes
' are chosen randomly.
Private Function TimeConsumingOperation( _
ByVal bw As BackgroundWorker, _
ByVal sleepPeriod As Integer) As Integer
Dim result As Integer = 0
Dim rand As New Random()
While Not bw.CancellationPending
Dim [exit] As Boolean = False
Select Case rand.Next(3)
' Raise an exception.
Case 0
Throw New Exception("An error condition occurred.")
Exit While
' Sleep for the number of milliseconds
' specified by the sleepPeriod parameter.
Case 1
Thread.Sleep(sleepPeriod)
Exit While
' Exit and return normally.
Case 2
result = 23
[exit] = True
Exit While
Case Else
Exit While
End Select
If [exit] Then
Exit While
End If
End While
Return result
End Function
' <summary>
' Clean up any resources being used.
' </summary>
' <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso (components IsNot Nothing) Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub 'Dispose
'Private Sub BackgroundWorker1_ProgressChanged() Handles BackgroundWorker1.ProgressChanged
' SetProgress_instanceSafe(1, 100)
' End Sub
Function BeginCopy(ByVal Source As String, ByVal Destination As String, ByRef bgwargs As bgwargs)
' Dim bgwargs As bgwargs = New bgwargs()
' Return value based on the argument.
' args._browserObject
Dim D As Integer
SetProgress_instanceSafe(50, 100)
Try
Dim SourceF As New System.IO.FileStream(Source, System.IO.FileMode.Open)
Dim DestinationF As New System.IO.FileStream(Destination, System.IO.FileMode.Create)
Do Until IsFileOpen(Destination, bgwargs) = False
Dim len As Long = SourceF.Length
Dim buffer(1024) As Byte
Dim byteCFead As Integer
' bgwargs._progressObject.Minimum = 0
While DestinationF.Position < len
D = CInt((DestinationF.Position / len * 100) / 2)
' MsgBox(SourceF.Position)
byteCFead = (SourceF.Read(buffer, 0, 1024))
DestinationF.Write(buffer, 0, byteCFead)
' MsgBox(D)
' Me.BackgroundWorker1.ReportProgress(D)
' bgwargs._progressObject.Step = D
' MsgBox(Progress.Step)
' Progress.Value = Progress.Step
Console.WriteLine(SetProgress_instanceSafe(D, 100).ToString() + " % Before")
SetProgress_instanceSafe(50 + D, 100)
If D + D < 100 Then
'progReport(D, Me.BackgroundWorker1)
SetProgress_instanceSafe(100, 100)
' Progress.PerformStep()
'System.Threading.Thread.Sleep(100)
' End If
End If
Console.WriteLine("Copying File..." + D.ToString())
Application.DoEvents()
End While
DestinationF.Flush()
DestinationF.Close()
SourceF.Close()
System.Threading.Thread.Sleep(1000)
SetProgress_instanceSafe(100, 100)
Loop
If D + D = 100 Then
' bgwargs._progressObject.Value = 0
' SetProgress_instanceSafe(100, 100)
SetSaveButton(True)
Console.WriteLine("File Copy Success!")
' MsgBox(bgwargs._browserReadyState)
openInBrowser(bgwargs)
Else
Console.WriteLine("More than 100 Value Reurned.")
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return D
End Function
Public Function IsFileOpen(ByVal file As String, ByRef bgwargs As bgwargs) As Boolean
' Get argument.
'Dim bgwargs As bgwargs = New bgwargs()
'Dim browser As WebBrowser = bgwargs._browserObject
Try
Dim stream As New System.IO.FileStream(file, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None)
stream.Close()
Catch ex As Exception
If TypeOf ex Is System.IO.IOException Then
' do something here, either close the file if you have a handle or as a last resort terminate the process - which could cause corruption and lose data
Console.WriteLine("Sorry. File in use." + Environment.NewLine + (file) + Environment.NewLine + "Retrying...")
BlankBrowser(bgwargs)
' MsgBox(bgwargs._browserReadyState)
Do Until bgwargs._browserReadyState <> WebBrowserReadyState.Complete
Application.DoEvents()
System.Threading.Thread.Sleep(100)
' MsgBox((bgwargs._browserReadyState) + "OR" + (bgwargs._browserReadyState))
' MsgBox("loop ifo readystate")
Loop
Return True
End If
End Try
Return False
End Function
Sub ReportProgress(ByRef bgwargs As bgwargs, ByRef BackgroundWorker1 As BackgroundWorker)
BackgroundWorker1.ReportProgress(100)
End Sub
End Class
Public Class bgwargs
Public _browserReadyState As Int32
Public _browserObject As WebBrowser
Public _progressObject As ProgressBar
Public _TempPDF As String
Public _NewPDF As String
Public _TemplatePDF As String
Public _ComboSelectedItem As String
Public _appPath As String
End Class
Private Function openInBrowse(Optional ByRef bgwargs As SomeClass = Nothing)
可能的用途:
' USAGE #1: A caller who wants to supply a value.
Dim bgwargs1 As SomeClass = ...
openInBrowse(bgwargs1)
' USAGE #2: A caller who has no value to supply, but would like a modified result (if any).
Dim bgwargs2 As SomeClass = Nothing
openInBrowse(bgwargs2)
' ... use "bgwargs2", which may have been changed by `openInBrowse`.
' USAGE #3: A caller who has no value to supply, and doesn't care about the result.
openInBrowse()
拥有这个"可选ByRef"的好处是,上面的"USAGE#3"不必定义和传递一个不包含任何内容的变量,这是它不需要的。
请注意很少使用这种组合("可选"+"ByRef"),一些经验丰富的程序员认为这是一种"代码气味"
也就是说,给定"ByRef",总是强制调用方定义并传入一个变量(在这种情况下,包含"Nothing")是"更安全的",这样任何未来检查代码的人都会知道所做的是有意的。
因此,最佳实践是声明任何不带Optional
:的ByRef
' "bgwargs" is allowed to be "Nothing".
Private Function openInBrowse(ByRef bgwargs As SomeClass)
然后上面的用法#3将不会编译;这样的呼叫者将不得不改为使用#2。
为了完整性,请注意,在VB中,有一种替代方法,我不推荐,它也不涉及"可选":
Private Function openInBrowse(ByRef bgwargs As SomeClass)
' Usage when you don't have a value to pass in, and don't care about any changes to the ByRef parameter.
openInBrowse(Nothing)
也就是说,将文本传递到ByRef是合法的。VB将编译它,就好像您创建了一个临时局部变量并为其赋值(在本例中为"Nothing")一样
在一种情况下,我可能会使用"Optional ByRef"。一种大量使用的方法,用于在内部创建以前从未需要公开的对象。现在一个新调用方可以使用该对象。我不想修改所有现有的调用方,添加新参数。我当然不想"复制/粘贴/修改"——制作第二个稍微不同的方法版本——这是编程中最严重的滥用之一。因此,我将以某种方式将此对象返回给那个调用方。"Optional ByRef…=Nothing"可能是最简单的解决方案。如果是,请执行,并附上注释说明原因。
(另一种解决方案是重构公共代码。99.9%的情况下,更好的答案是花时间这样做。)