用VC实现简单的录音和播音 && VC的管道操作

      用VC可以进行简单的录音和播音操作,这里调用的是微软的音频开发包,通过MCI函数(Media Control Interface,媒体控制接口)即可实现。只需要新建一个对话框,上面列四个按钮,分别是录音、停止、播放、保存即可。

                              用VC实现简单的录音和播音 && VC的管道操作_第1张图片 

(1)在StdAfx.h中加入下面的语句:

#include<vfw.h>                            //微软的音视频开发头文件

#pragma comment(lib,"vfw32.lib")  //表示链接vfw32.lib库。和在工程设置里写上链入vfw32.lib的效果一样

(2)在dlg.h中定义一个操作句柄,HWND mciwav;

(3)录音按钮实现函数:

void CSoundrecordandplayDlg::OnRecord()
{
      MCIWndClose(mciwav);    //打开一个声音的之前关闭以前的声音
      mciwav = MCIWndCreate(this->m_hWnd,AfxGetApp()->m_hInstance,WS_CAPTION,NULL);

//创建句柄,最后一个参数如果是NULL,就新建一个;如果是一个文件的路径就打开它。

//this->m_hWnd表示父句柄,AfxGetApp()获得当前应用进程的指针,进而取得实例
      MCIWndNew(mciwav,"waveaudio");        //创建设备

      if (MCIWndCanRecord(mciwav))         //判断是否能够录音
     {
          MCIWndRecord(mciwav);
      }
}

(4)录音停止按钮函数:

void CSoundrecordandplayDlg::OnStop()
{
        MCIWndStop(mciwav);
}

(5)录音播放函数:

void CSoundrecordandplayDlg::OnPlay()
{
        if (MCIWndCanPlay(mciwav))           //判断是否能够播放
       {
              MCIWndPlay(mciwav);
       }
}

(6)保存函数

void CSoundrecordandplayDlg::OnSave()
{
       CString m_path;
       CFileDialog wav(FALSE,NULL,NULL,OFN_ALLOWMULTISELECT,"wav File(*.wav)|*.wav");

//构造函数创建一个文件保存对话框,并且设定类型过滤
       if (wav.DoModal() == IDOK)            //如果选择保存按钮。DoModal实际上实现了对话框的创建、显示、关闭的全过程
      {
             m_path = wav.GetPathName();   //获得绝对路径和输入的文件名

      }
      else
      {
             return;
      }   
      if (MCIWndCanSave(mciwav))           //如果能保存
      {
             MCIWndSave(mciwav,"a");        //保存成默认的名字a
             CopyFile("a",m_path,FALSE);     //把a文件拷贝到另一路径和名字
      }
      else
      {
             MessageBox("can not save");
      }

}

//这里再说明DoModal的其它用法,除了上面创建打开或者另存为对话框之外,另一种方式就是调用其它对话框。比如,新建了一个对话框TestDialog,那么使用类向导时会提示为该对话框添加类TestDialogClass。在主对话框的按钮函数中,加入如下代码:

 TestDialogClass test;
 test.DoModal();

即可实现对子对话框的调用。注意编译之前要加上新类的头文件。

=======================================================================================

        管道(Pipe)实际是用于进程间通信的一段共享内存,创建管道的进程称为管道服务器,连接到一个管道的进程为管道客户机。一个进程在向管道写入数据后,另一进程就可以从管道的另一端将其读取出来。匿名管道(Anonymous Pipes)是在父进程和子进程间单向传输数据的一种未命名的管道,只能在本地计算机中使用,而不可用于网络间的通信。

(1)匿名管道实施细则

         匿名管道由CreatePipe()函数创建,该函数在创建匿名管道的同时返回两个句柄:管道读句柄和管道写句柄。CreatePipe()的函数原型为:

BOOL CreatePipe(PHANDLE hReadPipe, // 指向读句柄的指针
 PHANDLE hWritePipe, // 指向写句柄的指针
 LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全属性的指针
 DWORD nSize // 管道大小
);

通过hReadPipe和hWritePipe所指向的句柄可分别以只读、只写的方式去访问管道。调用WriteFile()将数据写入到管道,通过ReadFile()从管道读取出数据。匿名管道并不支持异步读、写操作,这也就意味着不能在匿名管道中使用ReadFileEx()和WriteFileEx(),

(2)通过管道实现执行ADB控制,也即利用管道执行CMD命令,并可得到回显。首先做出如下的一个界面:两个编辑框,一个文本框,两个按钮。

用VC实现简单的录音和播音 && VC的管道操作_第2张图片

主要的流程在执行的函数中,启动一个后台执行线程

void CPipeDlg::OnButton2() 
{
	// TODO: Add your control notification handler code herestrCmd
	_beginthreadex(NULL,0,CmdThread,NULL,0,NULL);
}

     线程函数如下:

unsigned __stdcall CmdThread(void *pParam)
{   
	//cd C:\Documents and Settings\Administrator\桌面\android-sdk-windows\platform-tools&adb devices&adb pull sdcard/DCIM/100ANDRO C:/MFC/

	SECURITY_ATTRIBUTES sa;
	HANDLE hRead,hWrite;
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;

	CString strCmd;
	g_dlg->m_cmdEdit.GetWindowText(strCmd);//从控件获得cmd命令串
	strCmd="cmd /k"+strCmd;//加上"cmd /k"是为了能执行类似dir的命令

	if(strCmd.IsEmpty())
	{
		return TRUE;
	}
	//创建命名管道
	if (!CreatePipe(&hRead,&hWrite,&sa,0)) {
		//MessageBox("Error On CreatePipe()");
		return FALSE;
	}
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	si.cb = sizeof(STARTUPINFO);
	GetStartupInfo(&si);
	si.hStdError = hWrite;//数据输出用的文件句柄
	si.hStdOutput = hWrite;//数据输出用的文件句柄
	si.wShowWindow = SW_HIDE;
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;


	OutputDebugString("1");

	if (!CreateProcess(NULL,strCmd.GetBuffer(strCmd.GetLength())//执行cmd命令,并在命名中管道中写入cmd命令返回的串
		,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi)) {
		//MessageBox("Error on CreateProcess()");
		return FALSE;
	}
	/*if(WaitForSingleObject(pi.hProcess, INFINITE)==WAIT_FAILED)//这里决定是否要等整个命令执行完,如ping等耗时较多的命令.
	{
		//MessageBox("Failed!");
		return FALSE;
	}*/
	CloseHandle(hWrite);
	OutputDebugString("2");
	
	char buffer[4096] ={0} ;
	DWORD bytesRead;
	CString strResult="";
	
	while(1)
	{
		memset(buffer,0,4096);
		if(ReadFile(hRead,buffer,4096,&bytesRead,NULL) != NULL)//从命名管道中读取数据
		{
			strResult += buffer;
			g_dlg->m_Ed.SetWindowText(strResult);//显示到界面上去
			OutputDebugString(buffer);
			
		}
		else
		{
			break;
		}
	}
	CloseHandle(hRead);
	return TRUE;
} 



 

 

 

 

 

参考原文:http://hi.baidu.com/rk1105/item/326be4e3e50b070b8d3ea8d3?qq-pf-to=pcqq.c2c

你可能感兴趣的:(File,null,Path,interface,微软)