windows 程序设计之「RECORD2.C」范例分析笔记

2024-05-01 03:18

本文主要是介绍windows 程序设计之「RECORD2.C」范例分析笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

/*----------------------------------------

   RECORD2.C -- Waveform Audio Recorder

                (c) Charles Petzold, 1998

------------------------------------------*/

 

#include <windows.h>

#include "..//record1//resource.h" // RECORD1.C 中的资源标识符头文件

 

BOOL CALLBACK DlgProc (HWND, UINT, WPARAM, LPARAM) ;

 

TCHAR szAppName [] = TEXT ("Record2") ;

 

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

                    PSTR szCmdLine, int iCmdShow)

{

     if (-1 == DialogBox (hInstance, TEXT ("Record"), NULL, DlgProc))

     {

          MessageBox (NULL, TEXT ("This program requires Windows NT!"),

                      szAppName, MB_ICONERROR) ;

     }

     return 0 ;

}

 

void ShowError (HWND hwnd, DWORD dwError)

{

     TCHAR szErrorStr [1024] ;

    

     mciGetErrorString (dwError, szErrorStr,

                        sizeof (szErrorStr) / sizeof (TCHAR)) ;

     MessageBeep (MB_ICONEXCLAMATION) ;

     MessageBox (hwnd, szErrorStr, szAppName, MB_OK | MB_ICONEXCLAMATION) ;

}

 

BOOL CALLBACK DlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

     static BOOL       bRecording, bPlaying, bPaused ;

     static TCHAR      szFileName[] = TEXT ("record2.wav") ;

     static WORD       wDeviceID ;

     DWORD             dwError ;

     MCI_GENERIC_PARMS mciGeneric ;

     MCI_OPEN_PARMS    mciOpen ;

     MCI_PLAY_PARMS    mciPlay ;

     MCI_RECORD_PARMS  mciRecord ;

     MCI_SAVE_PARMS    mciSave ;

    

     switch (message)

     {

     case WM_COMMAND:

          switch (wParam)

          {

          case IDC_RECORD_BEG:

                    // 删除现有的波形文件

               DeleteFile (szFileName) ;

               // 设置MCI_OPEN_PARMS结构

               // dwCallback 低位字指定一个窗口句柄;用于MCI_NOTIFY旗标

               mciOpen.dwCallback       = 0 ;

               // 调用后用于记录使用的设备标识符

               mciOpen.wDeviceID        = 0 ;

               // 常数标识符名称或设备类型

               mciOpen.lpstrDeviceType  = TEXT ("waveaudio") ;

               // 设备元件(通常是一个路径)

               mciOpen.lpstrElementName = TEXT ("") ;

               // 可选设备别名

               mciOpen.lpstrAlias       = NULL ;

               // MCI_OPEN  初始化一个设备或文件

               dwError = mciSendCommand (0, MCI_OPEN,

                   // MCI_WAIT  指导设备的等待,直到完成所要求的行动才返回控制权

                   // MCI_OPEN_TYPE 表示要使用MCI_OPEN_PARMS结构中的LpstrDiviceType参数

                   // MCI_OPEN_ELEMENT 表示LpstrDeviceType参数中的是设备表述字符串

                   // 还可以使用 MCI_OPEN_TYPE_ID 表示LpstrDeviceType参数中的是设备标识符

                                   MCI_WAIT | MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,

                                   // 指向一个结构,它包含命令的消息参数

                                   (DWORD) (LPMCI_OPEN_PARMS) &mciOpen) ;

               if (dwError != 0)

               {

                    ShowError (hwnd, dwError) ;

                    return TRUE ;

               }

                    // 储存设备ID

               wDeviceID = mciOpen.wDeviceID ;

              

                    // 设置用于录制的命令数据

               // dwCallback 低位字指定一个窗口句柄;用于MCI_NOTIFY旗标

               mciRecord.dwCallback = (DWORD) hwnd ;

               mciRecord.dwFrom     = 0 ;

               mciRecord.dwTo       = 0 ;

               // MCI_RECORD 启动录音功能

// MCI_NOTIFY 旗标导致录音结束后系统向mciRecord.dwCallback元素中指定的窗口句柄发送一条MM_MCINOTIFY通知消息

               mciSendCommand (wDeviceID, MCI_RECORD, MCI_NOTIFY,

                               (DWORD) (LPMCI_RECORD_PARMS) &mciRecord) ;

              

                    // 设置按钮是否有效和当前焦点

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), TRUE) ;

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   FALSE);

               SetFocus (GetDlgItem (hwnd, IDC_RECORD_END)) ;

              

               bRecording = TRUE ;

               return TRUE ;

               

          case IDC_RECORD_END:

                    // 停止录音

               mciGeneric.dwCallback = 0 ;

               // MCI_STOP 命令消息用于停止先前的录音命令

               mciSendCommand (wDeviceID, MCI_STOP, MCI_WAIT,

                               (DWORD) (LPMCI_GENERIC_PARMS) &mciGeneric) ;

              

                    // 保存声音文件

               mciSave.dwCallback = 0 ;

               mciSave.lpfilename = szFileName ;

               // MCI_SAVE 命令用于对先前录制在临时文件中的声音文件进行保持

               // MCI_SAVE_FILE 指出保存的文件名在mciSave.lpfilename元素中指定

               mciSendCommand (wDeviceID, MCI_SAVE, MCI_WAIT | MCI_SAVE_FILE,

                               (DWORD) (LPMCI_SAVE_PARMS) &mciSave) ;

              

                    // 关闭打开的设备

               // MCI_CLOSE命令消息用于删除所有的临时文件、释放已经建立的内存块并关闭设备

               mciSendCommand (wDeviceID, MCI_CLOSE, MCI_WAIT,

                               (DWORD) (LPMCI_GENERIC_PARMS) &mciGeneric) ;

 

               // 设置按钮是否有效和当前焦点

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), TRUE) ;

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   TRUE) ;

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   FALSE);

               SetFocus (GetDlgItem (hwnd, IDC_PLAY_BEG)) ;

               // 录音进行中标记

               bRecording = FALSE ;

               return TRUE ;

              

          case IDC_PLAY_BEG:

                    // 打开波形音频

 

               mciOpen.dwCallback       = 0 ;

               mciOpen.wDeviceID        = 0 ;

               mciOpen.lpstrDeviceType  = NULL ;

               mciOpen.lpstrElementName = szFileName ;

               mciOpen.lpstrAlias       = NULL ;

               

               // MCI_OPEN_ELEMENT 标记表示lpstrElementName字段是一个有效的文件名

               dwError = mciSendCommand (0, MCI_OPEN,

                                         MCI_WAIT | MCI_OPEN_ELEMENT,

                                         (DWORD) (LPMCI_OPEN_PARMS) &mciOpen) ;

              

               if (dwError != 0)

               {

                    ShowError (hwnd, dwError) ;

                    return TRUE ;

               }

                    // Save the device ID

              

               wDeviceID = mciOpen.wDeviceID ;

              

                    // Begin playing

              

               mciPlay.dwCallback = (DWORD) hwnd ;

               mciPlay.dwFrom     = 0 ;

               mciPlay.dwTo       = 0 ;

               // 播放波形音频文件

               // MCI_NOTIFY 旗标导致播放结束后系统向mciPlay.dwCallback元素中指定的窗口句柄发送一条MM_MCINOTIFY通知消息

               mciSendCommand (wDeviceID, MCI_PLAY, MCI_NOTIFY,

                               (DWORD) (LPMCI_PLAY_PARMS) &mciPlay) ;

              

                    // Enable and disable buttons

              

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), TRUE) ;

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   TRUE) ;

               SetFocus (GetDlgItem (hwnd, IDC_PLAY_END)) ;

              

               bPlaying = TRUE ;

               return TRUE ;

              

          case IDC_PLAY_PAUSE:

              // 如果暂停按钮之前没有被按下则执行暂停操作

               if (!bPaused)

               {

                    mciGeneric.dwCallback = 0 ;

                    // 发出暂停指令

                    mciSendCommand (wDeviceID, MCI_PAUSE, MCI_WAIT,

                                    (DWORD) (LPMCI_GENERIC_PARMS) & mciGeneric);

                    // 设置暂停按钮字样

                    SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Resume")) ;

                    // 标记暂停被按下

                    bPaused = TRUE ;

               }

               // 否者执行继续播放操作

               else

               {

                    mciPlay.dwCallback = (DWORD) hwnd ;

                    mciPlay.dwFrom     = 0 ;

                    mciPlay.dwTo       = 0 ;

                    // MCI_NOTIFY 旗标导致播放结束后系统向mciPlay.dwCallback元素中指定的窗口句柄发送一条MM_MCINOTIFY通知消息

                    mciSendCommand (wDeviceID, MCI_PLAY, MCI_NOTIFY,

                                    (DWORD) (LPMCI_PLAY_PARMS) &mciPlay) ;

                   

                    SetDlgItemText (hwnd, IDC_PLAY_PAUSE, TEXT ("Pause")) ;

                    bPaused = FALSE ;

               }

              

               return TRUE ;

              

          case IDC_PLAY_END:

                    // 停止播放,并关闭设备

              

               mciGeneric.dwCallback = 0 ;

              

               mciSendCommand (wDeviceID, MCI_STOP, MCI_WAIT,

                               (DWORD) (LPMCI_GENERIC_PARMS) &mciGeneric) ;

              

               mciSendCommand (wDeviceID, MCI_CLOSE, MCI_WAIT,

                               (DWORD) (LPMCI_GENERIC_PARMS) &mciGeneric) ;

              

                    // Enable and disable buttons

              

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_BEG), TRUE) ;

               EnableWindow (GetDlgItem (hwnd, IDC_RECORD_END), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_BEG),   TRUE) ;

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_PAUSE), FALSE);

               EnableWindow (GetDlgItem (hwnd, IDC_PLAY_END),   FALSE);

               SetFocus (GetDlgItem (hwnd, IDC_PLAY_BEG)) ;

               // 播放进行中标记

               bPlaying = FALSE ;

 

               bPaused  = FALSE ;

               return TRUE ;

          }

          break ;

              

     case MM_MCINOTIFY:

          switch (wParam)

          {

          case MCI_NOTIFY_SUCCESSFUL:

              // 如果播放或录音正在进行中,则发送停止消息

               if (bPlaying)

                    SendMessage (hwnd, WM_COMMAND, IDC_PLAY_END, 0) ;

              

               if (bRecording)

                    SendMessage (hwnd, WM_COMMAND, IDC_RECORD_END, 0);

              

               return TRUE ;

          }

          break ;

    

     case WM_SYSCOMMAND:

          switch (wParam)

          {

          case SC_CLOSE:

               if (bRecording)

                    SendMessage (hwnd, WM_COMMAND, IDC_RECORD_END, 0L) ;

              

               if (bPlaying)

                    SendMessage (hwnd, WM_COMMAND, IDC_PLAY_END, 0L) ;

              

               EndDialog (hwnd, 0) ;

               return TRUE ;

          }

          break ;

     }

     return FALSE ;

}

 

 

这篇关于windows 程序设计之「RECORD2.C」范例分析笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950600

相关文章

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

windows系统下shutdown重启关机命令超详细教程

《windows系统下shutdown重启关机命令超详细教程》shutdown命令是一个强大的工具,允许你通过命令行快速完成关机、重启或注销操作,本文将为你详细解析shutdown命令的使用方法,并提... 目录一、shutdown 命令简介二、shutdown 命令的基本用法三、远程关机与重启四、实际应用

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

javafx 如何将项目打包为 Windows 的可执行文件exe

《javafx如何将项目打包为Windows的可执行文件exe》文章介绍了三种将JavaFX项目打包为.exe文件的方法:方法1使用jpackage(适用于JDK14及以上版本),方法2使用La... 目录方法 1:使用 jpackage(适用于 JDK 14 及更高版本)方法 2:使用 Launch4j(

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

windows端python版本管理工具pyenv-win安装使用

《windows端python版本管理工具pyenv-win安装使用》:本文主要介绍如何通过git方式下载和配置pyenv-win,包括下载、克隆仓库、配置环境变量等步骤,同时还详细介绍了如何使用... 目录pyenv-win 下载配置环境变量使用 pyenv-win 管理 python 版本一、安装 和

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结