現有個mid文件﹐怎么使它在程序執行中一直重復播放?

mengjj 2004-06-24 11:48:22
播放我用的
mciSendCommand (OpenParms.wDeviceID, MCI_PLAY,
MCI_NOTIFY, (DWORD)(LPVOID)&PlayParms);
...全文
233 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
pomelowu 2004-06-24
  • 打赏
  • 举报
回复
噢,最后一个参数改成你的:
mciSendCommand(OpenParms.wMCIDeviceID, MCI_PLAY,
MCI_NOTIFY|MCI_DGV_PLAY_REPEAT,
(DWORD)(LPVOID)&PlayParms);
E17 2004-06-24
  • 打赏
  • 举报
回复
MCIWNDM_GETREPEAT 不知道这个 对你 有没有用
pomelowu 2004-06-24
  • 打赏
  • 举报
回复
这样:
mciSendCommand(OpenParms.wMCIDeviceID, MCI_PLAY,
MCI_NOTIFY|MCI_DGV_PLAY_REPEAT,
(DWORD)(LPMCI_DGV_PLAY_PARMS)&mciPlay);
pomelowu 2004-06-24
  • 打赏
  • 举报
回复
台湾人写的,译名略微有些不同,应该还能理解吧?
pomelowu 2004-06-24
  • 打赏
  • 举报
回复
汗~~上面帖的是重复播放AVI的参数~~~见谅见谅。下面这个是正解:

播放MIDI的程式作法

游戏中播放音乐的要点就是循环播放,也就是播放完毕以後,要让他从头开始播放,直到场景更换,或是游戏结束为止。所以当MIDI档案播放完毕以後,必须要能通知程式,让程式做出适当的处理。播放MIDI的作法只要藉由WINDOW的多媒体的支援,马上就搞定了,甚至直接从HELP的作法剪过来,稍微修改一下,也能符合需要,因为这种东西相当公式化,A君和B君写出来的程式码也大致上会长得差不多,废话不多说,看看程式多麽简单便是:

class CMidi

{

public:

DWORD Play(HWND,char* FileName);

void Replay();

void Stop();

private:

UINT wDeviceID;//MCI装置代号

DWORD dwReturn;

MCI_OPEN_PARMS mciOpenParms;

MCI_PLAY_PARMS mciPlayParms;

MCI_STATUS_PARMS mciStatusParms;

MCI_SEQ_SET_PARMS mciSeqSetParms;

};

将他包装成一个类别来使用也可以,而介面的部份需要单纯化,从直觉上来说,第一个动作就是播放(Play),接着是重播(Replay),最後当然是善後的工作了(Stop),不多不少,刚好三个,当然你会想到,是不是需要一个暂停的介面,没问题,这不是什麽难事,花额外的三分钟应该可以胜任愉快。

了解类别大致上的长相以後,让我们来看看实作的部份是怎麽一回事,先从CMidi::Play()开始:

DWORD CMidi::Play(HWND hwnd,char* MidiFile)

{

// 开启Midi的硬体装置,我们使用一般内定值

mciOpenParms.lpstrDeviceType = "sequencer";

//这个叁数就是要播放的MIDI档案名称

mciOpenParms.lpstrElementName = MidiFile;

// 使用Message的方式来播放MIDI而不是STRING的方式

if (dwReturn = mciSendCommand(NULL, MCI_OPEN,

MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,

(DWORD)(LPVOID) &mciOpenParms)

return (dwReturn);

// The device opened successfully; get the device ID.

wDeviceID = mciOpenParms.wDeviceID;

// Check if the output port is the MIDI mapper.

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);

}

// 为了达成重复播放的目的,必须让我们的程式能够接收到

// MM_MCINOTIFY的讯息,这个函示呼叫的方式,就是传递

// WM_PLAY讯息给装置,叫他开始播放。

mciPlayParms.dwCallback = (DWORD) hwnd;

if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,

(DWORD)(LPVOID) &mciPlayParms))

{

mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);

return (dwReturn);

}

return (0L);

};

播放MIDI的方式有两种,第一种是利用字串命令硬体动作,第二种是传递讯息的方式,我们采用第二种,原因很清楚了,必须透过讯息的传递,我们才能得知音乐是否播放完毕了。

接下来我们看看Cmidi::Replay是怎麽一回事:

void CMidi::Replay()

{

mciSendCommand(wDeviceID, MCI_SEEK,MCI_SEEK_TO_START, NULL);

mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID) &mciPlayParms);

}

真是不可思议地简单呀,函示里面只包含两条呼叫,第一条呼叫送讯息给装置,叫他把MIDI的播放指标移到最开头的部份,也就是MCI_SEEK_TO_START,

作法就像移动档案指标一样。接着第二条指令光看也明白,就是叫他继续播放就是了,而且别忘了MCI_NOTIFY,当下次播放完毕,还是得用讯息通知我们的程式。

最後看一下Cmidi::Stop()的作法:

void CMidi::Stop()

{

mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);

}

越来越单纯了,里面只有包含一个函示呼叫,其中的讯息叁数MCI_CLOSE,就是结束整个音乐的播放。当你结束播放以後,要播放另一首音乐,很简单,再次呼叫Cmidi::Play()即可。

整个类别的使用方法大致上是这样的:首先配置一个实际的CMidi物件给程式,只要在全域的地方下条指令 CMidi midi;即可,尔後midi就是真实的物件了。在场景初始化的部份呼叫midi.Play(hwnd,"ff3celes.mid");,输入正确的MIDI档名即可。此处我播放的是太空战士三代的音乐,只是示范一下,当然这首音乐确实很棒就是了。而在讯息回圈里面,我们必须定义一个讯息:

case MM_MCINOTIFY:

midi.Replay();

break;

在音乐播放完毕以後,我们的讯息回圈会收到MM_MCINOTIFY这个讯息,这时候如同我们前面所言,呼叫Cmidi::Replay()即可。而当场景更换,要重新一首新的音乐,或是程式结束的时候,就是呼叫Cmidi::Stop()的时机。因为一个场景同时间只会存在一首音乐,所以我们的类别表现良好,不用担心。

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧