Web Enabling SDK for Windows Apps

Thinfinity VirtualUI delivers your Windows applications on any device, anywhere. All with a single line of code.

 

Windows Applications in the Web InstantlyWindows apps to web

As users are migrating from traditional desktop computers to mobile devices, transitioning your Windows application to the Web is the next logical step to increase your exposure. You can make your Windows applications accessible from the Web TODAY.

Furthermore, you may enhance your existing applications with online data, rejuvenate your older software, and deliver your application to anywhere in the world, all with Thinfinity VirtualUI.
 
Continue reading

Use Cookies to Extend a Web-enabled App’s Login

remote data persistence using cookiesIn a previous post we explained how to add remote data persistence to your apps by saving cookies in the browser. In this opportunity we will take advantage of this feature to develop a small but useful demo that shows how to provide an extended sign-on for web users.

Thinfinity VirtualUI web enabled apps were born as desktop apps and most include their own login mechanism. In this opportunity, we will show you how to extend your own existing application’s sign-on process, getting the browser to identify the application’s user. In this way, users would only need to manually log in when accessing the application for the first time, after logging out or when the login ID has expired. Continue reading

Preview: Thinfinity VirtualUI session recording

Thinfinity VirtualUI session recordingComing soon, Thinfinity VirtualUI web-enabled applications will allow you to save application sessions and replay them later.

There are many scenarios for session recording: reproduction of issues, application demos and tutorials, technical support, audit monitoring, e-learning, etc.

In a previous post we explained how to record and play Thinfinity Remote Desktop Server sessions. In this opportunity, we will review a similar Thinfinity VirtualUI feature that helps developers record sessions of their own VirtualUI web-enabled applications.

Continue reading

Browser within the browser: breaking the Matryoshka effect.

When the browsers are nested.
image01

It has become increasingly common to expect desktop applications to be capable of integrating to the web to incorporate available external information. There are several ways this could be achieved: by consuming web services to get the raw data; or, by simply including a browser component within the application, in the form of a panel. In this second case, we’ll be capable of navigating to sites displaying up-to-date information or external multimedia content, such as maps, videos, images and sound —as an example, visit Fish Facts, a live demo that shows basic GUI virtualization capabilities as well as an integration with the web browser and external web resources.

Once we transform these applications with Thinfinity® VirtualUI™, and we invoke them from the web, an effect similar to the famous Russian Nested Dolls case occurs: we run from the browser an application that contains within itself another browser. In short, we surf to an application that internally re-surfs. This is not bad in itself, but we can take advantage of already being in the web to access the final resource directly from the main browser. By doing this we will avoid a roundabout that, among other things, would unnecessarily increase the consumption of resources.

Let’s take a look at the diagrams of the same application running from the desktop…

Matryoshka-image1

… and from the Web:

Matryoshka-image2

As we can see, when we run the application from the desktop we must necessarily navigate through an embedded Webbrowser component. The application is the one that connects to the desired web address, and this webpage is seen in an internal panel, within the application.

But once we load the application from a browser we would experience the aforementioned effect. As a result, the application browses on its own, and the visible result of that surfing is re-transferred to our browser.

If we transfer that navigation to the only browser we need to use, we will access the intended resource without delay or additional bandwidth, processing, or time consumption.

image00

The demo application

The application we use in the example (whose complete source can be found here) attempts to break this browser-within-the-browser effect, simply by using the internal browser only when the application is accessed from the desktop. If the application is being accessed from the web, instead of using that component, the app would load the desired page in an iframe created on the fly. To achieve this integration (which requires a little bit more interaction between the application and the browser) we will add a jsRO object, which will control the remote iframe from the application.

The first addition to our application will be the adding of VirtualUI and its initialization:

using System;
using System.Windows.Forms;

namespace matryoshka
{
   static class Program
   {
       /// <summary>
       /// The main entry point for the application.
       /// </summary>
       [STAThread]
       static void Main()
       {
           new Cybele.Thinfinity.VirtualUI().Start();
           Application.EnableVisualStyles();
           Application.SetCompatibleTextRenderingDefault(false);
           Application.Run(new Form1());
       }
   }
}

Let’s now see what we have to add to the main form code, which it only has a panel where to enter the browsing URL and another one where the WebBrowser component is located.

The following is the application code before adding the changes:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace matryoshka
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // Sets Google Maps URL to run in the embedded browser
            txtURL.Text = "https://maps.google.com";
            Navigate();
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            Navigate();
        }

        private void txtURL_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (Convert.ToInt32(e.KeyChar) == 13)
            {
                Navigate();
            }
        }

        private void Navigate()
        {
            if (!txtURL.Text.Equals(""))
            {
                if (!txtURL.Text.StartsWith("http"))
                {
                    txtURL.Text = "http://" + txtURL.Text;
                }
                webBrowser1.Navigate(new Uri(txtURL.Text));
            }
            else {
                webBrowser1.Navigate(new Uri("about:_blank"));
            }
        }
    }
}

As a first step, we will add to the class the objects in the Cybele.Thinfinity library:

using System;
using System.Drawing;
using System.Windows.Forms;
using Cybele.Thinfinity;

namespace matryoshka
{
    public partial class Form1 : Form
    {

        private VirtualUI vui = new VirtualUI();
        private IJSObject mRemoteLayout = null;

        public Form1()
        ...

This demo application loads a Google Map. To be run embedded in an iframe, Google Maps needs a different URL from the one used on a full page. We know that it will run embedded in the iframe (using VirtualUI) and directly when loaded into the internal browser.

public Form1()
{
    InitializeComponent();
    if (vui.Active)
    {
        // Code executed only when the application runs with Thinfinity VirtualUI
        // Sets Google Maps URL to run embedded in an iframe
        txtURL.Text = "https://www.google.com/maps/embed";
    }
    else
    {
        //* Code executed only when the application runs from desktop 
        // Sets Google Maps URL to run in the embedded browser
        txtURL.Text = "https://maps.google.com";
    }
}

Additionally, we must also make some changes to Navigate( ):

private void Navigate()
{
    string sURL = "";
    if (txtURL.Text.Equals("")){
        sURL = "about:_blank";
    } 
    else
    {
        sURL = txtURL.Text;
        if (!sURL.StartsWith("http"))
        {
            sURL = "http://" + sURL;
        }
    }
    if (vui.Active) {
        mRemoteLayout.Properties["url"].AsString = sURL;
    }
    else {
        webBrowser1.Navigate(new Uri(sURL));
    }
} 

The last (but not least important) addition is the one concerning the jsRO object management: the first method, for its instantiation and definition of their getters; the other one, for the later updating of the iframe’s bounds.

private void Form1_Shown(object sender, EventArgs e)
{
    // Creates jsRO object for iframe control
    mRemoteLayout = new JSObject("layout");
    mRemoteLayout.Properties.Add("windowId").AsString =
                String.Format("virtualui_canvas_{0}", Handle);
    mRemoteLayout.Properties.Add("url").AsString = txtURL.Text;
    mRemoteLayout.Properties.Add("bounds")
        .OnGet(new JSBinding(        // Adds a "getter" to bounds
            delegate(IJSObject AObj, IJSProperty AProp)
            {
                // Returns a JSON object
                Point p = pnlNav.PointToScreen(new Point(0, 0));
                p.Offset(-Left, -Top);
                AProp.AsJSON = "{" + String.Format("\"left\":{0}, \"top\":{1}, \"width\":{2}, \"height\":{3}",
                     p.X, p.Y, pnlNav.Width, pnlNav.Height) + "}";
            }));
    mRemoteLayout.ApplyModel();
}

private void pnlNav_Resize(object sender, EventArgs e)
{
    // Updates all mRemoteLayout's properties "getters"
    if (mRemoteLayout != null)
    {
        mRemoteLayout.ApplyChanges();
    }
}

We can now introduce the additional information that must be included, at javascript level, to the HTML page.

What follows is the base page to which we will be adding the functionality:

 

We will now create three global variables for the VirtualUI and jsRO objects, and for the iframe created on the fly.

<script type="text/javascript">
var virtualUI = null;
var jsro = null;
var nav = null;

$(document).ready(function () {
    ...

We will add three functions intended to create the iframe and keep it updated:

...
$(document).ready(function () {

    var navigate = function(url) {
        nav.src = url;
    }

    var applyBounds = function(bounds) {
        nav.style.left = bounds.left + "px";
        nav.style.top = bounds.top + "px";
        nav.style.width = bounds.width + "px";
        nav.style.height = bounds.height + "px";
    }

    var createNav = function () {
        nav = document.createElement("iframe");
        nav.id = "nav";
        nav.style.position = "absolute";
        nav.style.display = "none";
        nav.style.zIndex = 2;
        nav.style.border = "none";
    }
    ...

We will now instantiate the VirtualUI object, configure its events, and then connect to the application:

var createNav = function () {
   ...
   ...
}

virtualUI = new Thinfinity.VirtualUI();

virtualUI.onError = function (errorMsg) {
    alert("Application load failed");
};

virtualUI.onLoading = function () {
    console.log((virtualUI.devMode) ? "Waiting for application..." : "Loading...");
};

virtualUI.onClose = function (url) {
    if ((typeof url != 'undefined') && (url != '') && (url != null)) {
        if ((virtualUI.devMode != true) || (window.top.opener)) {
           window.top.close();
        }
        window.top.location.href = url;
        return;
    }
    if (virtualUI.devMode) { location.reload(); }
    if ((virtualUI.devMode != true) || (window.opener)) { window.close(); }
    if ((window.top == window) && (document.referrer) && (location.href != document.referrer)) {
        location.href = document.referrer;
    } 
    else {
        if (nav) { nav.style.display = "none"; }
        alert("Application closed");
    }
};

// -- Connect to server...
virtualUI.connect();

Finally, we will create the jsRO object instance. Please note that it’s in the creation of the layout jsRO model (defined in the application) where the iframe is injected into the application window. The other two events are used to keep both the URL and the inserted iframe bounds updated:

...
virtualUI.connect();

// Defining Javascript Remote Objects Elements
jsro = new Thinfinity.JsRO();

jsro.on('model:layout', 'created', function (obj) {
    layout = jsro.model.layout;
    if (nav == null) {
        createNav();
        document.getElementById(layout.windowId).appendChild(nav);
        nav.style.display = "inline-block";
    }
    applyBounds(layout.bounds);
});

jsro.on('model:layout.url', 'changed', function (obj) {
    navigate(obj.value);
});

jsro.on('model:layout.bounds', 'changed', function (obj) {
    applyBounds(layout.bounds);
});

With this procedure, we’ve been able to break the “Matryoshka Effect”. From now on, the embedded browser will be used from the desktop, while the external one will be used from the web —but always being controlled by the remote application.

 

Running the application from the browser

To see the end result, we must first add the application to the list of registered apps in the Thinfinity VirtualUI Server and configure its home page, making sure it points to the page modified by us in this tutorial.

Once this is done, we can access the application from the browser. If we are running the application from the Thinfinity VirtualUI Development Lab, we must change the virtual path’ address so as to match the one defined in the configuration —in the VirtualUI’s manager.

 

Windows and Web integration through Thinfinity® jsRO (Javascript Remote Objects) – Part 4

To achieve more interaction between the remote application and the browser, the object model provided by jsRO allows for the creation of remote methods and events defined in the application and added to a model by the developer.

Having learned how to interact with jsRO objects and their properties in previous articles, let’s see now how to create jsRO remote methods and custom events, and how to work with them from both the application and the browser side.

  Continue reading

How to programmatically register Thinfinity® VirtualUI applications

thinfinitycodegears

Thinfinity VirtualUI comes with a configuration library that allows for an automatic and transparent programmatic registration of an application on your Thinfinity VirtualUI Server. This way, you can avoid leaving this registration and configuration process in the hands of the end user.

Thinfinity VirtualUI’s configuration library allows you to:
Continue reading

Thinfinity® VirtualUI Video: Getting Started with Thinfinity VirtualUI (.Net)

We’d like to invite you to check out our latest video “Getting Started with Thinfinity VirtualUI (.Net)” that can be found in our Thinfinity Google+ page.

 

How to add the VirtualUI library to a .Net application

In this new installment of our video tutorials we show how to add the Thinfinity® VirtualUI™ library to a .Net application and to publish it to be accessed from the Web.

Don’t forget! Check this blog and visit our Google+ page often to find tips, news and videos that will help you get the most out of Thinfinity VirtualUI!

More online content is yet to come!

Please feel free to send us comments or feedback and connect with us on your social network.