Hi Everyone,
In my office I have given a work to open windows form application in browser. Its world wind Globe application which will show latitude and longitude values any where on the globe, I have searched google and I could find few articles which guided me to create an ActiveX Control.
I created C# Class library and added all the classes, Folders[Data, Layers, Location, Plugin Engine, Plugins, Terrain, Web], References, from C# windows application. Program.cs is main entry for the application and I given Attributes ProgID, guid, COMVisible...
The code goes as follows: Program.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using Microsoft.Win32;
using System.ComponentModel;
using System.Threading;
namespace Globe
{
[ProgId("Program")]
[ClassInterface(ClassInterfaceType.AutoDual), ComSourceInterfaces(typeof(ControlEvents))] //Implementing interface that will be visible from JS
[Guid("BB5E3B2B-E560-4199-8673-F7EDA38A8987")]
[ComVisible(true)]
public class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
//[STAThread]
//private string myParam = "Empty";
public event ControlEventHandler OnClose;
//<summary>
//Opens application. Called from JS
//</summary>
[ComVisible(true)]
public void Open()
{
//TODO: Replace the try catch in aspx with try catch below. The problem is that js OnClose does not register.
try
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new MainForm());
}
catch (Exception e)
{
//ExceptionHandling.AppException(e);
throw e;
}
}
[ComVisible(true)]
public void execute()
{
Application.Run(new MainForm());
}
/// <summary>
/// Parameter visible from JS
/// </summary>
[ComVisible(true)]
public void Close()
{
if (OnClose != null)
{
OnClose("http://otherwebsite.com"); //Calling event that will be catched in JS
}
else
{
MessageBox.Show("No Event Attached"); //If no events are attached send message.
}
}
/// <summary>
/// Register the class as a control and set it's CodeBase entry
/// </summary>
/// <param name="key">The registry key of the control</param>
[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();
MessageBox.Show("Registered");
}
/// <summary>
/// Called to unregister the control
/// </summary>
/// <param name="key">Tke registry key</param>
[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();
MessageBox.Show("UnRegistered");
}
}
/// <summary>
/// Event handler for events that will be visible from JavaScript
/// </summary>
public delegate void ControlEventHandler(string redirectUrl);
/// <summary>
/// This interface shows events to javascript
/// </summary>
[Guid("BB5E3B2B-E560-4199-8673-F7EDA38A8987")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ControlEvents
{
//Add a DispIdAttribute to any members in the source interface to specify the COM DispId.
[DispId(0x60020001)]
//[DispId(1)]
void OnClose(string redirectUrl); //This method will be visible from JS
}
};
I also successfully created ini and cab files.
I have given Java Scripting in HTML file which is:
<html xmlns="http://www.w3.org/1999/xhtml">
<head> <title></title> </head>
<body onload="myload();">
<object id="Program" name="Program" classid="clsid:4CBBC676-507F-11D0-B98B-000000000000" codebase="Program.cab"></object>
<script type="text/javascript">
function Program::OnClose(redirectionUrl)
{
alert(redirectionUrl); <!-- http://otherwebsite.com should be returned-->
//window.location = redirectionUrl;
}
</script>
<script type ="text/javascript">
function myload()
{
try
{
document.Program.Open(); //Running method from activeX
//document.MainForm().action = alert(Program.execute());
document.Program.execute();
alert(Program.execute());
//document.forms.item=Program.Open();
}
catch(Err)
{
alert(Err.description);
}
}
</script>
</body></html>
Mainform contains Private Members, Constructors, World Window Events, Main Form changing events, Main Form Events. I need to run [Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm());] from another class.
I tried and am getting error Object doesn't support this property or method, I would be very helpful if anyone fix this error for me.
Thanking you all in advance,
Regards,
Sharat.