<form id="hz9zz"></form>
  • <form id="hz9zz"></form>

      <nobr id="hz9zz"></nobr>

      <form id="hz9zz"></form>

    1. 明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

      用TAPI為掌上電腦開發通訊應用程序

      [摘要]中國地質大學(北京)計算機系 田東風掌上電腦(即PPC,Palmsize PC)以Windows CE為操作系統 。Windows CE是一種模塊化的、開放的、實時的、具有強大通信能力的、搶先式、多...
      中國地質大學(北京)計算機系 田東風

      掌上電腦(即PPC,Palmsize PC)以Windows CE為操作系統 。Windows CE是一種模塊化的、開放的、實時的、具有強大通信能力的、搶先式、多任務的嵌入式操作系統。它具備高性能、高效率的OS特性,包括按需換頁、共享存儲、交叉處理同步、支持大容量堆(heap)等。它支持文件系統、注冊表、以及對象存儲(ObjectStore)技術。通過UNICODE完全支持國際字符集。它具有靈活的電源管理,包括睡眠/喚醒模式。它有支持特定目標應用的豐富服務,例如手寫體、流式Video等等。
      由于掌上電腦有Windows圖形用戶界面,因此操作簡單方便。更由于掌上電腦只有手掌大小, 因此特別適用于移動計算和移動通訊領域。Windows CE提供了豐富的通信支持:撥號連接、LAN,提供與PC、內聯網、以及Internet的連接。提供基本的通信基礎結構,包括:套接字(socket)、Internet的TCP/IP、PPP、IrDA、遠程訪問、TAPI(Telephoney API)以及Unimodem、WinInet、Win32串行、SLIP驅動程序,以及PC連接性的支持。并支持廣泛的通信硬件。
      下面以兩個掌上電腦之間通過MODEM進行遠程通訊為例,說明掌上電腦上的通訊程序設計的主要過程。兩個掌上電腦之間通過MODEM進行遠程通訊程序設計時主要有兩種方法。一種方法是直接利用串行通訊函數而不用TAPI,另一種方法是利用TAPI及串行通訊函數。由于利用TAPI可以簡化使用MODEM的過程,并且TAPI已經成為事實上的工業標準,因此,本文介紹采用TAPI的方法。
      TAPI函數以lineXXXXX...的形式命名,其主要函數的具體功能介紹如下。
      1. LONG lineGetID(HLINE hLine, DWORD dwAddressID, HCALL hCall, DWORD dwSelect, LPVARSTRING lpDeviceID, LPCTSTR lpszDeviceClass):獲取或指定開放線路,地址或呼叫相關聯的設備標識符。它返回一個MODEM句柄。。在進行呼叫之前,程序常需要MODEM句柄來檢索MODEM的配置和性能,程序可以通過調用GetCommProperties()以讀取COMMPROP和COMMCONFIG結構來了解MODEM的信息,而GetCommProperties()就需要lineGetID()返回的MODEM句柄。
      2. LONG lineInitialize(LPHLINEAPP lphLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback, LPCTSTR lpszAppName, LPDWORD lpdwNumDevs):初始化TAPI線路。在用TAPI通過MODEM進行遠程通訊程序設計時,必不可少的是調用lineInitialize()函數以初始化TAPI。lineInitialize()分配為支持邏輯線路設備的使用而必須的內部資源。它還登記了一個回調函數,使操作系統通過該函數將有關線路狀態的消息返回給程序。
      3.lineShutDown(hTAPI):關閉TAPI。它是與lineInitialize()相對應的函數,當程序使用完線路設備后,應調用lineShutDown(hTAPI)以釋放為線路設備分配的資源。
      4.lineNegotiateAPIVersion(hAPI,dwDeviceID,dwLowVersion,dwHighVersion,&dwVersionToUse,&extensions):協商TAPI版本號。TAPI是需要版本協商的一種Win32 API。版本協商確保當安裝了新版本的TAPI驅動程序時,程序仍能安全正常運行。
      5.lineGetDevCaps(hAPI,dwLine,dwVersionToUse,dwExtVersion,&linedevcaps):返回指定邏輯線路設備的能力。
      6.LONG lineGetDevConfig (DWORD dwDeviceID, LPVARSTRING lpDeviceConfig, LPCTSTR lpszDeviceClass):返回指定邏輯線路設備的缺省配置。
      7.LONG lineSetDevConfig (DWORD dwDeviceID, LPVOID const lpDeviceConfig, DWORD dwSize, LPCTSTR lpszDeviceClass):設置指定媒體流設備。
      8.LONG lineConfigDialogEdit (DWORD dwDeviceID, HWND hwndOwner, LPCTSTR lpszDeviceClass, LPVOID const lpDeviceConfigIn, DWORD dwSize, LPVARSTRING lpDeviceConfigOut):顯示一個允許用戶改變邏輯線路設備的配置數據的對話框。
      9.LONG lineOpen(HLINEAPP hLineApp, DWORD dwDeviceID, LPHLINE lphLine, DWORD dwAPIVersion, DWORD dwExtVersion, DWORD dwCallbackInstance, DWORD dwPrivileges, DWORD dwMediaModes, LPLINECALLPARAMS const lpCallParams):打開指定邏輯線路設備,并提供后續監視和控制線路的功能。調用lineInitialize()函數初始化TAPI后,就可以調用lineOpen()函數以打開線路。
      10.LONG lineClose(HLINE hLine):關閉指定邏輯線路設備。
      11.LONG lineMakeCall(HLINE hLine, LPHCALL lphCall, LPCTSTR lpszDestAddress, DWORD dwCountryCode, LPLINECALLPARAMS const lpCallParams): 初始化輸出撥號,進行呼叫,并返回線路句柄以進行數據傳輸。
      12.LONG lineDrop(HCALL hCall, LPCTSTR lpsUserUserInfo, DWORD dwSize):收線或斷開呼叫。當程序結束呼叫時,需要調用lineDrop()函數以斷開或中止呼叫。
      13.LONG lineDeallocateCall(HCALL hCall):釋放系統為呼叫分配的內存。當程序結束呼叫時,除了需要調用lineDrop()函數以斷開或中止呼叫外,還調用lineDeallocateCall()函數以釋放系統為呼叫分配的內存,調用lineClose()函數以關閉線路,調用lineShutdown()函數以將程序與TAPI斷開。
      總之,在通過MODEM進行遠程通訊程序設計時,必不可少的是要調用lineInitialize()函數以初始化TAPI,以及調用lineOpen()函數以打開線路,調用lineMakeCall()函數以進行撥號。當程序撥號成功后,就可以使用由lineMakeCall()函數返回的線路句柄進行數據傳輸了!除此之外,為了編寫可靠的遠程通訊程序,還應調用有關檢測線路設備能力的函數,檢測TAPI版本兼容性的函數,檢測線路當前使用狀態的函數等以適應各種情況。當程序結束呼叫時,需要調用lineDrop()函數以斷開和中止呼叫,調用lineDeallocateCall()函數以釋放系統為呼叫分配的內存,調用lineClose()函數以關閉線路,調用lineShutdown()函數以將程序與TAPI斷開。

      下面結合主要代碼說明以上描述的過程。
      #include <tapi.h> //TAPI.DLL 頭文件
      #define TAPI_VERSION_2_0 0x00020000
      #define TAPI_CURRENT_VERSION TAPI_VERSION_2_0
      typedef struct tagLINEINFO
      {
      HLINE hLine;// 由lineOpen()返回的線路句柄
      BOOL bVoiceLine;
      DWORD dwAPIVersion,dwNumOfAddress,dwPermanentLineID;
      TCHAR szLineName[256];
      } LINEINFO, *LPLINEINFO;
      ......
      BOOL CALLBACK MainWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
      {
      switch (uMsg)
      {
      case WM_INITDIALOG:
      {
      ...
      // 初始化TAPI
      if (InitializeTAPI ())
      {
      if (g_hLineApp)
      lineShutdown (g_hLineApp);//關閉TAPI!
      DestroyWindow (hwnd);
      }
      return TRUE;
      }
      case WM_COMMAND:
      {
      switch (LOWORD(wParam))
      {
      case IDC_DIAL:
      {
      ......
      // 撥號!
      MakePhoneCall (g_szCurrentNum); return TRUE;
      }
      }
      break;
      }
      default:
      return DefWindowProc (hwnd, uMsg, wParam, lParam);
      }
      return FALSE;
      }
      //初始化TAPI函數:
      DWORD InitializeTAPI ()
      {
      DWORD dwLineID, dwReturn, dwTimeCount = GetTickCount ();
      //初始化TAPI
      while ( (dwReturn = lineInitialize (&g_hLineApp, g_hInst, (LINECALLBACK) lineCallbackFunc, g_szAppName,
      &g_dwNumDevs)) == LINEERR_REINIT)
      {
      if (GetTickCount () > 5000 + dwTimeCount)
      {
      if (MessageBox (g_hwndMain, TEXT("不能初始化..."),
      EXT("警告"), MB_OKCANCEL) == IDOK)
      break;
      dwTimeCount = GetTickCount ();
      }
      }
      if (dwReturn)
      return dwReturn;
      if (g_dwNumDevs == 0)
      {
      return LINEERR_NODEVICE;
      }
      if (! (g_lpLineInfo = (LPLINEINFO) LocalAlloc (
      LPTR,
      sizeof (LINEINFO) * g_dwNumDevs)))
      {
      return LINEERR_NOMEM;
      }
      for (dwLineID = 0; dwLineID < g_dwNumDevs; ++dwLineID)
      {//獲取線路信息
      GetLineInfo (dwLineID, &g_lpLineInfo [dwLineID]);
      }
      return ERR_NONE;
      }

      //撥號函數!
      VOID MakePhoneCall (LPCTSTR lpszPhoneNum)
      {
      DWORD dwReturn,
      dwSizeOfTransOut = sizeof (LINETRANSLATEOUTPUT),
      dwSizeOfCallParams = sizeof (LINECALLPARAMS);
      LPLINECALLPARAMS lpCallParams = NULL;
      LPLINETRANSLATEOUTPUT lpTransOutput = NULL;
      TCHAR szDialablePhoneNum[TAPIMAXDESTADDRESSSIZE + 1] = {'\0'};
      g_MakeCallRequestID = 0;
      //打開線路
      if (dwReturn = lineOpen (g_hLineApp,
      g_dwCurrentLineID,
      &g_CurrentLineInfo.hLine, g_CurrentLineInfo.dwAPIVersion, 0, 0, LINECALLPRIVILEGE_NONE,
      0, NULL))
      {
      goto exit;
      }
      ......
      //撥號:
      g_MakeCallRequestID = lineMakeCall (g_CurrentLineInfo.hLine,
      &g_hCall,
      szDialablePhoneNum,
      0,
      lpCallParams);
      if (g_MakeCallRequestID > 0)
      {
      g_bCurrentLineAvail = FALSE;
      DialogBoxParam (g_hInst,
      MAKEINTRESOURCE(IDD_DIALING),
      g_hwndMain,
      (DLGPROC) DialingProc, 0);
      }
      else
      {//關閉線路
      CurrentLineClose ();
      }

      ......
      return;
      }

      //為確定線路的狀態,發生的事件而必須提供的回調函數,
      VOID CALLBACK lineCallbackFunc (DWORD hDevice,
      DWORD dwMsg,
      DWORD dwCallbackInstance,
      DWORD dwParam1,
      DWORD dwParam2,
      DWORD dwParam3)
      {
      LPTSTR lpszStatus;
      switch (dwMsg)
      {
      case LINE_CALLSTATE:
      if (g_hCall != (HCALL) hDevice) return;
      switch (dwParam1)
      {
      case LINECALLSTATE_DIALING:
      lpszStatus = TEXT("撥號");
      break;
      case LINECALLSTATE_PROCEEDING:
      lpszStatus = TEXT("撥號完畢,正在呼叫")
      break;
      case LINECALLSTATE_CONNECTED:
      lpszStatus = TEXT("線路接上");
      break;
      case LINECALLSTATE_BUSY:
      ErrorBox (TEXT("線路忙, 關閉"));
      CurrentLineClose ();
      if (g_hwndDial)
      SendMessage (g_hwndDial, WM_COMMAND, MAKEWPARAM(IDOK,0), 0);
      break;
      ......
      }
      break;
      default:
      break;
      }
      }

      //關閉當前線路函數:
      VOID CurrentLineClose ()
      {
      if (g_CurrentLineInfo.hLine)
      lineClose (g_CurrentLineInfo.hLine);
      g_CurrentLineInfo.hLine = NULL;
      g_bCurrentLineAvail = TRUE;
      g_hCall = NULL;
      }
      //獲取線路信息
      DWORD GetLineInfo (DWORD dwLineID, LPLINEINFO LineInfo)
      {
      DWORD dwSize, dwReturn;
      LPTSTR lpszLineName = NULL;
      LPLINEDEVCAPS lpLineDevCaps = NULL;
      //協商TAPI版本號
      if (dwReturn = lineNegotiateAPIVersion (
      g_hLineApp, dwLineID, TAPI_VERSION_1_0, TAPI_CURRENT_VERSION, &(lpLineInfo->dwAPIVersion), NULL))
      {
      goto exit;
      }
      dwSize = sizeof (LINEDEVCAPS);
      do
      {
      if (!(lpLineDevCaps = (LPLINEDEVCAPS) LocalAlloc (LPTR, dwSize)))
      {
      dwReturn = LINEERR_NOMEM;
      goto exit;
      }
      lpLineDevCaps->dwTotalSize = dwSize;
      //獲取指定邏輯線路設備的能力。
      if (dwReturn = lineGetDevCaps (g_hLineApp,
      dwLineID, lpLineInfo->dwAPIVersion, 0, lpLineDevCaps))
      {
      goto exit;
      }
      if (lpLineDevCaps->dwNeededSize <= lpLineDevCaps->dwTotalSize)
      break;
      dwSize = lpLineDevCaps->dwNeededSize;
      LocalFree (lpLineDevCaps);
      lpLineDevCaps = NULL;
      } while (TRUE);
      lpLineInfo->dwPermanentLineID = lpLineDevCaps->dwPermanentLineID;
      ......
      dwReturn = ERR_NONE;
      exit:
      if (lpLineDevCaps)
      LocalFree (lpLineDevCaps);
      if (lpszLineName)
      LocalFree (lpszLineName);
      return dwReturn;
      }

      以上代碼在Visual C++ 5.0及WCE Toolkit for Visual C++ 5.0下調試通過。


      日韩精品一区二区三区高清