用VC可以进行简单的录音和播音操作,这里调用的是微软的音频开发包,通过MCI函数(Media Control Interface,媒体控制接口)即可实现。只需要新建一个对话框,上面列四个按钮,分别是录音、停止、播放、保存即可。
(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命令,并可得到回显。首先做出如下的一个界面:两个编辑框,一个文本框,两个按钮。
主要的流程在执行的函数中,启动一个后台执行线程
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