📄 sampldlg.cpp
字号:
// hold call - just set reservation flag to FALSE
RetCode_t rc = cstaHoldCall(m_TsapiWndPtr->m_AcsHandle, (InvokeID_t)pTsapi,
&connID, FALSE, NULL);
if(rc < 0)
{
AfxMessageBox("hold call failed");
return;
}
// now that the call has been held, change button text
m_HoldControl.SetWindowText(_T("Unh&old"));
}
return;
}
// this method enables/disables buttons (and input fields) based on current status
void CSampleDlg::DoButtonUpdates()
{
// get selected list item
int index = m_CallListControl.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
if(index < 0)
{
// if no item is selected, nothing can be done
m_HoldControl.EnableWindow(FALSE);
m_AnswerControl.EnableWindow(FALSE);
m_HangUpControl.EnableWindow(FALSE);
return;
}
// get the local connection state out of selected list control item
CString connState = m_CallListControl.GetItemText(index, LOCAL_CONNECTION_STATE);
// enable hold button - for holding or unholding
m_HoldControl.EnableWindow(TRUE);
// set hold text based on selected item's state
m_HoldControl.SetWindowText((connState == _T("Held")) ? _T("Unh&old") : _T("H&old"));
// enable answer and hang-up buttons based on selected item's state
m_AnswerControl.EnableWindow(connState == _T("Alerting"));
m_HangUpControl.EnableWindow(connState == _T("Connected"));
}
// this method is called when an item in the call list is selected
void CSampleDlg::OnClickCalllist(NMHDR* pNMHDR, LRESULT* pResult)
{
// update the buttons based on state of the selected item
DoButtonUpdates();
*pResult = 0;
}
// this method is called on every update to the "Make Call To" field.
void CSampleDlg::OnChangeTodeviceid()
{
// retrieve the data out of the dialog
UpdateData(TRUE);
// enable the Call button if the "Make Call To" field is not empty
m_CallControl.EnableWindow(!m_ToDeviceID.IsEmpty());
}
// this method is called when the CSTA DLL returns failure on an attempt
// to retrieve a TSAPI message.
// the failure code is in wParam. It is a RetCode_t and is one of the
// failure codes defined in acs.h.
LRESULT CSampleDlg::OnTsapiFailure(WPARAM wParam, LPARAM lParam)
{
char tempStr[10];
sprintf(tempStr, "TSAPI Message Retrieval Failure: %d", wParam);
AfxMessageBox(tempStr);
PostMessage(WM_COMMAND, IDCANCEL, 0);
return 0;
}
// this method is called when an ACS Unsolicited event is received
LRESULT CSampleDlg::OnTsapiAcsUnsolicited(WPARAM wParam, LPARAM lParam)
{
char tempStr[10];
sprintf(tempStr, "TSAPI Stream Failure: %d",
m_TsapiWndPtr->m_EventBufPtr->event.acsUnsolicited.u.failureEvent.error);
AfxMessageBox(tempStr);
PostMessage(WM_COMMAND, IDCANCEL, 0);
return 0;
}
// this method is called when a CSTA Confirmation event is received
LRESULT CSampleDlg::OnTsapiCstaConfirmation(WPARAM wParam, LPARAM lParam)
{
switch(m_TsapiWndPtr->m_EventBufPtr->eventHeader.eventType)
{
case CSTA_MAKE_CALL_CONF:
case CSTA_CLEAR_CONNECTION_CONF:
case CSTA_ANSWER_CALL_CONF:
case CSTA_HOLD_CALL_CONF:
case CSTA_RETRIEVE_CALL_CONF:
// let the unsolicited events take care of any updates
// Generally, nothing should be done with positive confirmation
// events - the unsolicited events should drive the application's
// behaviour.
break;
case CSTA_UNIVERSAL_FAILURE_CONF:
// something more elaborate should probably be done when
// a request fails!
AfxMessageBox("requested operation failed");
break;
default:
AfxMessageBox("unexpected response to requested operation");
break;
}
return 0;
}
// this method is called when a CSTA Unsolicited event is received
LRESULT CSampleDlg::OnTsapiCstaUnsolicited(WPARAM wParam, LPARAM lParam)
{
// Get the device record pointer out of the lParam
// Get the unsolicited event pointer out of the event buffer (for
// code efficiency and typing efficiency)
CTsapiDevice* pTsapi = (CTsapiDevice*)lParam;
CSTAUnsolicitedEvent* pUns = &(m_TsapiWndPtr->m_EventBufPtr->event.cstaUnsolicited);
switch(m_TsapiWndPtr->m_EventBufPtr->eventHeader.eventType)
{
// this is not a call-control event. just end the app if the monitor
// of the device was terminated for any reason.
case CSTA_MONITOR_ENDED:
AfxMessageBox("monitor failure");
PostMessage(WM_COMMAND, IDCANCEL, 0);
return 0;
// these are call-control events...
case CSTA_SERVICE_INITIATED: // null -> initiated (LOCAL only)
{
ConnectionID_t* pConnID = &(pUns->u.serviceInitiated.initiatedConnection);
// this is a new call - track it
long callHandle = pTsapi->CreateCallFromLocalConnection(*pConnID);
if(callHandle == 0)
{
AfxMessageBox("no memory to add new call");
return 0;
}
LV_ITEM lvItem;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.mask = LVIF_PARAM;
lvItem.lParam = callHandle;
// insert the call into the list control
int listIndex = m_CallListControl.InsertItem(&lvItem);
if(listIndex < 0)
{
pTsapi->RemoveCallViaConnection(*pConnID);
AfxMessageBox("no memory to add new call");
return 0;
}
// this event is always for the local connection
m_CallListControl.SetItemText(listIndex, LOCAL_CONNECTION_STATE, _T("Initiated"));
break;
}
case CSTA_ORIGINATED: // null/initiated -> connected (LOCAL only)
{
ConnectionID_t* pConnID = &(pUns->u.originated.originatedConnection);
// Attempt to find the call associated with the connection ID
// if a SERVICE INITIATED event was received, this call will
// be found.
// if no SERVICE INITIATED event was received, then this event is the
// first event received.
long callHandle = pTsapi->GetCallHandle(*pConnID, TRUE);
int listIndex;
if(callHandle == 0)
{
// assume this is a new call - track it
callHandle = pTsapi->CreateCallFromLocalConnection(*pConnID);
if(callHandle == 0)
{
AfxMessageBox("no memory to add new call");
return 0;
}
LV_ITEM lvItem;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.mask = LVIF_PARAM;
lvItem.lParam = callHandle;
// insert the call into the list control
listIndex = m_CallListControl.InsertItem(&lvItem);
if(listIndex < 0)
{
pTsapi->RemoveCallViaConnection(*pConnID);
AfxMessageBox("no memory to add new call");
return 0;
}
}
else
{
LV_FINDINFO findInfo;
findInfo.flags = LVFI_PARAM;
findInfo.lParam = callHandle;
listIndex = m_CallListControl.FindItem(&findInfo, -1);
}
// this event is always for the local connection
m_CallListControl.SetItemText(listIndex, LOCAL_CONNECTION_STATE, _T("Connected"));
CString calledDevice;
// get the number dialed out of calledDevice
// For calls originated via the phone, this is the first chance to
// place the information into the dialog.
// Modifying the "To Device" here and in other events illustrates
// how the PBX and/or PBX Driver what has been dialled. Apps need
// to be aware that this can happen.
if(pUns->u.originated.calledDevice.deviceIDStatus == ID_PROVIDED)
{
calledDevice = pUns->u.originated.calledDevice.deviceID;
}
else
{
calledDevice = _T("Not provided");
}
m_CallListControl.SetItemText(listIndex, 0, calledDevice);
break;
}
case CSTA_DELIVERED: // null -> alerting
{
ConnectionID_t* pConnID = &(pUns->u.delivered.connection);
SubjectDeviceID_t* pSubjectDevice = &(pUns->u.delivered.alertingDevice);
CallingDeviceID_t* pCallingDevice = &(pUns->u.delivered.callingDevice);
CalledDeviceID_t* pCalledDevice = &(pUns->u.delivered.calledDevice);
BOOL subjectProvided = (pSubjectDevice->deviceIDStatus == ID_PROVIDED);
BOOL callingProvided = (pCallingDevice->deviceIDStatus == ID_PROVIDED);
BOOL calledProvided = (pCalledDevice->deviceIDStatus == ID_PROVIDED);
BOOL outgoing;
if(subjectProvided)
{
outgoing = !(m_DeviceID == pSubjectDevice->deviceID);
}
else if(callingProvided)
{
outgoing = (m_DeviceID == pCallingDevice->deviceID);
}
else if(calledProvided)
{
outgoing = !(m_DeviceID == pCalledDevice->deviceID);
}
else
{
// nothing we can do if no IDs are provided!
return 0;
}
if(outgoing)
{
// don't bother storing remote connection while it is still alerting...
// Find the call handle based on call ID in given connection ID
// Unfortunately, we must crack open the ConnID here (the FALSE indicates
// an inexact match - just match on callID). Looking at the callID is
// not guaranteed to work on 100% of all PBX drivers - some implementations
// do not guarantee unique call IDs, only unique connection IDs.
// There are 2 alternatives to this, neither one of which is any better
// than this (and may even be worse).
// 1. Look at the calledDevice. The app should know the number that was called,
// and could store that number with the local connection ID. When execution
// reaches here, search for the called device and return the callHandle. This
// has 2 problems: a. calledDevice is not guaranteed to be supplied from all PBX
// drivers; b. if 2 calls to the same device are in progress simultaneously, which
// callHandle is for which device?
// 2. Do a cstaSnapshotCall() on the connection ID passed in here. That will give you
// a picture of what is happening with that connID - including the connID in the
// call that is associated with the monitored device. The snapshot can be used to
// match that local connID to what is stored in the app. This delays handling of
// the event with asynchronous queries to the server - in the meantime other things
// are happening to the call!
long callHandle = pTsapi->GetCallHandle(*pConnID, FALSE);
if(callHandle == 0)
{
return 0;
}
// need to get listIndex for where this message should go
LV_FINDINFO findInfo;
findInfo.flags = LVFI_PARAM;
findInfo.lParam = callHandle;
int listIndex = m_CallListControl.FindItem(&findInfo, -1);
m_CallListControl.SetItemText(listIndex, REMOTE_CONNECTION_STATE, _T("Alerting"));
CString calledDevice;
// get the called device out of subjectDevice or calledDevice
if(subjectProvided)
{
calledDevice = pSubjectDevice->deviceID;
}
else if(calledProvided)
{
calledDevice = pCalledDevice->deviceID;
}
else
{
calledDevice = _T("Not provided");
}
m_CallListControl.SetItemText(listIndex, 0, calledDevice);
}
else
{
// this is a new call (for this device) - track it
long callHandle = pTsapi->CreateCallFromLocalConnection(*pConnID);
if(callHandle == 0)
{
AfxMessageBox("no memory to add new call");
return 0;
}
LV_ITEM lvItem;
lvItem.iItem = 0;
lvItem.iSubItem = 0;
lvItem.mask = LVIF_PARAM;
lvItem.lParam = callHandle;
// insert the call into the list control
int listIndex = m_CallListControl.InsertItem(&lvItem);
if(listIndex < 0)
{
pTsapi->RemoveCallViaConnection(*pConnID);
AfxMessageBox("no memory to add new call");
return 0;
}
m_CallListControl.SetItemText(listIndex, LOCAL_CONNECTION_STATE, _T("Alerting"));
CString callingDevice;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -