In a previous article, we looked at using responsive design with enterprise applications by utilizing the Citrix XenApp Mobile Application SDK. Jonathan Chin left an interesting comment about hooking up an event handler to apply the responsive design to a reconnection event.  So, I decided to investigate doing just that and, as it turns out, it isn’t that hard.  

In the previous version, the responsive design code only kicked in on session initiation (i.e. logon) - meaning if you started a session on a fat client and then reconnected to the session on a mobile device, then the fat client display would show up on the mobile device. We don’t want that. So, by catching the reconnection event, we can re-style the app at any point (session initiation or reconnection). Start the application on a fat client and then reconnect via a mobile device and the mobile style will kick in (and vice versa).

Here’s the bit of code to take care of it (if you don’t care about the code and just want to skip to the download, just follow this link):

[DllImport("WtsApi32.dll")]
private static extern bool WTSRegisterSessionNotification(IntPtr hWnd, [MarshalAs(UnmanagedType.U4)]int dwFlags);

[DllImport("WtsApi32.dll")]
private static extern bool WTSUnRegisterSessionNotification(IntPtr hWnd);

private const int NOTIFY_FOR_THIS_SESSION = 0;
private const int WM_WTSSESSION_CHANGE = 0x2b1;
private const int WTS_REMOTE_CONNECT = 0x3;
private const int WTS_REMOTE_DISCONNECT = 0x4;
private bool registered = false;

protected override void OnHandleDestroyed(EventArgs e)
{
    // unregister the handle before it gets destroyed
    if(registered)
        WTSUnRegisterSessionNotification(this.Handle);

    base.OnHandleDestroyed(e);
}

protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);
    registered = WTSRegisterSessionNotification(Handle, NOTIFY_FOR_THIS_SESSION);
}

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_WTSSESSION_CHANGE)
    {
        if (m.WParam.ToInt32() == WTS_REMOTE_CONNECT)
        {
            // The session is in the reconnect state, so style the app for the new session
            setAppStyle();
        }

        if (m.WParam.ToInt32() == WTS_REMOTE_DISCONNECT)
        {
            // The session is in the disconnect state, so close the CMP if it is open
            if (this.cmp != null && this.cmp.IsChannelOpen())
            {
                try
                {
                    this.cmp.CloseChannel();
                }
                catch {}
            }
        }
    }
    base.WndProc(ref m);
}

Try It Out Yourself

Want to try it out yourself?  I have made the program and the source available so you can beat it up and come up with some more ideas.  You can download it here.