LoginSignup
3
1

More than 5 years have passed since last update.

Win32 CプログラマーがVBを扱ったときのメモ

Last updated at Posted at 2018-10-25

営業「むかーし納品したVB6アプリを、今のWindows10のPCに対応するようにしろ」
俺「VBなんていじったことないですよ」
営業「他に人いないし、同じようなもんでしょ」
俺「(いつも余裕ぶっこいて遊んでいるようにみられているからかなぁ)ぁぃ。。。」
営業「あ、あと追加機能もあるでよ」

当時の担当者は消えており、しかたなく、しぶしぶ対応したときのメモです。
(あまりそっち側に深く入り込む気がなかったので、適当対応です)

1. VB6 -> VB.NET(2017)

今回は追加機能あり、ということなのでコンパイルできないと始まらない
自分の環境だとVB6はインストールしていない
ということで、VS2017でコンパイルできるようにしようと調査したところ、一旦VS2008を間に挟むことによってコンバートできる、とのことでした
VS2008を拾ってきてインストールして、無事VB.NETにコンバート終了

2. MSFlexGrid.ocxのインストール

どれどれ、どんなアプリかな(いい加減な資料しか残ってません><)
と実行してみると、すぐにMSFlexGridがない、と怒られました
Windows10では個別にregsvr32.exeで登録する必要があるようです
さらに、MSFlexGridは64bitに対応してないのですね><
で、どうにかアプリを起動して使用してみると、別にグリッドをつかわなくてもリストで事足りる内容
多分、以前にそういうアプリを作ったことがあって、その部分だけ使いまわしたんだろうなっていう内容
このあたりで、前任者の先見的配慮の薄さに少し不安を感じました

3. ほとんどの処理をC(C++)で書いたDLLで処理するよ~

アプリの内容はだいたいわかった、とVBのソースコードを眺めてみたところ、、、
嫌な予感的中、流れのわかりにくいコード、場当たり的なコードのオンパレードでした><
こりゃ使いものにならんなぁ、と捨てたり整理していったら、各Formの定義くらいしか残ってませんでした
結局、その他は全部Cで書いたDLLに任せる方針にしました

4. DLL関数引数の定義

言語間の変数型表現の違い、文字列表現の違い、が鬱陶しいです

(1) 引数=変数配列
 これは別段わかりにくい点なし

dllヘッダー
  int __stdcall GetArrayData(double *d);
VB定義
  Public Declare Function GetArrayData Lib "Test.dll" (ByRef d As Double) As Integer
VB実装
  Public d(32) As Double
  GetArrayData(d);

(2) 引数=文字列
 文字列を引数にする場合は、VBではStribgBuilder型を使うのがよいようです

dllヘッダー
  int __stdcall SetText(char *t);
VB定義
  Public Declare Function SetText Lib "Test.dll" (ByVal t As Text.StringBuilder) As Integer
VB実装
  Dim txtbuf As Text.StringBuilder = New Text.StringBuilder(64)
  Dim srctxt As String = ""
  txtbuf.Append(srctxt)
  SetText(txtbuf)

(3) 引数=構造体
よく理解してませんwググって拾ってきたコードをコピペしただけ^^;
文字列を固定長配列にしてしまえば、構造体サイズも固定になって構造体の配列渡しも可能でしょう
この固定長文字列に対して、Cのコードでstrcpy()等をした場合に最後尾に\0が入るのですが、そのままVBのString型に代入するとエラーが起きるみたいです
なので、\0を取り除いた文字列をString型に代入するようにしています

dllヘッダー
  typedef struct _S
  {
    char cstr[64];
  }S;
  int __stdcall GetStructData(S *s);
VB定義
  <StructLayout(LayoutKind.Sequential)> Public Structure S
    <VBFixedString(64), MarshalAs(UnmanagedType.ByValArray, SizeConst:=64)> 
      Public cstr() As Char
  End Structure

  Public Declare Function GetStructData Lib "Test.dll" (<[In](), Out()> ByVal s() As S) As Integer
VB実装
  Public s(256) As S
  GetStructData(s)

  Private Sub mytrim(ByRef txt As String)
    Dim workbuf As String
    workbuf = txt
    Dim cp As Integer = InStr(workbuf, vbNullChar)
    If cp > 0 Then txt = VB.Left(workbuf, cp - 1)
  End Sub

  Dim c As String = s(0).cstr : mytrim(c)

5. VBのFormにメッセージを飛ばす

dllからVBのFormに通信することを考えると、慣れている分、メッセージを飛ばすのがわかりやすいですよね
VB.NETではお手軽に利用できます。
起動時にFormのHWNDを取得してdllに教え、dllはそのHWNDにPostMessage()するだけ

VB実装(起動時)
  Private Sub Test_Form_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
    Dim hWndMain As UInteger = Me.Handle.ToInt32
    '起動処理 ...
  End Sub
VB実装
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    If m.Msg = WM_APP + 1 Then
      If m.WParam = 1 Then
        'WParam==1のメッセージ処理
      End If
    End If
    MyBase.WndProc(m)  ' default message_proc
  End Sub
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1