PART4: ファイルの入出力 その1
(2002年3月24日)
今回はプログラムを作る上で基本的な処理の1つでもある、ファイルの入出力について調べてゆきたいと思います。
いきなりVB.NETでファイルを読んでみろ!といわれてもどこから手をつけてゆけば良いのかわかりませんので、まずはVB6にて簡単なテキストファイルビューワを作成してこれをアップグレードウィザードを使用しVB.NET用に変換した結果をみてみましょう。
今回の簡単な仕様です。
1.メインフォームにテキストボックスを全面配置。
2.スタートアップ時にD:\TEST.TXTを1行づつ読み込み、フォーム上のテキストへと内容を追加してゆきます。
3.フォームはサイズ変更可能とします。
ではVB6にて上記仕様のプログラムを作成してみましょう。
Option Explicit
Private Sub Form_Load()
Dim intFNo As Integer
Dim strBuf As String
Text1.Top = 0
Text1.Left = 0
Text1.Text = ""
intFNo = FreeFile
Open "D:\TEST.TXT" For Input As intFNo
Do While Not EOF(intFNo)
Line Input #intFNo, strBuf
Text1.Text = Text1.Text & Format$(strBuf,"00") & "行目" & vbCrLf
Loop
Close intFNo
End Sub
Private Sub Form_Resize()
Text1.Height = Me.ScaleHeight
Text1.Width = Me.ScaleWidth
End Sub
|
テキストボックスのプロパティの値に関してはMultiLineプロパティ以外すべてForm_Loadイベントにて設定しました。
多少の書き方の違いはあるとは思いますが、だいたいよく似たコーディングをされると思います。
それではこのプロジェクトを保存してください。保存が完了したら、VB6は閉じてください。
いよいよVB.NETの出番です。
先ほど保存したプロジェクト(VBP)をファイルメニュー→開く→プロジェクトから開いてみましょう。
このようなアップグレードウィザードが自動的に開かれます。
画面の指示に従い、ウィザードを進めてゆくとVB6で作成されたプロジェクトがVB.NETのプロジェクトへと変換された後、プロジェクトとして読み込まれます。
以下が変換後のForm1のコードです。
Option Strict Off
Option Explicit On
Friend Class Form1
Inherits System.Windows.Forms.Form
#Region "Windows Form デザイナによって生成されたコード"
Public Sub New()
MyBase.New()
If m_vb6FormDefInstance Is Nothing Then
If m_InitializingDefInstance Then
m_vb6FormDefInstance = Me
Else
Try
'スタートアップ フォームについては、最初に作成されたインスタンスが既定インスタンスになります。
If System.Reflection.Assembly.GetExecutingAssembly.EntryPoint.DeclaringType Is Me.GetType Then
m_vb6FormDefInstance = Me
End If
Catch
End Try
End If
End If
'この呼び出しは、Windows Form デザイナで必要です。
InitializeComponent()
End Sub
'Form は、コンポーネント一覧に後処理を実行するために dispose をオーバーライドします。
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
'Windows Fom デザイナで必要です。
Private components As System.ComponentModel.Container
Public ToolTip1 As System.Windows.Forms.ToolTip
Public WithEvents Text1 As System.Windows.Forms.TextBox
'メモ : 以下のプロシージャは Windows Fom デザイナで必要です。
'Windows Form デザイナを使って変更できます。
'コードエディタを使って修正しないでください。
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.ToolTip1 = New System.Windows.Forms.ToolTip(components)
Me.ToolTip1.Active = True
Me.Text1 = New System.Windows.Forms.TextBox
Me.Text = "Form1"
Me.ClientSize = New System.Drawing.Size(312, 206)
Me.Location = New System.Drawing.Point(4, 30)
Me.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultLocation
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.BackColor = System.Drawing.SystemColors.Control
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable
Me.ControlBox = True
Me.Enabled = True
Me.KeyPreview = False
Me.MaximizeBox = True
Me.MinimizeBox = True
Me.Cursor = System.Windows.Forms.Cursors.Default
Me.RightToLeft = System.Windows.Forms.RightToLeft.No
Me.ShowInTaskbar = True
Me.HelpButton = False
Me.WindowState = System.Windows.Forms.FormWindowState.Normal
Me.Name = "Form1"
Me.Text1.AutoSize = False
Me.Text1.Size = New System.Drawing.Size(265, 185)
Me.Text1.Location = New System.Drawing.Point(0, 0)
Me.Text1.MultiLine = True
Me.Text1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
Me.Text1.TabIndex = 0
Me.Text1.Text = "Text1"
Me.Text1.AcceptsReturn = True
Me.Text1.TextAlign = System.Windows.Forms.HorizontalAlignment.Left
Me.Text1.BackColor = System.Drawing.SystemColors.Window
Me.Text1.CausesValidation = True
Me.Text1.Enabled = True
Me.Text1.ForeColor = System.Drawing.SystemColors.WindowText
Me.Text1.HideSelection = True
Me.Text1.ReadOnly = False
Me.Text1.Maxlength = 0
Me.Text1.Cursor = System.Windows.Forms.Cursors.IBeam
Me.Text1.RightToLeft = System.Windows.Forms.RightToLeft.No
Me.Text1.TabStop = True
Me.Text1.Visible = True
Me.Text1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
Me.Text1.Name = "Text1"
Me.Controls.Add(Text1)
End Sub
#End Region
#Region "アップグレード ウィザードのサポート コード"
Private Shared m_vb6FormDefInstance As Form1
Private Shared m_InitializingDefInstance As Boolean
Public Shared Property DefInstance() As Form1
Get
If m_vb6FormDefInstance Is Nothing OrElse m_vb6FormDefInstance.IsDisposed Then
m_InitializingDefInstance = True
m_vb6FormDefInstance = New Form1()
m_InitializingDefInstance = False
End If
DefInstance = m_vb6FormDefInstance
End Get
Set
m_vb6FormDefInstance = Value
End Set
End Property
#End Region
Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
Dim intFNo As Short
Dim strBuf As String
Text1.Top = 0
Text1.Left = 0
Text1.Text = ""
intFNo = FreeFile
FileOpen(intFNo, "D:\TEST.TXT", OpenMode.Input)
Do While Not EOF(intFNo)
strBuf = LineInput(intFNo)
Text1.Text = Text1.Text & VB6.Format(strBuf, "00") & "行目" & ControlChars.CrLf
Loop
FileClose(intFNo)
End Sub
Private Sub Form1_Resize(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Resize
Text1.Height = Me.ClientRectangle.Height
Text1.Width = Me.ClientRectangle.Width
End Sub
End Class
|
たったあれだけのVB6プロジェクトなのに、よくもまぁこんなに長くなったものです。(大半はコンポーネントの初期化コードですが)
何だかよくわからないところも多いですが、例によってそんなところは後回しで、肝心の部分に注目して進めていきます。
何はともあれ、出来上がったプロジェクトを実行してみることにします。
「う〜ん...。」
なんだかしっくりきませんね。
というか、なぜテキストボックスがクライアント領域いっぱいに表示されていないのでしょう?
Form_Resizeのコードを見てみましょう。
Text1.Height = Me.ClientRectangle.Height
Text1.Width = Me.ClientRectangle.Width
となっています。
このコードを見る限り正しく設定されていると思われますが...。
もしかして起動時にResizeイベントが発生しないのか、イベントの発生順序がまったく違うのか?
適当にブレイクポイントを設定し、プロジェクトをステップ実行して調べてみることにしましょう。
すると、InitializeComponents プロシージャ内の
Me.ClientSize =
New System.Drawing.Size(312, 206)
という行でフォームサイズが変更され、ここで Resize イベントが発生しているにもかかわらず、その後
Me.Text1.Size =
New System.Drawing.Size(265, 185)
と、Text1のSizeプロパティがセットされているためと思われます。
アップグレードウィザードも完璧ではないようです。
どうせ、ResizeイベントでText1のSizeは変更されるのですから、この行は削除しても問題ないはずです。
思い切って削除して、さぁ実行です。
今度は予想通りの見た目になりました。
このフォームリサイズ時のテキストボックスのサイズ変更ですが、実はWindows.FormsのTextBoxには新しいプロパティが実装されており、これを利用することで簡単にコンテナにフィットさせるリサイズができるようになっています。
それがDockプロパティです。
上図のプロパティウィンドウのようにDockプロパティにてコンテナにドックする位置を指定します。
真中のボタンをクリックするとDockプロパティはFillとなり、全ての面がドックすることになります。
Dockプロパティの設定ができたら、Form_Resize内のコードは不要ですのですべて削除しましょう。
次にファイル読み込みの実行部分についてVB6とVB.NETのコードをよ〜く見較べてみましょう。
一見同じように見えますが、FileOpenやLineInputといったステートメントはVB6以前にはないものです。
FileのI/Oに関して VB.NETでは FileSystemクラスにまとめられ、各ステートメントもすべてこのクラスのメソッドとして見直されました。
以前の Open ステートメントや Line Input などに比べて、ものすごく読みやすくなったと思いませんか?
しかし、さっきから気になっていたんですが、このプロジェクトで使用していたVB6互換ライブラリの関数の使用時に VB6.Format(〜
という記述でOKなのでしょうか?
PART.2を参考に記述した場合、
Compatibility.VB6.Format(〜 と記述しなければならないはずです。
実はこれ、Namespace(名前空間)の指定の仕方によります。
プロジェクト内で使用する Nemespace の指定はプロジェクトのプロパティダイアログより行います。
ソリューションエクスプローラ内のプロジェクトアイコンを右クリックし、プロパティを選択して下さい。
上図のようなダイアログが開きますので名前空間のテキストボックスにインポートするライブラリの Namespace
を入力し、インポートの追加ボタンを押します。
これで指定されたNamespaceの使用が可能になります。
(実はこれを
Microsoft.VisualBasic.Compatibility.VB6とすれば、VB6と同じような記述で関数を記述することができるのですが、互換ライブラリの関数だか何だかわけがわからなくなってしまうのでお勧めはしません。)
ここで断っておきますが、ここで指定できるインポートとはあくまでも名前空間のインポートのみでライブラリを使用する際には参照設定にて別途行う必要があります。
ひとまずはこれでプロジェクトは完成といったところですが、実は ファイルI/Oに関してはもうひとつ別の方法があります。
少々長くなってしまいましたので、その方法については次回に解説したいと思います。
今日の収穫
1.VB6のプロジェクトをVB.NETに移行する際、アップグレードウィザードにてプロジェクトを変換する必要がある。
2.アップグレードウィザードを信用してはいけない。すべてのコードの動作チェックはもちろんコントロールのレイアウトもやり直しかも?
3.Windows.FormsのTextBox等のコントロールにはコンテナとのドッキング位置を指定するDockプロパティが追加された。
4.VB.NETではNamespace(名前空間)という概念が加わった。
|