1. EuCom - Matt Lewis
- Posted by Jonas Temple <jtemple at yhti.net> Jul 15, 2004
- 710 views
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
2. Re: EuCom - Matt Lewis
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Jul 16, 2004
- 663 views
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
3. Re: EuCom - Matt Lewis
- Posted by Jonas Temple <jtemple at yhti.net> Jul 16, 2004
- 834 views
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
4. Re: EuCom - Matt Lewis
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Jul 16, 2004
- 752 views
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
5. Re: EuCom - Matt Lewis
- Posted by Jonas Temple <jtemple at yhti.net> Jul 16, 2004
- 681 views
> 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
6. Re: EuCom - Matt Lewis
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Jul 16, 2004
- 689 views
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
7. Re: EuCom - Matt Lewis
- Posted by Jonas Temple <jtemple at yhti.net> Jul 16, 2004
- 694 views
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
8. Re: EuCom - Matt Lewis
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Jul 19, 2004
- 682 views
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
9. Re: EuCom - Matt Lewis
- Posted by Jonas Temple <jtemple at yhti.net> Jul 19, 2004
- 635 views
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
10. Re: EuCom - Matt Lewis
- Posted by Matt Lewis <matthewwalkerlewis at yahoo.com> Jul 19, 2004
- 651 views
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