zoukankan      html  css  js  c++  java
  • mfc小工具开发之定时闹钟之---时间获取和音频播放

    1.这里的音频文件是指*.wav格式的音频,参考了飞雪的音频文件,版本号:

    飞雪桌面日历 v2.84.1025 绿色版

    http://www.piaodown.com/down/soft/18512.htm

    在此表示感谢,播放函数接口如下

    一、使用PlaySound()函数

    该函数的原型的是:

    BOOL PlaySound(

         LPCSTR pszSound,  

         HMODULE hmod,     

         DWORD fdwSound    

    )

    其中,参数pszSound指定要播放文件的文件名,若该参数为NULL,则停止正在播放的声音;

            参数hmod说明资源的句柄;

            参数fdwSound则指定该命令的标志,也就是说明播放WAV文件的方式,可以取以下值:

    标志

    说明

    SND_ASYNC

    异步播放声音

    SND_SYNC

    同步播放声音(默认)

    SND_NODEFAULT

    若pszSound指定的文件找不到,不使用默认声音

    SND_MEMORY

    pszSound指向的一个内存文件

    SND_LOOP

    循环播放声音,直到下一次调用PlaySound()且pszSound参数为NULL,此标志要与SND_ASYNC一起使用

    SND_NOSTOP

    不停止当前正在播放的任何声音

    SND_RESOURCE

    表示pszSound是一个资源的标识符,而hmod则是包含这个资源的一个实例

    SND_FILENAME

    表示pszSound是一个文件名

    SND_ALIAS_ID

    表示pszSound预定义的声音标识符

    SND_ALIAS

    pszSound参数是在注册表或win.ini中定义的一个系统事件,不可与SND_FILENAME或 SND_RESOURCE同时使用。

    SND_NOWAIT

    如果设备正忙,则立即返回而不播放指定的声音

    例:

    //播放call2.wav

    PlaySound("call2.wav",NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);

    //关闭声音

    PlaySound(NULL,NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);

    二、使用sndPlaySound()函数

    该函数的原型的是:

    BOOL sndPlaySound(

         LPCSTR lpszSound,  

         UINT fuSound       

    )

    其中,参数lpszSound指定要播放的文件名,若为NULL,则停止正在播放的声音

             参数fuSound指定播放的方式,可取以下值:

    SND_ASYNC,SND_SYNC,SND_LOOP,SND_MEMORY,SND_DODEFAULT,SND_NOSTOP

    各个标志的含义同上。

    例:

    //播放call1.wav

    sndPlaySound("call1.wav",SND_ASYNC | SND_LOOP);

    //关闭声音

    sndPlaySound(NULL,SND_ASYNC | SND_LOOP);

           以上两个函数使用简洁、方便,但有两个缺陷,即:

    (1) 整个声音必须放入可用的物理内存中,因此,当文件大小小于100K时使用这两个函数,而在大

            于100K时,一般使用MCI方式

    (2) 该声音用的必须是已安装的音频驱动程序之一所支持的数据格式。

        

    三、使用MCI命令

          使用MCI命令实际上也就是利用以下几个相关的API函数完成播放声音的功能:

          mciSendCommand()     //向MCI设备发送命令消息

          mciSendString()      //向MCI设备发送命令字符串

          mciGetErrorString() //获取MCI函数的返回值的文本描述信息

    1.     mciSendCommand()函数

    函数原型:

    MCIERROR mciSendCommand(

         MCIDEVICEID IDDevice,   

         UINT           uMsg,       

         DWORD          fdwCommand,

         DWORD_PTR      dwParam     

    );

    其中,参数IDDevice是接收命令消息的MCI设备的标识,该参数不与命令消息MCI_OPEN同时使用

             参数uMsg是命令消息。具体信息可参考MSDN。

             参数fdwCommand用来设置命令消息的标志

             参数dwParam指向一个包含命令消息参数的结构体

    若函数执行成功返回值为0,否则为错误代码。错误信息可用mciGetErrorString()函数得到。

    例:

    /******************************

    打开音频设备

    *******************************/

    MCI_OPEN_PARMS mciOpenParms;

    DWORD dwResult;

    mciOpenParms.lpstrDeviceType=(LPSTR)MCI_DEVTYPE_WAVEFORM_AUDIO;

    dwResult=mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_WAIT,(DWORD)(LPVOID)&mciOpenParms);

    /******************************

    关闭音频设备

    *******************************/

    mciSendCommand(m_nDeviceID,MCI_CLOSE,NULL,NULL);

    /****************************

    播放WAV文件

    ****************************/

    MCI_OPEN_PARMS mciOpenParms;

    memset(&mciOpenParms,0,sizeof(MCI_OPEN_PARMS));

    //设置要播放的WAV文件名

    mciOpenParms.lpstrElementName=pFileName;

    //打开WAV文件

    DWORD dwResult=mciSendCommand(m_nDeviceID,MCI_OPEN,MCI_OPEN_ELEMENT,(DWORD)(LPVOID)&mciOpenParms);

    2. mciSendString()函数

    函数原型:

    MCIERROR mciSendString(

         LPCTSTR lpszCommand,  

         LPTSTR lpszReturnString,  

         UINT cchReturn,       

         HANDLE hwndCallback   

    );

    其中,参数lpszCommand是一个以''结尾的命令字符串,相关字符串与mciSendCommand()函数中参数uMsg的消息相对应,详见

    MSDN

             参数lpszReturnString指向一个用来存储返回信息的缓冲区。若不需要返回信息,可设为NULL

             参数cchReturn是用来存储返回信息的lpszReturnString的字节数

             若在命令字符串中指定了"notify"(通告),则参数hwndCallback指向一个回调窗口。

    返回值与mciSendCommand()函数相似

    3. mciGetErrorString()函数

    函数原型:

    BOOL mciGetErrorString(

         DWORD fdwError,        

         LPTSTR lpszErrorText,  

         UINT cchErrorText      

    );

    其中,参数fdwError是mciSendCommand()函数或mciSendString()函数返回的错误码

             参数lpszErrorText指向一个缓冲区,该缓冲区接收一个以''结尾的错误描述字符串

             参数cchErrorText用来存储返回信息的lpszErrorText的字节数

    例:

    char szErrorMsg[MAXERRORLENGTH];

    //获取错误描述信息

    if(!mciGetErrorString(dwError,szErrorMsg,sizeof(szErrorMsg)))

    strcpy(szErrorMsg,"Unknown Error!");

    另外,需要注意的是:要包含一个头文件"Mmsystem.h",在链接的时候也要使用一个库文件"Winmm.lib"

    http://blog.163.com/baansss0624@126/blog/static/55578661200822111632521/

    2.时间获取

    MFC获取当前时间

    windows相关 2009-10-05 23:22:16 阅读222 评论0 字号:大中小
    一、使用MFC可以用以下代码得到

    CTime time = CTime::GetCurrentTime();   ///构造CTime对象
    int m_nYear = time.GetYear();      ///年
    int m_nMonth = time.GetMonth();      ///月
    int m_nDay = time.GetDay();      ///日
    int m_nHour = time.GetHour();      ///小时
    int m_nMinute = time.GetMinute();   ///分钟
    int m_nSecond = time.GetSecond();   ///秒

    我们还可以用CTime::Format函数将CTime对象转换为字符串对象
    例如:
    CString m_strTime = time.Format("%Y-%m-%d %H:%M:%S");

    运行结果:m_strTime为 2001-8-1 12:11:05

    二、使用GetSystemTime()这个API函数得到系统时间

    SYSTEMTIME ti;
    GetSystemTime(&ti);
    ////我们可以通过读取SYSTEMTIME结构体成员直接得到时间
    typedef struct _SYSTEMTIME {
        WORD wYear;
        WORD wMonth;
        WORD wDayOfWeek;
        WORD wDay;
        WORD wHour;
        WORD wMinute;
        WORD wSecond;
        WORD wMilliseconds;
    } SYSTEMTIME, *PSYSTEMTIME;

    例如:ti.wMilliseconds;可以得到毫秒时间

    以下是转载的:CTime以及其它时间差

    一、DateTimePicker控件

    引用一个DateTimePicker控件,关联变量m_date为DateTimeCtrl类型,然后在响应事件中加入如下代码:

       CTime tm;
       m_date.GetTime(tm);
       CString strDate=tm.Format("%Y-%m-%d");

    就可以获取了...但是不知为何这个还和Vc的版本问题有关,开始时候我用的版本总是出错,或者srtDate为空,或者不是用户选择的日期,后来换了一个VC版本就能得到正确的数据了...

    另外如果关联一个CTime类型的变量也能解决上面的问题,但是初始化的日期是1970-01-01而上面方法中初始化的日期是当前日期...所以根据用户需要的设定可以选择任何一种方法进行解决...

    二、CTimeSpan获取时间差

    要获取两个时间差,如两个CTime的时间差,可以使用MFC中的CTimeSpan类。

    CTime time1 = CTime::GetCurrentTime(); ...其它代码... CTime time2 = CTime::GetCurrentTime(); // 两个CTime相减得到CTimeSpan CTimeSpan timeSpan = time2 - time1; // 得到总的秒数 int nTSeconds = timeSpan.GetTotalSeconds();

         注意GetTotalSeconds与GetSeconds的区别:GetTotalSeconds返回总的秒数,GetSeconds返回总是小于60,如:如果时间经过了100秒, GetTotalSeconds返回100,而GetSeconds返回40,因为有60秒转为一分钟了,同时使用GetMinutes会返回1,即1分40秒。

    其它类似函数:

    GetDays(); // 返回日数 GetHours(); // 返回小时数(-23至23之间) GetTotalHours(); // 返回总的小时数 GetMinutes(); // 返回分钟数(-59至59之间) GetTotalMinutes(); // 返回总的分钟数 GetSeconds(); // 返回秒数(-59至59之间) GetTotalSeconds(); // 返回总的秒数 三、CTime总结

    1.初始化
         m_begintime=CTime(2004,1,1,0,0,0,-1);//参数依次为year,month,day,hour,minite,second
         m_endtime =CTime::GetCurrentTime();//当前时间
    2.日期比较
    CTimeSpan span;
    span=time1-time2;
    得到两时间的间隔.
    可以取得span.GetHours().等
    3.access数据库查询
    使用DateDiff()函数,具体参照access帮助
    CString timesql;
    timesql.Format(" Where DateDiff('d',%s,'%s')<=0","日期",m_begintime.Format("%Y-%m-%d"));

    4读取日期字段(odbc)
        CDBVariant var;
          recset.GetFieldValue(i,var);
         s.Format("%d-%d-%d",(var.m_pdate)->year,(var.m_pdate)->month,
          (var.m_pdate)->day);
    5.CTime转换为CString
    例:
       m_begintime.Format("%Y-%m-%d");//2004-10-03

    6.CString转换为CTime
        //s="2004-10-5"
       int first=s.Find('-');
        int second=s.Find('-',first+1);
        int year=atoi(s.Left(4));
        int month=atoi(s.Mid(first+1,second-first+1));
        int day=atoi(s.Mid(second+1,s.GetLength()-second-1));
        CTime temp(year,month,day,0,0,0);
    7.判断CString是否表示的正确日期格式
    //判断是否为2004-01-13 ch 可代表其他分隔符
    bool IsDate(CString str,char ch)
    {
    if(str.IsEmpty()) return false;
    //日期分段
    int first=str.Find(ch);
    int second=str.Find(ch,first+1);
    int year=atoi(str.Left(4));
    int month=atoi(str.Mid(first+1,second-first+1));
    int day=atoi(str.Mid(second+1,str.GetLength()-second-1));
        //判断
    if (year < 2000 || year >= 2010)
    {
       return false;
    }
    else if (month< 1 || month >12)
    {
       return false;
    }
    else if (day< 1 || day > 31)
    {
       return false;
    }
    else if (month == 4 || month == 6 || month == 9 || month == 11)
    {
       if(day > 30)
       {
        return false;
       }
       else
       {
        return true;
       }
    }
    else if (month == '2')
    {
       if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
       {
        if (day>29)
        {
         return false;
        }
        else
        {
         return true;
        }
       }
       else if (day>28)
       {
        return false;
       }
       return true;
    }
    else
    {
       return true;
    }
       
    }
    四、
    在MFC中操作时间的类主要有两对:CTime和CTimeSpan与COleDateTime和COleDateTimeSpan,CTime和CTimeSpan主要封装了ANSI time_t和关于time_t的Run-Time库的主要函数,CTime里面使用的成员变量是time_t类型,该类型是个long型,由于long类型的原因,所以该类只能处理4294967296秒约68年的数据,所以用CTime只能处理1970年到2038年的日期。
        幸好,MFC同时提供了COleDateTime和COleDateTimeSpan类,使用该两个类完全可以代替CTime和CTimeSpan,COleDateTime和COleDateTimeSpan类所使用的成员变量是DATE类型,该类型是个double类型,而且使用的单位是日,所以可以处理从100年1月1日到9999年12月31日的日期时间,COleDateTime类的日期计算主要是操作公有成员变量COleDateTime::m_dt,该变量是DATE即double类型,该变量是为零时是1899年12月30日0时0分0秒,大于零时的日期比1899年12月30日0时0分0秒大,反之亦然,例如:
    COleDateTime t;
    t.m_dt=0;
    AfxMessageBox(t.Format("%Y-%m-%d %H:%M:%S"));
    运行的结果是:1899-12-30 00:00:00
    COleDateTime t;
    t.m_dt=39444.437731;
    AfxMessageBox(t.Format("%Y-%m-%d %H:%M:%S"));
    运行的结果是:2007-10-28 10:30:20
    反过来以可以得到变量的值,例如:
    COleDateTime t(2004,12,28,22,22,22);
    CString str;
    str.Format("%f",t.m_dt);
    AfxMessageBox(str);
    运行的结果是:38349.932199
    COleDateTimeSpan类是用于对COleDateTime类的两个时间的时间间隔的计算,COleDateTimeSpan类使用的成员变量COleDateTimeSpan::m_span是一个double类型是用于记录两个COleDateTime::m_dt的时间差,例如:
    COleDateTime t1(2006,1,1,0,0,0);
    COleDateTime t2(2007,1,1,0,0,0);
    COleDateTimeSpan ts=t2-t1;
    CString str;
    str.Format("%f",ts.m_span);
    AfxMessageBox(str);
    运行的结果是:365.000000
    反过来也可以得到日期
    COleDateTime t1(2006,1,1,0,0,0);
    COleDateTimeSpan ts;
    ts.m_span=400.0;
    COleDateTime t2=t1+ts;
    AfxMessageBox(t2.Format("%c"));
    运行的结果是:02/05/07 00:00:00
    可是在使用COleDateTimeSpan类中以下的几个函数可要小心,这不知道是不是MFC的一个Bug,
    double GetTotalDays( ) const;
    double GetTotalHours( ) const;
    double GetTotalMinutes( ) const;
    double GetTotalSeconds( ) const;
    几个函数的返回值都是double类型
    但是,如double GetTotalSeconds( ) const;在MFC内部的原形是:
    _AFXDISP_INLINE double COleDateTimeSpan::GetTotalSeconds() const
    { ASSERT(GetStatus() == valid);
       long lReturns = (long)(m_span * 24 * 60 * 60 + AFX_OLE_DATETIME_HALFSECOND);
       return lReturns;
    }
    看到没有,它返回的实际是个long类型,并不是一个double类型,所以在使用这几个函数的时候计算两个时间的间隔不要太大,特别是GetTotalSeconds( )函数,如计算两个时间的间隔大于68年时就会溢出,所以我建议直接读取COleDateTimeSpan::m_span变量的值,这是一个单位为日的时间间隔,例如:
    COleDateTime t1(2000,1,1,0,0,0);
    COleDateTime t2(2070,1,1,0,0,0);
    COleDateTimeSpan ts=t2-t1;
    CString str;
    str.Format("%f",ts.GetTotalSeconds());
    AfxMessageBox(str);
    运行的结果是:-2085892096.000000
    这个结果明显是一个溢出,如果使用
    str.Format("%f",ts.m_span*86400);
    则会得到2209075200.000000。
    所以灵活使用COleDateTime类的m_dt变量和COleDateTimeSpan类的m_span变量操作会得到意想不到的收获

    http://blog.csdn.net/andyvccc/article/details/5949098

  • 相关阅读:
    CSP2019-S2总结
    #期望dp#洛谷 6835 [Cnoi2020]线形生物
    #树状数组,概率,离散,双指针#洛谷 6834 [Cnoi2020]梦原
    #容斥,倍数,排列组合#洛谷 2714 四元组统计
    #莫队,bitset#洛谷 3674 小清新人渣的本愿
    #贪心#洛谷 3173 [HAOI2009]巧克力
    #树链剖分,LCA#洛谷 3398 仓鼠找sugar
    #树状数组,哈希#洛谷 6687 论如何玩转 Excel 表格
    小甲鱼Python第八讲课后习题
    小甲鱼Python第七讲课后习题
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/3813994.html
Copyright © 2011-2022 走看看