⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pbxdlg.cpp

📁 三汇CTI示例程序源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
 // PbxDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Pbx.h"
#include "PbxDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CH_INFO ChInfo[MAX_CH];
/////////////////////////////////////////////////////////////////////////////
// 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()

/////////////////////////////////////////////////////////////////////////////
// CPbxDlg dialog

CPbxDlg::CPbxDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPbxDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPbxDlg)
		// 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 CPbxDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPbxDlg)
	DDX_Control(pDX, IDC_CHINFOLIST, m_ChList);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPbxDlg, CDialog)
	//{{AFX_MSG_MAP(CPbxDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPbxDlg message handlers

BOOL CPbxDlg::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
	//Failed to load driver
	if(!IntiCtiBoard())		
	{
		PostQuitMessage(0);
		return FALSE;
	}
	else
	{
		//set event message programming mode 
		EVENT_SET_INFO EventSet;		
		EventSet.dwWorkMode = EVENT_MESSAGE;	
		EventSet.lpHandlerParam = this->GetSafeHwnd();	
		SsmSetEvent(-1, -1, TRUE, &EventSet);
		
		IntiChList();		//initialize list and channel concerned parameter 
	}

	return TRUE;		// return TRUE  unless you set the focus to a control
}

void CPbxDlg::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 CPbxDlg::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 CPbxDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


BOOL CPbxDlg::IntiCtiBoard(void)
{
	char szCurPath[MAX_PATH];		//current path
	char szShIndex[MAX_PATH];		//path of file ShIndex.ini
	char szShConfig[MAX_PATH];		//path of file ShConfig.ini
	CString CErrMsg;			//error message

	GetCurrentDirectory(MAX_PATH, szCurPath);
	strcpy(szShIndex, szCurPath);
	strcpy(szShConfig, szCurPath);
	strcat(szShIndex, "\\ShIndex.ini");
	strcat(szShConfig, "\\ShConfig.ini");
	
	//load configuration file and initialize system 
	if (SsmStartCti(szShConfig, szShIndex) == -1)
	{
		SsmGetLastErrMsg(CErrMsg.GetBuffer(300));	//300-character buffer at minimum
		AfxMessageBox(CErrMsg, MB_OK);
		CErrMsg.ReleaseBuffer();
		return FALSE;
	}
	
	//to judge whether number of voice board initialized successfully equials that of 
	//voice board set in configuration file. 
	if(SsmGetMaxUsableBoard() != SsmGetMaxCfgBoard())
	{
		SsmGetLastErrMsg(CErrMsg.GetBuffer(300));	//300-character buffer at minimum 
		AfxMessageBox(CErrMsg, MB_OK);
		CErrMsg.ReleaseBuffer();
		return FALSE;
	}

	return TRUE;
}


void CPbxDlg::IntiChList()
{
	char szChNum[10];		//channel number 
	char szChType[100];		//channel type
	int	 nIndex;			//list index 

	char szPhoneNumConfig[MAX_PATH];
	char KeyName[50];
	LPCTSTR lpAppName = "USERNUM";
	GetCurrentDirectory(MAX_PATH, szPhoneNumConfig);
	strcat(szPhoneNumConfig, "\\pbx.ini");
	
	nIndex =0;

	//to initialize list 
	LV_COLUMN lvcChList[MAX_CHLIST_ITEM];
	LIST_PARA MainList[MAX_CHLIST_ITEM] = 
		{
			{24 ,"Ch"},
			{80 ,"ChType"},
			{130 ,"Status"},
			{80 ,"CallerId"},
			{80 ,"CalleeId"},
			{100 ,"DTMFBuffer"},
		};
	
	for(int i=0; i<MAX_CHLIST_ITEM; i++)
	{
		lvcChList[i].mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
		lvcChList[i].iSubItem = i;
		lvcChList[i].pszText  = MainList[i].szText;
		lvcChList[i].cx       = MainList[i].ColumnWidth;
		lvcChList[i].fmt	  = LVCFMT_RIGHT;
		m_ChList.InsertColumn(i, &lvcChList[i]);	
	}
	m_ChList.SetExtendedStyle(m_ChList.GetExtendedStyle() | LVS_EX_FULLROWSELECT);

	nMaxCh = SsmGetMaxCh();		//to retrieve max channel number set in configuration file 

	//to initialize each on-board channel 
	if(nMaxCh >= 0)
	{
		for(int ch=0, i=1; ch<nMaxCh; ch++)
		{
			ChInfo[ch].nLinkToCh  = -1;
			ChInfo[ch].nIndex = -1;
			ChInfo[ch].nTimer = -1;
			ChInfo[ch].nSaveSubmiteCh = -1;
			ChInfo[ch].bPressFlag = FALSE;
			ChInfo[ch].bSubmiteChHookFlag = FALSE;
			memset(ChInfo[ch].szCallerId, '\0', sizeof(char)*NUM_LENGTH);		//to clear CallerId buffer 
			memset(ChInfo[ch].szCalleeId, '\0', sizeof(char)*NUM_LENGTH);		//to clear CalledId buffer
			
			//to retrive channel type information 
			if( (ChInfo[ch].nChType = SsmGetChType(ch)) == -1 )
			{
				AfxMessageBox(_T("Call of function SsmGetChType() failed at initialization"));
			}

			//to judge whether a channel is analog station or trunk channel 
			if(ChInfo[ch].nChType != 0 && ChInfo[ch].nChType !=2) 
			{
				continue;
			}

			//to clear DTMF buffer 
			if(SsmClearRxDtmfBuf(ch) == -1)
			{
				AfxMessageBox(_T("Call of function SsmClearRxDtmfBuf() failed at initialization "));
			}
			
			m_ChList.InsertItem(ch, _itoa(ch,szChNum,10));

			switch(ChInfo[ch].nChType)
			{
			case 0:
				ChInfo[ch].nStatus = TRUNK_IDLE;
				wsprintf(szChType, "Trunk");
				ChInfo[ch].nIndex = nIndex;
				break;
			case 2:
				ChInfo[ch].nStatus = USER_IDLE;
				wsprintf(szChType, "Station");
				ChInfo[ch].nIndex = nIndex;
				
				wsprintf(KeyName, "UserChPhoNum[%d]", i);
				
				GetPrivateProfileString(lpAppName, KeyName, "XXXXXXXX", ChInfo[ch].CUserNum.GetBuffer(16), 16, szPhoneNumConfig);
				wsprintf(szChType,"Station %s",ChInfo[ch].CUserNum);
				//itoa(nPhoneNum, ChInfo[ch].CUserNum.GetBuffer(10), 10);
				if(SsmSetASDT(ch, 1) == -1)
				{
					AfxMessageBox(_T("Call of function SsmSetASDT() failed at initialization "));
				}

				i++;
				//nPhoneNum++;
				break;
			default:
				break;
			}

			m_ChList.SetItemText(nIndex, ITEM_ChType, szChType);
			m_ChList.SetItemText(nIndex, ITEM_ChState, "Idle");
			nIndex++;
		}
	}
	else
	{
		if(nMaxCh == -1)
		{
			AfxMessageBox(_T("Call of function SsmGetMaxCh() failed at initialization "));
		}
	}
	
}

void CPbxDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: Add your message handler code here
	SsmCloseCti();	//To unload CTI driver successfully 
}


LRESULT CPbxDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class
	int nCh;			//channel number
	int nEventCode;		//event code 
	int nCheckChNum;

	if(message > WM_USER)
	{
		nEventCode = message - WM_USER;

		switch(nEventCode)
		{
		case E_SYS_TIMEOUT:
			//to identify channel number according to timer ID 
			for(nCheckChNum=0; nCheckChNum<nMaxCh; nCheckChNum++)
			{
				if(wParam == (WPARAM)ChInfo[nCheckChNum].nTimer)
				{
					nCh = nCheckChNum;
					break;
				}
			}
			
			if(nCheckChNum == nMaxCh)
			{
				return CDialog::WindowProc(message, wParam, lParam);
			}
			break;
		case E_CHG_HookState:
		case E_CHG_RcvDTMF:
		case E_CHG_FlashCount:
		case E_CHG_ChState:
		case E_US_SEIZURE:
		case E_US_RELEASE:
		case E_US_SEIZURE_ACK_IDLE:
		case E_US_SEIZURE_ACK_BUSY:
		case E_US_PICKUP:
		case E_US_SEIZURE_TK:
		case E_TK_SEIZURE_TK_ACK_IDLE:
		case E_TK_SEIZURE_TK_ACK_BUSY:
		case E_TK_RELEASE:
		case E_US_DTMF2TK:
		case E_TK_DIAL_OK:
		case E_TK_DIAL_FAIL:
		case E_TK_REMOTE_NOANSWER:
		case E_TK_REMOTE_PICKUP:
		case E_MSG_RELEASE:
		case E_MSG_FLASH:
		case E_MSG_CONNECT:
		case E_MSG_HANGUP:
		case F_US_SEIZURE:
			nCh = wParam;
			break;
		default:
			return CDialog::WindowProc(message, wParam, lParam);
			break;
		}

		//analog station or trunk channel 
		switch(ChInfo[nCh].nChType)
		{
		case 0:
			TrunkProc(nEventCode, nCh, lParam);
			UpdateChList(nCh);
			break;
		case 2:
			UserProc(nEventCode, nCh, lParam);
			UpdateChList(nCh);
			break;
		default:
			break;
		}
	}
	
	return CDialog::WindowProc(message, wParam, lParam);
}

void CPbxDlg::UpdateChList(int nCh)
{
	CString CNewState;			//new channel state 
	char	szTmpStr[201];		//DTMF buffer 
	
	switch(ChInfo[nCh].nStatus)
	{
	case USER_IDLE:					CNewState = "Idle";					break;
	case USER_LOCAL_RING:			CNewState = "Ringing";					break;
	case USER_GET_1STDTMF:			CNewState = "Select call type";			break;
	case USER_GET_DTMF:				CNewState = "Wait DTMF";		break;
	case USER_REQ_USER:				CNewState = "Wait response";				break;
	case USER_RING_BACK:			CNewState = "Ring back";					break;
	case USER_REQ_TRUNK:			CNewState = "Station request trunk";			break;
	case USER_DIALOUT:				CNewState = "Send Dtmf to trunk";			break;
	case USER_WAIT_REMOTE_PICKUP:	CNewState = "Wait called party's answer";			break;
	case USER_TALKING:				CNewState = "Talking";					break;
	case USER_WAIT_HANGUP:			CNewState = "Wait hangup";				break;
	case TRUNK_IDLE:				CNewState = "Idle";					break;
	case TRUNK_WAIT_1STNUM:			CNewState = "Wait dialing";				break;
	case TRUNK_DIALING:				CNewState = "Dialing";				break;
	case TRUNK_WAIT_REMOTE_PICKUP:	CNewState = "Ring back";					break;
	case TRUNK_WAIT_ACTUAL_PICKUP:	CNewState = "Ringing";					break;
	case TRUNK_WAIT_SELECTION:		CNewState = "Dial extension";				break;
	case TRUNK_REQ_USER:			CNewState = "Wait dial-up result";			break;
	case TRUNK_RING_BACK:			CNewState = "Play backgroun music";				break;
	case TRUNK_CONNECTED:			CNewState = "Talking";					break;
	case USER_F_GET_DTMF:			CNewState = "Dial number of extension to be transferred";			break;
	case USER_F_REQ_USER:			CNewState = "Wait extension's response";			break;
	case USER_F_RING_BACK:			CNewState = "Ring back";					break;
	case USER_F_TALKING:			CNewState = "Talking";			break;
	case USER_F_OPERATE:			CNewState = "Wait next step";		break;
	case USER_F_WAIT_TALK:			CNewState = "Wait connection with destination phone";	break;
	case TRUNK_FLASHING:			CNewState = "wait connection with destination phone";	break;
	default:
		break;
	}
	
	//to retrieve DTMF, size of dtmf buffer can be set in configuration file, with default value of 200 characters 
	if(SsmGetDtmfStr(nCh, szTmpStr) == -1)
	{
		AfxMessageBox(_T("call of functino SsmGetDtmfStr() failed in function UpdateChList()"));
	}

	//update channel information in list 
	m_ChList.SetItemText(ChInfo[nCh].nIndex, ITEM_ChState, CNewState);					//display channel number 
	m_ChList.SetItemText(ChInfo[nCh].nIndex, ITEM_CallerId, ChInfo[nCh].szCallerId);	//display CallerId 
	m_ChList.SetItemText(ChInfo[nCh].nIndex, ITEM_CalleeId, ChInfo[nCh].szCalleeId);	//display CalledId	
	m_ChList.SetItemText(ChInfo[nCh].nIndex, ITEM_RxDTMF, szTmpStr);					//display DTMF

	return;
}

void CPbxDlg::UserProc(UINT event, WPARAM wParam, LPARAM lParam)
{
	int nCh;						//number of station channel 
	DWORD dwDtmfLen;				//length of DTMF received
	UCHAR dwDtmfNum;				// DTMF received
	LONG nHook;						//nHook:0---station channel go on-hook; 1---station channel go off-hook 
	char szVoicePath[MAX_PATH];		//sound file 
	int nToneType = -2;				//tone type
	int nToneChResult;				//tone detection result
	int nPlayResult;				//return value of function SsmCheckPlay()

	nCh = wParam;

	switch(event)
	{
	/*+++++++++driver message +++++++++*/
	case E_CHG_HookState:		//station hook change event
		nHook = lParam;
		if(nHook == 0)			//station channel go on-hook 
		{
			switch(ChInfo[nCh].nStatus)
			{
			case USER_GET_1STDTMF:
				//close T1
				if(SsmStopTimer(ChInfo[nCh].nTimer) == -1)	
				{
					ShowErrMsg("E_CHG_HookState", "USER_GET_1STDTMF", "SsmStopTimer");
				}
				break;
			case USER_GET_DTMF:
				//close T2
				if(SsmStopTimer(ChInfo[nCh].nTimer) == -1)	
				{
					ShowErrMsg("E_CHG_HookState", "USER_GET_DTMF", "SsmStopTimer");
				}
				break;
			case USER_REQ_USER:
				//send E_US_RELEASE
				SendMessage(WM_USER+E_US_RELEASE, ChInfo[nCh].nLinkToCh, nCh);
				break;
			case USER_RING_BACK:
				//send E_US_RELEASE to channel Ch-k
				SendMessage(WM_USER+E_US_RELEASE, ChInfo[nCh].nLinkToCh, nCh);
				break;
			case USER_TALKING:
				//tear down bus connection 
				if(SsmStopTalkWith(nCh, ChInfo[nCh].nLinkToCh) == -1)		
				{
					ShowErrMsg("E_CHG_HookState", "USER_TALKING", "SsmStopSendTone");
				}
				//to send E_MSG_RELEASE to channel connected 
				SendMessage(WM_USER+E_MSG_RELEASE, ChInfo[nCh].nLinkToCh, nCh);
				break;
			case USER_WAIT_HANGUP:
				break;
			case USER_REQ_TRUNK:
				break;
			case USER_DIALOUT:
				//close T3
				if(SsmStopTimer(ChInfo[nCh].nTimer) == -1)	
				{
					ShowErrMsg("E_CHG_HookState", "USER_DIALOUT", "SsmStopTimer");
				}
				//send E_TK_RELEASE
				SendMessage(WM_USER+E_TK_RELEASE, ChInfo[nCh].nLinkToCh, nCh);
				break;
			case USER_WAIT_REMOTE_PICKUP:
				//send E_TK_RELEASE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -