Jaime Rodriguez On Windows Phone, Windows Presentation Foundation, Silverlight and Windows 7
HTML is quite easy for people to get started with, pretty broadly known, light weight, rich enough (if you work hard at it or have nice graphics), etc.. so there is a good set of reasons why the sidebar folks chose HTML as the presentation technology [ I am guessign here]
However, there are some things that are a little harder to do with HTML [at least they are for me] ... for example, charting (pie charts) ...I tried using VML for this, and had issues.. (it was a little unstable on how it rendered, some times it would stop rendering, I could not figure why)... so for these very extreme scenarios, I am thinking ActiveX might be OK... Note that by no means I am advocating activex as the best choice for gadgets, imho the activex registration (regsvr32) breaks the easy, per-user, non-impactful deployment model for gadgets... but I am thinking that there are enterprises (say internal, lob gadgets) that can get away with an impactful deployment model (via MSI or SMS) and benefit from the rich visualization of an activex -say for some BI KPIs...
Here is what I created code to do:
For reference, here are some good articles in creating .NET Activex controls for IE... I used a little bit from all of these..
http://msdn.microsoft.com/msdnmag/issues/02/01/UserCtrl/
http://www.codeproject.com/cs/miscctrl/exposingdotnetcontrols.asp
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/om/event_model.asp
http://www.cisco-cert.com/dotnet_general/574541-How-to-fire-Javascript-events-from-a--NET-winforms-user-control-back-to-Javascript-in-IE
Come on dude, get to it... show us the code!.. OK .. here you go ... All of the code is commented, please go through it in the project... here I am showing only the 4 tasks above.. |f you are to reuse this, you will have to replace all the lines that have a TODO with your own guids or your own names code
// Outgoing interface, wired via ComSourceInterfaces on my main class -- see step 3
In my class, I had to expose the events ( showing only RightClick here... the rest you can see in the code)
// Right Mouse Click will be passed to the gadget... I was hoping I could popup the context menu.. protected override void OnMouseClick(MouseEventArgs e){base.OnMouseClick(e);if (e.Button == MouseButtons.Right){// Did any one subscribe ??? if (RightClickRelay != null){ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); // fire the event .. RightClickRelay(e.X, e.Y);CodeAccessPermission.RevertAssert();} } }
2 -- Exposing an interface for gadget to call my Activex ..
to wire the interface, simply implement it in my class ... (see step3 )
3.- Creating the activex .. it is simply a .NET Class Library with a UserControl and some attributes:
// TODO: Replace GUID [Guid("A4B9C3C2-8DAC-451a-AEC1-DE3B042FB311")]// TODO: Replace Prog Id [ProgId("WindowsFormsUserControl.UserControl")]//Wire up my eventing interface ..(ComSource)... [ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IGadgetControlEvents))][ComVisible(true)]public partial class UserControl1 : UserControl, IGadgetIncoming
5.- Using the object from my gadget
<!-- using the object tag to call my ActiveX -->
<object id="sample" classid="clsid:A4B9C3C2-8DAC-451a-AEC1-DE3B042FB311"height="126" width="126" style="background-color:Transparent;" onclick="alert('clicked');" > </object><script>
<!-- one of several ways to sync event; another way is using the FOR statement --> function
---
So, the control is pretty trivial... download the sample code, replace the TODOs ( use GuidGen to generate your guids) and you will reuse it ... There were however a couple of note worthy issues I have not figured out .. [will get to these as soon as I have time ]
None of these are blockers, in fact some of the MS gadgets themselves (notes) have these issues but I would like to solve them for a different post ...
You can download the code for this project here... There are two directories in the download, the sample.gadget and the ActiveX code itself..
For dev/test deployment, the project in Visual Studio is using the "Register for COM Interop" checkbox in the Build section of the Project properties to do the registration ... if you are not rebuilding it, or installing it in a box where you are not building it, you will have to register it manually from a .NET Command prompt (or a command prompt with regasm in the path).. regasm /register /codebase WindowsFormsuserControl.dll
This leaves the whole topic of how to deploy at run-time... are you going to need admin, etc.. I will have to get back to these questions in a future (but will try to not make it to far into the future) post.. .
Cheers,
Last post we did a REST call using XmlHttp from a sidebar gadget... but let's admit it, we were all doing xmlhttp calls in 2000 and we were 'geeks'... it was not until 2005? that this exact same code became "cool" because it was called AJAX ... So here is the ticket to get you to the cool group -- every one knows I will never make that :(
Pre-requisites (or stuff you get with the sample code located here)
The client code:
The trick: Atlas by default uses frames to get around cross-site scripting...
Create a proxy to your web service from your gadget code..[So I added a new Javascript file, called AtlasServiceProxy.js and I put the same stuff that atlas gets by making the call to WebService.asmx/js [this is what they use to get the proxy] ... If you have an aspx website, with a webservice, you can just navigate to it using IE, and add the /js after the webservice URL ... (e.g. http://jaimersvr/AtlasWs/Webservice.asmx/js ] and it should look like the one below.. Notice I did have to add one line, the this.path = <url to my webservice> .. Type.registerNamespace('AtlasSample'); AtlasSample.WebService=new function() { // These parameters can of course be set at runtime... In my case, I hardcoded them here for brevity this.path = "http://jaimersvr/AtlasWS/WebService.asmx" ; this.appPath = "http://jaimersvr/AtlasWS/" ; var cm=Sys.Net.ServiceMethod.createProxyMethod; cm(this,"EchoString","s"); }
OK, I think that is all we needed... we are now ready to party w/ ajax.. :) To run the sample, simply click in the button in the gadget...
WHY BOTHER using Atlas to call webservices instead of just plain old XmlHttp like we did on my last post??... Well, there is one nice reason to do this: Atlas does some nice JSON serialization on the back-end and front-end, so the results come back as objects instead of as an XML file you need to parse... for example, my webservice returns an object... that looks like this in C#:
public
/*digress: why this weird object I started with a simple Echo function ... that returned what you sent.. but then I decided to do a more complex object .. so I thought an echo would do... here you get the echo at 10m ( LOUD ) at 50m ( LOud) and at 100m when it fades (loud) .... you can stop gagging now :) */
The code for this sample is located here, there is a client side component ( sample.gadget) and a server side component ( AtlasWS ) ... You will as usual have to change the URLs in AtlasServiceProxy.js from pointing to my servers to pointing to yours..
Cheers. ..