http://blog.csdn.net/badu_123/article/details/5618755
MCI函數與命令
Microsoft提供的MMSYSTEM.H文件中定義了調用MCI功能的數據類型和函數原型。在使用MCI功能的任何源模塊中都應包含該文件。
1. MCI函數
所有的MCI函數名都以mci爲前綴。對應於MCI命令消息和命令字符串接口方式,MCI函數也分爲兩類,即命令消息函數和命令字符串函數。在MMSYSTEM.H中定義了這些函數的原型。MCI函數如表3-1所示:
表3-1 MCI函數
函 數 名 |
功 能 |
類 型 |
mciSendCommand |
發送命令消息 |
命令消息接口函數 |
mciGetDeviceID |
獲取MCI設備的ID |
|
mciSetYieldProc |
設定一個回調函數,在結束帶wait標誌的命令時調用 |
|
mciGetYieldProc |
獲取當前的回調函數 |
|
mciSendString |
發送命令字符串 |
命令字符串接口函數 |
mciGetErrorString |
獲取當前MCI錯誤的字符串描述 |
公用函數 |
2. MCI命令
MCI命令可以分爲4類,如下所述:
a) 系統命令:直接由MCI解釋並由系統處理,是不傳送到MCI設備的命令。
b) 通用命令:所有的MCI設備都支持的MCI命令。
c) 可選命令:MCI設備可選擇使用的MCI命令。
d) 專用命令:針對某類MCI設備或集合的專有MCI命令。
MCI定義了兩種接口方式,即命令消息方式和命令字符串方式。相應地,MCI命令可分爲命令消息和命令字符串。主要的MCI命令及分類如表3-2所示,這些命令可能具有其相應的擴展形式。
表3-2 MCI命令列表
MCI命令消息 |
MCI命令字符串 |
MCI命令說明 |
MCI命令類型 |
MCI_SYSINFO |
SYSINFO |
返回有關MCI設備的信息 |
系統命令
|
MCI_BREAK |
BREAK |
爲一個指定的MCI設備設置一個終止鍵 |
|
MCI_SOUND |
SOUND |
播放一段Windows指定的系統聲音 |
|
MCI_CLOSE |
CLOSE |
關閉一個MCI設備 |
通用命令
|
MCI_GETDEVCAPS |
GETDEVCAPS |
獲得一個MCI設備的性能參數 |
|
MCI_INFO |
INFO |
從一個MCI設備得到有關的信息 |
|
MCI_OPEN |
OPEN |
初始化一個MCI設備 |
|
MCI_STATUS |
STATUS |
從一個MCI設備返回有關的狀態信息 |
|
MCI_LOAD |
LOAD |
從一個磁盤文件中加載數據 |
可選命令 |
MCI_PAUSE |
PAUSE |
暫停播放或記錄 |
|
MCI_PLAY |
PLAY |
開始播放數據 |
|
MCI_RECORD |
RECORD |
開始記錄數據 |
|
MCI_RESUME |
RESUME |
重新開始播放或記錄 |
|
MCI_SAVE |
SAVE |
將數據存儲到磁盤文件中 |
|
MCI_SEEK |
SEEK |
向前或向後檢索 |
|
MCI_SET |
SET |
設置設備信息 |
|
MCI_STOP |
STOP |
停止播放或記錄 |
3. MCI命令接口方式
MCI命令消息接口方式利用消息和數據結構來給多媒體設備發送命令和接收MCI設備傳來的的信息。這種方式的接口函數主要有3個,即mciSendCommand,mciGetDeviceID和mciGetErrorString。它們的函數原型如下:
MCIERROR mciSendCommand(
MCIDEVICEID wDevice, // 設備ID
UINT uMsg, // 命令消息
DWORD fdwCommand, // 命令消息標誌
DWORDdwParam // 命令消息使用的結構參數地址
);
MCIDEVICEID mciGetDeviceID( LPCTSTR lpszDevice ); // 設備類型
BOOL mciGetErrorString(
DWORD fdwError, // 錯誤代碼
LPTSTR lpszErrorText, // 錯誤描述
UINT cchErrorText // 錯誤描述長度
);
mciGetDeviceID通過傳送MCI設備名lpszDevice來獲取用於MCI_OPEN命令消息打 開MCI設備的標識號wDeviceID,其值可用於mciSendCommand的參數wDeviceID。mciSendCommand用於向標識號 爲wDeviceID的MCI設備發送命令消息uMsg。當用mciSendCommand發送MCI_OPEN命令消息打開一個設備時,將自動創建一個 設備標識號。如果設備打開成功,可以從MCI_OPEN_PARMS結構的wDeviceID數據域中取得該設備的標識號,該值將保存以供後續的MCI命 令使用。如果mciSendCommand調用成功,則返回值爲0;否則表示設備驅動出錯,這時可用mciGetErrorString來取得錯誤信息的 文字描述。
MCI提供一個名爲MCI_ALL_DEVICE_ID的特殊設備標識號。當前所有已打開的MCI設備都將接收到對MCI_ALL_DEVICE_ID發送的任何MCI命令。
使用任何一個MCI設備前都應先用MCI_OPEN打開它。打開MCI設備時,要求指定相應的MCI_OPEN_PARMS結構。如果打開設備成功,則該結構的wDeviceID域返回MCI設備的標識號ID。
使用MCI_OPEN 命令消息時可使用的命令消息標誌如表3-3所示。MCI_OPEN_PARMS結構定義如下:
typedef struct
{
DWORD dwCallback; // 回調窗口句柄
MCIDEVICEID wDeviceID; // 設備打開成功,返回的設備號
LPCSTR lpstrDeviceType; // 設備類型
LPCSTR lpstrElementName; // 複合設備的設備元素,通常爲
// 文件名
LPCSTR lpstrAlias; // 指定的設備別名
} MCI_OPEN_PARMS;
表3-3 MCI_OPEN 命令消息標誌
消 息 標 志 |
意 義 |
MC_OPEN_ALIAS |
MCI_OPEN_PARMS結構的lpstrAlias域中指定了設備別名 |
MC_OPEN_ELEMENT |
MCI_OPEN_PARMS結構的lpstrElementName域中指定了設備元素 |
MC_OPEN_SHAREABLE |
按共享設備方式打開設備 |
MC_OPEN_TYPE |
MCI_OPEN_PARMS結構的lpstrDeviceType域中指定了設備類型 |
MC_OPEN_TYPE_ID |
MCI_OPEN_PARMS結構的lpstrDeviceType域中指定了設備類型ID |
打開一個簡單的MCI設備不需要指定設備元素,即不需要指定一個數據文件,所以可以僅僅指定 MCI_OPEN_PARMS結構中的wDeviceID和lpstrDeviceType兩個數據域。要打開一個複合的MCI設備,必須指定設備元素數 據域lpstrElementName和設備類型數據域lpstrDeviceType。對於打開復合MCI設備,有以下3種方式可供選擇:
a)爲確定MCI設備的性能,可以只指定設備的類型來打開MCI設備。這時,只允許確定MCI設備的性能,然後關閉設備,一般不能進行其他的操作。
b) 爲使一個設備元素與指定設備相聯繫,應同時指定設備元素(數據文件名)和設備類型。這時可對設備進行相應的各種操作。
c)在使用隱含的MCI設備時,可只指定MCI設備元素(數據文件名),而把設備類型指定爲NULL;MCI將根據設備元素的擴展名從系統定義中選擇隱含約定的MCI設備。
應用程序在使用完一個MCI設備後應明確地關閉該MCI設備。MCI_CLOSE命令消息用於關閉並釋放MCI設備,即取消應用程序對MCI設備或設備元素的訪問權。
當用MCI_SYSINFO命令消息獲取MCI設備系統信息時,需要在mciSendCommand的 dwParam參數中指定MCI_SYSINFO_PARMS結構的地址,系統信息將通過該結構返回。與MCI_SYSINFO 命令消息相關的消息標誌如表3-4所示。 MCI_SYSINFO_PARMS結構定義如下:
typedef struct
{
DWORD dwCallback; // 回調窗口句柄
LPSTR lpstrReturn; // 返回信息緩衝區地址
DWORD dwRetSize; // 返回信息大小
DWORD dwNumber; // 索引號
UINT wDeviceType; // 設備類型
} MCI_SYSINFO_PARMS;
表3-4 MCI_SYSINFO 命令消息標誌
消 息 標 志 |
意 義 |
MCI_SYSINFO_QUANTITY |
返回指定的設備類型的數目,如與MCI_SYSINFO_OPEN一起使用,則僅返回已打開設備的數目 |
MCI_SYSINFO_NAME |
返回設備名,如與MCI_SYSINFO_OPEN一起使用,則僅返回已打開設備的名稱 |
MCI_SYSINFO_OPEN |
僅返回已打開設備的信息 |
MCI_SYSINFO_INSTALLNAME |
指定設備的安裝名稱 |
在使用MCI設備時,還應注意共享、等待與通告等標誌的使用。由於本次設計共享等的應用很少,因此在此另作說明。
4. MCI命令字符串接口方式
MCI命令字符串方式使用ASCII字符串來發送驅動MCI設備的命令,這種方式採用的接口函數有mciSendString、mciGetErrorString。
mciSendString 用於向MCI設備發送命令字符串,其函數原型如下:
MCIERROR mciSendString(
LPCTSTR lpszCommand,
LPTSTR lpszReturnString,
UINT cchReturn,
HANDLE hwndCallback
);
第一個參數是遠程指針lpszCommand,指向一個以NULL結尾的MCI命令字符串,該字符串的語法格式如下所示:
command device_name argument
其第二個參數lpszReturnString指向一個用於存儲MCI命令執行後返回的字符串信息的緩衝區。第 三個參數cchReturn用於指定該字符串緩衝區的大小。MCI命令執行後,返回的信息將存放在lpszReturnString中,如果返回信息的長 度大於cchReturn聲明的長度,MCI將返回一個錯誤代碼。如設置lpszReturnString爲NULL,則將忽略返回信息。
其第四個參數hwndCallback指定一個接受MM_MCINOTIFY的窗口的句柄,除非MCI命令中包含了notify標誌,否則該參數可忽略。如該函數返回非0值,則說明調用失敗,可用mciGetErrorString取得包含錯誤信息的字符串。
MCI的系統、通用和可選命令字符串列表於表3-1中,每一個命令字符串都對應着相應的命令消息。同樣,這些命令也可具有其相應的擴展形式。
4. 示例
(1)下例定義的函數GetNumberOfDevices利用MCI接口函數獲取當前系統已打開的MCI設備的數量。
////////////////////////////////////////////////////////////
// GetNumberOfDevices
// 獲取當前系統已打開的MCI設備數量
// 參數:無
// 返回值: 當前系統已打開的MCI設備數量
////////////////////////////////////////////////////////////
int GetNumberOfDevices (void)
{
MCI_SYSINFO_PARMSsysinfo;
DWORD dwDevices;
sysinfo.lpstrReturn= (LPSTR)(LPDWORD)&dwDevices;
sysinfo.dwRetSize =sizeof(DWORD);
if(mciSendCommand(MCI_ALL_DEVICE_ID,
MCI_SYSINFO,
MCI_SYSINFO_OPEN | MCI_SYSINFO_QUANTITY,
(DWORD)(LPMCI_SYSINFO_PARMS)&sysinfo)
!= 0)
return0; // 出錯
else
return(int)dwDevices;
}
(2)下例說明了播放CD音頻的方法。
/////////////////////////////////////////////////////////////////////////
// PlayCDTrack
//
// 使用MCI_OPEN, MCI_PLAY播放指定的CD音頻音軌,開始播放即
// 返回,當播放結束時,將通知回調窗口
//
// 參數:hWndNotify —— 接收通知消息的回調窗口句柄
// bTrack —— 指定的音軌
//
// 返回值:0 —— 成功
// 非0 —— 失敗,返回值爲MCI錯誤碼
////////////////////////////////////////////////////////////////////////
DWORD PlayCDTrack(HWND hWndNotify, BYTE bTrack)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_SET_PARMS mciSetParms;
MCI_PLAY_PARMS mciPlayParms;
// 打開CD音頻設備
mciOpenParms.lpstrDeviceType ="cdaudio";
if (dwReturn = mciSendCommand(NULL,MCI_OPEN,
MCI_OPEN_TYPE, (DWORD)(LPVOID) &mciOpenParms))
{
// 打開設備失敗,返回錯誤碼
return (dwReturn);
}
// 打開設備成功,獲取設備ID
wDeviceID = mciOpenParms.wDeviceID;
// 設置時間格式爲TMSF
mciSetParms.dwTimeFormat =MCI_FORMAT_TMSF;
if (dwReturn =mciSendCommand(wDeviceID, MCI_SET,
MCI_SET_TIME_FORMAT, (DWORD)(LPVOID)&mciSetParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
// 開始播放指定音軌,當音軌播放完畢時,用MM_MCINOTIFY 通知
// 消息通知父窗口。如設備出錯,關閉設備
mciPlayParms.dwFrom = 0L;
mciPlayParms.dwTo = 0L;
mciPlayParms.dwFrom = MCI_MAKE_TMSF(bTrack, 0, 0, 0);
mciPlayParms.dwTo = MCI_MAKE_TMSF(bTrack + 1, 0, 0, 0);
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY,
MCI_FROM | MCI_TO | MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
(3)下例將播放指定的MIDI文件。
/////////////////////////////////////////////////////////////////////////
// PlayMIDIFile
//
// 使用MCI_OPEN和MCI_PLAY播放指定的MIDI文件,開始播放即返回,
// 當播放結束時,將通知回調窗口
//
// 參數:hWndNotify —— 接收通知消息的回調窗口句柄
// lpszMIDIFileName —— 指定的MIDI文件名
//
// 返回值:0 —— 成功
// 非0 —— 失敗,返回值爲MCI錯誤碼
/////////////////////////////////////////////////////////////////////////
DWORD PlayMIDIFile(HWND hWndNotify, LPSTRlpszMIDIFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
MCI_STATUS_PARMS mciStatusParms;
MCI_SEQ_SET_PARMS mciSeqSetParms;
// 用指定的文件名打開設備
// MCI將試圖選取MIDI映射器作爲輸出端口
mciOpenParms.lpstrDeviceType ="sequencer";
mciOpenParms.lpstrElementName =lpszMIDIFileName;
if (dwReturn = mciSendCommand(NULL,MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms))
{
// 打開設備失敗,返回錯誤碼
return (dwReturn);
}
// 打開設備成功,獲取設備ID
wDeviceID = mciOpenParms.wDeviceID;
// 檢查輸出端口是否爲MIDI映射器
mciStatusParms.dwItem =MCI_SEQ_STATUS_PORT;
if (dwReturn =mciSendCommand(wDeviceID, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD)(LPVOID) &mciStatusParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
// 輸出端口不是MIDI映射器
// 詢問用戶是否繼續
if (LOWORD(mciStatusParms.dwReturn) !=MIDI_MAPPER)
{
if (MessageBox(hMainWnd,
"MIDI映射器不存在,繼續嗎 ?",
"", MB_YESNO) == IDNO)
{
// 不繼續,關閉設備並返回
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (0L);
}
}
// 開始播放,當播放完畢時,用MM_MCINOTIFY 通知
// 消息通知父窗口。如設備出錯,關閉設備
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn =mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return(dwReturn);
}
return (0L);
}
(4)下例說明了錄製並存儲數字化波形聲音的方法。
/////////////////////////////////////////////////////////////////////////
// RecordWAVEFile
// 使用 MCI_OPEN, MCI_RECORD和MCI_SAVE命令消息錄製並存儲數字
// 化波形聲音
// 參數:dwMilliSeconds —— 錄音的時間(ms)
// lpszFileName —— 指定的存盤文件名
//
// 返回值:0 —— 成功
// 非0 —— 失敗,返回值爲MCI錯誤碼
/////////////////////////////////////////////////////////////////////////
DWORD RecordWAVEFile(DWORD dwMilliSeconds, LPSTRlpszFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_RECORD_PARMS mciRecordParms;
MCI_SAVE_PARMS mciSaveParms;
MCI_PLAY_PARMS mciPlayParms;
// 用新文件打開波形聲音,以進行錄音
mciOpenParms.lpstrDeviceType ="waveaudio";
mciOpenParms.lpstrElementName ="";
if (dwReturn = mciSendCommand(0,MCI_OPEN,
MCI_OPEN_ELEMENT | MCI_OPEN_TYPE,
(DWORD)(LPVOID) &mciOpenParms))
{
// 打開設備失敗,返回錯誤碼
return (dwReturn);
}
// 打開設備成功,獲取設備ID
wDeviceID = mciOpenParms.wDeviceID;
// 按指定的時間(ms)長度開始錄音,等待錄音結束再繼續執行程序
// 設備的時間格式應設爲ms
mciRecordParms.dwTo = dwMilliSeconds;
if (dwReturn =mciSendCommand(wDeviceID, MCI_RECORD,
MCI_TO |MCI_WAIT, (DWORD)(LPVOID) &mciRecordParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return(dwReturn);
}
// 播放錄音,並提示用戶存盤
mciPlayParms.dwFrom = 0L;
if (dwReturn =mciSendCommand(wDeviceID, MCI_PLAY,
MCI_FROM | MCI_WAIT, (DWORD)(LPVOID)&mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
if (MessageBox(hMainWnd, "將錄音存盤嗎 ?",
"", MB_YESNO) == IDNO)
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (0L);
}
// 將錄音存爲lpszFileName文件, 等待存盤結束再繼續執行程序
mciSaveParms.lpfilename =lpszFileName;
if (dwReturn =mciSendCommand(wDeviceID, MCI_SAVE,
MCI_SAVE_FILE | MCI_WAIT, (DWORD)(LPVOID)&mciSaveParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
(5)下例說明了播放數字化視頻AVI的方法。
/////////////////////////////////////////////////////////////////////////
// PlayMovie
// 使用 MCI_OPEN和MCI_PLAY命令消息打開並播放數字化視頻AVI
// 參數:lpszFileName 指定的AVI文件名
// dwFrom —— 開始播放位置
// dwTo —— 結束播放位置
//
// 返回值:0 —— 成功
// 非0 —— 失敗,返回值爲MCI錯誤碼
/////////////////////////////////////////////////////////////////////////
DWORD PlayMovie(LPSTR lpszFileName, DWORD dwFrom, DWORDdwTo)
{
DWORD dwReturn;
// 打開AVI
MCI_DGV_OPEN_PARMS mciOpen;
mciOpen.dwCallback = 0L;
mciOpen.wDeviceID = 0;
mciOpen.lpstrDeviceType = AVI_VIDEO;
mciOpen.lpstrElementName =lpszFileName;
mciOpen.lpstrAlias = NULL;
mciOpen.dwStyle = 0;
mciOpen.hWndParent = NULL;
if (dwReturn=mciSendCommand(0,MCI_OPEN,
(DWORD)(MCI_OPEN_TYPE),
(DWORD)(LPMCI_DGV_OPEN_PARMS)&mciOpen) )
{
// 打開設備失敗,返回錯誤碼
return dwReturn;
}
// 播放AVI
MCI_DGV_PLAY_PARMSmciPlay; // play parameters
DWORD dwFlags = 0;
// 打開設備成功,獲取設備ID
WORD wDevID = mciOpen.wDeviceID;
// 檢查開始播放位置,如不等於0,則進行設置
if (dwFrom)
{
mciPlay.dwFrom = dwFrom; // 設置參數
dwFlags |= MCI_FROM; // 設置標誌
}
// 檢查結束播放位置,如不等於0,則進行設置
if (dwTo)
{
mciPlay.dwTo =dwTo; // 設置參數
dwFlags |=MCI_TO; // 設置標誌
}
// 用MCI_PLAY 命令播放並返回結果
return mciSendCommand(wDevID,MCI_PLAY, dwFlags,
(DWORD)(LPVOID)&mciPlay);