Консольная звонилка (PowerBasic)
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [18.97.9.172] |
|
|
Правила раздела Visual Basic: Общие вопросы
FAQ Сайта
FAQ Раздела
Кладовка
Наши Исходники
API-Guide
Поиск по Разделу
MSDN Library Online
Google
Консольная звонилка (PowerBasic)
|
Сообщ.
#1
,
|
|
|
|
Уважаемые форумчане! Возникла необходимость написания консольной звонилки.
Имеется код с использованием TAPI, который я немогу заставить адекватно работать. Длительные поиски не привели к успеху (встречалась пара подобных вопросов без ответов), задавал вопрос на другом форуме - ответа не получил, поэтому решил спросить и здесь. В чем заключается проблема: не удается получить ответ из CallBack функции. ![]() ![]() #Compile Exe #Dim All #Include "Tapi32.inc" #Include "WinUser.inc" Global hCall As Dword Function PBMain Local numberToDial As String numberToDial = $DefNumberToDial ' Зациклено в исследовательских целях 1: Con.Input "Nomer: ", numberToDial dial(numberToDial) GoTo 1 End Function Function Dial(phoneNumber As String) As Long Local lRet As Long, hApiVersion As Long, numLines As Long, lineNo As Long Local minVer As Long, maxVer As Long, dwAPIVersion As Dword Local hLine As Dword Local numberToDial As AsciiZ * 32 Local lineParams As LINECALLPARAMS, extID As LINEEXTENSIONID Local lip As LINEINITIALIZEEXPARAMS Local hInstance As Dword, hTapiApp As Dword Local i As Long Local Msg As tagMsg lip.dwtotalsize = Len(lip) lip.dwoptions = %LINEINITIALIZEEXOPTION_USEHIDDENWINDOW hApiVersion = %TAPI_CURRENT_VERSION numberToDial = phoneNumber hInstance = GetModuleHandle(ByVal %NULL) 'PeekMessage(msg, %Null, 0, 0, %PM_REMOVE) lRet = lineInitializeEx(hTapiApp, hInstance, CodePtr(tapiCallback), "weqweqweqeweqwe", numLines, hApiVersion, lip) If lRet Then Print "Error on LineInitialize: " + Str$(lRet) End If lineNo = -1 For i = 0 To numLines - 1 minVer = &h00010004 maxVer = &h00020000 lRet = LineNegotiateAPIVersion(ByVal hTapiApp, ByVal i, ByVal minVer, ByVal maxVer, dwAPIVersion, extID) If lRet Then Print "Error negotiation API Version: " + Str$(lRet) End If lRet = LineOpen (ByVal hTapiApp, ByVal i, hLine, ByVal dwAPIVersion, ByVal 0, ByVal 0, ByVal %LINECALLPRIVILEGE_NONE, ByVal %LINEMEDIAMODE_DATAMODEM, lineParams) If lRet Then Print "Error on LineOpen: " + Str$(lRet) Else lineNo = i Exit For End If Next i If lineNo < 0 Then Print "Could not find modem": Exit Function lineParams.dwTotalSize = SizeOf(LINECALLPARAMS) lineParams.dwMediaMode = %LINEMEDIAMODE_DATAMODEM lRet = LineMakeCall (ByVal hLine, hCall, numberToDial, ByVal 0, lineParams) If lRet < 0 Then Print "Error making call: " + Str$(lRet) Exit Function End If While PeekMessage(msg, %Null, 0, 0, %PM_REMOVE) TranslateMessage(msg) DispatchMessage(msg) '<-- вот здесь прога падает Loop Print ">>>" LineDrop(ByVal hCall, ByVal 0, ByVal 0) LineClose(ByVal hLine) LineShutdown(ByVal hTapiApp) End Function Function TapiCallback(ByVal hDevice&, ByVal dwMsg&, ByVal CBInstance&,_ ByVal Param1&, ByVal Param2&, ByVal Param3&) As Long Local nDim As Long, Dword As Long, dwNeed As Dword, sDevice As AsciiZ * 16 If dwMsg& = %LINE_REPLY Then If Param2& < 0 Then Print "Line Reply Error" Else Print "Line Reply Ok" End If ElseIf dwMsg& = %LINE_CALLSTATE Then Select Case Param1& Case %LINECALLSTATE_IDLE If hCall <> 0 Then Print "Line Idle" End If Case %LINECALLSTATE_CONNECTED If hCall <> 0 Then Print "Connected" End If Case %LINECALLSTATE_PROCEEDING Print "Proceeding" Case %LINECALLSTATE_DIALING Print "Dialing..." Case %LINECALLSTATE_DISCONNECTED If Param2& = %LINEDISCONNECTMODE_NORMAL Then Print "Disconnected Normal" ElseIf Param2& = %LINEDISCONNECTMODE_BUSY Then Print "Disconnected Busy" ElseIf Param2& = %LINEDISCONNECTMODE_NODIALTONE Then Print "No dial tone" ElseIf Param2& = %LINEDISCONNECTMODE_NOANSWER Then Print "No Answer" End If Case %LINECALLSTATE_BUSY Print "Line Busy" End Select End If End Function после LineMakeCall (если закомментирован цикл с PeekMessage) сразуже происходит вызов LineDrop, соответсвенно я никуда не звоню. Если между ними вставить что-то вроде Waitkey$ вызов происходит и завершается после нажатия любой клавиши. С незакомментированным циклом PeekMessage программа падает на DispatchMessage(msg) - Unhandled exception... (XP) или Прекращена работа программы (Win7). Без вызова DispatchMessage вызов произходит нормально (почти) и LineDrop происходит после отбоя вызываемого номера. Но смысл весь в том, что нужно видеть процесс дозвона и отбоя, а для этого использовать callback. В чем мооя ошибка? В какую сторну ковырять? Help!!! p.s. Извиняюсь за сумбурное изложение... |
|
Сообщ.
#2
,
|
|
|
|
А почему у тебя TapiCallback ничего не возвращает?
|
|
Сообщ.
#3
,
|
|
|
|
B.V., а она должна что-то возвращать?
MSDN: ![]() ![]() LONG WINAPI lineInitializeEx( LPHLINEAPP lphLineApp, HINSTANCE hInstance, LINECALLBACK lpfnCallback, LPCSTR lpszFriendlyAppName, LPDWORD lpdwNumDevs, LPDWORD lpdwAPIVersion, LPLINEINITIALIZEEXPARAMS lpLineInitializeExParams ); lpfnCallback Address of a callback function that is invoked to determine status and events on the line device, addresses, or calls, when the application is using the "hidden window" method of event notification (for more information see lineCallbackFunc). This parameter is ignored and should be set to NULL when the application chooses to use the "event handle" or "completion port" event notification mechanisms. вот я и передаю в функцию lineInitializeEx адрес tapiCallback при помощи функции CODEPTR lineInitializeEx(hTapiApp, hInstance, CodePtr(tapiCallback)... и в том-же MSDN сказано, что lineCallbackFunc не возвращает значения. В моём примере TapiCallback можно объявить и как процедуру, а не как функцию. Похоже разницы от этого никакой, так-что дело не в этом. (Кстати подобный код в PBWin работает (без While PeekMessage ... Loop) - дозванивается и выводит сообщения, например в ListBox). В итоге всё снова упирается в особенности консоли и очередь сообщений, а т.к. я в этом далеко не спец приходится спрашивать... |
|
Сообщ.
#4
,
|
|
|
|
Цитата gigamaxx @ В итоге всё снова упирается в особенности консоли и очередь сообщений Все упирается в неверное использование PeekMessage, которая в отличие от GetMessage не ждет появления событий в очереди. В итоге твой цикл "быстренько" обрабатывает сообщения, которые уже есть в очереди и завершается, не дожидаясь поступления новых сообщений. Причем поскольку ты зациклил вызов dial "в исследовательских" целях, то не исключено, что при повторных проходах PeekMessage извлекает из очереди сообщения, посланные (и не обработанные) в предыдущем цикле, которые могут быть уже невалидными из-за реинициализации линии. Для начала просто замени PeekMessage на GetMessage - если все заработает, то можно будет дальше что-то дорабатывть (например, добавить таймер, чтобы не ждать у моря погоды, и т.п.) |
|
Сообщ.
#5
,
|
|
|
|
Цитата gigamaxx @ Похоже разницы от этого никакой, так-что дело не в этом. Я и не говорил, что дело в этом. Просто если процедура обработки объявлена как функция и при этом ничего не возвращает, это логическая ошибка в коде |
|
Сообщ.
#6
,
|
|
|
|
leo, с GetMessage не работает, к тому-же из её описания следует что функция возвращает значение не нуль, если сообщение не wm_Quit; 0 - в пpотивном случае.
Получается, что выхода из цикла не будет (что я и наблюдаю), пока не прийдет wm_Quit. B.V. Согласен Раскопал пример на С++ Прикреплённый файл tapiwave.zip (61.29 Кбайт, скачиваний: 148)
Тоже консоль, дозвон и проигрывание wav файла. Так вот внем collback работает! После lineMakeCall идет вызов функции PumpMessages, за ней - lineShutdown. (Готовый exe-шник работает, а скомпилировать самому у меня не получилось ни под 6-й студией, ни под 2010 Express). Так вот в примере это выглядит так (сокращено): ![]() ![]() lRet = lineMakeCall(hLine, &hCall, szPhoneNumber, 0, lpLineCallParams); ... // TAPI callback is called only when messages are dispatched! while (!bReadyToEnd || hCall) { PumpMessages(TRUE); } ... lineShutdown(hLineApp); и сама функция PumpMessages: ![]() ![]() BOOL PumpMessages(BOOL bWaitForMessage) { static MSG msg; if (bReadyToEnd) return FALSE; if (bWaitForMessage) { if (!GetMessage(&msg, NULL, 0, 0)) return FALSE; } else if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) return TRUE; else if (msg.message == WM_QUIT) return FALSE; TranslateMessage(&msg); DispatchMessage(&msg); return TRUE; } которую я преобразовал в код PowerBasic, отбросив лишнее: ![]() ![]() Function PumpMessages(bWaitForMessage As Integer) As Integer Static MSG As tagmsg If bWaitForMessage Then If Not GetMessage(msg, %NULL, 0, 0) Then Function = 0 End If Else If Not PeekMessage(msg, %NULL, 0, 0, %PM_REMOVE) Then Function = 1 End If End If TranslateMessage(msg) DispatchMessage(msg) Function = 1 End Function вызываю так: ![]() ![]() lRet = LineMakeCall (ByVal hLine, hCall, numberToDial, ByVal 0, lineParams) While hCall PumpMessages(1) Loop LineDrop(ByVal hCall, ByVal 0, ByVal 0) Не работает - падает.... p.s. Не ясно, почему в PumpMessages передаётся TRUE, ведь тогда блок else никогда не выполняеся? или я что-то не так понимаю? Если принять, что bWaitForMessage всегда равно 1, то получается так: ![]() ![]() Function PumpMessages() As Integer Static MSG As tagmsg If Not GetMessage(msg, %NULL, 0, 0) Then Function = 0 End If TranslateMessage(msg) DispatchMessage(msg) Function = 1 End Function и вызов функции: While hCall PumpMessages Loop тоже не работает. Добавлено PS Как редактировать сообщение? В конце сообщения добавилось 4 одинаковых вложения Прикреплённый файл tapiwave.zip (61.29 Кбайт, скачиваний: 119)
Прикреплённый файл tapiwave.zip (61.29 Кбайт, скачиваний: 107)
Прикреплённый файл tapiwave.zip (61.29 Кбайт, скачиваний: 127)
Прикреплённый файл tapiwave.zip (61.29 Кбайт, скачиваний: 122)
|