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

Instantly Increase the Value of your Windows Application

Take your desktop application to the web.We already published a very popular article at CodeProject to discuss how the migration of PC desktop users to all kind of mobile devices affected the paradigm of software development.

The bring your own device (BYOD) era started more than a decade ago with Palms and the first smartphones, and now there are much more complex needs to solve. The exponential market growth of Chromebook, iPads and tablets demands a new approach to adapting applications to meet their users’ daily requirements. Continue reading

Remote Raw Printing from VirtualUI-Enabled Apps (1)

remote raw printsModern web browsers have been designed to protect end-users from malicious or unwanted access to computer’s local resources. Typically, web browsers have none or limited access to disk units, USB devices and peripherals devices attached to the local computer.

Local printers are not an exception; they are restricted to printing web content only. But what if our VirtualUI-enabled application needs to send raw print commands and data to a matrix or label printer such as Zebra, Epson, etc.?

This article will demonstrate how to access a printer connected to the web browser from our application so we can generate RAW prints remotely as if the remote application and the printer were available in the same environment.

Continue reading

Thinfinity VirtualUI Guide for a Smooth First Time User Experience

Thinfinity VirtualUI is designed to have a straightforward implementation. Thinfinity VirtualUI GuideInstallation and setup will only take a couple of minutes before you can enjoy access to your desktop application from a browser in a pure HTML5 interface.

In this article we want to tell you about some tips and tricks that can help you save time and ensure you have a smooth first time user experience.

Let’s walk through some configurations pitfalls you want to avoid!

Continue reading

Thinfinity jsRO remote events in C++

Thinfinity jsRO remote events in C++

Thinfinity jsRO allows programmers to get a better integration between a VirtualUI-extended desktop application and the web browser Javascript world.

We first presented the jsRO Delphi and .Net native interfaces when Thinfinity VirtualUI was launched, and we wrote several articles about it. Some months ago we implemented the jsRO native interface for C++. Today we will share with you how to create custom events in your application and replicate them in the web page.

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

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

Now that we’ve learned how to create a remote object and expose it on the Web, let’s see how to interact with jsRO objects in more detail.

 

The jsRO Object life cycle and the predefined Javascript Events

Let’s begin by noting that the jsRO objects are always defined inside the application and propagated to the browser. You can’t add new properties, methods or events to these objects in the browser side, but you can retrieve and modify property values, invoke objects’ methods and handle their events.

Four predefined Javascript events are related to the jsRO object life cycle, associated to its creation, updating and destruction.

Starting from the first ApplyModel invoked in the application, jsRO will create the object and propagate it to the browser, where it will trigger the created event:

on(“model:object”, “created”, ...)

also, for the properties that are created with an assigned value, jsRO will replicate their initial values in the browser and fire the corresponding events (one per property):

on(“model:object.property”, “changed”, ...)

and from that moment on, it will keep the state of the properties in the application and the browser synchronized with each other.

If the model needs to be updated by the addition of new attributes (such as new properties, events or methods) a new ApplyModel must be invoked, which will, now that the model has been created, fire a changed event on the model.

on(“model:object”, “changed”, ...)

Finally, if the object is destroyed in the application, the deleted event will be triggered and the object will be destroyed in Javascript too.

on(“model:object”, “deleted”)

This last event will also be triggered when closing the application.

Javascript "Model" Events

The opposite direction: OnPropertyChange(), OnSet() and OnGet() events

When publishing a model, jsRO will keep the created object’s state in the application and the browser side synchronized with each other. Each time a property is updated in the application side, this change fires an event to the browser, where, in addition to updating the value, it can be handled by the corresponding .on(“model:object.property”, “change”, …) event, if it has been declared.

When a property is updated on the browser side, this change is sent in the opposite direction (that is, from the web to the application) and triggers an OnPropertyChange event in the instantiated JSObject object. This  would be a good place to do things like propagating the change of a property’s value to some other element of the application, updating a group of values in a database, etc.

jsRO can also handle changes in its objects’ properties through the declaration of the OnSet and OnGet property events.

By invoking the ApplyChanges method on a JSObject object, its properties collection is traversed and any declared OnGet event is triggered.

Using Property OnGet

Whenever the value of a property is modified in the browser this change is propagated to the same property in the application side. If in the application the modified property has the OnSet event defined with its corresponding callback, the callback will be executed.

Using Property OnSetThe way to add the OnSet and OnGet event handlers to a property is based on their definitions.  It can be done when adding the property or afterwards, but always remember to invoke the ApplyModel method so that the model is propagated to the browser.

The following example shows how the browser can retrieve the application form background color in the #RRGGBB format, and also how to change the background color using a value sent from the browser. Since the desktop application doesn’t interpret colors the same way the web does, we need a conversion that works both ways.

The Delphi code for this example is:

// Creates the remote object
FRo := TJSObject.Create('ro');

// Property definition
FRo.Properties.Add('backgroundColor')
   .OnGet(TJSBinding.Create(
      procedure(const Parent: IJSObject; const Prop: IJSproperty)
      begin
         Prop.AsString := '#'
            + IntToHex(GetRValue(ColorToRGB(Form1.Color)), 2)
            + IntToHex(GetGValue(ColorToRGB(Form1.Color)), 2)
            + IntToHex(GetBValue(ColorToRGB(Form1.Color)), 2);
      end))
   .OnSet(TJSBinding.Create(
      procedure(const Parent: IJSObject; const Prop: IJSproperty)
      var value: string;
      begin
         value := LowerCase(Prop.AsString);
         if ((Length(value) = 7) and (copy(value, 1, 1) = '#')) then
         begin
            try
               Form1.Color := RGB(
                  StrToInt('$' + Copy(value, 2, 2)),
                  StrToInt('$' + Copy(value, 4, 2)),
                  StrToInt('$' + Copy(value, 6, 2))
               );
            except
            end;
         end;
      end));
   ...

Now, let’s see how to achieve this in .Net (C#):

// Creates the remote object
ro = new JSObject("ro");

// Property definition
ro.Properties.Add("backgroundColor")
   .OnGet(new JSBinding(
      // This anonymous procedure do the actual get
      delegate(IJSObject Parent, IJSProperty Prop)
      {
         Prop.AsString = "#"
            + this.BackColor.R.ToString("X2")
            + this.BackColor.G.ToString("X2")
            + this.BackColor.B.ToString("X2");
      }))
   .OnSet(new JSBinding(
      // This anonymous procedure do the actual set
      delegate(IJSObject Parent, IJSProperty Prop)
      {
         string value = Prop.AsString.ToLower();
         Regex reColor = new Regex(@"^#([0-9,a-f]{6})$");
         Match match = reColor.Match(value);
         if (match.Success)
         {
            string color = match.Groups[1].Value;
            this.BackColor = Color.FromArgb(
               int.Parse(color.Substring(0, 2), NumberStyles.AllowHexSpecifier),
               int.Parse(color.Substring(2, 2), NumberStyles.AllowHexSpecifier),
               int.Parse(color.Substring(4, 2), NumberStyles.AllowHexSpecifier)
            );
         }
      }));

To change the background color of the application to red, we just need to assign the property value in Javascript:

ro.backgroundColor = “#FF0000”;

This is the end of our presentation about predefined events and jsRO property setters and getters. In coming installments we will analyze how to work with remote methods and how to define custom events to jsRO object.

 

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

As stated in our previous article, the jsRO models are created in the application and then transmitted to the browser, where they can be consumed from Javascript through a Thinfinity.jsRO class instance.

To analyze this sequence in more detail, let’s take a look at a couple of complete cases. The next two examples create an “ro” object, which has a “text” property with the value “Hello!”.

In Delphi, in the Create method of the form:

// Creates the remote object and its property
 ro := TJSObject.Create('ro');
 ro.Properties.Add('text');
 ro.ApplyModel;

In C# (.Net Winform application), in the form constructor:

// Creates the remote object and its property
 ro = new JSObject("ro");
 ro.Properties.Add("text");
 ro.ApplyModel();

The ro.ApplyModel call propagates the created object to the browser, where it will be exposed as a javascript object.

In the browser side, to process changes in the replicated object, we have to add the jsRO’s javascript library to the HTML document and write a few extra lines of code.

Let’s see how to work with this object in Javascript:

$(document).ready(function () {
      ...
      ...
      var jsro = new Thinfinity.JsRO();
      var ro = null;
      ...
      ...
      jsro.on('model:ro', 'created', function () {
         ro = jsro.model.ro;
      });
   });

The first thing you can identify in the Javascript example above is how the Thinfinity.JsRO object is instantiated. This object must be created once, and its function is both to keep synchronized all registered models as well as manage all the remote application’s incoming and outgoing messages. So, through the jsro.on(‘model:ro’, ‘created’, ….) event we can get access to the model, a JSON version of the object created at the remote application.

The following is the sequence diagram for the creation of an object:

jsRO object creation

Once the object is instantiated, the only thing that remains is to read and/or write its properties. But, how will we be made aware of the changes produced in the object properties instantiated in the original application?

To address the changes in each model we should add a handler associated with the name of the object, as follows:

// Changes at Model level
jsro.on('model:ro', 'changed', function (obj) {
     alert(“The object ‘ro’ was changed: “ + JSON.stringify(obj))
});

// Changes at property level
jsro.on('model:ro.text', 'changed', function (obj) {
     alert(“The property ‘text’ of ‘ro’ was changed: “ + JSON.stringify(obj))
});

The next line assigns the “newvalue” string to the property text:

jsro.model.ro.text = “newvalue”;

When assigned, the new value for ro.text property is automatically synchronized with the Delphi/C# version of this remotable object.

In the next installment we will see how to work with these properties in a more neat and advanced way through the introduction of getters and setters.

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

One of Thinfinity VirtualUI’s strengths is, without a doubt, its web integration capabilities. Once the app was published, the urge of going beyond simple cosmetic changes usually appears, and one may wish to combine the application with native web resources, such as personalized web searches, multimedia resources, specialized information and data, and the like.

Some other times data just needs to be visually arranged in a different pattern from how it is presented to the user by the original application. Or the interface needs to be replaced or enhanced to better accommodate the device on which it is being accessed, for a more adequate functionality and integration.

Javascript Remote Objects (jsRO) is a framework designed to facilitate these and many other possible scenarios, by allowing a bidirectional communication between a web page or application and a Windows application. But, most importantly, to make that blending with the greatest possible transparency.

The key point is that jsRO enables the creation of objects in a Windows application that can be replicated on the browser as native Javascript objects. Every pair of objects keep in sync with each other on both ends of the communication, and behaves as the same entity. This synchronization ensures bidirectional interaction and therefore immediately replicating changes in the jsRO objects’ properties, both on the browser and the Windows application.

Web integration: jsRO 00 Comunication Model

This communication is made possible by two components: a dll library (Thinfinity VirtualUI SDK) that has to be added to the Windows application, and a Javascript library (Thinfinity jsRo) that must be added to the web page. By adding a few more lines of code to the Windows application, jsRO objects are ready to be created and published on a browser.

jsRO 00 Model Creation And Exposition

The diagram above shows the sequence of how a jsRO object is first created in the Windows application, then propagated, and finally presented on the browser, ready to be used in Javascript. From this point forward, any changes made on any of the objects created will be reflected accordingly on its counterpart.

 

jsRO objects architecture

The jsRO model is based on the creation of an object in the Windows application and its replication as a Javascript object in the browser. Both objects are connected and synchronized, thus enabling a dialogue between the Windows application and the website via Javascript.

A jsRO object can have properties, methods and events: the properties allow for data synchronization through both application and browser sides; the methods make possible the remote calling of application code; and the events help us to fire, from the Windows application, messages to the browser that could to be caught from javascript callbacks.

 

Object Properties

The jsRO object properties are synchronized on both the application and the browser sides. When a property value changes on one end it is spread to the other, firing an event handler that lets you take an action if necessary.

jsRO-00-Properties

 

Remote methods

When a remote method is called on the browser side, it method handler callback is called on the application. Additionally, the returned result value can be processed by a javascript callback.

jsRO-00-Methods

 

Remote events

Remote events allow developers to submit non-visual changes from the application to the javascript side. When the application fires an event, it is transmitted to the browser, enabling the javascript to receive and process it.

jsRO 00 Events

 

Hopefully, this is enough to get you started. In the next post we will learn how to create a jsRO object in our program to expose application’s data in the browser.

Then, in upcoming entries, we will be adding more complexities to leverage this framework to its full potential.