COMatePLUS version 1.2

Developed or developing a new product in PureBasic? Tell the world about it.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Sounds like a reference counting issue. Whether that is with COMatePLUS or the component itself I cannot say?

What OS you using?

What line in the code is it crashing on?

Which version of Acrobat reader do you have?
I may look like a mule, but I'm not a complete ass.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

srod wrote: What OS you using?
Vista Ultimate x64
srod wrote: What line in the code is it crashing on?
No line, it crashes on closing window, ms message comes.
srod wrote: Which version of Acrobat reader do you have?
Acrobat 9 Pro (no reader)

// edit
if i put the release before the closewindow, is the ima in release,
if i put the release after closewindow comes the message from bill
Last edited by ts-soft on Tue Apr 28, 2009 12:47 pm, edited 1 time in total.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I take it you are running COMatePLUS as a wow64 application?

If you are running it as a 64-bit application - well, I can not vouch for how reliable things may be?

That kind of crash is likely either a reference counting issue (although I would expect an invalid memory access error under those circumstances) or an internal error with the component. The debugger should pick up on any other error with COMatePLUS. Course it could be some clash with PB's window library?

A difficult one.
I may look like a mule, but I'm not a complete ass.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

I use a 32-Bit application and acrobat is also 32-Bit
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

ts-soft wrote:I use a 32-Bit application and acrobat is also 32-Bit
Sorry I can't help more Thomas. I wonder if anyone else running the 32-bit demo under Vista 64 experiences the same problem?
I may look like a mule, but I'm not a complete ass.
hm
User
User
Posts: 30
Joined: Mon Oct 27, 2003 12:15 pm
Location: Germany
Contact:

Post by hm »

I am trying to catch WebGadget events from DWebBrowserEvents2 interface, for example the BeforeNavigate2 and NewWindow3 events, using COMate PLUS 1.0.1.

The following code does catch events but not the events mentioned above. :(

Code: Select all

; test_COMate_WebGadget_events.pb

XIncludeFile "COMatePLUS.pbi"

Enumeration
  #Web_Gadget
  #Button_Start
EndEnumeration


Procedure EventProc(Object.COMateObject, eventName$, parameterCount)
  Debug eventName$
EndProcedure


If OpenWindow(0, 302, 15, 600, 300, "WebGadget Events Test",  #PB_Window_SystemMenu | #PB_Window_TitleBar )
  WebGadget(#Web_Gadget, 20, 20, 560, 215, "")
  ButtonGadget(#Button_Start, 20, 250, 110, 40, "Start")
  Global browser.COMateObject = COMate_WrapCOMObject(GetWindowLong_(GadgetID(#Web_Gadget), #GWL_USERDATA)) 
  ;browser\SetEventHandler("BeforeNavigate2", @EventProc())       ; <-- does not catch BeforeNavigate2 event :(
  browser\SetEventHandler(#COMate_CatchAllEvents, @EventProc())   ; <-- does not catch BeforeNavigate2 event :(
EndIf


Repeat
  Event = WaitWindowEvent()
  WindowID = EventWindow()
  GadgetID = EventGadget()
  EventType = EventType()
  
  If Event = #PB_Event_Gadget
    If GadgetID = #Button_Start

      browser\Invoke("Navigate('http://www.purebasic.com/')")

    EndIf
  EndIf
Until Event = #PB_Event_CloseWindow

browser\Release()

End
Since I am no COM expert i can only speculate that possibly COMate's SetEventHandler method connects to the old DWebBrowserEvents interface instead of DWebBrowserEvents2. To verify this, I tried to insert Debug statements into the definition of the SetEventHandler method to output the IID/UUID/CLSID/whatever of the event-interface connected (goal was to manually compare it to IDs in the typelib infos) but I did not succeed due to my limited knowledge of both COM and windows programming in PureBasic. :oops:

Looking at the TypeLib infos of "Microsoft Internet Controls" (SHDocVw) using Microsofts OLEViewer, I found multiple occurances of DWebBrowserEvents and DWebBrowserEvents2, both being tagged as "default" at some different locations. :?

Finally, my question:

Is it possible to catch the WebGadget's events by ways of DWebBrowserEvents2 using COMate? :?:
(... perhaps by enhancing the SetEventHandler to respect the "default" tags of the typelib infos or to accept another parameter containing the ID (34A715A0-6587-11D0-924A-0020AFC7AC4D) or name (DWebBrowserEvents2) of the desired event-interface ?)

ps. I am aware of soerenkj's and nico's solution to catch events of DWebBrowserEvents2 but I would like to accomplish the same thing using the great COMate lib. :)
The difference of this solution seems to be the use of IConnectionPointContainer.FindConnectionPoint whereas COMate uses IConnectionPointContainer.EnumConnectionPoints to detect the event-interface to connect to by analysing the typelib info, but again I may be wrong due to limited COM knowledge.

I would be happy to get suggestions from some specialist or people with more knowledge than myself. I think it is not so hard to find a solution but I must confess I am getting confused by COM event sinks and how to handle them at the WinAPI level in PureBasic. (nethack fans know that confusion can be dangerous to Objects around you.. just kidding)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Yes I may be able to do something here.

Let me take a look.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Okay I have it working okay.

Let me tidy up the code and then upload a new version of COMatePLUS.

By the way you can only set individual event handlers for ActiveX controls. Thus the command :

Code: Select all

browser\SetEventHandler("BeforeNavigate2", @EventProc()) 
will not work for a web-gadget.

For a web-gadget you need to use

Code: Select all

browser\SetEventHandler(#COMate_CatchAllEvents, @EventProc())
etc.
I may look like a mule, but I'm not a complete ass.
hm
User
User
Posts: 30
Joined: Mon Oct 27, 2003 12:15 pm
Location: Germany
Contact:

Post by hm »

srod wrote:Okay I have it working okay.

Let me tidy up the code and then upload a new version of COMatePLUS.
Thank you very much for the quick response and for your work on COMatePLUS.
I am looking forward to use the new version.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Update - 29th April 2009.

Version 1.0.2.

COMatePLUS version 1.0.2 adds a facility for specifying an 'out-going interface' when setting up an event handler for some object or other.

This is essentially for 'advanced users' only, but, basically, COMatePLUS event handlers are based upon an 'out-going' interface which is 'connected' to the underlying COM object through what is called a 'connection point'. Now, many components support different 'out-going' interfaces offering a different range of events which we can tap into and thus we can, if appropriate, direct COMatePLUS to use a specific out-going interface (and thus effectively choose a set of events which we might wish to consider).

To direct COMatePLUS to use a specific out-going interface, simply pass the address of a buffer holding the IID of the relevant interface to the SetEventHandler() method of the COMateObject class (through a newly added optional parameter).

Otherwise, COMatePLUS will simply use the first 'suitable' out-going interface which it encounters (which was the case with all previous versions of COMate) !

There is a new demo (thanks hm) to show this in action with a web-gadget.

The manual has also been updated, in particular limitations of COMatePLUS' event handling are discussed.

See the nxSoftware site for the download.
------------------------------------------------

@hm : I decided for reasons of simplicity to insist that you supply the required out-going interface's IID directly rather than attempt to match a 'friendly name' with the IID through a rummage through a type-library etc. The fact is that I have no real experience with type libraries and so simply shyed away from that!

I reckon though that this new feature will be required and used so infrequently that it really isn't worth my time and effort in adding such a facility. Course, if you happen to have some code lying around which will do this...... :wink:

**EDIT : actually, these 'friendly names' appear to be held in the registry so I may be able to hack up some code for retrieving the IIDs from the friendly names after all! :) That will have to wait though - sleepy time for this idiot!
I may look like a mule, but I'm not a complete ass.
hm
User
User
Posts: 30
Joined: Mon Oct 27, 2003 12:15 pm
Location: Germany
Contact:

Post by hm »

[supply IID, not 'friendly name']
That is perfectly acceptable for me. The new demo works great.

fyi. Small thing that i saw when comparing v1.0.1 and v1.0.2 COMatePLUS.pbi: Line 1565 still contains a "Debug 77" statement which is not commented out.

Many thanks again, srod, PureBasic COM wizard. :)

Without COMate I probably would not be doing any COM stuff in PureBasic at all after many years of PureBasic abstinence.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

hm wrote:fyi. Small thing that i saw when comparing v1.0.1 and v1.0.2 COMatePLUS.pbi: Line 1565 still contains a "Debug 77" statement which is not commented out.
Doh!

Fixed!

Thanks.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Update - 30th April 2009.

Version 1.0.3.

COMatePLUS version 1.0.3 adds a new 'helper' function :

Code: Select all

COMate_GetIIDFromName()
which takes a 'friendly name' of a COM interface and, if successful, places the 128-bit IID of the interface into a specified buffer.

I added this to assist with the SetEventHandler() method of the COMateObject class which, for more advanced uses, takes an optional IID etc.

NOTE that this function cannot be used to obtain a CLSID from a COM component's friendly name. COMatePLUS already does that automatically.

Tested on Vista only.

Examples of friendly names for COM interfaces :
  • iUnknown
  • iDispatch
  • DWebBrowserEvents2
  • ... etc.
---------------------------------------------------------------------------

@hm : I adjusted the web-gadget demo to use this new function which works by manually trawling the registry. It seems to be quite fast though.

I do need someone to test on XP if possible! :wink:
I may look like a mule, but I'm not a complete ass.
hm
User
User
Posts: 30
Joined: Mon Oct 27, 2003 12:15 pm
Location: Germany
Contact:

Post by hm »

srod wrote:@hm : I adjusted the web-gadget demo to use this new function which works by manually trawling the registry. It seems to be quite fast though.

I do need someone to test on XP if possible! :wink:
WebGadget demo v1.0.3 works perfectly on Windows XP Media Center Edition german. Thanks again :)
besko
User
User
Posts: 42
Joined: Tue Oct 28, 2008 1:08 pm

Post by besko »

Srod, how can i use this code with your glib?
I think with COMatePLUS it will be more smaller.



Get text from webgadget inFrames.

Code: Select all

Procedure.b SearchTextInFrames(WebGadget.l, StringToFind.s)
  
  Protected HTMLDocument.IHTMLDocument2
  Protected AllDocumentElems.IHTMLElementCollection
  Protected varReturn.VARIANT
  Protected URL.s
  
  Protected TagsDispatch.IDispatch
  Protected TagsDispatch2.IDispatch
  Protected TagName.VARIANT
  Protected TagsElemColl.IHTMLElementCollection
  Protected HTMLCodeElem.IHTMLElement
  
  Protected HTMLlength.l
  Protected HTMLcode.s
  
  Protected ZeroVariant.Variant
  
  ZeroVariant\vt = #VT_I4
  ZeroVariant\lval = 0
  
  TagName\vt = #VT_BSTR
  Protected MainTag.s = "HTML"
  
  Protected *bstr.l = SysAllocString_(Space((Len(MainTag)*2) + 2))
  
  PokeS(*bstr, MainTag, -1, #PB_Unicode)
  TagName\bstrVal = *bstr
  
  Protected *bstr_html.l = SysAllocString_(Space(14000))
  
  If HTMLDocument
    HTMLDocument\Release()
    HTMLDocument = 0
  EndIf
  Gadget.IWebBrowser2 = GetWindowLong_(GadgetID(WebGadget), #GWL_USERDATA)
  If (Gadget\get_Document(@Doc1.IDispatch) = #S_OK) And Doc1
    Doc1\QueryInterface(?IID_IHTMLDocument2, @HTMLDocument.IHTMLDocument2)
    If HTMLDocument\get_frames(@FrameCollection.IHTMLFramesCollection2) = #S_OK
      If FrameCollection\get_length(@FrameCount) = #S_OK
        If FrameCount>0
          For index = 0 To FrameCount-1
            varIndex.VARIANT\vt = #VT_UINT
            varIndex\lVal = index
            If FrameCollection\item(varIndex, varReturn) = #S_OK
              If varReturn\pdispVal\QueryInterface(?IID_IHTMLWindow2, @HTMLWindow.IHTMLWindow2) = #S_OK
                HTMLWindow\get_Document(@Doc2.IDispatch)
                If Doc2\QueryInterface(?IID_IHTMLDocument2, @FrameDocument.IHTMLDocument2) = #S_OK
                  ;Debug "Got frame."
                  If FrameDocument\get_all(@AllDocumentElems) = #S_OK
                    If AllDocumentElems\tags(TagName, @TagsDispatch) = #S_OK
                      If TagsDispatch\QueryInterface(?IID_IHTMLElementCollection, @TagsElemColl) = #S_OK
                        If TagsElemColl\item(ZeroVariant, ZeroVariant, @TagsDispatch2) = #S_OK
                          If TagsDispatch2\QueryInterface(?IID_IHTMLElement, @HTMLCodeElem) = #S_OK
                            HTMLCodeElem\get_innerHTML(@*bstr_html)
                            HTMLcode = PeekS(*bstr_html, -1, #PB_Unicode)
                            ;Debug HTMLcode
                            If (FindString(HTMLcode, StringToFind, 1)>0)
                              ProcedureReturn 1
                            EndIf
                            HTMLCodeElem\Release()
                            TagsDispatch2\Release()
                          EndIf
                          TagsElemColl\Release()
                        EndIf
                        TagsDispatch\Release()
                      EndIf
                    EndIf
                    FrameDocument\Release()
                  EndIf
                  Doc2\Release()
                EndIf
              EndIf
              HTMLWindow\Release()
            EndIf
          Next
        EndIf
        FrameCollection\Release()
      EndIf
      Doc1\Release()
    EndIf
  EndIf
  
  SysFreeString_(@*bstr)
  SysFreeString_(@*bstr_html)
  
  ProcedureReturn 0
EndProcedure
Post Reply