📄 tmonitorview.cpp
字号:
// tMonitorView.cpp : implementation of the CtMonitorView class
//
#include "stdafx.h"
#include "tMonitor.h"
#include "tMonitorDoc.h"
#include "tMonitorView.h"
#include "tPhoneNo.h"
#include "CallScreenDlg.h"
#include "LinesDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CtMonitorView
enum ListColumn
{
colName = 0,
colPhoneNo,
colDateTime,
colDuration,
colRings,
colState,
colColumns,
};
static
const char* g_pszStateName[] =
{
"Over", // Idle
"Offering",
"Accepted",
"Dial Tone",
"Dialing",
"Ringing",
"Busy",
"Special Info",
"Connect",
"Proceeding",
"On Hold",
"Conferenced",
"On Hold Pending Conference",
"On Hold Pending Transfer",
"Disconnected",
"Unknown",
};
// Translate bit field into the single set bit
// (0-based, of course)
static
int BitSet(DWORD dw)
{
if( !dw ) return -1;
int nBitSet = 0;
while( !(dw & 1) )
{
//dw /= 2;
dw = dw >> 1;
nBitSet++;
}
return nBitSet;
}
static
void GetBestCallerID(
const CtCallInfo& ci,
CString* psName,
CString* psPhoneNo)
{
LPCSTR pszName = 0;
LPCSTR pszPhoneNo = 0;
CtPhoneNo pno;
if( ci.GetCallerIDFlags() & LINECALLPARTYID_BLOCKED )
{
pszName = "<blocked>";
pszPhoneNo = "<blocked>";
}
else if( ci.GetCallerIDFlags() & LINECALLPARTYID_OUTOFAREA )
{
pszName = "<out of area>";
pszPhoneNo = "<out of area>";
}
else if( ci.GetCallerIDFlags() & LINECALLPARTYID_UNKNOWN )
{
pszName = "<unknown>";
pszPhoneNo = "<unknown>";
}
else if( ci.GetCallerIDFlags() & LINECALLPARTYID_UNAVAIL )
{
pszName = "<unavailable>";
pszPhoneNo = "<unavailable>";
}
else
{
pszName = ci.GetCallerIDName();
pno.SetWholePhoneNo(ci.GetCallerID());
pszPhoneNo = pno.GetTranslatable(0);
}
*psName = (pszName ? pszName : "<unknown>");
*psPhoneNo = (pszPhoneNo ? pszPhoneNo : "<unknown>");
}
IMPLEMENT_DYNCREATE(CtMonitorView, CListView)
BEGIN_MESSAGE_MAP(CtMonitorView, CListView)
//{{AFX_MSG_MAP(CtMonitorView)
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnDeleteitem)
ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetdispinfo)
ON_NOTIFY_REFLECT(NM_RETURN, OnReturn)
ON_WM_DESTROY()
ON_COMMAND(ID_MONITOR_DIAL, OnMonitorDial)
ON_UPDATE_COMMAND_UI(ID_MONITOR_DIAL, OnUpdateMonitorDial)
ON_COMMAND(ID_VIEW_AUTOSIZECOLUMNS, OnViewAutosizecolumns)
ON_UPDATE_COMMAND_UI(ID_VIEW_AUTOSIZECOLUMNS, OnUpdateViewAutosizecolumns)
ON_WM_TIMER()
ON_COMMAND(ID_VIEW_MESSAGES, OnViewMessages)
ON_COMMAND(ID_MONITOR_CALLSCREENSETTINGS, OnMonitorCallScreenSettings)
ON_COMMAND(ID_VIEW_LINES, OnViewLines)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CtMonitorView construction/destruction
CtMonitorView::CtMonitorView()
:
m_sp(0, TRUE),
m_bViewInited(FALSE),
m_nActiveCalls(0),
m_nTimer(0),
m_rgLines(0)
{
}
CtMonitorView::~CtMonitorView()
{
delete[] m_rgLines;
}
BOOL CtMonitorView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= LVS_REPORT | LVS_SINGLESEL | LVS_OWNERDRAWFIXED;
return CListViewEx::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CtMonitorView drawing
void CtMonitorView::OnDraw(CDC* pDC)
{
CtMonitorDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
void CtMonitorView::OpenValidLines()
{
// Open all of the lines to watch for new calls
if( m_rgLines = new CtLine[::TfxGetNumLines()] )
{
for( DWORD nLineID = 0; nLineID < ::TfxGetNumLines(); nLineID++ )
{
TRESULT tr;
// NOTE: Need automated voice to be able to generate digits
// NOTE: Need unknown to be able to get incoming calls
tr = m_rgLines[nLineID].Open(nLineID, this,
LINECALLPRIVILEGE_MONITOR | LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_UNKNOWN | LINEMEDIAMODE_AUTOMATEDVOICE);
if( FAILED(tr) )
{
// If we can't do automated voice, drop back and punt
tr = m_rgLines[nLineID].Open(nLineID, this,
LINECALLPRIVILEGE_MONITOR);
}
// Check for existing calls
if( TSUCCEEDED(tr) )
{
CtCallList cl;
if( TSUCCEEDED(cl.GetNewCalls(m_rgLines[nLineID].GetHandle())) )
{
for( DWORD nCall = 0; nCall < cl.GetNumCalls(); nCall++ )
{
MonitorCall(&m_rgLines[nLineID], cl.GetCall(nCall));
}
}
}
}
SetNumRings(::AfxGetApp()->GetProfileInt("Settings", "Rings", 4));
}
}
void CtMonitorView::OnInitialUpdate()
{
// Guard against re-initing during SDI view reuse
if( !m_bViewInited )
{
CWinApp* pApp = ::AfxGetApp();
m_sp.nColumn = pApp->GetProfileInt("Settings", "SortColumn", m_sp.nColumn);
m_sp.bAscending = pApp->GetProfileInt("Settings", "SortAscending", m_sp.bAscending);
int acxColumns[colColumns];
char szEntry[16];
// Set up column headers
CRect rect;
GetClientRect(&rect);
int nDefaultWidth = rect.Width()/colColumns;
for( int i = 0; i < colColumns; i++ )
{
::wsprintf(szEntry, "ColumnWidth%d", i);
acxColumns[i] = pApp->GetProfileInt("Settings", szEntry, nDefaultWidth);
}
CListCtrl& lc = GetListCtrl();
lc.InsertColumn(colName, "Name", LVCFMT_LEFT, acxColumns[colName]);
lc.InsertColumn(colPhoneNo, "Phone No.", LVCFMT_LEFT, acxColumns[colPhoneNo]);
lc.InsertColumn(colDateTime, "Date/Time", LVCFMT_LEFT, acxColumns[colDateTime]);
lc.InsertColumn(colDuration, "Duration", LVCFMT_LEFT, acxColumns[colDuration]);
lc.InsertColumn(colRings, "Rings", LVCFMT_LEFT, acxColumns[colRings]);
lc.InsertColumn(colState, "State", LVCFMT_LEFT, acxColumns[colState]);
OpenValidLines();
m_bViewInited = TRUE;
}
// Call parent (which calls OnUpdate())
CListViewEx::OnInitialUpdate();
}
BOOL CtMonitorView::AppendCallRecord(
CALLRECORD* pcr)
{
if( pcr )
{
CListCtrl& lc = GetListCtrl();
return (lc.InsertItem(LVIF_TEXT | LVIF_PARAM, lc.GetItemCount(),
LPSTR_TEXTCALLBACK, 0, 0, 0, LPARAM(pcr)) >= 0
? TRUE : FALSE);
}
else
{
return FALSE;
}
}
BOOL CtMonitorView::FindCallRecord(
CtCall* pCall,
CALLRECORD** ppcr,
int* pnItem)
{
ASSERT(pCall);
ASSERT(ppcr);
ASSERT(pnItem);
CListCtrl& lc = GetListCtrl();
for( int nItem = 0; nItem < lc.GetItemCount(); nItem++ )
{
CALLRECORD* pcr = (CALLRECORD*)lc.GetItemData(nItem);
ASSERT(pcr);
if( pcr->pCall == pCall )
{
*ppcr = pcr;
*pnItem = nItem;
return TRUE;
}
}
*ppcr = 0;
*pnItem = 0;
return FALSE;
}
BOOL CtMonitorView::FindCallRecord(
CtLine* pLine,
CALLRECORD** ppcr,
int* pnItem)
{
ASSERT(pLine);
ASSERT(ppcr);
ASSERT(pnItem);
CListCtrl& lc = GetListCtrl();
for( int nItem = 0; nItem < lc.GetItemCount(); nItem++ )
{
CALLRECORD* pcr = (CALLRECORD*)lc.GetItemData(nItem);
ASSERT(pcr);
if( pcr->pCall &&
pcr->pCall->GetLine() == pLine )
{
*ppcr = pcr;
*pnItem = nItem;
return TRUE;
}
}
*ppcr = 0;
*pnItem = 0;
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// CtMonitorView diagnostics
#ifdef _DEBUG
void CtMonitorView::AssertValid() const
{
CListViewEx::AssertValid();
}
void CtMonitorView::Dump(CDumpContext& dc) const
{
CListViewEx::Dump(dc);
}
CtMonitorDoc* CtMonitorView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CtMonitorDoc)));
return (CtMonitorDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CtMonitorView message handlers
void CtMonitorView::DoDial()
{
CListCtrl& lc = GetListCtrl();
int nItem = lc.GetNextItem(-1, LVNI_SELECTED);
if( nItem >= 0 )
{
CALLRECORD* pcr = (CALLRECORD*)lc.GetItemData(nItem);
ASSERT(pcr);
// Check for a non-empty and non-special phone number
if( !pcr->sPhoneNo.IsEmpty() && pcr->sPhoneNo[0] != '<' )
{
// Translate the phone number the best we can
// to canonical or at least all number format
CtPhoneNo pno(pcr->sPhoneNo);
TRESULT tr = ::tapiRequestMakeCall(pno.GetTranslatable(),
::AfxGetAppName(), pcr->sName, 0);
switch( tr )
{
case TAPIERR_NOREQUESTRECIPIENT:
::AfxMessageBox(IDS_NOREQUESTRECIPIENT);
break;
case TAPIERR_REQUESTQUEUEFULL:
::AfxMessageBox(IDS_REQUESTQUEUEFULL);
break;
case TAPIERR_INVALDESTADDRESS:
::AfxMessageBox(IDS_INVALDESTADDRESS);
break;
case TAPIERR_INVALPOINTER:
TRACE("TAPIERR_INVALPOINTER\n");
ASSERT(FALSE);
break;
}
}
}
}
void CtMonitorView::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult)
{
DoDial();
*pResult = 0;
}
int CALLBACK CompareItems(LPARAM lP1, LPARAM lP2, LPARAM lPSort)
{
CtMonitorView::CALLRECORD* pcr1 = (CtMonitorView::CALLRECORD*)lP1;
CtMonitorView::CALLRECORD* pcr2 = (CtMonitorView::CALLRECORD*)lP2;
CtMonitorView::SORTPARAMS* psp = (CtMonitorView::SORTPARAMS*)lPSort;
int nCompare;
// Compare assuming ascending sorting
switch( psp->nColumn )
{
// Sort by name and date/time
case colName:
nCompare = pcr1->sName.CompareNoCase(pcr2->sName);
if( !nCompare )
{
nCompare = pcr1->tmStart - pcr2->tmStart;
}
break;
// Sort by phone no., name and date/time
case colPhoneNo:
nCompare = pcr1->sPhoneNo.CompareNoCase(pcr2->sPhoneNo);
if( !nCompare )
{
nCompare = pcr1->sName.CompareNoCase(pcr2->sName);
if( !nCompare )
{
nCompare = pcr1->tmStart - pcr2->tmStart;
}
}
break;
// Sort by date/time and name
case colDateTime:
nCompare = pcr1->tmStart - pcr2->tmStart;
if( !nCompare )
{
nCompare = pcr1->sName.CompareNoCase(pcr2->sName);
}
break;
// Sort by duration and name
case colDuration:
nCompare = pcr1->GetDuration() - pcr2->GetDuration();
if( !nCompare )
{
nCompare = pcr1->sName.CompareNoCase(pcr2->sName);
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -