COMatePLUS version 1.2
Vista Ultimate x64srod wrote: What OS you using?
No line, it crashes on closing window, ms message comes.srod wrote: What line in the code is it crashing on?
Acrobat 9 Pro (no reader)srod wrote: Which version of Acrobat reader do you have?
// 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.
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
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.
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.
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.
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
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.
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.
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)
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
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)
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 :
will not work for a web-gadget.
For a web-gadget you need to use etc.
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())
For a web-gadget you need to use
Code: Select all
browser\SetEventHandler(#COMate_CatchAllEvents, @EventProc())
I may look like a mule, but I'm not a complete ass.
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......
**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!
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......
**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.
That is perfectly acceptable for me. The new demo works great.[supply IID, not 'friendly name']
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.
Update - 30th April 2009.
Version 1.0.3.
COMatePLUS version 1.0.3 adds a new 'helper' function :
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 :
@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!
Version 1.0.3.
COMatePLUS version 1.0.3 adds a new 'helper' function :
Code: Select all
COMate_GetIIDFromName()
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!
I may look like a mule, but I'm not a complete ass.
Srod, how can i use this code with your glib?
I think with COMatePLUS it will be more smaller.
Get text from webgadget inFrames.
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