www.pudn.com > tapi3.zip > TALKDLG.CPP


// talkdlg.cpp : implementation file 
// (c) Dialogic corp 1995, 1996 
 
#include "stdafx.h" 
#include  
#include "tapiapp.h" 
#include "tapiline.h" 
#include "tapicall.h" 
#include "talker32.h" 
#include  
#include "wavex.h" 
//#include "wavexg.h" 
#include "callinfo.h" 
#include "lineinfo.h" 
#include "talkdlg.h" 
#include "helpid.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char BASED_CODE THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CTalkDlg dialog 
 
CTalkDlg::CTalkDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CTalkDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CTalkDlg) 
	m_csDialString = _T(""); 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
	SetHelpID(HIDD_TALKER32_DialogMain); 
} 
 
void CTalkDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CTalkDlg) 
	DDX_Control(pDX, IDC_DIAL, m_btnDial); 
	DDX_Control(pDX, IDC_EDIT1, m_ctlDialString); 
	DDX_Control(pDX, IDC_CALLS, m_ctlActiveCalls); 
	DDX_Control(pDX, IDC_LINEFRAME, m_ctlLineFrame); 
	DDX_Control(pDX, IDC_NUMBER0, m_ctlLineNum0); 
	DDX_Control(pDX, IDC_INFO0, m_btnInfo0); 
	DDX_Control(pDX, IDC_ACTION0, m_btnAction0); 
	DDX_Control(pDX, IDC_IND0, m_ctlFrame0); 
	DDX_Text(pDX, IDC_EDIT1, m_csDialString); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CTalkDlg, CDialog) 
	//{{AFX_MSG_MAP(CTalkDlg) 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_WM_DESTROY() 
	ON_BN_CLICKED(IDC_DIAL, OnDial) 
	ON_MESSAGE(MM_WOM_DONE, OnWomDone)	// Finish playing WAVE 
	ON_MESSAGE(MM_WIM_DATA, OnWimData)	// Finish recording WAVE  
	ON_BN_CLICKED(IDC_CLEAR, OnClear) 
	ON_BN_CLICKED(ID_CONTEXT_HELP, OnContextHelp) 
	ON_WM_SETFOCUS() 
	ON_WM_ACTIVATE() 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CTalkDlg message handlers 
 
BOOL CTalkDlg::OnInitDialog() 
{ 
 
	DWORD i; 
	char szBuf[16]; 
	CTapiLine *ptlTemp; 
	CDialog::OnInitDialog(); 
	CenterWindow(); 
//	SetHelpID(HIDD_TALKER32_DialogMain); 
 
	// set the control ID so that the TapiApp object knows where to send notification messages 
	((CTalkApp *)AfxGetApp())->SetNotificationControlID(IDC_TAPIALERT); 
 
	m_dwLines = ((CTalkApp *)AfxGetApp())->m_dwLines; 
	m_LineControls[0].uiActionID = IDC_ACTION0; 
	m_LineControls[0].uiInfoID = IDC_INFO0; 
	m_LineControls[0].pbtnAction = &m_btnAction0; 
	m_LineControls[0].pbtnInfo = &m_btnInfo0; 
	m_LineControls[0].pFrame = &m_ctlFrame0; 
	m_LineControls[0].pctlLineNum = &m_ctlLineNum0; 
	m_LineControls[0].pInfoDlg = NULL; 
	m_nLastX = 	95;		   
	m_nLastY = 	25; 
	m_uiLastID = CONTROL_ARRAY_START; 
	memset((PBYTE)&(m_LineControls[1]), 0, sizeof(LINECONTROL)*(MAXLINES-1));	// zeroinit 
	//difference between non-existent & non-functional line:ctlLine=0-nonexist, hline=0-nonfunct 
	for(i=0; i< m_dwLines; i++) 
	{ 
		if(NULL == (ptlTemp = ((CTalkApp *)AfxGetApp())->GetTapiLine(i))) continue; 
		if(i) if(FALSE == CreateLineWindows(&(m_LineControls[i]))) continue; 
		m_LineControls[i].pctlLine = ptlTemp; // save the line pointer for future ref 
		sprintf(szBuf, "%d", i); 
		(m_LineControls[i].pctlLineNum)->SetWindowText(szBuf); 
		if(NULL != ptlTemp->ctlGetHLine())	// Line functional 
			(m_LineControls[i].pFrame)->m_Colorref = GREEN; //green=OK 
		else  
		{ 
			(m_LineControls[i].pFrame)->m_Colorref = BLACK; //black=nonfunctional 
			(m_LineControls[i].pbtnAction)->EnableWindow(FALSE); 
		} 
		m_LineControls[0].pInfoDlg = NULL; 
		(m_LineControls[i].pFrame)->Invalidate(); 
	} 
 
	if(!m_dwLines)	// remove the pilot windows 
	{ 
		m_btnAction0.ShowWindow(SW_HIDE); 
		m_btnInfo0.ShowWindow(SW_HIDE); 
		m_ctlFrame0.ShowWindow(SW_HIDE); 
		m_ctlLineNum0.ShowWindow(SW_HIDE); 
		MessageBox("No TAPI lines found, check TAPI configuration", "Talker32", MB_ICONEXCLAMATION);  
	} 
	m_btnDial.EnableWindow(FALSE); 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
// 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. 
 
BOOL CTalkDlg::CreateLineWindows(PLINECONTROL pLineControl) 
{ 
	CRect rCur, rNew, rWork; 
	CFont *pcfTemp = m_btnAction0.GetFont(); 
	POINT pntNew; 
	 
	if(NULL == (pLineControl->pctlLineNum = new CStatic)) return FALSE; 
	if(NULL == (pLineControl->pFrame = new CXstatic)) return FALSE; 
	if(NULL == (pLineControl->pbtnAction = new CButton)) return FALSE; 
	if(NULL == (pLineControl->pbtnInfo = new CButton)) return FALSE; 
	m_uiLastID++; 
 
	// Get the position & IDs for the new controls 
	if(FALSE == DetermineLinePos(&pntNew)) return FALSE;	// main wnd too small 
	rNew.left = pntNew.x; 
	rNew.top = pntNew.y; 
	rNew.right = pntNew.x + 8;  
	rNew.bottom = pntNew.y + 10; 
	rWork = rNew; 
	MapDialogRect(&rWork);	   // convert from dialog base units to screen units 
	if(!pLineControl->pctlLineNum->Create(" ", m_ctlLineNum0.GetStyle(), rWork,  
		this, m_uiLastID)) return FALSE; 
	pLineControl->pctlLineNum->ShowWindow(SW_SHOW); 
	pLineControl->pctlLineNum->SetFont(pcfTemp); 
	m_uiLastID++; 
	m_nLastX = rNew.left;						// Save new values 
	m_nLastY = rNew.top;  
	rCur = rNew; 
	GetNextRect(&rCur, &rNew, 13, 0, 10, 10); 	// Lamp 
	rWork = rNew; 
	MapDialogRect(&rWork);	  // convert from dialog base units to screen units 
	if(!pLineControl->pFrame->Create(" ", m_ctlFrame0.GetStyle(), rWork,  
		this, m_uiLastID)) return FALSE; 
	pLineControl->pFrame->ShowWindow(SW_SHOW); 
	m_uiLastID++; 
	rCur = rNew; 
	GetNextRect(&rCur, &rNew, 15, 0, 35, 15); 	// Action button 
	rWork = rNew; 
	MapDialogRect(&rWork); 
	if(!pLineControl->pbtnAction->Create("Call", m_btnAction0.GetButtonStyle(), rWork,  
		this, m_uiLastID)) return FALSE; 
	pLineControl->uiActionID = m_uiLastID; 
	pLineControl->pbtnAction->ShowWindow(SW_SHOW); 
	pLineControl->pbtnAction->SetFont(pcfTemp); 
	m_uiLastID++; 
	rCur = rNew; 
	GetNextRect(&rCur, &rNew, 40, 0, 20, 15); 	// Info button 
	rWork = rNew; 
	MapDialogRect(&rWork); 
	if(!pLineControl->pbtnInfo->Create("Info", m_btnInfo0.GetButtonStyle(), rWork,  
		this, m_uiLastID)) return FALSE; 
	pLineControl->uiInfoID = m_uiLastID; 
	pLineControl->pbtnInfo->ShowWindow(SW_SHOW); 
	pLineControl->pbtnInfo->SetFont(pcfTemp); 
	return TRUE; 
	//may use DeferWindowPos ?... 
} 
 
void CTalkDlg::GetNextRect(RECT *pLastRect, RECT *pNewRect, int ndX, int ndY, int nW, int nH) 
{ 
	// put bounds check here 
	pNewRect->top = pLastRect->top + ndY; 
	pNewRect->bottom = pNewRect->top + nH; 
	pNewRect->left = pLastRect->left + ndX; 
	pNewRect->right = pNewRect->left + nW;	 
} 
 
// Calculate position for new line of controls; resize window if needed 
BOOL CTalkDlg::DetermineLinePos(POINT *ppntNew) 
{ 
	CRect rctLimit1, rctNew; 
	CRect rcT(10, 10, 10, 10); 
 
	MapDialogRect(&rcT);				// isn't it a shame... 
	//LONG ldbu = GetDialogBaseUnits(); 
	m_ctlLineFrame.GetWindowRect(&rctLimit1); 
	ScreenToClient(&rctLimit1); 
	// the real rect 
	CRect rctLimit((rctLimit1.left*10)/rcT.left, (rctLimit1.top*10)/rcT.top, 
				(rctLimit1.right*10)/rcT.right ,(rctLimit1.bottom*10)/rcT.bottom); 
 
	if(m_nLastY > (rctLimit.bottom - 40)) 	// resize window; start next row 
	{ 
		AddColumn();		   
		ppntNew->x = m_nLastX + 100;  
		ppntNew->y = rctLimit.top + 20;		// 25 it should be 
	} 
	else  
	{ 
		ppntNew->x = m_nLastX; 
		ppntNew->y = m_nLastY + 20; 
	} 
//	if(ppntNew->x > (rctLimit1.right - 100)) return FALSE;	// need to resize the main wnd 
	return TRUE; 
} 
 
// add a new column of controls 
void CTalkDlg::AddColumn() 
{ 
	CRect rctMain, rctFrame; 
	CRect rcT(100, 100, 100, 100); 
 
	MapDialogRect(&rcT); 
 
	GetWindowRect(&rctMain);	 			// resize main window 
	rctMain.right += rcT.left;			// do everything in dialog units ONLY 
	MoveWindow(&rctMain); 
	m_ctlLineFrame.GetWindowRect(&rctFrame); // resize frame 
	ScreenToClient(&rctFrame); 
	rctFrame.right += rcT.left;		// only horizontally 
	m_ctlLineFrame.MoveWindow(&rctFrame); 
} 
 
void CTalkDlg::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 CTalkDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
// User clicked on Action button; find out what to do & do it 
void CTalkDlg::OnAction(DWORD dwIndex)  
{ 
	PLINECONTROL plcTemp = &m_LineControls[dwIndex]; 
	LONG lrc; 
	CTapiCall *pCall = plcTemp->pctlLine->ctlGetActiveCall(); 
	WORD wCallState; 
	CString csTemp; 
	LPTSTR lpTemp; 
 
	plcTemp->pbtnAction->GetWindowText(csTemp); 
	plcTemp->pbtnAction->EnableWindow(FALSE);	// disable for now 
	// find out what the line state is 
	if(pCall == NULL && !csTemp.CompareNoCase("Call"))	// no active calls, try to call 
	{ 
		UpdateData();			// to get m_csDialString 
		if(m_csDialString.IsEmpty()) lpTemp = NULL; 
		else lpTemp = m_csDialString.GetBuffer(256); 
		lrc = plcTemp->pctlLine->ctlLineMakeCall((LPCTSTR)lpTemp, 0); 
		if(lrc < 0) 
		{  
			csTemp.Format("Make call failed reason=%lx", lrc); 
			MessageBox(csTemp);		// restore call state-WHERE? 
		} 
		else return; 
	} 
	else  
	{ 
		wCallState = pCall->GetCallState(); 
		switch (wCallState)			// find out what to do depending on state 
		{ 
			case MAKING: 
			case PROGRESS: 
			case CONNECTED: 
			case HOLD: 
				if(!csTemp.CompareNoCase("Hangup"))  
				{ 
					((CTalkApp *)AfxGetApp())->m_wLineOptions[dwIndex] &= ~PLAY_ONCE; 
					plcTemp->pctlLine->ctlLineDrop(); 
				} 
				return; //break; 
 
			case OFFERING: 
				if(!csTemp.CompareNoCase("Pickup")) 
					lrc = plcTemp->pctlLine->ctlLineAnswer();  
					if(lrc < 0) TRACE("*** TALKER32 ***: Answer failed rc=%lx\n",lrc);  
				break; 
 
			case ANSWERING:	  // do nothing 
				break; 
 
			case DROPPING:	  // unclear what to do 
				break; 
 
			case DISCONNECTED: 
				if(!csTemp.CompareNoCase("Hangup"))  
					plcTemp->pctlLine->ctlLineDrop(); 
				break; 
 
			default: 
				break;				 
			} 
	} 
 
	plcTemp->pbtnAction->EnableWindow(TRUE);	// reenable 
} 
 
// User clicked on Info button; find out what to do & do it 
void CTalkDlg::OnInfo(DWORD dwIndex)  
{ 
	CTapiLine *pLine = (&m_LineControls[dwIndex])->pctlLine; 
	// set the line in the info dialog, let it do the rest 
	CString csTemp; 
	csTemp.Format("Line #%d information", dwIndex); 
 
	// Always destroy before creation 
	DestroyPropSheet(dwIndex); 
 
	if(m_LineControls[dwIndex].pInfoDlg == NULL)	// reallocate brand new 
		m_LineControls[dwIndex].pInfoDlg = (LPVOID)new CInfo(csTemp, NULL, 0, pLine); 
	if(m_LineControls[dwIndex].pInfoDlg != NULL) 
		((CInfo *)m_LineControls[dwIndex].pInfoDlg)->Create(); 
	return;	    
	 
	/***PLINECONTROL plcTemp = &m_LineControls[dwIndex];		// temporary for testing play!!! 
	CTapiCall *pCall = plcTemp->pctlLine->ctlGetActiveCall(); 
	if(pCall != NULL) pCall->Play("record1.wav"); 
	***/ 
} 
 
// Update the indicator & other status 
void CTalkDlg::UpdateDisplayStatus(DWORD dwLineID) 
{ 
	CTapiCall *pCall; 
	WORD wCallState = IDLE; 
	DWORD dwError = NULL; 
	CString csTemp, csWaveName; 
	int nNum; 
 
	if(dwLineID == 0xffff || dwLineID >= m_dwLines) {return;}	// update all lines info 
	PLINECONTROL plcTemp = &m_LineControls[dwLineID]; 
	if(NULL != (pCall = plcTemp->pctlLine->ctlGetActiveCall())) 
	{ 
		wCallState = pCall->GetCallState();	// No active call==state IDLE 
		dwError = pCall->GetCallError(); 
	} 
	switch(wCallState) 
	{ 
		case IDLE: 
		m_LineControls[dwLineID].pFrame->m_Colorref = GREEN; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Call"); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(); 
		DestroyPropSheet(dwLineID, TRUE);	 // destroy if has calls 
//		if(1 == m_ctlActiveCalls.GetCount()) 	// the last one 
//		{ 
//			m_ctlActiveCalls.ResetContent(); 
//			m_btnDial.EnableWindow(FALSE); 
//		} 
		csTemp.Format("line %d", dwLineID); 
		nNum = m_ctlActiveCalls.FindString(-1, (LPCTSTR) csTemp); 
		if(nNum != CB_ERR) m_ctlActiveCalls.DeleteString(nNum); 
		break; 
 
		case MAKING: 
		case PROGRESS: 
		m_LineControls[dwLineID].pFrame->m_Colorref = PURPLE; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Hangup"); 
		csTemp.Format("line %d", dwLineID); 
		nNum = m_ctlActiveCalls.FindString(-1, (LPCTSTR) csTemp); 
		if(nNum == CB_ERR) nNum = m_ctlActiveCalls.AddString((LPCTSTR) csTemp); 
		m_ctlActiveCalls.SetCurSel(nNum); 
		m_btnDial.EnableWindow(); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(); 
		break; 
		 
		case OFFERING: 
		m_LineControls[dwLineID].pFrame->m_Colorref = BROWN; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Pickup"); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(); 
		if(((CTalkApp *)AfxGetApp())->m_wLineOptions[dwLineID] & AUTOANSWER) //answer immediately	 
			PostMessage(WM_COMMAND, MAKELONG(m_LineControls[dwLineID].uiActionID, BN_CLICKED),  
					(LPARAM)m_LineControls[dwLineID].pbtnAction->GetSafeHwnd()); 	 
		break; 
 
		case ANSWERING: 
		m_LineControls[dwLineID].pFrame->m_Colorref = BROWN; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Hangup"); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(FALSE); 
		break; 
 
		case CONNECTED: 
		m_LineControls[dwLineID].pFrame->m_Colorref = YELLOW; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Hangup"); 
		csTemp.Format("line %d", dwLineID); 
		nNum = m_ctlActiveCalls.FindString(-1, (LPCTSTR) csTemp); 
		if(nNum == CB_ERR) nNum = m_ctlActiveCalls.AddString((LPCTSTR) csTemp); 
		m_ctlActiveCalls.SetCurSel(nNum); 
		m_btnDial.EnableWindow(); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(); 
		if(((CTalkApp *)AfxGetApp())->m_wLineOptions[dwLineID] & AUTOPLAY) //play immediately	 
		{ 
			if(!(((CTalkApp *)AfxGetApp())->m_wLineOptions[dwLineID] & PLAY_ONCE)) break; 
			((CTalkApp *)AfxGetApp())->m_wLineOptions[dwLineID] &= ~PLAY_ONCE; 
			csTemp.Format("line%d", dwLineID); 
			csWaveName = AfxGetApp()->GetProfileString((LPCTSTR)csTemp, "WaveFile", ""); 
			if(csWaveName.IsEmpty()) csWaveName = "play.wav"; 
			pCall->Play(csWaveName.GetBuffer(128)); 
		} 
		break; 
 
		case HOLD: 
		m_LineControls[dwLineID].pFrame->m_Colorref = BLUE; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Hangup"); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(); 
		break; 
 
		case STOP_MAKING: 
		case DROPPING: 
		case DISCONNECTED: 
		m_LineControls[dwLineID].pFrame->m_Colorref = ORANGE; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Hangup"); 
		csTemp.Format("line %d", dwLineID); 
		if(1 == m_ctlActiveCalls.GetCount()) 	// the last one 
		{ 
			m_ctlActiveCalls.ResetContent(); 
			m_btnDial.EnableWindow(FALSE); 
		} 
		nNum = m_ctlActiveCalls.FindString(-1, (LPCTSTR) csTemp); 
		if(nNum != CB_ERR) m_ctlActiveCalls.DeleteString(nNum); 
		break; 
 
		default: 
		break; 
	} 
	if(dwError != NULL)		 	// indication that something went wrong 
	{ 
		m_LineControls[dwLineID].pFrame->m_Colorref = RED; 
		m_LineControls[dwLineID].pbtnAction->SetWindowText("Hangup"); 
		m_LineControls[dwLineID].pbtnAction->EnableWindow(); 
	} 
	UpdateData(); 
	m_LineControls[dwLineID].pFrame->Invalidate(); 
} 
 
void CTalkDlg::DestroyPropSheet(DWORD dwIndex, BOOL bDestroyIfCalls) 
{ 
	DWORD i; 
	// Destroy specific one 
	if(dwIndex != 0xffffffff)  
	{ 
		if(m_LineControls[dwIndex].pInfoDlg != NULL) 
		{ 
			if(bDestroyIfCalls && 
			  ((CInfo *)m_LineControls[dwIndex].pInfoDlg)->m_LineInfo.m_dwCalls == 0) 
				return; 
			if(((CInfo *)m_LineControls[dwIndex].pInfoDlg)->m_hWnd &&  
				((CInfo *)m_LineControls[dwIndex].pInfoDlg)->IsWindowVisible()) 
				((CInfo *)m_LineControls[dwIndex].pInfoDlg)->DestroyWindow(); 
			delete ((CInfo *)m_LineControls[dwIndex].pInfoDlg); 
			m_LineControls[dwIndex].pInfoDlg = NULL; 
		} 
		return; 
	} 
	for(i=0; i < m_dwLines; i++) 
	{ 
		// Destroy prop sheets if any 
		if(m_LineControls[i].pInfoDlg != NULL) 
		{ 
			if(bDestroyIfCalls &&  
			  ((CInfo *)m_LineControls[i].pInfoDlg)->m_LineInfo.m_dwCalls == 0) 
				continue; 
			if(((CInfo *)m_LineControls[i].pInfoDlg)->m_hWnd &&  
				((CInfo *)m_LineControls[i].pInfoDlg)->IsWindowVisible()) 
				((CInfo *)m_LineControls[i].pInfoDlg)->DestroyWindow(); 
			delete ((CInfo *)m_LineControls[i].pInfoDlg); 
			m_LineControls[i].pInfoDlg = NULL; 
		} 
	} 
} 
 
void CTalkDlg::OnDestroy()  
{ 
	DWORD i; 
	// destroy all allocated controls 
	for(i = 1; i < m_dwLines; i++) 
	{ 
		if(NULL != m_LineControls[i].pctlLineNum) delete m_LineControls[i].pctlLineNum; 
		m_LineControls[i].pctlLineNum = NULL; 
		if(NULL != m_LineControls[i].pFrame) delete m_LineControls[i].pFrame; 
		m_LineControls[i].pFrame = NULL; 
		if(NULL != m_LineControls[i].pbtnAction) delete m_LineControls[i].pbtnAction; 
		m_LineControls[i].pbtnAction = NULL; 
		if(NULL != m_LineControls[i].pbtnInfo) delete m_LineControls[i].pbtnInfo; 
		m_LineControls[i].pbtnInfo = NULL; 
		DestroyPropSheet();		// remove all 
	}	 
 
	CDialog::OnDestroy(); 
} 
 
BOOL CTalkDlg::OnCommand(WPARAM wParam, LPARAM lParam)  
{ 
	DWORD i; 
 
	if(wParam == IDC_TAPIALERT) 
	{ 
		UpdateDisplayStatus((DWORD) lParam);	 
		return TRUE; 
	} 
	WORD wID = LOWORD(wParam); 
	 
	if((wID < (CONTROL_ARRAY_START + 1)) && wID > IDC_IND0) goto CommandFinish;	// not in array 
	if(!lParam || !wID || HIWORD(wParam) != BN_CLICKED) goto CommandFinish;	 
	for(i=0; i< m_dwLines; i++) 
	{ 
		if(m_LineControls[i].uiActionID == wID)	// Action button clicked 
		{ 
			OnAction(i); 
			break; 
		} 
		else if(m_LineControls[i].uiInfoID == wID)	// Info button clicked 
		{ 
			OnInfo(i); 
			break; 
		} 
	} 
 
	switch(wID)			// Handle digits here 
	{ 
		case IDC_0: 
			AddDigit("0"); 
			break; 
		case IDC_1: 
			AddDigit("1"); 
			break; 
		case IDC_2: 
			AddDigit("2"); 
			break; 
		case IDC_3: 
			AddDigit("3"); 
			break; 
		case IDC_4: 
			AddDigit("4"); 
			break; 
		case IDC_5: 
			AddDigit("5"); 
			break; 
		case IDC_6: 
			AddDigit("6"); 
			break; 
		case IDC_7: 
			AddDigit("7"); 
			break; 
		case IDC_8: 
			AddDigit("8"); 
			break; 
		case IDC_9: 
			AddDigit("9"); 
			break; 
		case IDC_POUND: 
			AddDigit("#"); 
			break; 
		case IDC_STAR: 
			AddDigit("*"); 
			break; 
		default: 
			break; 
	} 
 
CommandFinish:	 
	return CDialog::OnCommand(wParam, lParam); 
} 
 
void CTalkDlg::AddDigit(LPCSTR lpDigit) 
{ 
	if(lpDigit == NULL)		// Clear 
	{ 
	 	m_csDialString.Empty(); 
		UpdateData(FALSE); 
		return; 
	}			 
	if(m_ctlDialString.GetSel()) 
	{ 
		m_ctlDialString.ReplaceSel(lpDigit); 
		UpdateData(TRUE); 
	} 
	else 
	{ 
		UpdateData(TRUE);		// retrieve 
		m_csDialString += lpDigit; 
		UpdateData(FALSE);		// save 
	} 
} 
 
// If there is a call, try to dial on it	 
void CTalkDlg::OnDial()  
{ 
	int nNum; 
	DWORD i; 
	CString csTemp, csTemp1;  
	LONG lrc; 
 
	// first, get the currently selected call 
	nNum = m_ctlActiveCalls.GetCurSel(); 
	if(nNum == CB_ERR) return; 
	m_ctlActiveCalls.GetLBText(nNum, csTemp); 
	for(i=0; i= m_dwLines) i--; 
	UpdateData(); 
	lrc = m_LineControls[i].pctlLine->ctlLineDial(NULL, (LPCSTR) m_csDialString, 0L);	// Country code=0 for now 
	if(lrc < 0)  
	{ 
		char szErr[48]; 
		if(!((CTalkApp *)AfxGetApp())->Code2Error(lrc, szErr, 46)) 
			csTemp.Format("Dial on line %d failed reason=%lx", i, lrc); 
		else 
			csTemp.Format("Dial on line %d failed reason=%s", i, szErr); 
		AfxMessageBox(csTemp); 
	} 
} 
 
// Find the pCall using hWave, finish palying on that call. 
LONG CTalkDlg::OnWomDone(UINT wParam, LONG lParam) 
{ 
	CTapiCall *pCall = (CTapiCall *)(((CTalkApp *)AfxGetApp())->GetCallByParm(KEY_WAVEOUTHANDLE, (DWORD) wParam)); 
	if(pCall != NULL)  
	{ 
	// For MT implementation, signal the semaphore here  
		pCall->FinishPlay(wParam, lParam);	// override this for MT implementation 
	}  
	//::WavexFinishPlay(wParam, lParam); 
	return TRUE; 
} 
 
// End of recording handler 
LONG CTalkDlg::OnWimData(UINT wParam, LONG lParam) 
{ 
	TRACE("*** TALKER32 ***: WIM_DATA wParam=%lx, lParam=%lx\n", wParam, lParam); 
	CTapiCall *pCall = (CTapiCall *)(((CTalkApp *)AfxGetApp())->GetCallByParm(KEY_WAVEINHANDLE, (DWORD) wParam)); 
	if(pCall != NULL)  
	{ 
	// For MT implementation, signal the semaphore here  
		pCall->FinishRecord(wParam, lParam);	// override this for MT implementation 
	}	 
	//::WavexFinishRecord(wParam, lParam, NULL);		  
	return TRUE; 
} 
 
 
void CTalkDlg::OnCancel()  
{ 
//	lineConfigDialog(0, m_hWnd, "tapi/line"); 
	((CTalkApp *)AfxGetApp())->Cleanup(); 
	// may have to wait until all calls are actually closed 
	CDialog::OnCancel(); 
} 
 
void CTalkDlg::OnOK()  
{ 
} 
 
void CTalkDlg::OnClear()  
{ 
	AddDigit(NULL);	 
} 
 
void CTalkDlg::OnContextHelp()  
{ 
	CDialog::WinHelp(HIDD_TALKER32_DialogMain, HELP_CONTEXT); 
} 
 
void CTalkDlg::OnSetFocus(CWnd* pOldWnd)  
{ 
	CDialog::OnSetFocus(pOldWnd); 
	((CTalkApp *)AfxGetApp())->SetHelpId(HIDD_TALKER32_DialogMain); 
} 
void CTalkDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)  
{ 
	CDialog::OnActivate(nState, pWndOther, bMinimized); 
	((CTalkApp *)AfxGetApp())->SetHelpId(HIDD_TALKER32_DialogMain); 
} 
 
/************************* 
void CTalkDlg::OnCheck1()  
{ 
	CTapiCall *pCall = m_LineControls[0].pctlLine->ctlGetActiveCall(); 
	if(pCall == NULL) return; 
	if(m_ctlMonitor.GetCheck()) 
	{ 
		LONG lrc = lineMonitorDigits(pCall->m_hCall, LINEDIGITMODE_DTMF);	 
		if(lrc) AfxMessageBox("Monitor failed"); 
	} 
	else 
		lineMonitorDigits(pCall->m_hCall,0); 
} 
 
void CTalkDlg::OnCheck2()  
{ 
	if(m_ctlGather.GetCheck()) 
	{ 
		CTapiCall *pCall = m_LineControls[0].pctlLine->ctlGetActiveCall(); 
		if(pCall == NULL) return; 
		 
//		LONG lrc = pCall->GatherDigits(20, "*#", 10000, 5000, ""); 
		LPSTR lpDigits = (LPSTR)malloc(2048); 
		LPSTR lpDelimit = (LPSTR) malloc(16); 
		lstrcpy(lpDelimit, "*#"); 
		memset(lpDigits, 0, sizeof(lpDigits)); 
		LONG lrc = lineGatherDigits(pCall->m_hCall, LINEDIGITMODE_DTMF, lpDigits, 
				20, lpDelimit, 8000, 5000); 
		if(lrc) AfxMessageBox("Gather failed"); 
	} 
} 
*********************/