windrobin / winforms-geplugin-control-library

Automatically exported from code.google.com/p/winforms-geplugin-control-library
GNU General Public License v3.0
0 stars 1 forks source link

Unable to register for events via GEWebBrowser AddEventListener method outside of PluginReady callback #103

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Create a new instance of GEWebBrowser and call LoadEmbeddedPlugin
2. After browser has completed, create a new placemark instance (not in the 
callback method for the PluginReady event).
3. Attempt to register for events via the GEWebBrowser AddEventListner method

What is the expected output? What do you see instead?
I would expect that the registration would succeed. If I call AddEventListener 
from the PluginReady event callback method the registration succeeds. If I call 
from outside the callback method I get an InvalidCastException. 

What version of the product are you using? On what operating system?
Latest

Please provide any additional information below.
I have included a copy of the stack trace. 

Original issue reported on code.google.com by john.s.o...@gmail.com on 27 Mar 2013 at 1:41

Attachments:

GoogleCodeExporter commented 9 years ago
If you actually read the StackTrace - you can clearly see that you are getting 
errors in the native browser web browser control...

'System.Windows.Forms.UnsafeNativeMethods.IHTMLDocument2.GetLocation()'

This is *not* called by the control library - it is something in your code.

The same is true for...

XXX.PlacemarkFactory.CreatePlacemark() in XXX.PlacemarkFactory.cs:line 48

So the fault is in code that is not part of the library.

If general, if you are calling `GEWebBrowser.AddEventListener` outside the 
plugin ready event then you should ensure that the plug-in is really ready 
before calling the method.  

i.e.
if(geWebBrowser1.pluginIsReady)
{
  geWebBrowser1.AddEventListener(...

Original comment by fraser.c...@gmail.com on 29 Mar 2013 at 3:19

GoogleCodeExporter commented 9 years ago
Also, if you are testing code you should try compiling with the debug flag set 
and check for any error messages. 

Original comment by fraser.c...@gmail.com on 29 Mar 2013 at 3:35

GoogleCodeExporter commented 9 years ago
I understand that the exception is coming from the native web browser. I am 
definitely calling after the browser plugin in ready and the globe is fully 
displayed. The work-around I have for this issue is to pre-generate a bulk set 
of placemarks in the plugin ready callback and register for events then. After 
I do that I can just grab the placemarks and fill in what I need and things 
work fine. It just seems weird that I can register for events during the plugin 
ready callback, but after things fail.

From the debugger window, I have no inner exceptions. The exception raised is 
System.InvalidCastException, and the stack trace provided earlier.

Original comment by john.s.o...@gmail.com on 29 Mar 2013 at 3:47

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
> If you do get errors - check the objects you are passing to AddEventListener, 
are they all initialized, etc?

This is the what I am doing internally when I create the placemark and register 
for events. The placemark is successfully generated as I get back a type of 
"KmlPlacemark". 

    dynamic placemark = this.ge.createPlacemark("");
    string type = placemark.GetType();
    this.browser.AddEventListener(placemark, EventId.Click);
    this.browser.AddEventListener(placemark, EventId.DblClick);
    this.browser.AddEventListener(placemark, EventId.MouseDown);
    this.browser.AddEventListener(placemark, EventId.MouseMove);
    this.browser.AddEventListener(placemark, EventId.MouseOut);
    this.browser.AddEventListener(placemark, EventId.MouseUp);

> It very much sounds like you are trying to do something; create placemarks, 
add events, etc - *before* the plugin is ready - if it works when it is ready 
(you are 100% in the ready callback) but not otherwise then I would be fairly 
sure that this is the issue.

Again, I doing this well after the plugin ready event has been fired. I even 
added a pause in the method where the placemark is generated to wait if the 
browser PluginIsReady property is false, ie, 

    while (this.browser.PluginIsReady == false)
        System.Threading.Thread.Sleep(100);
    ...
    // create and register for placemarks

And I'm fairly certain the placemarks are valid, since if I don't attempt to 
register for events, I am able to successfully fill in geometries and what not 
and have the placemarks appear in the Google Earth plugin and interact with 
them in the standard click the object and get a balloon.

Original comment by john.s.o...@gmail.com on 29 Mar 2013 at 4:22

GoogleCodeExporter commented 9 years ago
So what code is making a call to the native GetLocation() method? It isn't part 
of this library.

As I indicated, it very much sounds to me like you are trying to do something; 
create placemarks, add events, work with KML/DOM objects, etc - before either 
the plugin/document is fully ready - somewhere, somehow in code that isn't part 
of this library you are probably trying to work with something that isn't 
initialised...

If it works when it is ready (you are 100% in the ready callback) but not 
otherwise then I would be fairly sure that this is the issue. 

If you are making calls on IHTMLDocument2 then are you sure the document is 
ready, accessible, etc? How are you sure? The following simple test will show 
you can add an event outside the actual plugin ready method.

Move all and only the event adding code from your current plugin ready method 
to a new one, i.e.  

void foo(dynamic ge) {
  geWebBrowser1.AddEventListener( ...
}

Then call this new method from the one you just modified, i.e. 

void  MyPluginReady(object o, GEEventArgs e) {
  //...
  foo(e.ApiObject);
}

Does this work? It really should, but if not and you do get errors with this 
simple case then check the objects you are passing to AddEventListener, are 
they all initialized, etc? Also, what else are you doing in your 'PluginReady' 
event handler? If you redirect debug/trace to the console, what is the output?

Original comment by fraser.c...@gmail.com on 29 Mar 2013 at 4:27

GoogleCodeExporter commented 9 years ago
This works, but it always has. Maybe there's a misunderstanding. I've wrapped 
the GoogleEarth API into a Winform App. So the user is able to create new 
objects at any time. So where I'm getting errors is after the Google Earth 
Plugin has fired up and the PluginReady event has completed, ie, all the event 
handler methods have completed and the app is now just waiting for the user to 
do something. 

So after Google Earth is up and running, the user creates a new object, foo, 
which results in a new placemark being created in Google Earth. At that time, I 
can successfully create the placemark, fill in its geometry / styles, etc, and 
get Google Earth to render that object. What I cannot successfully do is 
register for events, which is where the exception is getting raised. 

Does that help clarify ?

// Updated to register for events
public void GEPluginReady(object sender, GEEventArgs e)
{
    this.browser             = sender as GEWebBrowser;
    this.ge                  = e.ApiObject;
    this.browser.KmlEvent   += EventBroadcaster.Instance.KmlEventHandler;

    for (int i = 0; i < PlacemarkCount; ++i)
    {
        dynamic placemark = this.ge.createPlacemark("");
        this.RegisterForEvents(placemark);                
        this.placemarks.Push(placemark);
    }
}

private void RegisterForEvents(dynamic placemark)
{
    this.browser.AddEventListener(placemark, EventId.Click);
    this.browser.AddEventListener(placemark, EventId.DblClick);
    this.browser.AddEventListener(placemark, EventId.MouseDown);
    this.browser.AddEventListener(placemark, EventId.MouseMove);
    this.browser.AddEventListener(placemark, EventId.MouseOut);
    this.browser.AddEventListener(placemark, EventId.MouseUp);
}

Original comment by john.s.o...@gmail.com on 29 Mar 2013 at 4:42

GoogleCodeExporter commented 9 years ago
So I guess the overarching question I have is 

Is the Google Earth Plugin in some special state during the plugin callback 
that allows you to successfully register for events? I understand that there is 
some magic / handwaving going on in the background to bind the JavaScript 
events to C# events. Is the time you are able to do that binding specific to 
the PluginReady callback event ?

Original comment by john.s.o...@gmail.com on 29 Mar 2013 at 4:46

GoogleCodeExporter commented 9 years ago
No there is no special state...there is nothing to stop one adding events 
outside the ready method in the library...

Could it be that you are simply trying to add events to 'foo'  before you have 
added it to the plugin...For example, are you calling 

ge.getFeatures().appendChild(foo); 

before you call...

this.browser.AddEventListener(foo, EventId.Click);

Also, how are you creating the actual Placemarks, what dos the "factory" do?

Original comment by fraser.c...@gmail.com on 30 Mar 2013 at 3:12

GoogleCodeExporter commented 9 years ago

Original comment by fraser.c...@gmail.com on 8 Apr 2013 at 6:41