Dan said:
Sounds simple enough - problem is there seems to be WAY too much
documentation and can't seem to find the right one.
I thought twice about replying. But I saw that you said you were desperate.
So, I'm gonna do it but be warned that this drips with personal opinion.
I have to tell you upfront that I am not a big fan of COM. It is not that I
don't appreciate what it does. It came into being, in my view, so that
components could be used by "developers" whose preferred language is not
_the_ one true language. <gd&r> My attitude to those folks is a lot like
Marie Antoinette's was to her subjects - let them use C++.
(Just by the way, .Net addresses COM's issues in a sensible way as all .Net
languages share the same object model so _ultimately_ we won't need a
different and strange component object model).
And just to make it interesting, there are is "raw" COM where everyone and
his brother has to consider what effect his usage of a component has on its
reference count and then the COM often used by C++ developers.
The link below describes the #import compiler directive which causes the C++
compiler to read a COM object's type library and then to create wrapper
classes so you can think in C++ terms rather than in COM terms. Using the
wrappers, for example, insures that when one of these objects is destroyed
its reference count is automatically decremented.
http://msdn.microsoft.com/library/d...e98/HTML/_predir_the_.23.import_directive.asp
Not to be outdone, .Net provides Runtime Callable Wrappers (RCW) for the
same purpose - i.e. so that code in member functions of .Net classes can
make use of the services provided by COM objects. About a year or so ago,
Helen Warn, posted in the TAPI group that there was "some" problem with the
RCW's for TAPI3. I don't remember the issue but I do know that she created
her own wrappers for TAPI (v2?) and was encouraged to post them here:
http://www.gotdotnet.com/Community/...mpleGuid=5d893af6-b340-49d8-9162-b90bf6932414
Finally, the view of lots of types (at least in my experience) who do much
TAPI is that the version 2 procedural API is a better choice than the COM
based stuff of 3.0.
I don't want this to sound negative - C++ rocks, TAPI2 rocks, NET rocks. COM
and TAPI3 well that's something else in my view.
However, if you are looking for a .Net-targeting Managed C++ sample that
uses TAPI3, and if you are willing to use the compiler's COM support then
take a look at the hack below.
It makes a call on a line - here the one with the name "56Kbps Internal
Modem" to the MoviePhone service - here (212) 777-3456.
Note that a proper TAPI application would look for a line which is capable
of carrying a call of the type in question - TAPIMEDIATYPE_AUDIO - and use
it instead of a hard-coded line. You'll need to use the name of whatever
device you have handy.
Regards,
Will
// Don't forget to link against UUID.LIB
#define _WIN32_WINNT 0x0400
#include <windows.h>
#import <tapi3.dll>
using namespace TAPI3Lib;
#using <mscorlib.dll>
using namespace System;
extern "C" const CLSID CLSID_TAPI;
void MakeTapiCall(_bstr_t &, _bstr_t &);
int main()
{
// Look ma, it really is .Net ...
Console::WriteLine(S"Hello World");
// ... but I can have COM too
CoInitializeEx(0, COINIT_MULTITHREADED);
// ... and use COM to call on TAPI 3
MakeTapiCall( _bstr_t("56Kbps Internal Modem"),
_bstr_t("2127773456") );
CoUninitialize();
return 0;
}
// Searches for a line and makes a call to the requested number on it
void MakeTapiCall(_bstr_t &bstrLine, _bstr_t &bstrNumber)
{
ULONG ul;
_bstr_t name;
HRESULT hr;
ITTAPIPtr pTapi;
ITAddressPtr pAddress;
IEnumAddressPtr pEnumAddress;
ITBasicCallControlPtr pCall;
// Initialize TAPI
hr = pTapi.CreateInstance(CLSID_TAPI);
hr = pTapi->Initialize();
// Look for the requested line
pEnumAddress = pTapi->EnumerateAddresses();
while ( pEnumAddress->Next(1, &pAddress, &ul) == S_OK )
{
name = pAddress->AddressName;
if ( name == bstrLine )
break;
pAddress.Release();
pAddress = 0;
}
// If the line was found, then make a call
if ( pAddress )
{
pCall = pAddress->CreateCall(bstrNumber,
LINEADDRESSTYPE_PHONENUMBER,
TAPIMEDIATYPE_AUDIO);
// Make the call
hr = pCall->Connect(true);
// Wait a while - do something sensible here
// while the call is ongoing
Sleep(10000);
// Hangup
hr = pCall->Disconnect(DC_NORMAL);
}
// Shutdown TAPI
hr = pTapi->Shutdown();
pTapi.Release();
}