www.pudn.com > agentnet.zip > AgentNetClientDlg.cpp


// AgentNetClientDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "AgtSvr.h" 
#include "AgtSvr_i.c" 
#include "AgentNetClient.h" 
#include "AgentNetClientDlg.h" 
#include "logindlg.h" 
#include "toserversocket.h" 
#include "msg.h" 
#include "sendgeneralmsgdlg.h" 
#include "receivegeneralmsgdlg.h" 
#include "notify.h" 
#include "common.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
//agent 定义 
long				g_lNotifySinkID = -1; 
 
///////////////////////////////////////////////////////////////////////////// 
// CAboutDlg dialog used for App About 
 
class CAboutDlg : public CDialog 
{ 
public: 
	CAboutDlg(); 
 
// Dialog Data 
	//{{AFX_DATA(CAboutDlg) 
	enum { IDD = IDD_ABOUTBOX }; 
	//}}AFX_DATA 
 
	// ClassWizard generated virtual function overrides 
	//{{AFX_VIRTUAL(CAboutDlg) 
	protected: 
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support 
	//}}AFX_VIRTUAL 
 
// Implementation 
protected: 
	//{{AFX_MSG(CAboutDlg) 
	//}}AFX_MSG 
	DECLARE_MESSAGE_MAP() 
}; 
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 
{ 
	//{{AFX_DATA_INIT(CAboutDlg) 
	//}}AFX_DATA_INIT 
} 
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAboutDlg) 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 
	//{{AFX_MSG_MAP(CAboutDlg) 
		// No message handlers 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CAgentNetClientDlg dialog 
 
CAgentNetClientDlg::CAgentNetClientDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CAgentNetClientDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CAgentNetClientDlg) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 
 
void CAgentNetClientDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CAgentNetClientDlg) 
	DDX_Control(pDX, IDC_TREE, m_TreeCtrl); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CAgentNetClientDlg, CDialog) 
	//{{AFX_MSG_MAP(CAgentNetClientDlg) 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_WM_DESTROY() 
	ON_WM_TIMER() 
	ON_NOTIFY(NM_DBLCLK, IDC_TREE, OnDblclkTree) 
	ON_COMMAND(ID_MENUITEM_AGENT_HIDE, OnMenuitemAgentHide) 
	ON_COMMAND(ID_MENUITEM_AGENT_READ_NEWS, OnMenuitemAgentReadNews) 
	ON_COMMAND(ID_MENUITEM_EXIT_AGENT_NET, OnMenuitemExitAgentNet) 
	ON_COMMAND(ID_MENUITEM_READ_CLIPBORAD, OnMenuitemReadClipborad) 
	ON_COMMAND(ID_MENUITEM_STOP_ALL, OnMenuitemStopAll) 
	ON_COMMAND(ID_MENUITEM_SET_CAN_SPEAK, OnMenuitemSetCanSpeak) 
	ON_COMMAND(ID_MENUITEM_SET_CANNOT_SPEAK, OnMenuitemSetCannotSpeak) 
	ON_COMMAND(ID_MENUITEM_GET_MAIL, OnMenuitemGetMail) 
	ON_COMMAND(ID_MENUITEM_READ_MAIL, OnMenuitemReadMail) 
	//}}AFX_MSG_MAP 
 
    //语音识别事件消息处理 
	ON_MESSAGE(WM_RECOEVENT,ProcessRecoEvent) 
	//在AGENT上弹出右键菜单 
	ON_MESSAGE(WM_SHOW_POP_MENU,ShowPopupMenu) 
 
    //邮件账号没设定事件消息处理 
	ON_MESSAGE(WM_MAIL_ACCOUNT_NOT_SET,ProcessMailAccountNotSet) 
 
    //邮件账号没设定事件消息处理 
	ON_MESSAGE(WM_MAIL_CANNOT_LOGIN,ProcessMailCannotLogin) 
 
    //有邮件要处理事件消息处理 
	ON_MESSAGE(WM_MAIL_PROCESS,ProcessReadMail) 
 
    //没有新邮件要处理事件消息处理 
	ON_MESSAGE(WM_MAIL_NO_NEW_MAIL,ProcessNoMail) 
 
    //邮件处理完成事件消息处理 
	ON_MESSAGE(WM_MAIL_PROCESS_DONE,ProcessMailDone) 
 
 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CAgentNetClientDlg message handlers 
 
BOOL CAgentNetClientDlg::OnInitDialog() 
{ 
	CDialog::OnInitDialog(); 
 
	// Add "About..." menu item to system menu. 
 
	// IDM_ABOUTBOX must be in the system command range. 
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 
	ASSERT(IDM_ABOUTBOX < 0xF000); 
 
	CMenu* pSysMenu = GetSystemMenu(FALSE); 
	if (pSysMenu != NULL) 
	{ 
		CString strAboutMenu; 
		strAboutMenu.LoadString(IDS_ABOUTBOX); 
		if (!strAboutMenu.IsEmpty()) 
		{ 
			pSysMenu->AppendMenu(MF_SEPARATOR); 
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 
		} 
	} 
 
	// Set the icon for this dialog.  The framework does this automatically 
	//  when the application's main window is not a dialog 
	SetIcon(m_hIcon, TRUE);			// Set big icon 
	SetIcon(m_hIcon, FALSE);		// Set small icon 
	 
	// TODO: Add extra initialization here 
	InitSetup();				//初始化设置 
	InitOthers();				//初始化好友烈表时钟 
	InitSocket();				//初始化网络socket 
	InitTree();					//初始化好友树 
	InitSR();					//初始化SR语音识别引擎 
	InitTTS();					//初始化TTS语音合成引擎 
	InitAgent();				//初始化agent接口 
	InitMailAccount();          //初始化邮件账号 
 
	 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CAgentNetClientDlg::OnSysCommand(UINT nID, LPARAM lParam) 
{ 
	if ((nID & 0xFFF0) == IDM_ABOUTBOX) 
	{ 
		CAboutDlg dlgAbout; 
		dlgAbout.DoModal(); 
	} 
	else 
	{ 
		CDialog::OnSysCommand(nID, lParam); 
	} 
} 
 
// If you add a minimize button to your dialog, you will need the code below 
//  to draw the icon.  For MFC applications using the document/view model, 
//  this is automatically done for you by the framework. 
 
void CAgentNetClientDlg::OnPaint()  
{ 
	if (IsIconic()) 
	{ 
		CPaintDC dc(this); // device context for painting 
 
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 
 
		// Center icon in client rectangle 
		int cxIcon = GetSystemMetrics(SM_CXICON); 
		int cyIcon = GetSystemMetrics(SM_CYICON); 
		CRect rect; 
		GetClientRect(&rect); 
		int x = (rect.Width() - cxIcon + 1) / 2; 
		int y = (rect.Height() - cyIcon + 1) / 2; 
 
		// Draw the icon 
		dc.DrawIcon(x, y, m_hIcon); 
	} 
	else 
	{ 
		CDialog::OnPaint(); 
	} 
} 
 
// The system calls this to obtain the cursor to display while the user drags 
//  the minimized window. 
HCURSOR CAgentNetClientDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
 
void CAgentNetClientDlg::OnReceive() 
{ 
	do 
	{ 
		//接收消息 
		ReceiveMsg(); 
		if (m_pSocket==NULL) 
			return; 
	} 
	while (!m_pArchiveIn->IsBufferEmpty()); 
	 
} 
 
void CAgentNetClientDlg::InitSocket() 
{ 
	//初始化socket 
	m_pSocket=m_pLoginDlg->m_pSocket; 
 
	//创建CSocketFile类对象 
	m_pFile=new CSocketFile(m_pSocket); 
	//创建CArchive类对象 
	m_pArchiveIn=new CArchive(m_pFile,CArchive::load); 
	m_pArchiveOut=new CArchive(m_pFile,CArchive::store); 
 
	//设定socket为online 可以让socket调用主对话框 
	m_pSocket->SetOnLine(); 
	m_pSocket->SetMainDlg(this); 
 
} 
 
void CAgentNetClientDlg::InitTree() 
{ 
	 
	CAgentNetClientApp *pApp=(CAgentNetClientApp *)AfxGetApp();//取得控制程序 
    m_ImageList.Create(16,16,ILC_COLOR,0,1);     //建立16*16图像控制 
	m_ImageList.SetBkColor(RGB(255,255,255)); 
     
	m_ImageList.Add(pApp->LoadIcon(IDI_ICON_MEMBER1)); //增加好友图像 
 
	//树控件 
    m_TreeCtrl.SetImageList(&m_ImageList,TVSIL_NORMAL);  //设置图像控制列表 
 
	m_TreeCtrl.DeleteAllItems(); 
	AskServerListOnlineBuddy(); 
 
} 
 
void CAgentNetClientDlg::InitOthers() 
{ 
	m_strUserName=m_pLoginDlg->m_strUserName; 
	m_bProcessMailThread=FALSE; 
 
	//改变对话框标题为用户名 
	SetWindowText(m_strUserName); 
	//开列好友时钟 8秒钟更新 
	SetTimer(1,8*1000,NULL); 
} 
 
void CAgentNetClientDlg::AskServerListOnlineBuddy() 
{ 
	CMsg* pMsg=new CMsg; 
	pMsg->m_strCommand="ask_server_list_online_buddy"; 
	pMsg->m_strUser=m_strUserName; 
	SendMsg(pMsg); 
 
} 
 
void CAgentNetClientDlg::SendMsg(CMsg *pMsg) 
{ 
	if (m_pArchiveOut!=NULL) 
	{ 
		TRY 
		{ 
			//发送消息 
			pMsg->Serialize(*m_pArchiveOut); 
			//将CArchive对象中数据强制存储到CSocketFile对象中 
			m_pArchiveOut->Flush(); 
		} 
		CATCH(CFileException,e) 
		{ 
			//错误处理 
			m_pArchiveOut->Abort(); 
			delete m_pArchiveOut; 
			m_pArchiveOut=NULL; 
			CString strTemp; 
			strTemp="服务器重置连接!"; 
			AfxMessageBox(strTemp); 
		} 
		END_CATCH 
	} 
} 
 
void CAgentNetClientDlg::ReceiveMsg() 
{ 
	CMsg msg; 
	TRY 
	{ 
		//接收消息 
		msg.Serialize(*m_pArchiveIn); 
		if (msg.m_strCommand!="") 
		{ 
 
			if (msg.m_strToUser==m_strUserName) 
			{ 
				if (msg.m_strCommand=="reply_server_list_online_buddy") 
				{ 
					//处理更新好友列表信息 
					ProcessReplyListOnlineBuddy(msg.m_strText); 
				} 
				if (msg.m_strCommand=="buddy_logout") 
				{ 
					//处理好友下线信息 
					ProcessBuddyLogout(msg.m_strText); 
				} 
				if (msg.m_strCommand=="receive_general_message") 
				{ 
					//处理好友信息 
					ProcessReceiveGeneralMsg(msg.m_strUser,msg.m_strText); 
				} 
				if (msg.m_strCommand=="request_read_news") 
				{ 
					//处理好友下线信息 
					ProcessRequestReadNews(msg.m_strText); 
				} 
 
			} 
 
		} 
	} 
	CATCH(CFileException,e) 
	{ 
		//错误处理 
		m_pArchiveOut->Abort(); 
		CString strTemp; 
		strTemp="连接关闭!"; 
		AfxMessageBox(strTemp); 
	} 
	END_CATCH 
 
 
} 
 
void CAgentNetClientDlg::OnDestroy()  
{ 
	// TODO: Add your message handler code here 
	LogOut(); 
	ReleaseAgent(); 
	ReleaseTTS(); 
	ReleaseSR(); 
	CoUninitialize(); 
 
 
	CDialog::OnDestroy(); 
	 
 
} 
 
void CAgentNetClientDlg::OnTimer(UINT nIDEvent)  
{ 
	// TODO: Add your message handler code here and/or call default 
	//好友列表更新 
	if (nIDEvent==1) 
	{ 
		AskServerListOnlineBuddy(); 
	} 
	//语音命令 
	if (nIDEvent==2) 
	{ 
		KillTimer(2); 
		SetHearCommand(FALSE); 
		m_bWantExit=FALSE; 
		m_bAnswer=FALSE; 
		AgentStop(); 
	} 
 
	 
	CDialog::OnTimer(nIDEvent); 
} 
 
void CAgentNetClientDlg::ProcessReplyListOnlineBuddy(CString strUserName) 
{ 
	//处理更新好友列表信息 
	int nTreeCount; 
	int nTemp; 
	CString strTempUserName; 
	strTempUserName=""; 
	BOOL bFound=FALSE; 
 
	HTREEITEM tempItem=m_TreeCtrl.GetRootItem();	 
 
	//若客户端没有,添加 
	nTreeCount=m_TreeCtrl.GetCount(); 
	for (nTemp=1;nTemp<=nTreeCount;nTemp++) 
	{ 
		strTempUserName=m_TreeCtrl.GetItemText(tempItem); 
		if (strUserName==strTempUserName) 
			bFound=TRUE; 
		tempItem=m_TreeCtrl.GetNextItem(tempItem,TVGN_NEXT); 
	} 
	 
	if (bFound==FALSE) 
	{ 
		//添加到树上 
		HTREEITEM hRoot = m_TreeCtrl.InsertItem(strUserName, 0, 0, TVI_ROOT, TVI_LAST); 
		m_TreeCtrl.Expand(hRoot, TVE_EXPAND);	 
		//通知用户 
		AgentPlay("Pleased"); 
		AgentSpeak("你的好友 "+strUserName+" 登陆了!"); 
	} 
 
} 
 
void CAgentNetClientDlg::ProcessBuddyLogout(CString strUserName) 
{ 
	//若此好友以前在线,删除他 
	int nTreeCount; 
	int nTemp; 
	CString strTempUserName; 
	strTempUserName=""; 
	BOOL bFound=FALSE; 
 
	HTREEITEM tempItem=m_TreeCtrl.GetRootItem();	 
 
	nTreeCount=m_TreeCtrl.GetCount(); 
	for (nTemp=1;nTemp<=nTreeCount;nTemp++) 
	{ 
		strTempUserName=m_TreeCtrl.GetItemText(tempItem); 
		if (strUserName==strTempUserName) 
		{ 
			bFound=TRUE; 
			break; 
		} 
		tempItem=m_TreeCtrl.GetNextItem(tempItem,TVGN_NEXT); 
	} 
	 
	if (bFound==TRUE) 
	{ 
		//从树上删除 
		m_TreeCtrl.DeleteItem(tempItem); 
	} 
 
} 
 
void CAgentNetClientDlg::LogOut() 
{ 
	//退出网络 
	if ((m_pSocket!=NULL)&&(m_pFile!=NULL)&&(m_pArchiveOut!=NULL)) 
	{ 
		//发送客户离开的消息 
		CMsg msg; 
		msg.m_strCommand="logout_agent_net"; 
		msg.m_strUser=m_strUserName; 
		msg.m_strToUser=SERVER_AGENT_NAME; 
 
		msg.Serialize(*m_pArchiveOut); 
		m_pArchiveOut->Flush(); 
	} 
	//删除CArchive对象 
	delete m_pArchiveOut; 
	m_pArchiveOut=NULL; 
	//删除CArchive对象 
	delete m_pArchiveIn; 
	m_pArchiveIn=NULL; 
	delete m_pFile; 
	//删除CSOcketFile对象 
	m_pFile=NULL; 
	if (m_pSocket!=NULL) 
	{ 
		BYTE Buffer[50]; 
		m_pSocket->ShutDown(); 
		while (m_pSocket->Receive(Buffer,50)>0); 
	} 
	delete m_pSocket; 
	m_pSocket=NULL; 
	 
 
} 
 
void CAgentNetClientDlg::OnDblclkTree(NMHDR* pNMHDR, LRESULT* pResult)  
{ 
	// TODO: Add your control notification handler code here 
	HTREEITEM SelItem=m_TreeCtrl.GetSelectedItem( ); 
	CString strToUserName; 
	strToUserName=m_TreeCtrl.GetItemText(SelItem); 
	 
	CSendGeneralMsgDlg dlg; 
	dlg.m_strToUserName=strToUserName; 
     
	if (dlg.DoModal()==IDOK) 
	{ 
		ProcessSendGeneralMsg(strToUserName,dlg.m_strText); 
	} 
	 
	*pResult = 0; 
} 
 
void CAgentNetClientDlg::ProcessSendGeneralMsg(CString strToUserName, CString strText) 
{ 
	//发送一般消息到好友 
 
	CMsg* pMsg=new CMsg; 
	 
	pMsg->m_strCommand="send_general_message"; 
	pMsg->m_strUser=m_strUserName; 
	pMsg->m_strToUser=strToUserName; 
	pMsg->m_strText=strText; 
 
	SendMsg(pMsg); 
 
} 
 
void CAgentNetClientDlg::ProcessReceiveGeneralMsg(CString strUserName, CString strText) 
{ 
/* 
	CReceiveGeneralMsgDlg RevDlg; 
	RevDlg.m_strText=strText; 
	RevDlg.m_strFromUserName=strUserName; 
 
	RevDlg.DoModal(); 
 
	if (RevDlg.m_bReply==TRUE) 
	{ 
		//回复 
		CSendGeneralMsgDlg SendDlg; 
     	SendDlg.m_strToUserName=strUserName; 
     
    	if (SendDlg.DoModal()==IDOK) 
		{ 
			ProcessSendGeneralMsg(strUserName,SendDlg.m_strText); 
		} 
	} 
*/ 
	//提示有消息 
	AgentPlay("GetAttentionContinued"); 
 
	AgentSpeak(strUserName+" 对你说:"); 
	Sleep(100); 
//	AgentPlay("GetAttentionReturn"); 
	AgentSpeak(strText); 
 
 
} 
 
BOOL CAgentNetClientDlg::InitAgent() 
{ 
	//初始化agent 
 
	HRESULT				hRes; 
	VARIANT				vPath; 
	_TCHAR				szError[256]; 
 
	 
	m_pCharacterEx=NULL; 
 
	    
	if (FAILED(CoInitialize(NULL)))  
	{ 
		MessageBox(_T("There was an error initializing COM.")); 
	} 
 
	hRes = CoCreateInstance(CLSID_AgentServer, 
                     NULL, 
                     CLSCTX_SERVER, 
                     IID_IAgentEx, 
                     (LPVOID *)&m_pAgentEx); 
 
	 
	if (FAILED(hRes))  
	{ 
		MessageBox(_T("There was an error initializing Microsoft Agent, code = 0x%x")); 
		CoUninitialize(); 
		return -1; 
	} 
 
	CString strPath = m_stuSetup.strAgentCharPath; 
 
    VariantInit(&vPath); 
 
    vPath.vt = VT_BSTR; 
    vPath.bstrVal = SysAllocString(strPath.AllocSysString()); 
 
   // Load the character 
 
    hRes = m_pAgentEx->Load(vPath, &m_lCharID, &m_lRequestID); 
 
	if (FAILED(hRes)) 
	{ 
		AfxMessageBox("装入agent人物数据时出错!"); 
		return FALSE; 
	}	 
 
   // Get its IAgentCharacterEx interface 
 
    hRes = m_pAgentEx->GetCharacterEx(m_lCharID, &m_pCharacterEx); 
 
	hRes = m_pCharacterEx->SetLanguageID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED)); 
 
	//装入notify sink 
	try  
	{ 
		// Create a notify sink 
		m_pSink = new AgentNotifySink; 
 
		if (m_pSink == NULL) { 
			hRes = E_OUTOFMEMORY; 
			return FALSE; 
		} 
 
		// AddRef it 
		m_pSink->AddRef(); 
 
		// And register it with Microsoft Agent 
		hRes = m_pAgentEx->Register(m_pSink, &g_lNotifySinkID); 
 
		if (FAILED(hRes)) 
			return FALSE; 
		 
	} 
	catch(...) 
	{ 
 
		if (FAILED(hRes))  
		{ 
 
			wsprintf(szError, _T("注册Agent时发生错误, 错误代码:0X%x.\r请检查Agent 2.0安装是否正确."), hRes); 
 
			::MessageBox(NULL,  
					   szError,  
					   _T("AgentNetClient"),  
					   MB_OK | MB_ICONERROR | MB_TOPMOST); 
			return FALSE; 
		} 
	} 
	//设置在notify sink 对像内的dlg 指针 
	m_pSink->SetDlgHwnd(GetSafeHwnd()); 
 
	m_pCharacterEx->SetAutoPopupMenu(FALSE); 
 
 
 
   // Show the character.  The first parameter tells Microsoft 
   // Agent to show the character by playing an animation. 
   //gentSpeak("hello"): 
 
	hRes = m_pCharacterEx->Show(FALSE, &m_lRequestID); 
 
	AgentPlay("Greet"); 
	AgentSpeak("你好"+m_strUserName); 
 
    //清除OLE变量 
    VariantClear(&vPath); 
 
    return TRUE; 
 
} 
 
void CAgentNetClientDlg::ReleaseAgent() 
{ 
	if (m_pCharacterEx) 
	{ 
    	//所再见 
		m_pCharacterEx->Stop(m_lRequestID); 
		 
    	AgentPlay("Wave"); 
    	AgentSpeak("再见!"); 
    	Sleep(3000); 
 
		//释放IAgentCharacter接口 
		m_pCharacterEx->Release(); 
 
		m_pCharacterEx = NULL; 
		 
		//卸载动画人物数据 
		m_pAgentEx->Unload(m_lCharID); 
	} 
 
	if (m_pSink)  
	{ 
 
		if (g_lNotifySinkID != -1) 
			m_pAgentEx->Unregister(g_lNotifySinkID); 
 
		m_pSink->Release(); 
		m_pSink = NULL; 
	} 
	 
	//释放Agent对象 
	m_pAgentEx->Release(); 
 
	CoUninitialize(); 
 
} 
 
void CAgentNetClientDlg::AgentPlay(CString strAnimation) 
{ 
	//放agent动画 
	HRESULT				hRes; 
	BSTR				bszPlay; 
     
    //bszPlay =strAnimation.AllocSysString(); 
	bszPlay=SysAllocString(strAnimation.AllocSysString()); 
 
	hRes=m_pCharacterEx->Play(bszPlay,&m_lRequestID); 
 
 
    SysFreeString(bszPlay); 
} 
 
void CAgentNetClientDlg::AgentSpeak(CString strSpeak) 
{ 
    // Make the character speak 
	HRESULT				hRes; 
	BSTR				bszSpeak; 
 
    bszSpeak =strSpeak.AllocSysString(); 
 
//	AgentPlay("Explain"); 
 
	//语言合成 
	if( m_cpTTSVoice != NULL ) 
	{ 
		m_cpTTSVoice->Speak(bszSpeak, SPF_ASYNC,NULL ); 
	} 
	 
	//显示有说的话 
    hRes = m_pCharacterEx->Think(bszSpeak, &m_lRequestID); 
 
 
    SysFreeString(bszSpeak); 
} 
 
 
void CAgentNetClientDlg::InitTTS() 
{ 
	if( FAILED(CoInitialize(NULL)) ) 
	{ 
		AfxMessageBox("初始化TTS引擎是出错!"); 
	// Terminate the application 
	} // Else full speed ahead! 
 
	//初始化TTS 
 
    if( SUCCEEDED( CoCreateInstance( CLSID_SpVoice, NULL, CLSCTX_INPROC, IID_ISpVoice, (void**)&m_cpTTSVoice))) 
	{ 
		m_cpTTSVoice->AddRef(); 
	} 
	else 
	{ 
		m_cpTTSVoice = NULL; 
	} 
 
	if( m_cpTTSVoice != NULL ) 
	{ 
		m_cpTTSVoice->SetRate( 2 ); 
	} 
	// 
	m_bEnableTTS=TRUE; 
 
} 
 
void CAgentNetClientDlg::ReleaseTTS() 
{ 
	if (m_cpTTSVoice!=NULL) 
	{ 
		m_cpTTSVoice->Release(); 
		m_cpTTSVoice = NULL; 
	} 
 
} 
 
void CAgentNetClientDlg::InitSR() 
{ 
    // test is COM is successfully initialized 
    if (FAILED( CoInitialize( NULL ) ) ) 
	{ 
		AfxMessageBox("CoInitialize 初始化失败!"); 
		return; 
	} 
 
    HRESULT hr = S_OK; 
     
	// create a recognition engine	 
	hr = m_cpEngine.CoCreateInstance(CLSID_SpSharedRecognizer); 
	if ( FAILED(hr) ) 
	{ 
		AfxMessageBox("CoCreateInstance 初始化失败!"); 
		return; 
	} 
 
    // create the command recognition context 
	hr = m_cpEngine->CreateRecoContext( &m_cpRecoCtxt ); 
    if ( FAILED( hr ) ) 
	{ 
		AfxMessageBox("CreateRecoContext 初始化失败!"); 
		return; 
	} 
 
    // Let SR know that window we want it to send event information to, and using 
    // what message 
    hr = m_cpRecoCtxt->SetNotifyWindowMessage(m_hWnd, WM_RECOEVENT, 0, 0 ); 
    if ( FAILED( hr ) ) 
    { 
		AfxMessageBox("SetNotifyWindowMessage初始化失败!"); 
		return; 
	} 
 
    // Tell SR what types of events interest us.  Here we only care about command 
    // recognition. 
    hr = m_cpRecoCtxt->SetInterest( SPFEI(SPEI_RECOGNITION), SPFEI(SPEI_RECOGNITION) ); 
    if ( FAILED( hr ) ) 
    { 
		AfxMessageBox("SetInterest 初始化失败!"); 
		return; 
    } 
 
    // Load our grammar, 文件名为  SRGrammar.cfg 
     
    hr = m_cpRecoCtxt->CreateGrammar(GRAMMARID1, &m_cpCmdGrammar); 
    if (FAILED(hr)) 
    { 
        AfxMessageBox("CreateGrammar 初始化失败!"); 
		return; 
    } 
     
	//从cfg文件装入语法 
	hr = m_cpCmdGrammar->LoadCmdFromFile(L"srgrammar.cfg",SPLO_DYNAMIC); 
 
    if ( FAILED( hr ) ) 
    { 
        AfxMessageBox("LoadCmdFromFile 装入语法时失败!"); 
		return; 
    } 
     
	// Set rules to active, we are now listening for commands 
	//使不能接受命令,直到喊agent的名字 
	SetHearCommand(FALSE); 
 
 
	if ( FAILED( hr ) ) 
    { 
        AfxMessageBox("SetRuleIdState(MyName) 失败!"); 
		return; 
    } 
	m_bWantExit=FALSE; 
	m_bAnswer=FALSE; 
 
} 
 
void CAgentNetClientDlg::ReleaseSR() 
{ 
	// Release grammar, if loaded 
    if ( m_cpCmdGrammar ) 
    { 
        m_cpCmdGrammar.Release(); 
    } 
    // Release recognition context, if created 
    if ( m_cpRecoCtxt ) 
    { 
        m_cpRecoCtxt->SetNotifySink(NULL); 
        m_cpRecoCtxt.Release(); 
    } 
    // Release recognition engine instance, if created 
	if ( m_cpEngine ) 
	{ 
		m_cpEngine.Release(); 
	} 
 
} 
 
void CAgentNetClientDlg::ProcessRecoEvent() 
{ 
	CSpEvent event;  // Event helper class 
 
    // Loop processing events while there are any in the queue 
    while (event.GetFrom(m_cpRecoCtxt) == S_OK) 
    { 
        // Look at recognition event only 
        switch (event.eEventId) 
        { 
            case SPEI_RECOGNITION: 
                ExecuteSRCommand(event.RecoResult()); 
                break; 
 
        } 
    } 
 
} 
 
void CAgentNetClientDlg::ExecuteSRCommand(ISpPhrase *pPhrase) 
{ 
    HRESULT hr = S_OK; 
	 
	WCHAR* pwszText; 
 
    // get the phrase's entire text string, including replacements 
    hr = pPhrase->GetText(SP_GETWHOLEPHRASE,SP_GETWHOLEPHRASE, TRUE, &pwszText, NULL); 
 
    SPPHRASE *pElements; 
	if (SUCCEEDED(pPhrase->GetPhrase(&pElements))) 
    {         
        switch(pElements->Rule.ulId) 
		{ 
			case VID_MyName: 
			{ 
//				AfxMessageBox("lt"); 
				StartHearing(); 
			} 
			break; 
			case VID_ReadNews: 
			{ 
				switch( pElements->pProperties->vValue.ulVal ) 
				{ 
				case VID_News://看新闻 
					{ 
						//AfxMessageBox("in"); 
						ProcessReadNews(); 
					} 
					break; 
				} 
				SetHearCommand(FALSE); 
			} 
			break; 
 
			case VID_GetMail: 
			{  	//收邮件 
				OnMenuitemGetMail(); 
				SetHearCommand(FALSE); 
			} 
			case VID_ReadMail: 
			{  	//读邮件 
				OnMenuitemReadMail(); 
				SetHearCommand(FALSE); 
			} 
 
			break; 
 
			case VID_StopAll: 
			{ 
				//停止动作 
				OnMenuitemStopAll(); 
				SetHearCommand(FALSE); 
			} 
			case VID_AnswerYes: 
			{ 
				//回答是 
				//若问了问题 
				if (m_bWantExit) 
					m_bAnswer=TRUE; 
			 
				//ProcessAnswerExit(); 
				SetHearCommand(FALSE); 
			} 
			case VID_AnswerNo: 
			{ 
				//回答否 
				//若问了问题 
				if (m_bWantExit) 
					m_bAnswer=FALSE; 
				//ProcessAnswerExit(); 
 
				SetHearCommand(FALSE); 
			} 
			case VID_Exit: 
			{ 
				//退出程序 
				//ProcessExit();			 
			} 
			break; 
		} 
			 
        // Free the pElements memory which was allocated for us 
        ::CoTaskMemFree(pElements); 
    } 
 
} 
 
void CAgentNetClientDlg::ShowPopupMenu() 
{ 
	CPoint point; 
	point = (CPoint) GetMessagePos(); 
 
	ScreenToClient(&point); 
	CMenu menu; 
	CMenu *pPopup; 
 
	if (!menu.LoadMenu(IDR_MENU_MAIN)) 
	{ 
		AfxMessageBox("menu error!"); 
		return; 
	} 
 
 
	pPopup = menu.GetSubMenu(0); 
 
	if (m_bEnableTTS==TRUE) 
	{ 
		pPopup->CheckMenuItem(ID_MENUITEM_SET_CAN_SPEAK,MF_BYCOMMAND | MF_CHECKED); 
		pPopup->CheckMenuItem(ID_MENUITEM_SET_CANNOT_SPEAK,MF_BYCOMMAND | MF_UNCHECKED); 
	} 
	else 
	{ 
		pPopup->CheckMenuItem(ID_MENUITEM_SET_CAN_SPEAK,MF_BYCOMMAND | MF_UNCHECKED); 
		pPopup->CheckMenuItem(ID_MENUITEM_SET_CANNOT_SPEAK,MF_BYCOMMAND | MF_CHECKED); 
	} 
 
 
 
	ClientToScreen(&point); 
	pPopup->TrackPopupMenu( TPM_LEFTALIGN|TPM_LEFTBUTTON,point.x, point.y, this); 
 
	PostMessage(WM_NULL, 0, 0); 
 
	DestroyMenu(menu); 
 
 
} 
 
void CAgentNetClientDlg::OnMenuitemAgentHide()  
{ 
	// TODO: Add your command handler code here 
	//隐藏AGENT 
	AgentSpeak("我走了!"); 
	AgentPlay("Hide"); 
 
} 
 
void CAgentNetClientDlg::OnMenuitemAgentReadNews()  
{ 
	// TODO: Add your command handler code here 
	ProcessReadNews(); 
} 
 
void CAgentNetClientDlg::ProcessReadNews() 
{ 
	CMsg* pMsg=new CMsg; 
	 
	pMsg->m_strCommand="ask_read_news"; 
	pMsg->m_strUser=m_strUserName; 
//	pMsg->m_strText=strText; 
 
	SendMsg(pMsg); 
 
} 
 
void CAgentNetClientDlg::ProcessRequestReadNews(CString strNews) 
{ 
	AgentStop(); 
	AgentSpeak(strNews); 
 
} 
 
void CAgentNetClientDlg::OnMenuitemExitAgentNet()  
{ 
	// TODO: Add your command handler code here 
	CDialog::OnOK(); 
} 
 
void CAgentNetClientDlg::StartHearing() 
{ 
	AgentStop(); 
	AgentPlay("Hearing_1"); 
	StartHearingTimer(); 
	SetHearCommand(TRUE); 
} 
 
void CAgentNetClientDlg::StartHearingTimer() 
{ 
 
	SetTimer(2,3*1000,0); 
} 
 
void CAgentNetClientDlg::AgentStop() 
{ 
	m_pCharacterEx->StopAll(STOP_TYPE_ALL); 
} 
 
void CAgentNetClientDlg::SetHearCommand(BOOL bActive) 
{ 
	if (bActive==TRUE) 
	{ 
		//除了MyName其他都是可以 
		m_cpCmdGrammar->SetRuleState(NULL,NULL,SPRS_ACTIVE); 
		m_cpCmdGrammar->SetRuleIdState(VID_MyName,SPRS_INACTIVE); 
	} 
	else 
	{ 
		//除了MyName其他都不可以 
		m_cpCmdGrammar->SetRuleState(NULL,NULL,SPRS_INACTIVE); 
		m_cpCmdGrammar->SetRuleIdState(VID_MyName,SPRS_ACTIVE); 
	} 
 
} 
 
 
 
void CAgentNetClientDlg::OnMenuitemReadClipborad()  
{ 
	// TODO: Add your command handler code here 
	if( IsClipboardFormatAvailable(CF_TEXT)) 
	{ 
		if (OpenClipboard())                      
		{ 
			LPWSTR pwsz; 
			UINT cch; 
			HGLOBAL hglb; 
			LPSTR lpstr; 
				 
			hglb = GetClipboardData(CF_TEXT); 
			lpstr = (LPSTR)GlobalLock(hglb); 
			cch = lstrlen(lpstr); 
			if( cch > 0) 
			{ 
				pwsz = new WCHAR[cch + 1]; 
				MultiByteToWideChar(CP_ACP, 0, lpstr, -1, pwsz, cch); 
				pwsz[cch] = '\0'; 
 
				AgentPlay("Read"); 
				AgentSpeak(pwsz); 
				AgentPlay("ReadReturn"); 
				delete pwsz; 
			} 
			GlobalUnlock(hglb); 
			CloseClipboard(); 
		} 
	} 
	 
} 
 
void CAgentNetClientDlg::OnMenuitemStopAll()  
{ 
	// TODO: Add your command handler code here 
	AgentStop(); 
	OnMenuitemSetCannotSpeak(); 
	OnMenuitemSetCanSpeak(); 
} 
 
void CAgentNetClientDlg::OnMenuitemSetCanSpeak()  
{ 
	// TODO: Add your command handler code here 
	//设置tts继续 
	m_cpTTSVoice->Resume(); 
	 
} 
 
void CAgentNetClientDlg::OnMenuitemSetCannotSpeak()  
{ 
	// TODO: Add your command handler code here 
	//设置tts暂停 
	m_cpTTSVoice->Skip(L"SENTENCE",100000,NULL); 
	m_cpTTSVoice->Pause(); 
	 
} 
 
 
UINT GetMailThread(LPVOID pParam) 
{ 
	//收有邮件进程处理函数 
	stuThreadInfo* pstuInfo=(stuThreadInfo*)pParam; 
 
	//若用户信息(包括邮箱地址,登陆名,密码)还没设置,退出) 
	//并发没设置消息 
	if (pstuInfo->m_bUserSet==FALSE) 
	{ 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_PROCESS_DONE,0,0); 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_ACCOUNT_NOT_SET,0,0); 
		return 0; 
	} 
	 
	//读邮箱信息 
	CPOP3 pop3(pstuInfo->m_strMailServer); 
	pop3.SetUserProperties(pstuInfo->m_strMailAccount,pstuInfo->m_strMailPassword); 
 
	if (!pop3.Connect()) 
	{ 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_PROCESS_DONE,0,0); 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_CANNOT_LOGIN,0,0); 
		return 0; 
	} 
	//取新邮件数量 
	int iMsgNumber=0; 
	iMsgNumber=pop3.GetNumMessages(); 
 
	if (iMsgNumber==0) 
	{ 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_PROCESS_DONE,0,0); 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_NO_NEW_MAIL,0,0); 
		return 0; 
	} 
 
	//若有邮件,读第一封 
	CMailMessage msg; 
	if (!pop3.GetMessage(1,&msg)) 
	{ 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_PROCESS_DONE,0,0); 
		::PostMessage(pstuInfo->m_hWnd,WM_MAIL_CANNOT_LOGIN,0,0); 
		return 0; 
	} 
 
	if( !pop3.Disconnect() ) 
	{ 
//		AfxMessageBox( pop3.GetLastError() ); 
		return 0; 
	} 
 
	//AfxMessageBox( _T( "Successfully disconnected" ) ); 
 
	//发消息到主线程,有邮件要处理 
	pstuInfo->m_strFrom=msg.m_sFrom; 
	pstuInfo->m_strSubject=msg.m_sSubject; 
	pstuInfo->m_strBody=msg.m_sBody; 
	pstuInfo->m_iMsgNumber=iMsgNumber; 
 
	::PostMessage(pstuInfo->m_hWnd,WM_MAIL_PROCESS_DONE,0,0); 
	::PostMessage(pstuInfo->m_hWnd,WM_MAIL_PROCESS,0,0); 
 
	return 0; 
} 
 
void CAgentNetClientDlg::OnMenuitemGetMail()  
{ 
	// TODO: Add your command handler code here 
 
	if (m_bProcessMailThread==TRUE) 
		return; 
 
	//表演处理 
	AgentStop(); 
	AgentPlay("Searching"); 
	AgentSpeak("好的,收邮件"); 
	//收邮件 
 
	//使可收邮件 
	m_bProcessMailThread=TRUE; 
	m_stuThreadInfo.m_bUserSet=TRUE; 
 
	//开新线程首邮件 
	AfxBeginThread(GetMailThread,&m_stuThreadInfo,THREAD_PRIORITY_NORMAL); 
 
} 
 
void CAgentNetClientDlg::InitMailAccount() 
{ 
	HWND hWnd; 
	hWnd=GetSafeHwnd(); 
	m_stuThreadInfo.m_hWnd=hWnd; 
	m_stuThreadInfo.m_bUserSet=FALSE; 
	m_stuThreadInfo.m_iMsgNumber=0; 
	m_stuThreadInfo.m_strMailServer=m_stuSetup.strMailServer; 
	m_stuThreadInfo.m_strMailAccount=m_stuSetup.strMailAccount; 
	m_stuThreadInfo.m_strMailPassword=m_stuSetup.strMailPassword; 
 
	m_bProcessMailThread=FALSE; 
 
} 
 
void CAgentNetClientDlg::ProcessMailAccountNotSet() 
{ 
	AgentStop(); 
	AgentPlay("Decline"); 
	AgentSpeak("邮件账号没设定!"); 
 
} 
 
void CAgentNetClientDlg::ProcessMailCannotLogin() 
{ 
	AgentStop(); 
	AgentPlay("Decline"); 
	AgentSpeak("现在登陆不到邮箱!"); 
} 
 
void CAgentNetClientDlg::ProcessReadMail() 
{ 
 
	if (m_stuThreadInfo.m_iMsgNumber<1) 
	{ 
		ProcessNoMail(); 
		return; 
	} 
 
	CString strFrom,strSubject,strBody; 
 
	strFrom=m_stuThreadInfo.m_strFrom; 
	strSubject=m_stuThreadInfo.m_strSubject; 
	strBody=m_stuThreadInfo.m_strBody; 
 
	AgentStop(); 
	AgentPlay("Congratulate"); 
	AgentSpeak("你有一封发自 "+strFrom+" 的邮件!"); 
 
} 
 
void CAgentNetClientDlg::ProcessNoMail() 
{ 
	AgentStop(); 
	AgentPlay("Sad"); 
	AgentPlay("Decline"); 
	AgentSpeak("没有邮件!"); 
} 
 
void CAgentNetClientDlg::OnMenuitemReadMail()  
{ 
	// TODO: Add your command handler code here 
	if (m_stuThreadInfo.m_iMsgNumber<1) 
	{ 
		ProcessNoMail(); 
		return; 
	} 
 
	CString strFrom,strSubject,strBody; 
 
	strFrom=m_stuThreadInfo.m_strFrom; 
	strSubject=m_stuThreadInfo.m_strSubject; 
	strBody=m_stuThreadInfo.m_strBody; 
 
	AgentStop(); 
	AgentPlay("Reading"); 
	AgentSpeak(strFrom+" 的邮件!"); 
	AgentSpeak("主题是 "+strSubject); 
	AgentSpeak("内容是 "+strBody); 
 
	AgentStop(); 
	AgentPlay("ReadReturn"); 
	 
} 
 
void CAgentNetClientDlg::ProcessExit() 
{ 
	AgentStop(); 
	AgentPlay("Suggest"); 
	AgentSpeak("真的吗?"); 
	m_bWantExit=TRUE; 
 
} 
 
void CAgentNetClientDlg::ProcessAnswerExit() 
{ 
	if (m_bWantExit==FALSE) 
		return; 
 
	if (m_bAnswer==FALSE) 
		return; 
 
	CDialog::OnOK(); 
 
} 
 
 
 
void CAgentNetClientDlg::InitSetup() 
{ 
	m_stuSetup.strAgentCharPath=m_pLoginDlg->m_stuSetup.strAgentCharPath; 
 
	m_stuSetup.strServerIpAddress=m_pLoginDlg->m_stuSetup.strServerIpAddress; 
 
	m_stuSetup.strMailServer=m_pLoginDlg->m_stuSetup.strMailServer; 
	m_stuSetup.strMailAccount=m_pLoginDlg->m_stuSetup.strMailAccount; 
	m_stuSetup.strMailPassword=m_pLoginDlg->m_stuSetup.strMailPassword; 
 
} 
 
void CAgentNetClientDlg::ProcessMailDone() 
{ 
	m_bProcessMailThread=FALSE; 
	Sleep(500); 
}