1. EuCom - Matt Lewis

Matt,

Really trying hard now to use some ActiveX/COM controls and have a question:

If an object has another object as one of it's properties and I need to
put the "child" object into the "parent" object, how should this be done?

Thanks,

Jonas

new topic     » topic index » view message » categorize

2. Re: EuCom - Matt Lewis

Jonas Temple wrote:
> 
> Matt,
> 
> Really trying hard now to use some ActiveX/COM controls and have a question:
> 
> If an object has another object as one of it's properties and I need to
> put the "child" object into the "parent" object, how should this be done?

Assuming that you are able to use the IDispatch interface by calling 
invoke(), you probably need to set the property.  It would probably look
something like this (assuming you're using a wrapper generated by
tbrowse):

void = invoke( anObject, {anObject_p_SomeObject, DISPID_PROPERTYPUT}, 
    {someObject}, {VT_UNKNOWN}, DISPATCH_PROPERTYPUT )

You might need to use DISPATCH_PROPERTYPUTREF instead--I've never entirely
figured out which gets used when.  I generally go by trial and error.

Do you have any documentation on the object?  Some example VB or C++ code
would be helpful.  There is some information in the faq that talks about 
porting VB and C++ that might be helpful.

Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

3. Re: EuCom - Matt Lewis

Matt Lewis wrote:
> 
> Jonas Temple wrote:
> > 
> > Matt,
> > 
> > Really trying hard now to use some ActiveX/COM controls and have a question:
> > 
> > If an object has another object as one of it's properties and I need to
> > put the "child" object into the "parent" object, how should this be done?
> 
> Assuming that you are able to use the IDispatch interface by calling 
> invoke(), you probably need to set the property.  It would probably look
> something like this (assuming you're using a wrapper generated by
> tbrowse):
> 
> void = invoke( anObject, {anObject_p_SomeObject, DISPID_PROPERTYPUT}, 
>     {someObject}, {VT_UNKNOWN}, DISPATCH_PROPERTYPUT )
> 
> You might need to use DISPATCH_PROPERTYPUTREF instead--I've never entirely
> figured out which gets used when.  I generally go by trial and error.
> 
> Do you have any documentation on the object?  Some example VB or C++ code
> would be helpful.  There is some information in the faq that talks about 
> porting VB and C++ that might be helpful.
> 
> Matt Lewis
> 

Matt,

Well, glad to know I wasn't far off!  Here's my code thus far:

include cwbx.ew
with trace
without warning

integer cwb_cmd, as400_system, errors
atom void, sys_ptr, ptr, err_count

com_err_out(1)
trace(1)

cwb_cmd = create_com_object( Command_clsid_ix )
as400_system = create_com_object( AS400System_clsid_ix )

sys_ptr = allocate_string(ansi_to_unicode("DILBERT.MKG.COM"))
void = invoke(as400_system,
{AS400System_m_Define},{sys_ptr},{VT_BSTR},DISPATCH_METHOD)
void = invoke(cwb_cmd, {Command_p_system,DISPID_PROPERTYPUT},{as400_system},
	{VT_UNKNOWN},DISPATCH_PROPERTYPUT)

ptr = allocate_string(ansi_to_unicode("SNDMSG MSG('This is a test')
TOUSR(JOTEMPL)"))
void = invoke(cwb_cmd, {Command_m_Run},{ptr},{VT_BSTR},DISPATCH_METHOD)
errors = ref_com_object(Errors_clsid_ix, invoke(cwb_cmd, {Command_p_Errors}, {},
{},
	DISPATCH_PROPERTYGET))

err_count = invoke(errors, {Errors_p_Count}, {}, {}, DISPATCH_PROPERTYGET)

free(sys_ptr)
free(ptr)
release_com()


What this program is attempting to do is connect to an AS400 and execute
a command to send me a message.

The problem I'm having is with the as400_system object.  I set the system
name correctly but the problem comes up when I try to set the 
as400_system object in the cwb_cmd object.  I get a "Member not found" 
error message.  I also tried you suggestion of DISPATCH_PROPERTYPUTREF
and I got a machine exception.

Here's the sample VB code from the documentation:

' Declare variables
Dim systemNames As New cwbx.systemNames
Dim as400 As New cwbx.AS400System
Dim cmd As New cwbx.Command
' Retrieve the default system and use it to initialize the AS400System
' object
as400.Define systemNames.DefaultSystem
' Set the System property of the command object
Set cmd.System = as400

In the cwbx.ew that tbrowse created the property comments for the
Command_p_system has a type of IcwbxSystem instead of the usual VT_xxxx
value.  Don't know if that has anything to do with it.  I could send you
the cwbx.ew file, if that would help.

The end result of this is when I try to run the command I get a "Value
for property System not correct".  Lots of help there...

Thanks for your help, I really want to try and get this working!

Jonas

new topic     » goto parent     » topic index » view message » categorize

4. Re: EuCom - Matt Lewis

Jonas Temple wrote:
> 
> 
> Here's my code thus far:

include cwbx.ew
with trace
without warning

integer cwb_cmd, as400_system, errors
atom void, sys_ptr, ptr, err_count

com_err_out(1)
trace(1)

cwb_cmd = create_com_object( Command_clsid_ix )
as400_system = create_com_object( AS400System_clsid_ix )

sys_ptr = allocate_string(ansi_to_unicode("DILBERT.MKG.COM"))
void = invoke(as400_system,
{AS400System_m_Define},{sys_ptr},{VT_BSTR},DISPATCH_METHOD)
void = invoke(cwb_cmd, {Command_p_system,DISPID_PROPERTYPUT},{as400_system},
	{VT_UNKNOWN},DISPATCH_PROPERTYPUT)

ptr = allocate_string(ansi_to_unicode("SNDMSG MSG('This is a test')
TOUSR(JOTEMPL)"))
void = invoke(cwb_cmd, {Command_m_Run},{ptr},{VT_BSTR},DISPATCH_METHOD)
errors = ref_com_object(Errors_clsid_ix, invoke(cwb_cmd, {Command_p_Errors}, {},
{},
	DISPATCH_PROPERTYGET))

err_count = invoke(errors, {Errors_p_Count}, {}, {}, DISPATCH_PROPERTYGET)

free(sys_ptr)
free(ptr)
release_com()


First thing I notice is that you're not using the bstr routines.  These
actually let COM allocate the memory, which is important because they're
reference counted.  Other objects might be using the pointers, so a simple
free() could cause problems later.  Make sure you use alloc_bstr() and
free_bstr().  They're documented under "Utilities" in eucom.htm.

> 
> What this program is attempting to do is connect to an AS400 and execute
> a command to send me a message.
> 
> The problem I'm having is with the as400_system object.  I set the system
> name correctly but the problem comes up when I try to set the 
> as400_system object in the cwb_cmd object.  I get a "Member not found" 
> error message.  I also tried you suggestion of DISPATCH_PROPERTYPUTREF
> and I got a machine exception.
> 
> Here's the sample VB code from the documentation:
> 
> ' Declare variables
> Dim systemNames As New cwbx.systemNames
> Dim as400 As New cwbx.AS400System
> Dim cmd As New cwbx.Command
> ' Retrieve the default system and use it to initialize the AS400System
> ' object
> as400.Define systemNames.DefaultSystem
> ' Set the System property of the command object
> Set cmd.System = as400

The "Set " here indicates that you need to use DISPATCH_PROPERTYPUTBYREF
(according to my FAQ that I just reread :).

> In the cwbx.ew that tbrowse created the property comments for the
> Command_p_system has a type of IcwbxSystem instead of the usual VT_xxxx
> value.  Don't know if that has anything to do with it.  I could send you
> the cwbx.ew file, if that would help.

IcwbcSystem is a COM interface for your cwbx object.  This should be
VT_UNKNOWN.  VT_UNKNOWN really means IUnknown, which is the most basic
interface, and which is included in all interfaces.  Try this:

void = invoke(cwb_cmd, {Command_p_system,DISPID_VALUE},
	{get_obj_this(as400_system)},{VT_UNKNOWN},DISPATCH_PROPERTYPUTBYREF)


You might be able to get rid of the DISPID_VALUE (some objects require
you to always pass named arguments, and some don't care).  The 
get_obj_this() is important, because as400_system is a EuCOM index 
(think Win32Lib control ids), but you need to pass the actual pointer.

Good luck,
Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

5. Re: EuCom - Matt Lewis

> The "Set " here indicates that you need to use DISPATCH_PROPERTYPUTBYREF
> (according to my FAQ that I just reread :).

I assume you meant DISPATCH_PROPERTYPUTREF, right?  That's what I used.

> 
> You might be able to get rid of the DISPID_VALUE (some objects require
> you to always pass named arguments, and some don't care).  The 
> get_obj_this() is important, because as400_system is a EuCOM index 
> (think Win32Lib control ids), but you need to pass the actual pointer.
> 

Here's the code that I got to work:

include cwbx.ew
with trace
without warning

integer cwb_cmd, as400_system, errors
atom void, sys_ptr, ptr, err_count

com_err_out(1)
trace(1)

cwb_cmd = create_com_object( Command_clsid_ix )
as400_system = create_com_object( AS400System_clsid_ix )

sys_ptr = alloc_bstr("DILBERT.MKG.COM")
void = invoke(as400_system,
{AS400System_m_Define},{sys_ptr},{VT_BSTR},DISPATCH_METHOD)
void = invoke(cwb_cmd,
{Command_p_system,DISPID_PROPERTYPUT},{get_obj_this(as400_system)},
	{VT_UNKNOWN},DISPATCH_PROPERTYPUTREF)

ptr = alloc_bstr("SNDMSG MSG('This is a test') TOUSR(JOTEMPL)")
void = invoke(cwb_cmd, {Command_m_Run},{ptr},{VT_BSTR},DISPATCH_METHOD)
errors = ref_com_object(Errors_clsid_ix, invoke(cwb_cmd, {Command_p_Errors}, {},
{},
	DISPATCH_PROPERTYGET))

err_count = invoke(errors, {Errors_p_Count}, {}, {}, DISPATCH_PROPERTYGET)

free_bstr(sys_ptr)
free_bstr(ptr)
release_com()


Using DISPID_VALUE gave me a "Parameter not found" error from the object.
I removed DISPID_VALUE and got the same result.  It finally worked when
I changed it to DISPID_PROPERTYPUT.  Don't ask me how I figured that out,
I just got lucky.  Why did that work instead of DISPID_VALUE?  

Also, I looked at the EuCom docs and wondered how do I know when to use
the {this,vtbl} obj parm for the invoke routine versus just the object?  
Maybe I'm not reading the docs correctly or it's just my lack of COM/ActiveX
knowledge.

Thanks for the assistance!  I'll definitely have more questions.

Jonas

new topic     » goto parent     » topic index » view message » categorize

6. Re: EuCom - Matt Lewis

Jonas Temple wrote:
> 
> > The "Set " here indicates that you need to use DISPATCH_PROPERTYPUTBYREF
> > (according to my FAQ that I just reread :).
> 
> I assume you meant DISPATCH_PROPERTYPUTREF, right?  That's what I used.

Yep. :)

> Here's the code that I got to work:
include cwbx.ew
with trace
without warning

integer cwb_cmd, as400_system, errors
atom void, sys_ptr, ptr, err_count

com_err_out(1)
trace(1)

cwb_cmd = create_com_object( Command_clsid_ix )
as400_system = create_com_object( AS400System_clsid_ix )

sys_ptr = alloc_bstr("DILBERT.MKG.COM")
void = invoke(as400_system,
{AS400System_m_Define},{sys_ptr},{VT_BSTR},DISPATCH_METHOD)
void = invoke(cwb_cmd,
{Command_p_system,DISPID_PROPERTYPUT},{get_obj_this(as400_system)},
	{VT_UNKNOWN},DISPATCH_PROPERTYPUTREF)

ptr = alloc_bstr("SNDMSG MSG('This is a test') TOUSR(JOTEMPL)")
void = invoke(cwb_cmd, {Command_m_Run},{ptr},{VT_BSTR},DISPATCH_METHOD)
errors = ref_com_object(Errors_clsid_ix, invoke(cwb_cmd, {Command_p_Errors}, {},
{},
	DISPATCH_PROPERTYGET))

err_count = invoke(errors, {Errors_p_Count}, {}, {}, DISPATCH_PROPERTYGET)

free_bstr(sys_ptr)
free_bstr(ptr)
release_com() 


> Using DISPID_VALUE gave me a "Parameter not found" error from the object.
> I removed DISPID_VALUE and got the same result.  It finally worked when
> I changed it to DISPID_PROPERTYPUT.  Don't ask me how I figured that out,
> I just got lucky.  Why did that work instead of DISPID_VALUE?  

I think it depends on how the object was built.  That's really a named 
parameter.  Have you seen VB code, for instance, where parameters are 
named, like:

myObject.myMethod thisParam:=1, thatParam:="a"

This is what you're doing, except that it's a 'special' name that's being
used.  Something like VB would take care of this for you automatically,
but EuCOM and I aren't that smart.
 
> Also, I looked at the EuCom docs and wondered how do I know when to use
> the {this,vtbl} obj parm for the invoke routine versus just the object?  
> Maybe I'm not reading the docs correctly or it's just my lack of COM/ActiveX
> knowledge.

You can use the {this,vtbl} way of doing things if you're working directly
with the pointers, instead of a EuCOM index.  I've found that sometimes,
I'm creating and destroying lots of little 'helper' objects--take a look
at tbrowse, if you dare.  It's sometimes quicker and easier to not have 
to make lots of calls to ref_com_object().  It is also a little quicker,
since EuCOM has to look up these values from a table before it can make
the call, so another reason to use it is if you want to speed something 
up (although the gain is likely to be miniscule, unless you make lots of
calls, and then you're probably better off calling a real interface, 
rather that the DispInterface).

Some of your difficulties are undoubtedly due to lack of COM experience
on your part, and the rest is assuredly my lack of COM experience and
my mediocre documentation skills (plus other included 'features' and 
real missing features of EuCOM).

> Thanks for the assistance!  I'll definitely have more questions.

I'll definitely have more answers.  If we're lucky, they'll be correct!

Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

7. Re: EuCom - Matt Lewis

Matt Lewis wrote:

> > Thanks for the assistance!  I'll definitely have more questions.
> 
> I'll definitely have more answers.  If we're lucky, they'll be correct!
> 
Matt,

Well, like I promised, here I am again!  This time trying another COM 
control.  Here's the code:

include unocxtl.ew
include win32lib.ew

with trace

constant
Win = create( Window, "Test UNOCX Control", 0, 0, 0, 400, 800, 0 )

object void
atom as400_tree, as400_list, list_ptr
com_err_out( 1 )

as400_tree = create_com_control( AS400Tree_clsid_ix , getHandle( Win ), 5, 5,
375, 375 )
as400_list = create_com_control( AS400List_clsid_ix, getHandle( Win ), 5, 400,
375, 375)
list_ptr= invoke(as400_list, {AS400List_m_ReturnPtr},{},{},DISPATCH_PROPERTYGET)
void = invoke(as400_tree,
{AS400Tree_m_SetListOcx},{list_ptr},{VT_I4},DISPATCH_PROPERTYPUT)

WinMain(Win, Normal )


Here I'm trying to create two controls, the list being tied to the tree so
whenever a selection is made in the tree the list is automatically
updated.  

The docs for the control specify that the AS400Tree_m_SetListOcx takes a
pointer to the list control, which can be retrieved via the 
AS400List_m_ReturnPtr method.  When I use invoke() to set the list control
I get the following message:

80020005: Type mismatch, arg 1: #00C90210 / vt = 3
Exception Source:
Exception Description:

Not sure what it's trying to tell me.

Here's a VB example I found for doing what I'm attempting to do:

    TreePtr = AS400Tree1.ReturnPtr
    ListPtr = AS400List1.ReturnPtr
    AS400Tree1.SetListOcx (ListPtr)
    AS400List1.SetTreeOcx (TreePtr)

At this point I haven't even gotten to the point of setting the list
control with the tree control.

Also, in my example code the list/tree seem to overlap on the window.  Have
any idea why that might be happening?

Thanks again for your help,

Jonas

new topic     » goto parent     » topic index » view message » categorize

8. Re: EuCom - Matt Lewis

Jonas Temple wrote:
> 
> 
> Well, like I promised, here I am again!  This time trying another COM 
> control.  Here's the code:
include unocxtl.ew
include win32lib.ew

with trace

constant
Win = create( Window, "Test UNOCX Control", 0, 0, 0, 400, 800, 0 )

object void
atom as400_tree, as400_list, list_ptr
com_err_out( 1 )

as400_tree = create_com_control( AS400Tree_clsid_ix , getHandle( Win ), 5, 5,
375,
as400_list = create_com_control( AS400List_clsid_ix, getHandle( Win ), 5, 400,
375,
list_ptr= invoke(as400_list, {AS400List_m_ReturnPtr},{},{},DISPATCH_PROPERTYGET)
void = invoke(as400_tree,
{AS400Tree_m_SetListOcx},{list_ptr},{VT_I4},DISPATCH_PROPERTYPUT)

WinMain(Win, Normal )

 

First thing I see is that SetListOcx is a method, not a property, so you
should be using DISPATCH_METHOD.  Tbrowse differentiates between the two
by either adding _p_ or _m_ between the object and the member names.
 
> Here I'm trying to create two controls, the list being tied to the tree so
> whenever a selection is made in the tree the list is automatically
> updated.  
> 
> The docs for the control specify that the AS400Tree_m_SetListOcx takes a
> pointer to the list control, which can be retrieved via the 
> AS400List_m_ReturnPtr method.  When I use invoke() to set the list control
> I get the following message:
> 
> 80020005: Type mismatch, arg 1: #00C90210 / vt = 3
> Exception Source:
> Exception Description:
> 
> Not sure what it's trying to tell me.

It's saying that your type is wrong (or maybe it's just the method/property
thing).  My guess is that it should be either VT_UNKNOWN or VT_PTR.  You
can look in variant.ew for all different VT_ constants.

> Here's a VB example I found for doing what I'm attempting to do:
> 
>     TreePtr = AS400Tree1.ReturnPtr
>     ListPtr = AS400List1.ReturnPtr
>     AS400Tree1.SetListOcx (ListPtr)
>     AS400List1.SetTreeOcx (TreePtr)
> 
> At this point I haven't even gotten to the point of setting the list
> control with the tree control.
> 
> Also, in my example code the list/tree seem to overlap on the window.  Have
> any idea why that might be happening?

No.  The values look good to me.

Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

9. Re: EuCom - Matt Lewis

Matt Lewis wrote:
> First thing I see is that SetListOcx is a method, not a property, so you
> should be using DISPATCH_METHOD.  Tbrowse differentiates between the two
> by either adding _p_ or _m_ between the object and the member names.

D-uh!!!!  Yep, didn't even think about that.  I stared at this code for a
long time...probably too long.

> It's saying that your type is wrong (or maybe it's just the method/property
> thing).  My guess is that it should be either VT_UNKNOWN or VT_PTR.  You
> can look in variant.ew for all different VT_ constants.
> 

Well, I tried VT_UNKNOWN and VT_PTR but it didn't like those, so I went
back to VT_I4 and it worked!

Now the only problem I'm having is the tree and list controls are in the
same location in the window (regardless of what I specified in
create_com_control).  Any idea what might be going on there?

Thanks for all the help, Matt.

Jonas

new topic     » goto parent     » topic index » view message » categorize

10. Re: EuCom - Matt Lewis

Jonas Temple wrote:
> 
> Matt Lewis wrote:
> 
> > It's saying that your type is wrong (or maybe it's just the method/property
> > thing).  My guess is that it should be either VT_UNKNOWN or VT_PTR.  You
> > can look in variant.ew for all different VT_ constants.
> > 
> 
> Well, I tried VT_UNKNOWN and VT_PTR but it didn't like those, so I went
> back to VT_I4 and it worked!

COM is usually pretty good about converting variants as need be, and the
more specific types are usually pretty specialized.  I find that I rarely
need any types other than VT_I4 and VT_BSTR.
 
> Now the only problem I'm having is the tree and list controls are in the
> same location in the window (regardless of what I specified in
> create_com_control).  Any idea what might be going on there?

Not sure.  It could be that the controls are using some other method than
the one that I 'figured out' in writing EuCOM to position themselves.
Try manually calling move_obj().  I see now that it's undocumented,
which I'll fix.  Very simple to use:

proc move_obj( integer obj_ix, sequence new_rect )
+ obj_ix: EuCOM index of the object
+ new_rect: { x, y, cx, cy }

Matt Lewis

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu