MCIによる、お手軽サウンドプレイヤー
公式サイトで毎日のようにABのバグフィックスが行われていた頃…公式にMCIを使った解説があった。
AB4.24のサンプルにCDPlayerがあるが、これもMCIを使ったもの。
MCIでmpegやavi、waveやmidiなどを簡単に再生することができるので、エロゲー制作にはもってこいだ。
ただしMCIには問題があって、再生終了などのメッセージを受け取るにはウインドウハンドルが必要なことだ。
つまり、コンソールアプリ、N88アプリでは、扱えないということになってしまうような気がする。

その回避方法は、ダミーウインドウを作り、そいつにメッセージを送らせるようにする。
ダミーと言ってもウインドウ。見えないだけ。

そこで登場するのがサブクラス化だ。
ウインドウプロシージャを横取りするものである。

#N88BASIC 
#include <api_mmsys.sbp> 
 
 
Function callback(hwnd As HWND, msg As DWord, wp As WPARAM, lp As LPARAM) As Long 
Dim dwCallback As DWord 
  If msg=MM_MCINOTIFY And wp=MCI_NOTIFY_SUCCESSFUL Then 
    'デバイスを閉じる 
    mciSendCommand(mop.wDeviceID,MCI_STOP,MCI_WAIT,dwCallback) 
    mciSendCommand(mop.wDeviceID,MCI_CLOSE,MCI_WAIT,dwCallback) 
    mop.wDeviceID=0 
 Exit Function
  End If 
  callback = CallWindowProc(DefProc , hwnd , msg , wp , lp) 
End Function 
 
Function mciplay() As Long 
  If mop.wDeviceID <> 0 Then Exit Function 
  Dim ofn As OPENFILENAME   
  Dim mpp As MCI_PLAY_PARMS 
  Dim bErr As Long 
  Dim buffer[MAX_PATH-1] As Byte 
  'ファイル名を取得 
  ofn.lStructSize=SizeOf(OPENFILENAME) 
  ofn.hwndOwner=_PromptSys_hWnd 
  ofn.lpstrFilter=Ex"音楽 ファイル(*.wav;*.mid;*.mp3;*.wma)\0*.wav;*.mid;*.mp3;*.wma;\0動画 ファイル(*.avi;*.mpg;*.wmv;)\0*.avi;*.mpg;*.wmv;\0すべてのファイル(*.*)\0*\0\0" 
  ofn.nFilterIndex=1 
  ofn.nMaxFile=MAX_PATH 
  ofn.lpstrFile=buffer 
  If GetOpenFileName(ofn) = FALSE Then 
    MessageBox(_PromptSys_hWnd,"ファイルのオープンに失敗","error",MB_OK) 
    Exit Function 
  End If 
 
  mop.lpstrElementName=buffer 
  If mciSendCommand(0,MCI_OPEN,MCI_OPEN_ELEMENT or MCI_WAIT,mop) Then 
    MessageBox(_PromptSys_hWnd,"デバイスのオープンに失敗","error",MB_OK) 
    Exit Function 
  End If 
 
  mpp.dwCallback=_PromptSys_hWnd 
  If mciSendCommand(mop.wDeviceID,MCI_PLAY,MCI_NOTIFY,mpp) Then 
    MessageBox(_PromptSys_hWnd,"デバイスの再生に失敗","error",MB_OK) 
    Exit Function 
  End If 
  Print "再生>";MakeStr(buffer) 
  mciplay = GetTickCount() 
End Function 
 
Function GetTime() As Long 
  If mop.wDeviceID = 0 Then Exit Function 
  Dim msp As MCI_STATUS_PARMS 
  msp.dwItem=MCI_STATUS_POSITION 
  mciSendCommand(mop.wDeviceID,MCI_STATUS,MCI_WAIT or MCI_STATUS_ITEM,msp) 
  GetTime=msp.dwReturn 
End Function 
 
'ここからメイン処理 
Dim mop As MCI_OPEN_PARMS 
 
'サブクラス 
Dim DefProc As Long 
DefProc = GetWindowLong(_PromptSys_hWnd, GWL_WNDPROC) 
SetWindowLong(_PromptSys_hWnd , GWL_WNDPROC , AddressOf(callback)) 
 
*INFINITY 
If mciplay() = 0 Then End 
While(mop.wDeviceID) 
  Locate 0,2 
  Print "時間>";GetTime() 
  Sleep(500) 
Wend 
MessageBox(_PromptSys_hWnd,"再生終了しました。","N88MCI",MB_OK) 
Cls 3 
Goto *INFINITY