Click here to Skip to main content
Click here to Skip to main content

Embed PicLens

, 23 Mar 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Simple article showing how you to embed PicLens in your own apps

Table Of Contents

Introduction

I should point out that this article starts out with me thinking it was going to be a blog post, nothing more, and in reality it is not much more than a blog post, but I have a rethink and although it is very small I think it may be useful to some folks, which is why I decided to release it as an article in the end. As I think that there may be some readers that take this the extra step and use it in their own apps.

So enough of the self flagellation, what does the thing attached actually do.

Well ok, here it is, for ages I have marvelled at the Web addin by CoolIris called "PicLens", which I have to say is the best add in I have ever seen. I have even tried to write my own version of this which myself and fellow coder Marlon Grech did for WPF, we did not do as good a job as CoolIris.

We called ours MarsaX, which you can look at right here.

Ours looks like this:

Whilst CoolIris PicLens looks like this:

Now as CoolIris PicLens is a browser addin, what makes it even more impressive is the fact that it runs in the browser. How the hell is this possible. I decided to have a look at whether it would be possible to host the CoolIris PicLens addin in my own WPF app, and to see if I could manipulate what was shown on the 3d wall, and that is what this small article is all about.

Pre-Requisites

The only things you will need are:

  • VS2008/VS2010
  • .NET 3.5 SP1 or later

The Code

This section will explain how the demo WPF app hosts the CoolIris PicLens browser addin.

Flash (COM)

The very cool thing (at least I think so, there are folks who detest Flash but I love it), is that the CoolIris PicLens browser addin is just a standard Flash SWF file. That is kind of cool, as it means I can embed it in my own page. I know people hate Flash but as I stated I like it, and CoolIris has fully exposed its functionality via JavaScript. You can read more about how to embed the CoolIris PicLens addin using their documentation link, which you can find at http://www.cooliris.com/developer/reference/.

It is quite detailed. But for me, all I wanted to achieve was to be able to host the addin in my own web page which itself was hosted inside my own WPF app. So let's have a look into that, shall we.

Step 1: Creating some XAML to host the HTML page that will in turn host PicLens

This is by far the easiest part, all we have to do is create a WebBrowser (.NET SP1) control, that we can use to host an arbitrary web page. This is the relevant XAML:

<Window x:Class="EmbeddedPicLensWpfApp.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="650" Width="650" Background="#ff121212">
        
        <WebBrowser x:Name="browser" 
                   Grid.Row="1" Width="650" Height="650"  />

    </Grid>
</Window>

And then in the code behind, all we have to do is set the WebBrowser document to be our HTML page that is in turn hosting the CoolIris PicLens browser addin. This too is easily achieved as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace EmbeddedPicLensWpfApp
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            this.Loaded += Window1_Loaded;
        }

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            String fullPath = System.IO.Path.Combine(
                                    System.IO.Directory.GetCurrentDirectory(),
                                    @"PicLensHostPage.htm");

            browser.Navigate(
                new Uri(fullPath));
        }
    }
}

Step 2: Creating the HTML

The moderately hard part of all of this is setting up the CoolIris PicLens addin. CoolIris actually exposes a express wall creator, but that uses an EMBED object tag, which is bit more rigid and less flexible that creating the CoolIris PicLens addin using JavaScript. I chose to use JavaScript as it offered me greater flexibility.

The entire page to host the CoolIris PicLens addin looks like this (I will explain some of this later):

<!-- saved from url=(0014)about:internet -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<head>

<style type="text/css">
Html, body 
{
    Overflow:auto;
}

#wall 
{
    background-color: #121212;
    Overflow:auto;
}
</style>


<script type="text/javascript" 
    src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js">
</script>

<script type="text/javascript">

function LoadPicLensWithSearchWord(keyword)
{
    try
    {
        var flashvars = {
            feed: "api://www.flickr.com/?search=" 
                + keyword,
            showEmbed: "false",
            showSearch: "false"
        };
        
        var params = {
            allowFullScreen: "true",
            allowscriptaccess: "always"
        };

        swfobject.embedSWF(
            "http://apps.cooliris.com/embed/cooliris.swf",
            "wall", "600", "600", "9.0.0", "",
            flashvars, params);
    }
    catch(err)
    {
        alert(err);
    }
}

</script>

</head>
<body onload="javascript:LoadPicLensWithSearchWord('robots')" 
    bgcolor="#121212">
    <div id="wall" >
        <!-- 3D Wall Goes Here -->
    </div>
</body>
</html>

But for now, all you need to understand is that the CoolIris PicLens addin is a Flash SWF file and we can create an instance of it using JavaScript.

FlashVars

As you can see from the above example HTML file, there are really 2 main parts. One of them is the FlashVars, which is really a dictionary of configuration values, that can be used to configure the CoolIris PicLens addin.

Let me explain what I am setting there for the CoolIris PicLens addin.

  • feed: Dictates what media stream to use (more on this later)
  • showEmbed: Toggles the visibility state of the show embed button (I have it turned off)
  • showSearch: Toggles the visibility state of the show search button (I have it turned off)

For a complete list of available options, you can check out the CoolIris PicLens addin documentation at the following URL:

http://www.cooliris.com/developer/reference/flashvars/

SwiftObject

The next thing that the JavaScript makes use of is the swfobject.embedSWF library. This small but of JavaScript allows the embedding of Flash SWF files. This is a standard library and can be obtained from the following URL:

http://code.google.com/p/swfobject/wiki/documentation

You can see that it sets various options such as the URL to the SWF and various other bits and pieces such as height/width, etc.

Media Feeds

The more eagle eyed amongst you will notice that I am using the Flickr API, which has a URL similar to this "api://www.flickr.com/?search=Robots". Now according to the CoolIris PicLens addin documentation, you should be able to create your own custom RSS media stream.

This is described at http://www.cooliris.com/developer/reference/media-rss/. To do this, you would need to create an actual web site hosted in IIS, with an HTML file which hosted the CoolIris PicLens addin in it (similar to the example file included), and also create a RSS XML document which is also part of the IIS web site. The documentation suggests that you just also create a crossdomain.xml file which MUST also be located at the root of you IIS installation. I tried this and almost got it working, to the point I knew it was using my own RSS stream, but it still complained about a missing crossdomain.xml. I am not the most patient of people when it comes to the web, it just ain't my bag man, so I leave this as an exercise for the reader.

The demo app simply allows the user to type a keyword, which is then used against the Flickr API. This still obviously requires some interaction between the managed C# code and the browsers JavaScript, more on this in just a minute.

Browser Manipulation

As I just eluded, the attached code makes use of the Flickr media stream API. So all the attached demo code really does, is allow the user to input a new keyword and creates the appropriate Flickr media stream API URL, based on the new keyword, and then passes that to the CoolIris PicLens addin via a JavaScript call. This does mean we need some way of getting stuff from managed code (WPF in this case, though this would be the same in WinForms I would think), into the browser to call some JavaScript.

So let's have a look at that, it is fairly easy to do, we just need to use the System.Windows.Controls.WebBrowser.InvokeScript() method. Here is how the demo app does this:

private void Search_Click(object sender, RoutedEventArgs e)
{
    if (String.IsNullOrEmpty(txtKeyWord.Text))
    {
        MessageBox.Show("You need to enter a search word", "Error", 
            MessageBoxButton.OK, MessageBoxImage.Error);
        return;
    }
    //Invoke the JavaScript in the Browsers page
    browser.InvokeScript("LoadPicLensWithSearchWord", new Object[] { txtKeyWord.Text });
}

An Interesting Discovery

Along the way while I was looking for the best way to invoke JavaScript inside the WebBrowser, I came across a rather cool DLL/Namespace, which is as follows:

The Microsoft.mshtml DLL can be referenced to give you access to some rather rich HTML interaction types.

Then you just need to include this namespace using mshtml; and then look what you can do with the WebBrowsers document. You can basically do any of the typical DOM things you would expect like adding child nodes, adding attributes, injecting JavaScript, etc.

This however is not used in the demo app, I just thought it was cool, and could be very useful. You can read more about the Microsoft.mshtml DLL and its exposed types over at:

If you want to know more about this approach, I found several very good links:

  1. Injecting JavaScript (by Ayende, so you know it rocks) from managed code
  2. Interacting with the Web Browser Control
  3. Alkampfer's Place (blog)

Mark Of The Web

One interesting thing that nags the crap out of me is when I open a web page up and I get the security bar. You may be interested to know that you can get rid of this, by using some special markup in your web content. I have done just that. This is called "Mark Of The Web", which you can read more about right here: http://msdn.microsoft.com/en-us/library/ms537628(VS.85).aspx.

This is what MSDN has to say about it:

"The Mark of the Web (MOTW) is a feature of Windows Internet Explorer that enhances security by enabling Internet Explorer to force Web pages to run in the security zone of the location the page was saved from—as long as that security zone is more restrictive than the Local Machine zone—instead of the Local Machine zone. The role of the MOTW is more prominent with Microsoft Internet Explorer 6 for Windows XP Service Pack 2 (SP2) because of increased security restrictions in the Local Machine zone. When you are developing Web content, the MOTW enables you to test your active HTML documents in the security zone where you intend the pages to run. Adding the MOTW to your Web pages also enables you to fully test their compatibility with users' security settings."

Again, this is from http://msdn.microsoft.com/en-us/library/ms537628(VS.85).aspx.

The effect of this is quite apparent, for example here is the attached demo apps HTML file without the special "Mark Of The Web" markup.

Notice the annoying nag notice.

And here it is again, this time with the special "Mark Of The Web" markup supplied in the demo apps HTML file.

All you have to do is add this to your HTML file.

<!-- saved from url=(0014)about:internet -->

The Finished Thing

Here is a screen shot of the finished thing working inside a WPF Window:

That's It Folks

Anyways folks, that is all I have to say for now. I know this is a very small article (and would have made a nice blog posting), but I just felt that some of you may find it useful, and I would rather a wider audience receive something useful.

So apologies that this article is so small and not my normal mammoth of an article (remember mammoths died out).

History

  • 24th March, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
 
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
 
Both of these at Sussex University UK.
 
Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
GeneralAgain... Pinmemberpranav9525-May-11 22:38 
GeneralRe: Again... PinmvpSacha Barber25-May-11 22:44 
GeneralRe: Again... Pinmemberpranav9525-May-11 22:45 
GeneralRe: Again... PinmvpSacha Barber25-May-11 22:46 
GeneralRe: Again... Pinmemberpranav9525-May-11 22:50 
GeneralRe: Again... PinmvpSacha Barber25-May-11 22:54 
GeneralRe: Again... Pinmemberpranav9525-May-11 22:56 
GeneralStanding Ovation PinmemberDr.Luiji12-Apr-10 5:49 
GeneralRe: Standing Ovation PinmvpSacha Barber12-Apr-10 6:32 
GeneralNice One Sacha PinmvpAbhijit Jana2-Apr-10 6:43 
GeneralRe: Nice One Sacha PinmvpSacha Barber2-Apr-10 7:52 
GeneralRe: Nice One Sacha PinmvpAbhijit Jana2-Apr-10 8:52 
Generalx86 vs. x64 Pinmemberdave.brumbaugh1-Apr-10 11:01 
GeneralRe: x86 vs. x64 PinmvpSacha Barber1-Apr-10 22:14 
GeneralAnother top article PinmemberChris Grove29-Mar-10 23:35 
GeneralRe: Another top article PinmvpSacha Barber30-Mar-10 0:19 
GeneralRe: Another top article PinmemberChris Grove30-Mar-10 1:00 
GeneralRe: Another top article PinmvpSacha Barber30-Mar-10 1:45 
GeneralNot working in IE6 PinmemberChintan P Shah29-Mar-10 19:36 
GeneralRe: Not working in IE6 PinmvpSacha Barber29-Mar-10 21:01 
GeneralRe: Not working in IE6 PinmemberChintan P Shah30-Mar-10 0:40 
GeneralRe: Not working in IE6 PinmvpSacha Barber30-Mar-10 0:43 
GeneralNice one! PinmemberSandeep Mewara27-Mar-10 5:58 
Looks good! Thumbs Up | :thumbsup:
GeneralRe: Nice one! PinmvpSacha Barber27-Mar-10 6:24 
Generalnice One PinmemberGhasemKarimi25-Mar-10 10:30 
GeneralRe: nice One PinmvpSacha Barber25-Mar-10 10:32 
GeneralNice one PinmemberKatka Vaughan24-Mar-10 13:27 
GeneralRe: Nice one PinmvpSacha Barber24-Mar-10 22:00 
GeneralRe: Nice one PinmemberKatka Vaughan25-Mar-10 0:03 
GeneralRe: Nice one PinmvpSacha Barber25-Mar-10 0:04 
GeneralGreat work PinmvpDaniel Vaughan24-Mar-10 13:22 
GeneralRe: Great work PinmvpSacha Barber24-Mar-10 21:57 
GeneralCool - you are the man :) PinmemberAlomgir Miah A24-Mar-10 9:50 
GeneralRe: Cool - you are the man :) PinmvpSacha Barber24-Mar-10 12:59 
Generalthis is what cool means:) PinmemberMDL=>Moshu24-Mar-10 8:37 
GeneralRe: this is what cool means:) PinmvpSacha Barber24-Mar-10 12:58 
GeneralGreat, Sacha! PinmemberMarcelo Ricardo de Oliveira24-Mar-10 1:45 
GeneralRe: Great, Sacha! PinmvpSacha Barber24-Mar-10 2:49 
GeneralRe: Great, Sacha! PinmemberMarcelo Ricardo de Oliveira24-Mar-10 4:43 
GeneralRe: Great, Sacha! PinmvpSacha Barber24-Mar-10 4:56 
GeneralGreat one PinmentorBrij23-Mar-10 23:42 
GeneralRe: Great one PinmvpSacha Barber23-Mar-10 23:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 24 Mar 2010
Article Copyright 2010 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid