Basic言語でDLLを作るだって?冗談言うなよ!

それが、ActiveBasicでは自然な形で作れてしまいます。ネイティブ コードにコンパイルされるため、DLLプログラムとして要求されるだけの実行速度、プログラム サイズが期待できます。

作り方はとてもシンプル

通常のEXEプログラムと違う点は以下の2つだけ。
① プロジェクト作成時に「DLL」を選択する
② エクスポートする関数には "Export" 指定をする

①は画面の説明に従うだけなので解説の必要はありませんね。②に関してですが、今までは関数を定義するというと、

Sub func1(parm...)
...
End Sub

Function func2(oarm...) As Long
...
End Sub

という感じに定義するのに対し、エクスポートする関数に関しては、

Sub Export func1(parm...)
...
End Sub

Function Export func2(oarm...) As Long
...
End Sub

などと、"Sub/Function" の後に "Export" という指定をしましょうということです。エクスポートとは、外部プログラムから呼び出すことができる関数のことです。例えば、func1という関数をエクスポートし、test.dllを作成すると、

Declare Sub func1 Lib "test.dll" (parm...)


というように、外部プログラム(EXEやDLL)からの呼び出しが可能になります。

実際にDLLを作ってみよう



DLLの利点は、なんといっても汎用性の高いプログラムを様々なアプリケーション プログラムから共有する形で呼び出すことができることにつきます。そこで、今回は2つの役立ちそうな機能(関数)をDLL化してみたいと思います。

  • GetFileDlg … OPENFILENAME構造体の初期化、GetOpenFileName/GetSaveFileName関数の呼び出し
  • GetFolderDlg … GetFileDlgにちなんで、フォルダ(ディレクトリ)パスを取得するためのダイアログボックスを表示するプログラムをまとめる

まずは、プロジェクトの作成から。プロジェクト名を "FileDlg" などとし、タイプを "DLL" にします。プロジェクト オプションなどの設定は特に必要ありません。



プロジェクトの作成はできたでしょうか?ここから皆さんが扱うファイルは、FileDlg.sbp のみになります。このファイルに関数郡を定義していくのですが、なにやら、初期状態ですでにDllMainといった関数が定義されています。これはDLLのロードやスレッド開始、終了などの処理を記述するための特別な関数ですが、めったなことではいじりませんので、ほっときましょう。そのDllMain関数の下に独自の関数を定義していきます。

エクスポート関数 "GetFileDlg" を作る

この関数では、「ファイルを開く」「ファイルの保存」ダイアログボックスを表示します。OPENFILENAME構造体の内容を共有する形で、GetOpenFileName関数、GetSaveFileName関数を呼び出します。ユーザーがファイルを選択すると1が、キャンセルすると0が返るようにします。

Function Export GetFileDlg(hWnd As Long, lpBuf As BytePtr, lpFilter As BytePtr, bOpen As Long) As Long
Dim ofn As OPENFILENAME

'OPENFILENAME構造体の初期化
FillMemory(VarPtr(ofn),Len(ofn),0)
ofn.lStructSize=Len(ofn)
ofn.hwndOwner=hWnd
SetDWord(VarPtr(ofn.lpstrFilter),lpFilter)
ofn.nFilterIndex=1
SetDWord(VarPtr(ofn.lpstrFile),lpBuf)
ofn.nMaxFile=MAX_PATH
ofn.Flags=OFN_FILEMUSTEXIST or OFN_HIDEREADONLY or OFN_PATHMUSTEXIST
ofn.lpstrDefExt="*"

If bOpen Then
ofn.lpstrTitle="ファイルを開く"
'「ファイルを開く」ダイアログ ボックスを表示
If GetOpenFileName(ofn)=0 Then
GetFileDlg=0
Exit Sub
End If
Else
ofn.lpstrTitle="ファイルの保存"
'「ファイルの保存」ダイアログ ボックスを表示
If GetSaveFileName(ofn)=0 Then
GetFileDlg=0
Exit Sub
End If
End If

GetFileDlg=1
End Function


エクスポート関数 "GetFolderDlg" を作る

SHBrowseForFolder関数、SHGetPathFromIDList関数を初めて目にした方がほとんどでしょう。SHBrowseForFolder関数で「フォルダの参照」ダイアログボックスを表示し、ユーザーがOKボタンを押すとSHGetPathFromIDList関数でフォルダへのパスを取得する流れになっています。ユーザーがフォルダを選択すると1が、キャンセルボタンを押すと0が返るようにします。

Function Export GetFolderDlg(hWnd As Long, lpFolder As BytePtr) As Long
Dim bi As BROWSEINFO
Dim pidlBrowse As VoidPtr

'BROWSEINFO構造体の初期化
FillMemory(VarPtr(bi),Len(bi),0)
bi.hwndOwner=hWnd
bi.lpszTitle="フォルダの選択"
bi.ulFlags=BIF_RETURNONLYFSDIRS

'「フォルダの参照」ダイアログボックスを表示
pidlBrowse=SHBrowseForFolder(bi)

If pidlBrowse Then
'フォルダへのパスを取得(lpFolderポインタが示すバッファにコピー)
SHGetPathFromIDList(pidlBrowse, lpFolder)
GetFolderDlg=1
Else
GetFolderDlg=0
End If
End Function


DLL内のプログラムはこれですべてです。コンパイルが正常に行われると、"FileDlg.dll" というファイルが生成されるはずです。



"FileDlg.dll" を作ったはいいが、どうやって使うの?

ということで、DLL呼び出しのサンプル プログラムを作ってみましょう。ProjectEditorの新規作成でBasicプログラムを選択し、以下のソースコードを入力します。コンパイル前に、"test.abp" などというファイル名でFileDlgプロジェクトのディレクトリに保存しておきましょう。

Declare Function GetFileDlg Lib "FileDlg" (
hWnd As Long,
lpBuf As BytePtr,
lpFilter As BytePtr,
bOpen As Long) As Long
Declare Function GetFolderDlg Lib "FileDlg" (
hWnd As Long,
lpFolder As BytePtr) As Long

Dim i As Long

Dim buf As String
Dim FileFilter As String
buf=ZeroString(MAX_PATH)
FileFilter="すべてのファイル(*.*)" + Chr$(0) + "*" + Chr$(0)

'開くダイアログを表示
i=GetFileDlg(0, _
StrPtr(buf), _
StrPtr(FileFilter), _
1)
If i Then
MessageBox(0,buf,"「ファイルを開く」で選択されたファイル",MB_OK)
Else
MessageBox(0,"ファイルは選択されませんでした","エラー",MB_OK)
End If

'保存ダイアログを表示
i=GetFileDlg(0, _
StrPtr(buf), _
StrPtr(FileFilter), _
0)
If i Then
MessageBox(0,buf,"「ファイルの保存」で選択されたファイル",MB_OK)
Else
MessageBox(0,"ファイルは選択されませんでした","エラー",MB_OK)
End If

'「フォルダの参照」ダイアログを表示
i=GetFolderDlg(0,StrPtr(buf))
If i Then
MessageBox(0,buf,"「ファイルの参照」で選択されたフォルダ",MB_OK)
Else
MessageBox(0,"フォルダは選択されませんでした","エラー",MB_OK)
End If

ExitProcess(0)



上のプログラムでわかるとおり、Win32APIの関数を定義したことがある方なら、自作DLL内の関数の定義、呼び出しは朝飯前ですね!?
DLL作成は初めてだったというかたはどうだったでしょうか?今回作成したFileDlg.dllは、意外と便利なDLLなので、テキスト エディタ プログラムなどで採用してみるのも良いかもしれません。