问题1:为什么每次拨号后都弹出一个“呼叫状态”的对话框。
问题2:为什么程序总走不到我写的回调里面。
问题3:为什么对方摘机后我能听见对方的声音,但是对方听不到我的声音。
问题4:如何利用tapi写一个拨号上网的程序,(我现在已经能拨通了。但是我不知道拨通后应该做些什么,比如如何传密码和用户名。希望大家能够在这里畅所欲言。如果好的话我会再开新的贴子加分。
//.h file
#include <tapi.h>
class CTapiConn  
{
public:
bool WaitDial(HWND hWnd);
bool Dial(HWND hWnd, char *chPhoneNum);
LPSTR GetTapiStatus() const
{
return (LPSTR)m_szMessage;
} CTapiConn();
virtual ~CTapiConn();
private:
static      CTapiConn* This;
HWND m_hWnd;
char        m_chPhoneNum[32];   //phone number
HCALL m_hCall; // Call handle
HLINEAPP m_hLineApp;
DWORD m_dwTAPIVer; // TAPI Version
DWORD m_dwNumDevs; // Total number of TAPI devices
DWORD m_dwDevId; // TAPI device used.
DWORD m_dwMediaMode; // MediaMode for calls.
HLINE m_hLine; // Line handle
    char m_szMessage[128]; // Tapi reults
char     m_chText[512]; void TapiStatus(const char *fmt, ...);
bool beginWaitDial();
bool beginDial();
bool Create(int nType);
DWORD SelectLine();
LPSTR FormatLineError(long lLineError, LPSTR lpszOutputBuffer);
LONG HangupCall( void );    static void CALLBACK lineCallbackFunc( DWORD dwDevice, 
DWORD dwMessage, 
DWORD dwCallbackInstance, 
DWORD dwParam1, 
DWORD dwParam2, 
DWORD dwParam3 );};//cpp file
LPSTR pszLineError[] = 
{
"",
"LINEERR_ALLOCATED",
"LINEERR_BADDEVICEID",
"LINEERR_BEARERMODEUNAVAIL",
"LINEERR Unused constant, ERROR!!",
"LINEERR_CALLUNAVAIL",
"LINEERR_COMPLETIONOVERRUN",
"LINEERR_CONFERENCEFULL",
"LINEERR_DIALBILLING",
"LINEERR_DIALDIALTONE",
"LINEERR_DIALPROMPT",
"LINEERR_DIALQUIET",
"LINEERR_INCOMPATIBLEAPIVERSION",
"LINEERR_INCOMPATIBLEEXTVERSION",
"LINEERR_INIFILECORRUPT",
"LINEERR_INUSE",
"LINEERR_INVALADDRESS",
"LINEERR_INVALADDRESSID",
"LINEERR_INVALADDRESSMODE",
"LINEERR_INVALADDRESSSTATE",
"LINEERR_INVALAPPHANDLE",
"LINEERR_INVALAPPNAME",
"LINEERR_INVALBEARERMODE",
"LINEERR_INVALCALLCOMPLMODE",
"LINEERR_INVALCALLHANDLE",
"LINEERR_INVALCALLPARAMS",
"LINEERR_INVALCALLPRIVILEGE",
"LINEERR_INVALCALLSELECT",
"LINEERR_INVALCALLSTATE",
"LINEERR_INVALCALLSTATELIST",
"LINEERR_INVALCARD",
"LINEERR_INVALCOMPLETIONID",
"LINEERR_INVALCONFCALLHANDLE",
"LINEERR_INVALCONSULTCALLHANDLE",
"LINEERR_INVALCOUNTRYCODE",
"LINEERR_INVALDEVICECLASS",
"LINEERR_INVALDEVICEHANDLE",
"LINEERR_INVALDIALPARAMS",
"LINEERR_INVALDIGITLIST",
"LINEERR_INVALDIGITMODE",
"LINEERR_INVALDIGITS",
"LINEERR_INVALEXTVERSION",
"LINEERR_INVALGROUPID",
"LINEERR_INVALLINEHANDLE",
"LINEERR_INVALLINESTATE",
"LINEERR_INVALLOCATION",
"LINEERR_INVALMEDIALIST",
"LINEERR_INVALMEDIAMODE",
"LINEERR_INVALMESSAGEID",
"LINEERR Unused constant, ERROR!!",
"LINEERR_INVALPARAM",
"LINEERR_INVALPARKID",
"LINEERR_INVALPARKMODE",
"LINEERR_INVALPOINTER",
"LINEERR_INVALPRIVSELECT",
"LINEERR_INVALRATE",
"LINEERR_INVALREQUESTMODE",
"LINEERR_INVALTERMINALID",
"LINEERR_INVALTERMINALMODE",
"LINEERR_INVALTIMEOUT",
"LINEERR_INVALTONE",
"LINEERR_INVALTONELIST",
"LINEERR_INVALTONEMODE",
"LINEERR_INVALTRANSFERMODE",
"LINEERR_LINEMAPPERFAILED",
"LINEERR_NOCONFERENCE",
"LINEERR_NODEVICE",
"LINEERR_NODRIVER",
"LINEERR_NOMEM",
"LINEERR_NOREQUEST",
"LINEERR_NOTOWNER",
"LINEERR_NOTREGISTERED",
"LINEERR_OPERATIONFAILED",
"LINEERR_OPERATIONUNAVAIL",
"LINEERR_RATEUNAVAIL",
"LINEERR_RESOURCEUNAVAIL",
"LINEERR_REQUESTOVERRUN",
"LINEERR_STRUCTURETOOSMALL",
"LINEERR_TARGETNOTFOUND",
"LINEERR_TARGETSELF",
"LINEERR_UNINITIALIZED",
"LINEERR_USERUSERINFOTOOBIG",
"LINEERR_REINIT",
"LINEERR_ADDRESSBLOCKED",
"LINEERR_BILLINGREJECTED",
"LINEERR_INVALFEATURE",
"LINEERR_NOMULTIPLEINSTANCE"
};
CTapiConn::CTapiConn()
{
}CTapiConn::~CTapiConn()
{
}bool CTapiConn::Dial(HWND hWnd, char *chPhoneNum)
{
memset(m_chPhoneNum,'\0',sizeof m_chPhoneNum);
strcpy(m_chPhoneNum,chPhoneNum);
m_hWnd = hWnd; return Create(0);
}bool CTapiConn::WaitDial(HWND hWnd)
{
m_hWnd = hWnd;
return Create(1);
}//nType = 0 Dial
//nType = 1 Wait Dial
bool CTapiConn::Create(int nType)
{
LINEINITIALIZEEXPARAMS lineInitializeExParams;
LONG lRes; // Clear the structure before using...
memset(&lineInitializeExParams, 0, sizeof(LINEINITIALIZEEXPARAMS));
// Populate the options...
lineInitializeExParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
lineInitializeExParams.dwUsedSize = sizeof(LINEINITIALIZEEXPARAMS);
//选择异步处理中的事件句柄方式
lineInitializeExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; m_dwTAPIVer = TAPI_CURRENT_VERSION;
m_hCall = NULL; // Initialize TAPI.
lRes = ::lineInitializeEx(&m_hLineApp, AfxGetInstanceHandle(), lineCallbackFunc, 
"tstTapi", &m_dwNumDevs, &m_dwTAPIVer, &lineInitializeExParams); if(lRes != 0)  //Oops!
{
FormatLineError(lRes, m_chText);
TapiStatus("初始化线路发生错误。Error:[%s]",m_chText);
return false;
}
else
TapiStatus("初始化线路..." );
m_dwMediaMode = LINEMEDIAMODE_DATAMODEM; m_dwDevId = SelectLine();
if(m_dwDevId == 0xffffffff) 
{
TapiStatus("No suitable line found.\r\n");
lineShutdown(m_hLineApp);
return false;
} // Open the line...
lRes = ::lineOpen(m_hLineApp, m_dwDevId, &m_hLine, m_dwTAPIVer, 0x00000000, 1, 
LINECALLPRIVILEGE_OWNER, m_dwMediaMode, NULL);
if(lRes != 0)
{ //  Doh!
FormatLineError(lRes, m_chText);
TapiStatus("TAPI Error: %s on lineOpen.\r\n", m_chText);
return false;
} // We want to be notified for everything
lRes = lineSetStatusMessages(m_hLine, 0x1ffffff, 0);
if(lRes != 0)
{
FormatLineError(lRes, m_chText);
TapiStatus("TAPI Error: %s on lineOpen.\r\n", m_chText);
return false;
} if(nType == 0)
{//Dial
return beginDial();
}
else
{//Wait Dial
return beginWaitDial();
} return true;
}

解决方案 »

  1.   

    DWORD CTapiConn::SelectLine()
    {
    DWORD dwResult = 0xFFFFFFFF;
    DWORD dwAPIVersion;
    LINEEXTENSIONID ExtentionId;
    LINEDEVCAPS *lpDevCaps;
    DWORD i;
    LONG lRes;
    BOOL bDone; for(i = 0 ; i < m_dwNumDevs ; i++)
    { lRes = ::lineNegotiateAPIVersion(m_hLineApp, i, 0x00010003, m_dwTAPIVer, 
    &dwAPIVersion, &ExtentionId);
    if(lRes != 0)  //Oops!
    {
    FormatLineError(lRes, m_chText);
    TapiStatus("TAPI Error: %s on lineNegotiateAPIVersion.\r\n", m_chText);
    }
    else
    {
    m_dwTAPIVer = dwAPIVersion;
    return i;
    lpDevCaps = (LINEDEVCAPS *)malloc(sizeof(LINEDEVCAPS)+1000); // Allocate a little extra memory...
    if(lpDevCaps == NULL) return dwResult; // No luck allocating memory... memset(lpDevCaps, 0, sizeof(LINEDEVCAPS)+1000);
    lpDevCaps->dwTotalSize = sizeof(LINEDEVCAPS)+1000;
    bDone = FALSE;
    do // Go around and keep trying until there's enough memory
    {
    lRes = lineGetDevCaps(m_hLineApp, i, dwAPIVersion, 0, lpDevCaps);
    if(lRes != 0)  //Oops!
    {
    FormatLineError(lRes, m_chText);
    TapiStatus("TAPI Error: %s on lineGetDevCaps.\r\n", m_chText);
    free(lpDevCaps);
    break;
    }
    if(lpDevCaps->dwNeededSize > lpDevCaps->dwTotalSize)
    // Reallocate for dwNeededSize
    lpDevCaps = (LINEDEVCAPS *)realloc(lpDevCaps, lpDevCaps->dwNeededSize);
    else bDone = TRUE;
    }
    while (!bDone); TapiStatus("Line %d is %s.\r\n", i, (LPBYTE)((DWORD)lpDevCaps+(DWORD)lpDevCaps->dwLineNameOffset));
    if(lpDevCaps->dwMediaModes & m_dwMediaMode)
    {
    dwResult = i;
    TapiStatus("Line device %d selected.\r\n", i);
    }
    else TapiStatus("Line device %d rejected.\r\n", i);
    free(lpDevCaps);
    }
    }
    return dwResult;
    }LPSTR CTapiConn::FormatLineError(long lLineError, LPSTR lpszOutputBuffer)
    {
       DWORD dwError;   if (lpszOutputBuffer == NULL)
          return NULL;   // Strip off the high bit to make the error code positive.
       dwError = (DWORD)lLineError & 0x7FFFFFFF;   if ((lLineError > 0) || (dwError > sizeof(pszLineError)))
          wsprintf(lpszOutputBuffer, "Unknown LINEERR_ code: 0x%lx", lLineError);
       else
          strcpy(lpszOutputBuffer, pszLineError[dwError]);   return lpszOutputBuffer;
    }
    bool CTapiConn::beginDial()
    {
    LONG lRes; TapiStatus("Calling %s\r\n", m_chPhoneNum);
    lRes = lineMakeCall(m_hLine, &m_hCall, m_chPhoneNum, 0, NULL);
    if(lRes != 0)
    { //  Doh!
    FormatLineError(lRes, m_chText);
    TapiStatus("TAPI Error: %s on lineMakeCall.\r\n", m_chText);
    } return true;
    }bool CTapiConn::beginWaitDial()
    { return true;
    }void CTapiConn::TapiStatus(const char *fmt, ...)
    {
    va_list ap; memset(m_szMessage,'\0',sizeof m_szMessage); va_start(ap, fmt);
    vsprintf(m_szMessage, fmt, ap); /* this is not safe */
    va_end(ap); ::SendMessage(m_hWnd, WM_TAPI_STATUS, 0, 0); 
    }
    void CALLBACK CTapiConn::lineCallbackFunc(DWORD dwDevice, 
    DWORD dwMessage, 
    DWORD dwCallbackInstance, 
    DWORD dwParam1, 
    DWORD dwParam2, 
    DWORD dwParam3 )
    {   
    }
      

  2.   

    建议事件通知机制用LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
    建议lineSetStatusMessages(m_hLine, 0x1ffffff, 0x1ff); 
    "tstTapi"是否是真正的应用程序名?
    m_dwMediaMode = LINEMEDIAMODE_DATAMODEM ?如果是语音模式,严格来讲,应该是LINEMEDIAMODE_INTERACTIVEVOICE
    如果要answer,lineOpen的权限参数应该是LINECALLPRIVILEGE_OWNER+LINECALLPRIVILEGE_MONITOR
    问题1没碰见过,单步调试看哪一句弹出的对话框吧。
    问题3不应该是程序的问题吧?不知道你的测试环境,不好判断。
    问题4写拨号上网程序不应该用TAPI,而是用RAS。
      

  3.   

    建议事件通知机制用LINEINITIALIZEEXOPTION_USEHIDDENWINDOW;
    建议lineSetStatusMessages(m_hLine, 0x1ffffff, 0x1ff); 
    "tstTapi"是否是真正的应用程序名?
    m_dwMediaMode = LINEMEDIAMODE_DATAMODEM ?如果是语音模式,严格来讲,应该是LINEMEDIAMODE_INTERACTIVEVOICE
    如果要answer,lineOpen的权限参数应该是LINECALLPRIVILEGE_OWNER+LINECALLPRIVILEGE_MONITOR
    问题1没碰见过,单步调试看哪一句弹出的对话框吧。
    问题3不应该是程序的问题吧?不知道你的测试环境,不好判断。
    问题4写拨号上网程序不应该用TAPI,而是用RAS。