capturing a click event on Google Earth plugin - c#

Using the Google Earth Plugin in C#, I want to get clicked position on the earth; how can I do this?
using GEPlugin;
m_ge = (IGEPlugin)pluginInstance;
KmlLookAtCoClass lookAt = m_ge.createLookAt("");
lookAt.set(35.337919, 33.321576, 0, m_ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 0, 5000);
m_ge.getView().setAbstractView(lookAt);
m_ge.getLayerRoot().enableLayerById(m_ge.LAYER_ROADS, 1);
Now I want to add Click Event listener that I want to get click event.
How can this be done?

EDIT
The GEWebBrowser inherits from the
standard
System.Windows.Forms.WebBrowser
control class and has the same base
members, methods, properties and
events.
Because of this, you'll need to manually create bi-directional communication between this control and your C# class.
See this article for how to wire up C# to javascript events in a browser control. http://support.microsoft.com/kb/312777
Also, you may find the following C# method useful for adding javascript events to the GEWebBrowser.
Void AddEventListener(object, string,
string)
Wrapper for the the google.earth.addEventListener method
Parameters
object: The target plug-in Api object
string: The event Id
string: The name of javascript callback function to use
example: GEWebBrowser.AddEventListener(object,"click","function(event){alert(event.getType());}");
src: http://code.google.com/p/winforms-geplugin-control-library/wiki/GEWebBrowser
Not entirely sure, but perhaps one of these links will help you out.
http://fraserchapman.blogspot.com/2008/08/google-earth-plug-in-and-c.html
http://groups.google.com/group/google-earth-browser-plugin/browse_thread/thread/90dfb80960094828?pli=1
http://interactiveearth.blogspot.com/2008/01/create-your-own-google-earth.html
http://www.xtremevbtalk.com/showthread.php?t=287038

The problem is that the standard event handlers are part of the google.earth namespace and are not directly accessible via managed code. You need to 'relay' the events to your application via javascript and a COM visible class.
I have developed a free control library that allows you to easily embed the google earth plugin into an application.
It supports the AddEventListner and RemoveEventListner functions that you are looking for
http://code.google.com/p/winforms-geplugin-control-library/wiki/AddEventListener
It is worth noting that it does not use, as in your example, the GEPlugin Type Library - rather the dynamic type in C#4.0. This means that it is not 'version dependent' on a particular version of the Google Earth Plugin
The main project is here
http://code.google.com/p/winforms-geplugin-control-library/

Related

How to access android system settings with Unity in C#

I'm making an app and need to be able to check if settings like : Bluetooth/Phone Rotation/Flashlight/Plane Mode/GPS/Phone Brightness/Silent Mode, are activated on an android phone.
I haven't found any way to do it within Unity, using C#. I found ways to do it using Xamarin but none of them work with Unity (or maybe I haven't done it right), the only way I found is using Java and making it into a plugin and call it in a C# script. But I can't find a clear way to make this work. If this is the only solution could you please explain how to do it, all the documentation I find is from old versions from 2014.
I think there is a simple solution for this but I simply can't find it. And the manifest part is not a problem, I'll add the permissions needed.
In Java the methods you want to call should be public or static, you must build your java source as a library (in build.gradle: apply plugin: 'com.android.library'), and add the .aar to Unity's Assets/Plugins/Android/ folder.
Then you can instantiate your plugin in Unity like so:
// this class string is the package at the top of your Java class extended with the class name, e.g.:
// package com.yourcompany.you.package;
string classString = "com.yourcompany.you.package.className";
// Get the class
var tempAjc = new AndroidJavaClass(classString);
// Here you can call a static method on the class that returns an instance of the class if you want to pass some parameters upon creation
_androidObject = tempAjc.CallStatic<AndroidJavaObject>("CreateInstance",
new object[] {arg1, arg2});
// non static call on your new instance
_androidObject.Call("PassingMoreStuff", initParam);
// if you want to return something from Java to Unity:
int javaVal = _androidObject.Call<int>(methodName, parameters);

Fetching C# Logs in Python

I have built a python library that uses C# code(which is built and stored as a dll), using pythonnet. In that library, I generate logs using the python logger.
mylibrary.py
logger = logging.getLogger('mylibrary')
logger.info('logging from my library')
The root logger is configured from the user code. For example, the handlers for the root logger is set by the user using logger's "addhandler()" method specifying the format, output file etc. Inside my library, I just log (logger.info()...) without configuring anything and the root handler set by the user takes care of writing this to the file.
usercode.py
root_logger = getLogger()
root_logger.addHandler(FileHandler('abc.log'))
root_handler.setFormat(...)
The user can control what my library can log by setting the level of the logger used by my library. The line below in usercode.py sets the logging level of my library's logger to critical so that the library can't log anything below it (logger.info() won't get into abc.log).
getLogger('mylibrary').setLevel(CRITICAL)
The problem comes now. Since I am using C# code in my library,
I want to capture the C# logs into abc.log
I also want to configure the C# log just like I did for python logs
So the the line
getLogger('mylibrary').setLevel(CRITICAL)
in usercode.py should now make sure that only the critical logs in both the python as well as C# get into abc.log
Is there a way to achieve this?
No, you cannot log from both Python and C# at the same time to the same file. The reason for this is that Python's logging (and likely the C# logging too) is not equipped for concurrent logging - even if the log file is not 'locked' by one of them, there is a chance of getting different logs mixed together due to multiple writers.
If you do not own the C# dll you're probably out of luck - unless it would allow you to configure the log file/level from a C# program, there is no magic that Python can do to fix it. However, if you control the source and can build a new dll, consider changing the C# class to allow you to pass in a delegate/lambda (assuming this is implemented in PythonNet), which will simply call back into Python's logger function.
Example:
c# code:
public class CoolImportedFeature
{
private readonly Action<string> LogCallback;
public CoolImportedFeature(string inputA, int inputB, Action<string, string> logCallback)
{
LogCallback = logCallback;
// do other constructor stuff
}
public void SomeMethod()
{
// do something
LogCallback("critical", "An error occurred");
}
}
python code:
def log_callback(log_level, message):
getattr(logger, log_level)(message)
import CoolImportedFeature
feat = CoolImportedFeature("hello", 1, log_callback)
feat.SomeMethod()
Something like that - there is no magic translation between Python's log levels and C#'s, so you will need to do some translation there (or the getattr reflection I used above).

How to populate the fields in browser using Java or C#

As I have a web form I need to fill in repeatedly, can I construct a Java or C# program to populate the form automatically? For example below is a sample contact us form, I wish that when I click on the Java or C# program, the form could be filled in automatically. How to achieve this?
maybe you need to use some autotesting techology. For example: selenium (Java), watir (Ruby), watin (.net).
Those tool provide browser abstraction that help manipulate with page and controls on it.
There is little example:
package selenium.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
public class ExampleSearch {
public static void main(String[] args) {
WebDriver driver = new HtmlUnitDriver();
// Open Google
driver.get("http://www.google.com");
WebElement element = driver.findElement(By.name("q"));
element.sendKeys("selenium best practices");
// Send form with element
element.submit();
}
}
JavaScript is a much better way to do this. Use the right tool for the right job.

How to create an ActiveX control in C#?

I am not able to create a functioning ActiveX control in C#; I have tried following tutorials to do so without success.
I create a sample Class Library project which includes this code:
namespace AACWCSurvey
{
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Class1
{
public Class1()
{
MessageBox.Show("FIRETRUCK!!!");
}
}
}
I then did the following steps:
Properties => Application => Assembly Information => Make Assembly COM-visible
Build => Register for COM interop TRUE (checked)
Make Strong name for assembly (signing)
Build the project
regasm MyDll.dll /tlb /codebase
Can't see Prisoner.PrisonerControl in tstcon32 =(
My OS is WinXP x86.
UPD: it works from VBScript:
Dim objJava
Set objJava = WScript.CreateObject("Prisoner.PrisonerControl")
but it is not visible in tstcon32.
If you read the actual article using the Prisoner.PrisonerControl control a sub key named Control is created inside the key with your control GUID.
On my machine with the guid {9DEA5F06-E324-31A7-837B-D0F3BDE91423} creating the key
HKEY_CLASSES_ROOT\CLSID\{9DEA5F06-E324-31A7-837B-D0F3BDE91423}\Control
Make the control appears in tstcon32. And with or without it the ActiveX is usable for javascript
var x = new ActiveXControl("Prisoner.PrisonerControl");
Actually i had to fight windows on both the javascript execution and registry path to test it on my system because it's an x64 machine but that's another story.
You have created a COM server but not an ActiveX control, which is a far more intricate COM object, the kind that you can exercise with tstcon32.exe.
It must implement a bunch of interfaces, key ones are IOleObject and IOleWindow. The kind of interfaces that allows it to do the required negotiations with an ActiveX host and create a visible window. The Winforms Control class is your best bet to create one.
Here are the relevant steps as documented externally. This is summarized leaving out some exposition but not any necessary steps.
This example is also very similar to the article Using Managed Controls as ActiveX Controls by Garry Trinder, November 25, 2008 and I've included some notes from this article as well.
Exposing Windows Forms Controls as ActiveX controls
This article will describe how to utilise Windows Forms controls
outside of .NET.
Writing the control
Create a new control project from within Visual Studio - my examples are all in C# but VB.NET could also be used.
[Here Garry's article suggests, "First, create a managed usercontrol project – either a Windows Forms class library or control library project. Use the usercontrol designer to design your custom usercontrol the way you want it (using any standard controls you like)."]
Add controls etc to the form, put in the code etc.
Add in the following using clauses...
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using Microsoft.Win32;
Attribute your class so that it gets a ProgID. This isn't strictly necessary as one will be generated, but it's almost always best to be
explicit.
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
This assigns the ProgID, and also defines that the interface
exposed should be 'AutoDual' - this crufts up a default interface for
you from all public, non-static members of the class. If this isn't
what you want, use one of the other options.
Update the project properties so that your assembly is registered for COM interop.
If you're using VB.NET, you also need a strong named assembly.
Curiously in C# you don't - and it seems to be a feature of the
environment rather than a feature of the compiler or CLR.
Add the following two methods into your class.
[ComRegisterFunction()]
public static void RegisterClass ( string key )
{
// Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
StringBuilder sb = new StringBuilder ( key ) ;
sb.Replace(#"HKEY_CLASSES_ROOT\","") ;
// Open the CLSID\{guid} key for write access
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
// And create the 'Control' key - this allows it to show up in
// the ActiveX control container
RegistryKey ctrl = k.CreateSubKey ( "Control" ) ;
ctrl.Close ( ) ;
// Next create the CodeBase entry - needed if not string named and GACced.
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ;
inprocServer32.Close ( ) ;
// Finally close the main key
k.Close ( ) ;
}
The RegisterClass function is attributed with ComRegisterFunction -
this static method will be called when the assembly is registered for
COM Interop. All I do here is add the 'Control' keyword to the
registry, plus add in the CodeBase entry.
CodeBase is interesting - not only for .NET controls. It defines a URL
path to where the code can be found, which could be an assembly on
disk as in this instance, or a remote assembly on a web server
somewhere. When the runtime attempts to create the control, it will
probe this URL and download the control as necessary. This is very
useful when testing .NET components, as the usual caveat of residing
in the same directory (etc) as the .EXE does not apply.
[ComUnregisterFunction()]
public static void UnregisterClass ( string key )
{
StringBuilder sb = new StringBuilder ( key ) ;
sb.Replace(#"HKEY_CLASSES_ROOT\","") ;
// Open HKCR\CLSID\{guid} for write access
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
// Delete the 'Control' key, but don't throw an exception if it does not exist
k.DeleteSubKey ( "Control" , false ) ;
// Next open up InprocServer32
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
// And delete the CodeBase key, again not throwing if missing
k.DeleteSubKey ( "CodeBase" , false ) ;
// Finally close the main key
k.Close ( ) ;
}
The second function will remove the registry entries added when (if)
the class is unregistered - it's always a good suggestion to tidy up
as you go.
Now you are ready to compile & test your control.
Additional notes from Garry's blog:
[The] additional registry entries: Control, MiscStatus, TypeLib and
Version [can be created] with a .REG script, but it’s generally better
to write functions that will be called on registration/unregistration
He describes the registry keys in some detail:
Control is an empty subkey. TypeLib is mapped to the GUID of the
TypeLib (this is the assembly-level GUID in the assemblyinfo.cs).
Version is the major and minor version numbers from the assembly
version. The only mildly interesting subkey is MiscStatus. This needs
to be set to a value composed of the (bitwise) values in the OLEMISC
enumeration, documented here. To make this enum available, add a
reference to Microsoft.VisualStudio.OLE.Interop (and a suitable
‘using’ statement for the namespace).
His final note is a warning:
Note: this seems to work OK for Excel (with the very limited testing
I've done), partly works with PowerPoint, but fails miserably with
Word. Possibly, some more of the OLEMISC values might improve this;
possibly there are some messages we need to hook; possibly there are
some more interfaces we need to implement ... The fact that I’ve only
barely got it to work in a very limited way should tell you that this
is probably not a technique you want to use in any serious way.

ASP.Net - How do I include an embedded JavaScript file from another project?

I've got two projects, one is a control library and another is my main project. From the control library I am currently using a user control and some css files which are embedded in the control library.
I can use the embedded CSS files in my main project by doing the following from my user control's PreRender event:
// Register the default CSS resource
string includeTemplate = "<link rel='stylesheet' text='text/css' href='{0}' />";
string includeLocation = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "MyCompany.ControlLibrary.WebNotify.WebNotify.css");
LiteralControl cssInclude = new LiteralControl(String.Format(includeTemplate, includeLocation));
((System.Web.UI.HtmlControls.HtmlHead)Page.Header).Controls.Add(cssInclude);
I thought it would then make sense to include all my javascript files in a similar fashion, so I included the embedded javascript file doing the following:
// Register the js
string includeTemplate = "<script type='text/javascript' src='{0}'></script>";
string includeLocation = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "MyCompany.ControlLibrary.Scripts.MyScript.js");
LiteralControl jsInclude = new LiteralControl(String.Format(includeTemplate, includeLocation));
((System.Web.UI.HtmlControls.HtmlHead)Page.Header).Controls.Add(jsInclude);
Now, the CSS all works perfectly, however my JS functions throw Object Required exceptions when trying to call them.
Am I going about this the correct way? Or is there a better way of including an embedded js file from another assembly into another project?
Personnally, as others have suggested, use some tools such as FireBug for Firefox, Fiddler, or the Developer Tools for Internet Explorer to check what calls are being made to your servers, and what responses they are sending back - that's what BigBlondeViking's referring to.
I'd also check that you have marked the JS file as "build" in the solution - rather than the default of "take no action".
However, there is indeed a cleaner way of adding embedded script resouces, the ClientScriptManager's "RegisterClientScriptResource" method:
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Register the client resource with the page.
cs.RegisterClientScriptResource(rstype,
"MyCompany.ControlLibrary.Scripts.MyScript.js");
Seems fine; however, at this point I'd really be using client tools to determine whether or not everything's getting there and being used (fiddler/ie toolbar/firebug/etc).
If I had to guess, I would say your code is working, but whatever browser you're using is ignoring the javascript due to the script tag not having a closing tag (i.e. <script></script> opposed to <script />); for some reason some browsers are picky about that

Categories

Resources