「ステップ14 「DLLを作る」」の編集履歴(バックアップ)一覧に戻る
ステップ14 「DLLを作る」」を以下のとおり復元します。
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なので、テキスト エディタ プログラムなどで採用してみるのも良いかもしれません。

復元してよろしいですか?