📄 acdclnt.c
字号:
//////////////////////////////////////////////////////////////////////////////
//
// ACDCLNT.C
//
// ACDClient app
//
//////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tapi.h>
#include "acdclnt.h"
#include "resource.h"
//////////////////////////////////////////////////////////////////////////////
// PROTOTYPES
//////////////////////////////////////////////////////////////////////////////
static BOOL CreateMainWindow (int nCmdShow);
static LRESULT CALLBACK MainWndProc (HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
LRESULT CALLBACK AgentStateDlgProc (HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
VOID CALLBACK LineCallback (DWORD hDevice,
DWORD dwMsg,
DWORD dwCallbackInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3);
BOOL InitTapi();
BOOL CloseTapi();
BOOL RedoWindow();
BOOL SetStatusMessage(LPTSTR lpszMessage);
BOOL SetButton(DWORD dwAddress,
BOOL bAnswer,
BOOL bEnable);
LRESULT WaitForLineReply();
LONG ThreadRoutine(LPVOID lpv);
//////////////////////////////////////////////////////////////////////////////
//
// GLOBALS
//
//////////////////////////////////////////////////////////////////////////////
HINSTANCE ghInstance; // main instance
HWND ghMainWnd; // main window
PADDRESSINFO pAddressInfo = NULL; // array of info about each address
HLINEAPP ghLineApp; // hlineapp
DWORD gdwAddresses; // number of addresses on our line
DWORD gdwDeviceID; // our device
HLINE ghLine; // our line
HANDLE ghCompletionPort; // tapi message completionport
CRITICAL_SECTION csLineReply;
// using global variables to keep track of line
// replies, since the main thread will only have at most one outstanding
// line reply at a time
BOOL gbReply;
LONG glResult;
//////////////////////////////////////////////////////////////////////////////
//
// WinMain()
//
//////////////////////////////////////////////////////////////////////////////
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow)
{
MSG msg;
ghInstance = hInstance;
if(!InitTapi())
{
MessageBox(NULL,
TEXT("Failed to initialize TAPI"),
TEXT("Cannot start ACDClient"),
MB_OK);
return 0;
}
if (!CreateMainWindow(nCmdShow))
{
return 0;
}
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 1;
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateMainWindow()
//
///////////////////////////////////////////////////////////////////////////////
BOOL CreateMainWindow (int nCmdShow)
{
// main window
ghMainWnd = CreateDialog(ghInstance,
MAKEINTRESOURCE(IDD_MAINDLG),
NULL,
MainWndProc);
if (ghMainWnd == NULL)
{
return FALSE;
}
SetStatusMessage(TEXT("Waiting for call"));
// create buttons
RedoWindow();
ShowWindow(ghMainWnd, nCmdShow);
UpdateWindow(ghMainWnd);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////
//
// BOOL SetStatusMessage(LPTSTR lpszMessage)
//
// Sets text in the static control at the bottom of the main window to
// lpszMessage
//
/////////////////////////////////////////////////////////////////////////////////
BOOL SetStatusMessage(LPTSTR lpszMessage)
{
return (SetWindowText(GetDlgItem(ghMainWnd,
IDC_STATIC1),
lpszMessage));
}
/////////////////////////////////////////////////////////////////////////////////
//
// BOOL ClearCall(HCALL hCall)
//
// Called when a CALLSTATE_IDLE message is recieved. Looks for the call in the
// global pAddressInfo array. If it finds it, is clears the appropriate members
// of the structure
//
/////////////////////////////////////////////////////////////////////////////////
BOOL ClearCall(HCALL hCall)
{
DWORD dwCount;
for (dwCount = 0; dwCount < gdwAddresses; dwCount++)
{
if (pAddressInfo[dwCount].hCall == hCall)
{
pAddressInfo[dwCount].hCall = (HCALL)((DWORD_PTR)NULL);
pAddressInfo[dwCount].bCall = FALSE;
SetButton(dwCount,
TRUE,
FALSE);
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////////
//
// BOOL SetButton()
//
// Sets the status and text of the answer/drop button for a specific address
//
//////////////////////////////////////////////////////////////////////////////////
BOOL SetButton(DWORD dwAddress,
BOOL bAnswer,
BOOL bEnable)
{
if (dwAddress >= gdwAddresses)
return FALSE;
if (bAnswer)
{
SetWindowText(pAddressInfo[dwAddress].hAnswer,
TEXT("Answer"));
}
else
{
SetWindowText(pAddressInfo[dwAddress].hAnswer,
TEXT("Hang Up"));
}
EnableWindow(pAddressInfo[dwAddress].hAnswer,
bEnable);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// VOID CALLBACK LineCallback ()
//
// TAPI callback function. Handles all tapi messages
//
///////////////////////////////////////////////////////////////////////////////
VOID CALLBACK LineCallback (DWORD hDevice,
DWORD dwMsg,
DWORD dwCallbackInstance,
DWORD dwParam1,
DWORD dwParam2,
DWORD dwParam3)
{
LPLINECALLINFO pLCI;
LPLINECALLSTATUS pLCS;
TCHAR szBuffer[64];
switch (dwMsg)
{
case LINE_REPLY:
{
EnterCriticalSection(&csLineReply);
if (dwParam1 == (DWORD)glResult)
{
gbReply = TRUE;
glResult = dwParam2;
}
LeaveCriticalSection(&csLineReply);
}
break;
case LINE_CALLSTATE:
{
if (dwParam1 == LINECALLSTATE_OFFERING)
{
// get the call privilege
// note note note the new LINE_APPNEWCALL
// give call privilege
pLCS = LineGetCallStatus((HCALL)hDevice);
if (!pLCS)
return;
if (!(pLCS->dwCallPrivilege & LINECALLPRIVILEGE_OWNER))
{
// not our call
GlobalFree(pLCS);
return;
}
GlobalFree(pLCS);
// we're getting offered a call
// first get the address
pLCI = LineGetCallInfo((HCALL)hDevice);
if (!pLCI)
{
// error
return;
}
// set the status message text
wsprintf(szBuffer,
TEXT("Incoming call on address %lu"),
pLCI->dwAddressID);
pAddressInfo[pLCI->dwAddressID].hCall = (HCALL)hDevice;
SetStatusMessage(szBuffer);
// set the button to answer
SetButton(pLCI->dwAddressID,
TRUE,
TRUE);
GlobalFree(pLCI);
break;
}
if (dwParam1 == LINECALLSTATE_IDLE)
{
// see if we have this call
ClearCall((HCALL)hDevice);
// dealloc no matter what
lineDeallocateCall((HCALL)hDevice);
break;
}
}
break;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// BOOL GetAddressFromhWnd()
//
///////////////////////////////////////////////////////////////////////////////
BOOL GetAddressFromhWnd(HWND hWnd,
LPDWORD pdwAddress,
LPBOOL pbStatus)
{
DWORD dwAddress;
// go through the array of addressinfo and see
// if the hwnd matches
for (dwAddress = 0; dwAddress < gdwAddresses; dwAddress++)
{
if (pAddressInfo[dwAddress].hStatus == hWnd)
{
*pdwAddress = dwAddress;
*pbStatus = TRUE;
return TRUE;
}
if (pAddressInfo[dwAddress].hAnswer == hWnd)
{
*pdwAddress = dwAddress;
*pbStatus = FALSE;
return TRUE;
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
//
// BOOL DoLineAnswerDrop(DWORD dwAddress)
//
// Handles what happens when the answer/drop button is pressed
//
/////////////////////////////////////////////////////////////////////////////
BOOL DoLineAnswerDrop(DWORD dwAddress)
{
// if we have a call, then we want to drop it
if (pAddressInfo[dwAddress].bCall)
{
SetStatusMessage(TEXT("Hanging up call ..."));
EnterCriticalSection(&csLineReply);
glResult = lineDrop(pAddressInfo[dwAddress].hCall,
NULL,
0);
if (glResult < 0)
{
LeaveCriticalSection(&csLineReply);
// error
}
else if (WaitForLineReply())
{
// error
}
// error or not, deallocate and set button
lineDeallocateCall(pAddressInfo[dwAddress].hCall);
SetButton(dwAddress,
TRUE,
FALSE);
pAddressInfo[dwAddress].hCall = (HCALL)((DWORD_PTR)NULL);
pAddressInfo[dwAddress].bCall = FALSE;
SetStatusMessage(TEXT("Waiting for a call"));
}
else
{
BOOL bError = FALSE;
// answer
SetStatusMessage(TEXT("Answering call..."));
EnterCriticalSection(&csLineReply);
glResult = lineAnswer(pAddressInfo[dwAddress].hCall,
NULL,
0);
if (glResult < 0)
{
LeaveCriticalSection(&csLineReply);
bError = TRUE;
//error
}
else if (WaitForLineReply())
{
bError = TRUE;
// error
}
if (bError)
{
SetStatusMessage(TEXT("Hanging up call ..."));
lineDeallocateCall(pAddressInfo[dwAddress].hCall);
pAddressInfo[dwAddress].hCall = (HCALL)((DWORD_PTR)NULL);
SetButton(dwAddress,
TRUE,
FALSE);
SetStatusMessage(TEXT("Waiting for a call"));
return FALSE;
}
SetStatusMessage(TEXT("On a call"));
pAddressInfo[dwAddress].bCall = TRUE;
SetButton(dwAddress,
FALSE,
TRUE);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
//
// LRESULT DoCommand(WPARAM wParam,
// LPARAM lParam)
//
// Handles WM_COMMAND messages for the main window
//
//////////////////////////////////////////////////////////////////////
LRESULT DoCommand(WPARAM wParam,
LPARAM lParam)
{
DWORD dwAddress;
BOOL bStatus;
// check to see if a button is being clicked
if (HIWORD(wParam) == BN_CLICKED)
{
// check to see if it is a button we care about
if (GetAddressFromhWnd((HWND)lParam,
&dwAddress,
&bStatus))
{
// if it's the status button, display the status
// dialog
if (bStatus)
{
DialogBoxParam(ghInstance,
MAKEINTRESOURCE(IDD_AGENTSTATE),
ghMainWnd,
AgentStateDlgProc,
(LPARAM)dwAddress);
}
// else it's the answer/drop button
else
{
DoLineAnswerDrop(dwAddress);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -