Quote
"Onno Broekmans" <obroe...@angelfire.com> wrote in message
news:3d0cb243_2@dnews...
Quote
> In the past few days, I've been messing around a bit with
> the MS Agent ActiveX control.
You should have a look at my free TMSAgent VCL component,
http://msagent.lebeausoftware.org. It is a native VCL component written in
C++ that wraps the entire MSAgent Server Interface. Worth looking at for
learning from. There are also C++ code samples available at
http://www.microsoft.com/msagent/vstudiocode.htm (though they are geared
towards VC++ and MFC, not Builder), and they use the MSAgent Server
Interface, not the MSAgent Client Control.
You really should be programming the MSAgent Server Interface anyway when
working with C++. Not the Client Control, which is what you get when you
use the "Import ActiveX Control" option. You have to use CoCreateInstance()
at runtime to instantiate the Server Interface. The Server Interface
provides direct access to the MSAgent control directly, whereas the Client
Control is meant for scripting languages (JScript, VBScript) and similar
languages (like VB and FoxPro), which do not have access to using the Server
Interface at all. Even the MSAgent documentation from Microsoft
specifically suggests using the Server Interface when working with C++.
Quote
> First of all, all the Agent control's methods etc. work with
> 'widestrings', which seems to complicate things.
No, actually, they all work with BSTR. WideString is just a VCL wrapper
around BSTR to make it easier to work with. BSTR is the native string type
for COM programming in general.
Quote
> For example, I can't write:
> Agent->Characters->Load("Genie", "Genie.acs");
> since 'char*' and 'BSTR' are not compatible!
Correct. You have to convert the char* first. A char is a single byte per
character, whereas BSTR uses wchar_t instead, which is two bytes per
character. You can't simply cast between the two data types, you have to
actually convert from single- to double-byte, and vice versa. This is done
with the MultiByteToWideChar() and WideCharToMultiByte() functions from the
Win32 API. The easiest way is to use WideString class, which uses those
functions internally:
Agent->Characters->Load(WideString("Genie"), WideString("Genie.acs"));
Quote
> though a similar syntax should work in Delphi.
That's because Delphi has native support for working with interfaces and
such built into the Pascal language itself. C++ doesn't have that, so you
have to do things manually.
Quote
> I have to do something like:
> WideString a = "Genie", b = "Genie.acs";
> Agent->Characters->Load(a.c_bstr(), b.c_bstr());
You don't need to use c_bstr(), as WideString has a BSTR conversion operator
so that you can pass a WideString directly whereever a BSTR is expected.
See my example above.
Quote
> I was wondering if this could be done differently...
See above.
Quote
> Furthermore, I can't get the hang of these 'collections'. I thought
> this would work:
> Agent->Characters["Genie"]->Show();
Nope. COM collections are still interfaces like any other, and as such you
have to use their exposed methods for accessing the members of the
collection. There is no '[]' operator defined, nor do they have __property
values such that you're used to programming with, either. You won't see the
methods listed in the documentation, because the documentation for the
Client Control (which you're currently using) is geared for VB, not C++.
You'll have to refer to the actual header file for the control to see what
is actually available for use.
In the particular case above, you have to access the character using the
Characters collection's Character() method, ie:
IAgentCtlCharacter *pGenie = NULL;
if(SUCCEDED(Agent->Characters->Character(WideString("Genie"), &pGenie)))
{
pGenie->Show();
pGenie->Release();
}
Or, if you use the auto-generated VCL wrapper classes:
IAgentCtlCharacterDisp Genie;
Agent->Characters->Character(WideString("Genie"), &pGenie);
if(Genie)
Genie->Show();
Quote
> Maybe BCB4 doesn't support COM collections?
Yes, it does, you're just not using them correctly.
Quote
> Do I have to use some 'manual' functions?
Yes, you have to use the exposed methods of the collection interface itself.
Gambit