Re: RE : RE : RE : RE : RE : RE : [fpc-pascal] support for using an activex

2011-05-30 Thread Roberto Padovani
Hi Ludo,

I really cannot get the items to work. I simplyfied the source code to
the minimum in order to test the items stuff.

var   obj, item, items : variant;

obj := CreateOleObject('WRGactiveX.Device');  // OK
items := obj.Transducers;   // OK
writeln('Count: ', items.Count); // OK ,
always prints 8

item := items.item[1]; // Crash: EOleSysError : Numero di
parametri non valido.

Where the exception comment translates to wrong number of parameters.
Instead, writing item := items[1]  gives the exception
EVariantInvalidArgError : Invalid argument: Dispatch

In the activex source code I hav these interface declarations:

interface ITransducer : IDispatch
{
[propget, id(1), helpstring(property Name)] HRESULT Name([out,
retval] BSTR *pVal);
[propget, id(2), helpstring(property Status)] HRESULT 
Status([out,
retval] WRG_TransdStatus *pVal);
[propget, id(4), helpstring(property Meas)] HRESULT Meas([out,
retval] double *pVal);
};

interface ITransducers : IDispatch
{
[propget, id(1), helpstring(property Count)] HRESULT 
Count([out,
retval] long *pVal);
[propget, id(DISPID_VALUE), helpstring(property Item)] HRESULT
Item(long Index, [out, retval] ITransducer* *pVal);
[propget, id(DISPID_NEWENUM), helpstring(property _NewEnum),
hidden] HRESULT _NewEnum([out, retval] LPUNKNOWN *pVal);
};

and used inside the IDevice class like:

[propget, id(21), helpstring(property Transducers)] HRESULT
Transducers([out, retval] ITransducers* *pVal);


I would be very grateful if you could help me once more.

Roberto



2011/5/25 Ludo Brands ludo.bra...@free.fr:
 Using variants you can transparently walk along the exposed objects. The
 variant contains the Idispatch of the object and gets the exposed methods at
 runtime. Properties are implemented as get and put methods or just get
 methods for read only properties.

 If you have something like
 Itransducers = interface
  ..
  property transducer[Index:integer]:Itransducer;
 end;

 Then you would do
 transducer := transducers.transducer[index];

 transducer := transducers[index];  works only if transducer is the default
 property for Itransducers. I'm not sure if fpc supports this.

 Ludo


 -Message d'origine-
 De : fpc-pascal-boun...@lists.freepascal.org
 [mailto:fpc-pascal-boun...@lists.freepascal.org] De la part de Roberto
 Padovani
 Envoyé : mercredi 25 mai 2011 19:34
 À : FPC-Pascal users discussions
 Objet : Re: RE : RE : RE : RE : RE : [fpc-pascal] support for using an
 activex


 2011/5/25 Ludo Brands ludo.bra...@free.fr:
 The code in article
 http://www.informit.com/articles/article.aspx?p=130494seqNum=5 goes a
 long way in doing what you want to do. Unit Eventsink does pretty much
 of the legwork. You should remove the procedure register since that is
 the Delphi way to get a component on the toolbar. Remove also the
 {$IFDEF VER100} and {$ENDIF}. The unit actually includes the code for
 InterfaceConnect!!

 found that! great!


 As for the tlb conversion, in your case

 IEventIntfEvents = dispinterface
  ['{168F5642-5751-49F5-9AA4-B8A7A5F6A5B8}']
  end;

 should do (that is for the events part). AFAIK the procedure and
 dispid definitions are only needed for the server. You are only
 concerned with dispid's. No need to create prototypes for
 OnCommChanged() etc. EventSink1Invoke would be a simple case DispID of
  1: // do CommChanged
  2: // do StatesChanged
 ...
 end;



 Now I am wasting time making the tlb pascal definitions.
 For the event part I'm fine with the dispid's
 Until now I was calling the activex method with variants, in and out, but
 now I discovered that this IDevice class has a property like: property
 Sensors: ISensors;
 which inside is a list of items like   Sensor: ISensor.

 Can I read the sensores with a variant? Then, to see the fields inside each
 sensor, I think a I need a class to do that... The activex has all of these
 classes with the suitable dispinterfaces and uuids and so on. But if I
 define
     var device, transducers, transducer : variant;
 and create
     device := CreateOleObject('Device');
 then, can i simply write the following ?
     transducers := device.Transducers;
     transducer := transducers[index];


 It's a long path until I get this stuff working...

 R#
 ___
 fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
 http://lists.freepascal.org/mailman/listinfo/fpc-pascal

 ___
 fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
 http://lists.freepascal.org/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: RE : RE : RE : RE : [fpc-pascal] support for using an activex

2011-05-25 Thread Roberto Padovani
2011/5/25 Ludo Brands ludo.bra...@free.fr:
 Regarding the tlb to pascal conversion, AFAIK there is no support in fpc.
 Delphi is clearly better equiped to work with COM objects.

 I have also been playing around with a generic eventsink class but the
 problem is that events can have parameters (and a lot do). Your suggestion
 of using TNotifyEvents could work for events without parameters. You could
 leave the parameter stuff to the user of the eventsink, eventually helping
 him by exposing the number and type of parameters, but that means that the
 user has to have a reasonable good understanding of COM, including the data
 types compatible with COM marshalling.


Thanks for the explanation. In fact, that is the reason why I called
it TSimpleEventSink, meaning that it was good for simple situation.
In my case, for example, the activex controls a hardware stuff which
only request the user to take an action sometimes.
In the C++ source code for the class Device I have:

[
uuid(168F5642-5751-49F5-9AA4-B8A7A5F6A5B8),
helpstring(_IDeviceEvents Interface)
]
dispinterface _IDeviceEvents
{
properties:
methods:
[id(1), helpstring(method OnCommChanged)] HRESULT OnCommChanged();
[id(2), helpstring(method OnStatesChanged)] HRESULT OnStatesChanged();
[id(3), helpstring(method OnContact)] HRESULT OnContact();
[id(4), helpstring(method OnMeasUpdate)] HRESULT OnMeasUpdate();
};

where this four simple events only alert the user about a change
situation; then the user takes the suitable actions.
Do you think it could work for me?

Now I'm trying to write by hand a minimalist tlb, looking for the
definitions in the activex source code

Thanks a lot!!

  Roberto
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


RE : RE : RE : RE : RE : [fpc-pascal] support for using an activex

2011-05-25 Thread Ludo Brands
The code in article
http://www.informit.com/articles/article.aspx?p=130494seqNum=5 goes a long
way in doing what you want to do. Unit Eventsink does pretty much of the
legwork. You should remove the procedure register since that is the Delphi
way to get a component on the toolbar. Remove also the {$IFDEF VER100} and
{$ENDIF}. The unit actually includes the code for InterfaceConnect!! 
In the MainForm unit you'll have to do in a TForm1.Create 

EventSink1:=TEventSink.Create(Self); 
EventSink1.OnInvoke:=@EventSink1Invoke;

because the example assumes you have dropped the component on the form and
entered EventSink1Invoke in the properties box.

As for the tlb conversion, in your case 

IEventIntfEvents = dispinterface
  ['{168F5642-5751-49F5-9AA4-B8A7A5F6A5B8}']
 end;

should do (that is for the events part). AFAIK the procedure and dispid
definitions are only needed for the server. You are only concerned with
dispid's. No need to create prototypes for OnCommChanged() etc.
EventSink1Invoke would be a simple 
case DispID of
  1: // do CommChanged
  2: // do StatesChanged
...
end;


Ludo

-Message d'origine-
De : fpc-pascal-boun...@lists.freepascal.org
[mailto:fpc-pascal-boun...@lists.freepascal.org] De la part de Roberto
Padovani Envoyé : mercredi 25 mai 2011 16:01 À : FPC-Pascal users
discussions Objet : Re: RE : RE : RE : RE : [fpc-pascal] support for using
an activex


2011/5/25 Ludo Brands ludo.bra...@free.fr:
 Regarding the tlb to pascal conversion, AFAIK there is no support in
 fpc. Delphi is clearly better equiped to work with COM objects.

 I have also been playing around with a generic eventsink class but the
 problem is that events can have parameters (and a lot do). Your 
 suggestion of using TNotifyEvents could work for events without 
 parameters. You could leave the parameter stuff to the user of the 
 eventsink, eventually helping him by exposing the number and type of 
 parameters, but that means that the user has to have a reasonable good 
 understanding of COM, including the data types compatible with COM 
 marshalling.


Thanks for the explanation. In fact, that is the reason why I called it
TSimpleEventSink, meaning that it was good for simple situation. In my case,
for example, the activex controls a hardware stuff which only request the
user to take an action sometimes. In the C++ source code for the class
Device I have:

[
uuid(168F5642-5751-49F5-9AA4-B8A7A5F6A5B8),
helpstring(_IDeviceEvents Interface)
]
dispinterface _IDeviceEvents
{
properties:
methods:
[id(1), helpstring(method OnCommChanged)] HRESULT OnCommChanged();
[id(2), helpstring(method OnStatesChanged)] HRESULT
OnStatesChanged();
[id(3), helpstring(method OnContact)] HRESULT OnContact();
[id(4), helpstring(method OnMeasUpdate)] HRESULT OnMeasUpdate();
};

where this four simple events only alert the user about a change situation;
then the user takes the suitable actions. Do you think it could work for me?

Now I'm trying to write by hand a minimalist tlb, looking for the
definitions in the activex source code

Thanks a lot!!

  Roberto
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: RE : RE : RE : RE : RE : [fpc-pascal] support for using an activex

2011-05-25 Thread Roberto Padovani
2011/5/25 Ludo Brands ludo.bra...@free.fr:
 The code in article
 http://www.informit.com/articles/article.aspx?p=130494seqNum=5 goes a long
 way in doing what you want to do. Unit Eventsink does pretty much of the
 legwork. You should remove the procedure register since that is the Delphi
 way to get a component on the toolbar. Remove also the {$IFDEF VER100} and
 {$ENDIF}. The unit actually includes the code for InterfaceConnect!!

found that! great!


 As for the tlb conversion, in your case

 IEventIntfEvents = dispinterface
  ['{168F5642-5751-49F5-9AA4-B8A7A5F6A5B8}']
  end;

 should do (that is for the events part). AFAIK the procedure and dispid
 definitions are only needed for the server. You are only concerned with
 dispid's. No need to create prototypes for OnCommChanged() etc.
 EventSink1Invoke would be a simple
 case DispID of
  1: // do CommChanged
  2: // do StatesChanged
 ...
 end;



Now I am wasting time making the tlb pascal definitions.
For the event part I'm fine with the dispid's
Until now I was calling the activex method with variants, in and out,
but now I discovered that this IDevice class has a property like:
property Sensors: ISensors;
which inside is a list of items like   Sensor: ISensor.

Can I read the sensores with a variant? Then, to see the fields inside
each sensor, I think a I need a class to do that...
The activex has all of these classes with the suitable dispinterfaces
and uuids and so on. But if I define
 var device, transducers, transducer : variant;
and create
 device := CreateOleObject('Device');
then, can i simply write the following ?
 transducers := device.Transducers;
 transducer := transducers[index];


It's a long path until I get this stuff working...

R#
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


RE : RE : RE : RE : RE : RE : [fpc-pascal] support for using an activex

2011-05-25 Thread Ludo Brands
Using variants you can transparently walk along the exposed objects. The
variant contains the Idispatch of the object and gets the exposed methods at
runtime. Properties are implemented as get and put methods or just get
methods for read only properties.  

If you have something like
Itransducers = interface
  ..
  property transducer[Index:integer]:Itransducer;
end;

Then you would do 
transducer := transducers.transducer[index];

transducer := transducers[index];  works only if transducer is the default
property for Itransducers. I'm not sure if fpc supports this.

Ludo


-Message d'origine-
De : fpc-pascal-boun...@lists.freepascal.org
[mailto:fpc-pascal-boun...@lists.freepascal.org] De la part de Roberto
Padovani
Envoyé : mercredi 25 mai 2011 19:34
À : FPC-Pascal users discussions
Objet : Re: RE : RE : RE : RE : RE : [fpc-pascal] support for using an
activex


2011/5/25 Ludo Brands ludo.bra...@free.fr:
 The code in article 
 http://www.informit.com/articles/article.aspx?p=130494seqNum=5 goes a 
 long way in doing what you want to do. Unit Eventsink does pretty much 
 of the legwork. You should remove the procedure register since that is 
 the Delphi way to get a component on the toolbar. Remove also the 
 {$IFDEF VER100} and {$ENDIF}. The unit actually includes the code for 
 InterfaceConnect!!

found that! great!


 As for the tlb conversion, in your case

 IEventIntfEvents = dispinterface
  ['{168F5642-5751-49F5-9AA4-B8A7A5F6A5B8}']
  end;

 should do (that is for the events part). AFAIK the procedure and 
 dispid definitions are only needed for the server. You are only 
 concerned with dispid's. No need to create prototypes for 
 OnCommChanged() etc. EventSink1Invoke would be a simple case DispID of
  1: // do CommChanged
  2: // do StatesChanged
 ...
 end;



Now I am wasting time making the tlb pascal definitions.
For the event part I'm fine with the dispid's
Until now I was calling the activex method with variants, in and out, but
now I discovered that this IDevice class has a property like: property
Sensors: ISensors;
which inside is a list of items like   Sensor: ISensor.

Can I read the sensores with a variant? Then, to see the fields inside each
sensor, I think a I need a class to do that... The activex has all of these
classes with the suitable dispinterfaces and uuids and so on. But if I
define
 var device, transducers, transducer : variant;
and create
 device := CreateOleObject('Device');
then, can i simply write the following ?
 transducers := device.Transducers;
 transducer := transducers[index];


It's a long path until I get this stuff working...

R#
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: RE : RE : RE : RE : RE : RE : [fpc-pascal] support for using an activex

2011-05-25 Thread Roberto Padovani
Always thanks!

Given your evident experience on this matter, I kindly ask your advice
on what is best to do.

opt 1) create a fpc class with some pascal style methods, which in
their implementation use variants and call the IDevice class with
late-binding . meaning that there is no compiler check and if my
collegue changes the dll, then I have to change these implementations

opt 2) in a reference of those you sent me, there is some example code
from which I take the lines below. In the tlb conversion unit, the
interface and dispinterface of the class are some replicated. Then
also the eventinterface is defined.
The main interface class is defined without and with dispids. With the
dispids, only the properties are defined and not the methods.

  IFileZapper = interface(IDispatch)
['{2E2FC5E0-5C0E-4C4F-8CC1-D9F6C5A92BA6}']
function Get_Directory: WideString; safecall;
procedure Set_Directory(const Value: WideString); safecall;
function Get_FileMask: WideString; safecall;
procedure Set_FileMask(const Value: WideString); safecall;
procedure BringToFront; safecall;
property Directory: WideString read Get_Directory write Set_Directory;
property FileMask: WideString read Get_FileMask write Set_FileMask;
  end;

  IFileZapperDisp = dispinterface
['{2E2FC5E0-5C0E-4C4F-8CC1-D9F6C5A92BA6}']
property Directory: WideString dispid 1;
property FileMask: WideString dispid 3;
procedure BringToFront; dispid 10;
  end;

  IFileZapperEvents = dispinterface
['{7B6F8ADD-7980-4A35-838B-E1600C43D29E}']
procedure OnSelectionChanged; dispid 1;
procedure OnDirectoryChanged(const DirName: WideString); dispid 2;
  end;

Is this somewhat the same thing as the wrapper of option 1? If I write
all of this conversion (and, by the way, how to convert C++ data types
to pascal?? widestring ?), then how can I use it?

In the end, maybe the wiki page about COM interfaces should be update
to something more than 'Word.Application.NewFile'.
I can't share the activex I have, otherwise it would be a good example
to see something useful to start with.

Roberto

2011/5/25 Ludo Brands ludo.bra...@free.fr:
 Using variants you can transparently walk along the exposed objects. The
 variant contains the Idispatch of the object and gets the exposed methods at
 runtime. Properties are implemented as get and put methods or just get
 methods for read only properties.

 If you have something like
 Itransducers = interface
  ..
  property transducer[Index:integer]:Itransducer;
 end;

 Then you would do
 transducer := transducers.transducer[index];

 transducer := transducers[index];  works only if transducer is the default
 property for Itransducers. I'm not sure if fpc supports this.

 Ludo


 -Message d'origine-
 De : fpc-pascal-boun...@lists.freepascal.org
 [mailto:fpc-pascal-boun...@lists.freepascal.org] De la part de Roberto
 Padovani
 Envoyé : mercredi 25 mai 2011 19:34
 À : FPC-Pascal users discussions
 Objet : Re: RE : RE : RE : RE : RE : [fpc-pascal] support for using an
 activex


 2011/5/25 Ludo Brands ludo.bra...@free.fr:
 The code in article
 http://www.informit.com/articles/article.aspx?p=130494seqNum=5 goes a
 long way in doing what you want to do. Unit Eventsink does pretty much
 of the legwork. You should remove the procedure register since that is
 the Delphi way to get a component on the toolbar. Remove also the
 {$IFDEF VER100} and {$ENDIF}. The unit actually includes the code for
 InterfaceConnect!!

 found that! great!


 As for the tlb conversion, in your case

 IEventIntfEvents = dispinterface
  ['{168F5642-5751-49F5-9AA4-B8A7A5F6A5B8}']
  end;

 should do (that is for the events part). AFAIK the procedure and
 dispid definitions are only needed for the server. You are only
 concerned with dispid's. No need to create prototypes for
 OnCommChanged() etc. EventSink1Invoke would be a simple case DispID of
  1: // do CommChanged
  2: // do StatesChanged
 ...
 end;



 Now I am wasting time making the tlb pascal definitions.
 For the event part I'm fine with the dispid's
 Until now I was calling the activex method with variants, in and out, but
 now I discovered that this IDevice class has a property like: property
 Sensors: ISensors;
 which inside is a list of items like   Sensor: ISensor.

 Can I read the sensores with a variant? Then, to see the fields inside each
 sensor, I think a I need a class to do that... The activex has all of these
 classes with the suitable dispinterfaces and uuids and so on. But if I
 define
     var device, transducers, transducer : variant;
 and create
     device := CreateOleObject('Device');
 then, can i simply write the following ?
     transducers := device.Transducers;
     transducer := transducers[index];


 It's a long path until I get this stuff working...

 R#
 ___
 fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
 http://lists.freepascal.org/mailman/listinfo/fpc-pascal