VB6→VB2005アップグレード (VB:Microsoft Visual Basic)

はじめに

 ここでは、VB6によるソースプログラムをVB2005にアップグレードする方法について書く。

 VB6とVB2005はかなり違うという印象が強い。言語仕様は似ているが同じではない。が、言語仕様の違いはあまり問題にならないだろう。慣れやサンプルソースで解決できるから。むしろ大きいのは、画面に貼り付けたりして使う各種オブジェクトの違いだろう。つまりオブジェクトの名称も、Property、Method、Eventもかなり変わった。例えば、LabelコントロールのCaptionプロパティはTextプロパティに変わった、など。しかし、これは機械的に変更できる部分であまり気にする必要は無い。それでも新規にコーディング(プログラムを記述)する場合は、あのプロパティはどう表記するのだったか、と慣れないうちは苦労するだろう。

 VB6からVB2005に書き換えるに当たって最も面倒なのは、従来の(VB6の)仕組みに1対1に対応しない部分だ。例えば、File I/Oはかなり変わった。これについては従来型に近い記述も出来るが、この際.NetFrameworkのやり方に書き換える事を勧める。(従来の記述に近い書き方でも、Microsoft.VisuaiBasic.Open()関数を使うという具合に、記述を変える必要はある。)

 次に、Graphic Displayの部分は完全に書き換える必要がある。これも大きな変更点だ。Lineメソッドは無くなり、色の定義なども従来の記述とかなり変わった。そもそもFormに線を引くのでなく、Form上にGraphicオブジェクトを定義してそこに線を引くという風だ。その代わりポリゴン塗り潰しMethodなど、VB6に無かった機能が多く用意されている。(.NetFrameworkの機能。)

 また従来、VB6に無い機能を実現するためWinAPIを使っていた場合、これは全面的に.NetFrameworkに書き換える方が良いだろう。.NetFrameworkに無いような特殊な機能をAPIでやっている場合はちょっと分からない。(この場合はVB6のままの方が良いかもしれない。)できるだけ.NetFrameworkにある機能に置き換え、WinAPIは使わない方が良いように思う。

 以上、断片的にVB2005に切り替える場合の基本的考え方を記した。
 次に、実際のアップグレードに当たってのやり方について記す。

 次に記す方法は一つのやり方で、他にもやり方はあると思う。が筆者は、次の方法が最も確実で、精神的負担が小さいと思っている。最短時間で済むかどうかは不明だが、精神的負担が少ないという事は重要な事と考える。


VB6→VB2005アップグレード手順

1.VB6で動く完全なプロジェクトを一式別フォルダにCopyする
  つまり.vbpファイル以下全て。これは次に記す予備更新を行う為である。
  予備更新を行った場合、VB6ソースとしては使用不能になるから。

2.VB2005になるソース保管の為、フォルダを2つ作って置く
  VB2005のアップグレード操作の途中で問われるので、そこで答えるため。
  普通、保存フォルダは1つで足りるが、VB6ソースの内容によっては2つ必要
  になる場合もある。

3.VB6の.frmファイルに前もって下記◆の変更を加えて置く
  これは普通、VB6の開発環境で行うが、直接Editorで行っても良い。
  アプリケーションとして機能しなくなるが、中途段階だから構わない。
  これを実施せずに、アップグレード後にすぐVB2005でコンパイルすると、
  膨大なエラーメッセージが出るので、これを避ける為の予備更新である。
  形式的にVB6でコンパイルエラー出ない様にして置く方が、後の操作は楽である。

 ---------------------------------------------------------------------
 [予備更新]:VB6ソース上で前もってやって置く

 ◆ReDim:VB2005では次元の数は変えられない:個別の対策が必要
      Dim aTb() As .. , bTb(,) As .. と必要あれば先に区別要す。
  他に、 ReDim配列を下位Subに引数で渡す時:ReDim定義を厳密にすべき。

 ◆Dim配列:VB2005ではBaseは必ず0から:変更する
  0 は不使用でも良い。が、0 から使うよう関連全て変更するのも良い。

 ◆コントロール配列:VB2005に無い:個別の対策が必要
  該当のコントロール名を全て変え、配列番号を未定義にする。
  元ProcedureをSubとし、Index相当の変数を引数で渡すなど考えられる。

 ◆KeyPress、GotFocusは、VB2005に無いEventだから、着想を変える必要ある。

 ◆固定長文字列:VB2005に無く可変長になる
  どうしても固定長にしたい場合、VBFixedStringAttributeクラスを使う方法も
  あるが、固定長文字列を使う必然性を見直す方が良い。
  Stringの他に、Char()配列も使えるので検討する。

 ◆Timerコントロール:VB2005にも有り注意要すが、自動更新でOKのケース多い。

 ◆File読み書きは全面変更要す:最初の段階は、関連部分をコメント化
  (Open、Close、Line Input、Print文など無くなった。)

  VB2005へアップグレード後、
  System.IO.FileクラスかMy.Computer.FileSystemクラスで全面的に書き換える。
  が、あまり手をかけたく無い場合、VB6表現に似たOpen,Put,Get,Closeメソッド
  が有り、これが使えるケースもある。

 ◆Graphic表示機能は全面変更要す:最初の段階は、関連部分をコメント化
  (Line、Pset、Clsなどのメソッド無し、Form.Printも無し)

  VB2005へアップグレード後、
  全面的な書き換えが必要だから、個別にプログラミングする。
  アップグレードとして時間のかかる箇所だから、共通機能の設計など工夫が必要。

 ◆WinAPI使っている箇所は全面変更要す:最初の段階は、関連部分をコメント化

  VB2005へアップグレード後、
  .NetFrameworkに機能ある場合多いので、調査し、個別にプログラミング。

 ◆Form_Loadなどイベント関連:(これは自動的に変わるので無操作)
  参考までに、若干説明して置く。
  Formという表現でなく、プログラム名がコントロール名になる。
  _UnLoadイベントは無いが、_FormClosingイベントに自動的に変わる。
  他に、_FormClosedイベントもあり、必要あればこちらに書き換える。
  _Activateイベントは有るが、VB6と挙動が異なり、必要に応じて変更要す。
 ---------------------------------------------------------------------

4.次に、VB2005起動し、
  [プロジェクト開く]メニュで、VB6の.vbpファイル読み込む。
  Solution2の保存箇所を問われたら、一方のフォルダを指示する。
  次にプロジェクトの保存箇所を問われるので、先と同じフォルダを指示するが、
  拒否された場合は、もう一方のフォルダを指示する。
  (このあたり、元のVB6ソースによって異なる。)
  すると、「Visual Basicアップグレード ウィザード」が動き出す。

5.変換が終ると、VB2005の新プロジェクトが作られる。

6.コンパイルエラーを出す為、一度[デバッグ開始]する。

7.普通はエラーが多く出るのでこれを修正するが、類型パターンがある。
  ・VB6との解釈の違いで、未入力変数が多く出る:
              値の初期化ステートメントなど追加する。
  ・TextBox_ChangedイベントでWorningでるが、個別に対応する。

8.その他、補足事項

 ・予備更新として手を入れたVB6ソースは、アップグレード後に削除してよい。
 ・UpGradeReport.htmなどは、一度見たら削除して構わない。
 ・最近使ったプロジェクトに不要なものが残る場合、実体を削除して、
  その後に当該をクリックすればリストから消える。
  またはregeditで、VBExpressのProjectMRUListを直に変更しても良い。
 ・その他、.slnと.suoファイルは削除しても影響ないが、プロジェクトを
  参照した時点でまた作られる。


注1)3.の予備更新を実施しなかった場合、
   最初の[デバッグ開始]で出るエラーが莫大になり、うまくない。
注2)最初の段階では、FileI/OやGraphic表示など根幹部分を働かさないので、
   アプリケーションとしてほとんど機能しないが、第一段階として、画面の形式
   チェックができれば、VB2005への変換として、半分は出来たと言える。
   後はFileI/OやGraphic表示など、VB2005表記法にのっとり記述すれば良い。

(以上)




--------(参考)------------------------------------------------------------------------

VB2005によるFileIO

'---My.Computer.FileSystem:使う必要性薄い-----------------------------------
 Dim fInfo As System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(fiNam) '←非推薦(!)
 If fInfo.Exists Then                             '←非推薦
    My.Computer.FileSystem.DeleteFile(fiNam)
nDire = My.Computer.FileSystem.CurrentDirectory                'CurDir()
 moj = My.Computer.FileSystem.ReadAllText(fnam, System.Text.Encoding.Default)
                              'Encoding.UTF8 なども
    My.Computer.FileSystem.WriteAllText(pathnam, moj, False)
    My.Computer.FileSystem.GetFileInfo(f)メソッド             'file長さ

 Dim infoReader As System.IO.FileInfo
 infoReader = My.Computer.FileSystem.GetFileInfo(".....")
 MsgBox("f.L=" & infoReader.Length)


'---My.Computer.FileSystem:バイナリデータを読み書き:これは使える-----------
  Dim binDt As Byte()
  binDt = My.Computer.FileSystem.ReadAllBytes(fiNam)
  Dim moj As String = System.IO.Path.GetExtension(fiNam)           ' .jpgなど
  My.Computer.FileSystem.WriteAllBytes("\temp\bin" & moj, binDt, False)

'---整数などの配列 ←→ バイト配列-------------------------------------------

'---ShortTb() ---> ByteTb()--------
 Dim lpmax As Integer = UBound(B16Tb2)  'B16Tb2(nnn) As Short
 Dim bbTb() As Byte
 ReDim bbTb(lpmax * 2 + 1)
 Dim bbbb As Byte()
 Dim lp As Integer
 For lp = 0 To lpmax
  bbbb = BitConverter.GetBytes(B16Tb2(lp)) '2B←Short変数
  bbTb(lp * 2) = bbbb(0)
  bbTb(lp * 2 + 1) = bbbb(1)
 Next lp

'---ByteTb() ---> ShortTb()--------
  Dim bbTb As Byte()
  bbTb = My.Computer.FileSystem.ReadAllBytes("ファイルパス")
  Dim lpmax As Integer = (UBound(bbTb) - 1) / 2
  Dim lp As Integer
  For lp = 0 To lpmax
   B16Tb2(lp) = BitConverter.ToInt16(bbTb, lp * 2)
  Next lp

'---System.IO.----:これでほとんど間に合う-----------------------------------

 If System.IO.File.Exists(fnam) = True Then          'File有無調査
 NowFoldr = System.IO.Directory.GetCurrentDirectory      'カレントフォルダ名取得
 strFiles = System.IO.Directory.GetFiles(NowFoldr)       'File一覧Collection取得
   fnam = System.IO.Path.GetFileName(strFile)        'Path名→File名取得
   fext = System.IO.Path.GetExtension(strFile)        'Path名→File拡張子取得
       System.IO.File.Delete(fpath)            'File削除
       System.IO.File.Copy("\fn1.ext", ".\fn2.ext", True) 'File Copy
       System.IO.FileInfo.Lengthプロパティ
       (例) Dim instance As New FileInfo("......")
        fleng = instance.Length

 Dim myFi As New System.IO.FileInfo("\fn.txt")         'File情報:(!)の代わり
 moj = System.IO.File.ReadAllText("\fn.txt", System.Text.Encoding.Default)

'---順次読込と順次書込---

'-Dim myRdr As System.IO.StreamReader = New _   '----下の書き方が標準的らしい
'---System.IO.StreamReader("\fn.ext", System.Text.Encoding.Default)
 Dim myRdr As New System.IO.StreamReader _
   ("\fn.ext", System.Text.Encoding.Default)
  buff = myRdr.ReadLine()
  If (buff Is Nothing) Then Exit For
 myRdr.Close()

'-Dim myWriter As System.IO.StreamWriter = New _  '----下の書き方が標準的らしい
'---System.IO.StreamWriter("fn.ext", False, System.Text.Encoding.Default) 'False:上書,True:追加
 Dim myWriter As New System.IO.StreamWriter _
   ("fn.ext", False, System.Text.Encoding.Default)
  myWriter.Write("......" & vbCrLf)
  myWriter.Write("......" & vbCrLf)
  myWriter.Write("......" & vbCrLf)
  myWriter.Write("......" & vbCrLf)
 myWriter.Close()




--------(参考2:時刻関係)------------------------------------------------------------

'--日付_時刻は DateTime 構造体を使って.
  Dim locTm, locTb() As String
  Dim myNow As DateTime = DateTime.Now
  locTm = myNow.TimeOfDay.ToString    '13:11:46.2035036
  locTb = locTm.Split(".")
  locTm = locTb(0).Replace(":", "")    '131146
'--時刻の6桁表現は下記でも.
  Dim iii As Integer = 10000 * myNow.Hour + 100 * myNow.Minute + myNow.Second
'
'--1日のシリアル秒をミリ秒まで表現するとき,
'--DateTime 構造体を使う場合,下記のようにやや面倒.
  Dim locTm, locTb() As String, srSec as Double
  Dim myNow As DateTime = DateTime.Now
  locTm = myNow.TimeOfDay.ToString    '13:11:46.2035036
  locTb = locTm.Split(":")
  srSec = 3600 * locTb(0) + 60 * locTb(1) + CDbl(locTb(2))
'
'--Microsoft.VisualBasic 名称空間を使う方が明瞭に記述できる.
  Dim srSec As Double = Microsoft.VisualBasic.DateAndTime.Timer 'シリアル秒
'           (.NetFramework2.0の中にMicrosoft.VisualBasic.dllがある)

サイト先頭へ戻る