Shahed's blog

Sharing my thoughts and work

  Home  |   Contact  |   Syndication    |   Login
  18 Posts | 0 Stories | 102 Comments | 10 Trackbacks

News

Archives

Post Categories

Sunday, October 24, 2010 #

In my last post, I introduced TouchToolkit – a toolkit for developing touch-enabled applications. This is the first of a multi-part post where I will explain how TouchToolkit can help simplify the development process of multi-touch applications in Silverlight or WPF 4.0.

While we can use the recorded touch interactions (I will explain the recorder module in another post), its better to have a touch-enabled device (e.g. Dell XT2) or an emulator (e.g. MultiTouchVista) to test the application.

First, we need to install the Visual Studio Templates for TouchToolkit. This will add a number of project templates and item templates in Visual Studio 2010. Although we can just add the reference of A toolkit to simplify the multi-touch application development and testing complexities dlls in an existing project, the project template is a better choice for new projects.

Let’s create a sample application in WPF 4.0. To start, we choose the “TouchToolkit for Windows 7” project template. The template will create a WPF 4.0 project with a few additional things:

  • Some sample codes in MainWindow.xaml.cs that shows how to subscribe to gesture events, add visual feedbacks etc.
  • The “TouchToolkit” folder that contains framework assemblies and necessary files to extend the framework (e.g. create new gesture, return type, etc.)

TT-newproject TT-win7

We could just press F5 and see the sample code in action. However, Let’s go through some of the important sections first.

Step 1: Initialize the framework

The A toolkit to simplify the multi-touch application development and testing complexities framework supports a number of devices including Windows 7 based tablets, TUIO based devices, Microsoft Surface and so on. So, we need to inform the framework about the current input source. To do so, we need to pass the right provider. This makes rest of the framework device independent and also allows to add new providers to support additional devices.

image

Since I am using a tablet that supports Windows 7 Touch (Dell XT2), I used the Windows7TouchInputProvider. The second parameter is the root panel that contains all UI elements (sorry, we currently only support Canvas as the root container) and the third parameter is a reference to the current project assembly. This allows to extend the toolkit (e.g. new gestures, return types, visual effects) and the framework automatically search this assembly for new types.

Next, we want to get visual feedbacks when someone touches the screen. So, we we added a touch feedback. The toolkit currently provides one touch feedback (i.e. BubblesPath). However, we can easily create our own visual effect class and use them instead. Another type of visual feedback is the gesture-feedback. Like touch, we can also specify visual feedback when a gesture is detected. For example, the following screenshot shows a visual effect that highlights the area selected by a lasso gesture.

lasso.png    image

Step 2: Subscribe to gesture events

The template added a few rectangles in the main window. The following code shows how we can add the gestures (drag, zoom, pinch, rotate) to each of the rectangle using the AddEvent method in EventManager. The AddEvent method takes three parameters:

  1. the scope of the gesture (i.e. the rect UI element)
  2. the name of the gesture, and
  3. the callback method that will be invoked when the gesture is detected.

image

While the Gestures class contains the names of the gestures that are available out of the box, we can also define our own gesture and pass the name as string (e.g. “MyGesture”). I will explain the process of creating new gestures in another post. Following is the definition of the “Drag” gesture. As you can see, the return type may contain more that one objects.

drag.png

So, the event argument (e.Values) of the callback method contains the return types specified in gesture definition. The Get<>() is an extension method that helps you get the return object you want.

image

We can also get the raw touch data from the following events:

  • GestureFramework.EventManager.MultiTouchChanged: When there are multi-touch active touch points, this event will be raised once and the event argument will contain data for all active touch points.
  • GestureFramework.EventManager.SingleTouchChanged: When there are multi-touch active touch points, this event will be raised for each of the touch points and the event argument of each callback will contain data for the specific touch point.

Now that we have reviewed the code generated by the templates, lets run the application. You should be able to drag, rotate and resize the blue and green rectangles. Here is a few more examples of gestures in a Silverlight application.

I hope I was able to give you some idea on TouchToolkit. In the up coming posts, I will explain rest of the toolkit including: how to define new gestures, the touch recorder and automated test framework.

If you are interested on developing multi-touch applications using TouchToolkit, I would be happy to help you any way I can.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, October 12, 2010 #

I have been developing TouchToolkit for some time now and just released the October community technical preview (CTP) at the codeplex project website. The key features are:

  • A domain-specific language to define custom gestures (e.g. sample gestures)
  • Supports Windows 7/WPF 4.0 Touch API, Microsoft Surface, Silverlight and TUIO
  • A record/replay module to simplify multi-touch testing and simulate multi-user scenarios
  • A test framework to write unit test for testing gestures (integrated with Visual Studio Test)
  • A visual effects framework to provide consistent visual feedback for touch interactions & gestures

We can also add new primitive conditions and return types in the gesture definition language as necessary. In next few days, I will explain each of these features in detail. Here is a 3 min intro that shows how we can use TouchToolkit to build multi-touch applications in WPF or Silverlight. The Visual Studio template installer is available in the download page.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, March 05, 2008 #

Just installed the runtime and Silverlight Tools for Visual Studio 2008. You can find the necessary tools here. The beta 1 now has a good set of controls including Data Grid, cool!

To run the Silverlight 1.1 Alpha projects in Beta 1, you need to manually modify few things.


First, if you try to open the old projects in VS 2008 after installing the latest bits, you will get the following error message:

"Unable to read the project file '... .csproj'. ... The imported project "C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\Silverlight\Microsoft.Silverlight.Csharp.targets" was not found."

Just open the project file with notepad and replace the <import> node value.

Old: <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\Silverlight\Microsoft.Silverlight.Csharp.targets" />

New: <Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight\v2.0\Microsoft.Silverlight.CSharp.targets" />

Save the project file and now you can load it in Visual Studio. Now that you have the projects opened, if you expand the Reference node you will see this:

image

You need to delete agclr, system.silverlight and system.Xml.core from the reference list. Then add the new assemblies: System.Windows, System.Windows.Browser, System.Windows.Controls and System.Windows.Controls.Extended.

image 

Ok, lets do a rebuild now. Don't worry if you get a long list or errors. Here is a quick list the things you may just do find and replace:

  • There is a PointCollection class now. So if you have List<Point> then you can change it to PointCollection
  • For Keyboard events (i.e. KeyUp, KeyDown...) replace KeyboardEventArgs with KeyEventArgs
  • System.Windows.Browser.Serialization is moved, so you need to block //using System.Windows.Browser.Serialization
  • Previously, in xaml we used to write x:Class="SilverlightApplication1.Page;assembly=ClientBin/... .dll". Now we don't need to mention the assembly part. Just write x:Class="SilverlightApplication1.Page"
  • For mouse events (i.e. MouseEnter, MouseLeave...) replace the EventHandler with MouseEventHandler and for MouseLeftButtonUp/MouseLeftButtonDown change it to MouseButtonEventHandler

Now, look into the web service. Lets assume you have a service named MyService and you have added the necessary web reference. The Silverlight 1.1 Alpha would generate a MyService class and to call any method asynchronously you would probably write something like this:

void Test()
{
    MyService service = new MyService();
    AsyncCallback callback = new AsyncCallback(FooCallback);
    Core.BeginFoo(parameter, service);
}

FooCallback(IAsyncResult result)
{
    MyService service = result.AsyncState as MyService;
    service.EndSyncCommand(result);
}

In silverlight 2 beta 1, you need to do this slightly differently. It will generate a MySerciceSoapClient class. So, you may write something like this:

void Test()
{
    MyServiceSoapClient service = new MyServiceSoapClient();

    service.FooAsync();

    service.FooCompleted += new EventHandler<FooCompletedEventArgs>(service_FooCompleted);
}

void service_FooCompleted(object sender, FooCompletedEventArgs e)
{
    ...
    ...
}


In addition to the above mentioned points, you should also look into the new App.xaml.cs file where you can handle any application wide exception as well as application startup and exit codes.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, February 07, 2007 #

In this article, I will explain how you can track class activities like function calls, parameters and return values by simply inheriting one class which I named "Spy". The "Spy" class encapsulates the tracking and logging relates the complexities . This class can be used for debugging function call sequence, state change of objects & parameters on the way of nested function calls and their return steps.

How it works?

The Spy class adds small spy properties at the time of object creation with each method to intercept their activity. As your class is inherited from Spy class, all methods of your class will also be logged in the same way. Now, the question is, "How Spy class do this!". The Spy class is inherited from ContextBoundObject and has a custom attribute called AttributeSpy. Although there are some performance issues for inheriting the ContextBoundObject but it gives the cool feature - a context bound with the object. A context carries the properties and rules of the object. The cool thing is that these properties travel with the object and can be accessed by sinks. Now, The attribute AttributeSpy does the important task. It checks if spy property is already added for any particular method otherwise adds that. Before going to detail, lets see the object initialization process first. 

What happens when user creates an object?

When the user creates an instance of a new client-activated object by calling new or Activator.CreateInstance and before the thread returns to the user code, a IConstructionCallMessage is sent to the remote application. When the construction message arrives at the remote application, it is processed by a remoting activator (either the default one, or one that is specified in the Activator property) and a new object is created. The remoting application then returns a IConstructionReturnMessage to the local application. The IConstructionReturnMessage contains an instance of ObjRef, which packages information about the remote object. The remoting infrastructure converts the ObjRef instance into a proxy to the remote object, which is returned to the user code.

Now, briefly, here is the workflow for any class which inherits from Spy class:

 

The Spy class is just few lines. It has the custom attribute AttributeSpy with the name in parameter and it is inherited from ContextBoundObject.

[AttributeSpy("Spy")]
class Spy : ContextBoundObject
{
}

 

The AttributeSpy class is inherited from ContextAttribute and overrides the IsContextOK() method which checks whether our PropertySpy (I will explain it shortly) is in ContextProperties list. By returning false, another override method GetPropertiesForNewContext() is invoked, where we are adding the PropertySpy in ContextProperties list.

[AttributeUsage(AttributeTargets.Class)]
class AttributeSpy : ContextAttribute{
    private string _name = string.Empty;

    public AttributeSpy(string name)
        : base(name)
    {
        _name = name;
    }

    public override void GetPropertiesForNewContext(System.Runtime.Remoting.Activation.IConstructionCallMessage ctorMsg)
    {
        ctorMsg.ContextProperties.Add(new PropertySpy(_name));
    }

    public override bool IsContextOK(Context ctx, System.Runtime.Remoting.Activation.IConstructionCallMessage ctorMsg)
    {
        PropertySpy spy = ctx.GetProperty(_name) as PropertySpy;

        if (spy == null)
            return false;
        return true;
    }
}

The PropertySpy class implements IContextProperty and IContributeObjectSink interface. The IContributeObjectSink interface is implemented to get the GetObjectSink() method which is called during the method invocation and the parameter nextSink ( type of IMessageSink) contains the detail information of method. Here we created our own MessageSinkSpy class inheriting from IMessageSink and added to the spying code in Synchronous and Asynchronous methods for SyncProcessMessage and AsyncProcessMessage and returned it GetObjectSink(). When any method gets invoked, these methods keep the logs in a text file.

 

class MessageSinkSpy : IMessageSink
{
    ...
    ...
    IMessageCtrl IMessageSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
    {
        if (msg is IMethodCallMessage)
        {
            IMethodCallMessage callingMessage = msg as IMethodCallMessage;
            LogHelper.LogMethodCall(callingMessage);

        }

        return _nextSync.AsyncProcessMessage(msg, replySink);
    }

    IMessage IMessageSink.SyncProcessMessage(IMessage msg)
    {
        IMethodCallMessage callingMessage = msg as IMethodCallMessage;
        LogHelper.LogMethodCall(callingMessage);

        IMethodReturnMessage returnMessage = _nextSync.SyncProcessMessage(msg) as IMethodReturnMessage;
        LogHelper.LogMethodReturn(returnMessage);

        return returnMessage;
    }
    ...
    ...
}

Writing custom objects in log:

Writing simple primitive datatypes (int, char, bool...) is easy but writing custom objects in log in a meaningful way needs some extra work.

private static string GetObjectDetail(Object obj, string padding)
{
    if (obj == null)
        return "Object is NULL";

    StringBuilder objDescription = new StringBuilder();

    //Object type
    objDescription.Append(padding);
    objDescription.Append("(" + obj.GetType() + ")");

    //Object detail
    objDescription.Append(":");
    if (IsPrimptiveDataType(obj))
    {
        //int, string, bool
        objDescription.Append(" " + obj.ToString());
    }
    else if (IsArray(obj))
    {
        if (obj is Array)
            //Array[]
            foreach (object o in (Array)obj)
                GetObjectDetail(o, padding + DEFAULT_PADDING);
        else
            //IList
            foreach (object o in (IList)obj)
                GetObjectDetail(o, padding + DEFAULT_PADDING);
    }
    else
    {
        // Collect object properties
        PropertyInfo[] infos = obj.GetType().GetProperties();

        // Log object details
        foreach (PropertyInfo info in infos)
        {
            object value = info.GetValue(obj, (object[])null);
            objDescription.Append(DEFAULT_PADDING + info.Name + GetObjectDetail(value, padding + DEFAULT_PADDING));
        }

        // New line
        objDescription.Append(Environment.NewLine);
    }

    return objDescription.ToString();
}

 To keep it simple, I used regular .net class - StreamWriter. But for any large size application you should use optimized logging application like log4net or EnterpriseLibrary - Logging Application Block.

 

Source code & sample project

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, January 09, 2007 #

Recently, I faced a problem where I need to ensure that someone really clicked on a link from a browser. One possible option could be using javascript instead of a direct link. But as many of the referrer sites have already set the link in their pages, I can't ask all of them to fix in their sites. And although this can solve bot or crawler but can't block if someone programmatically hits this page.

The page link was like following:

One option is the check on server side to prevent Crawler. But this is not enough for all cases.

if( Request.Browser.Crawler )
      //do something else

So, I did a trick. Instead of directly reffereing to the actual url, first redirect to a dummy page. And the dummy page will redirect to actual url using javascript. We know that javascript will work only in browsers. Which means anyone hitting the page programmatically will get the dummy page. 

You can also generate the actual page url at runtime and managed that in Application_BeginRequest in global.ascx. Although this saves you from automated hit attacts but also creates a problem. It creates a loop if you press the "browser->back" button from your site in IE6. Because the browser will take you back to the dummy page and dummy page will send you back again. This could be resolved easily if I could have little more access in window.history object. But unfortunately, recent browsers restrict access of this object and allows only go(), back(), forward() and length property.

Now, the problem is how the dummy page will know whether it has been redirected from a referrer site or from your own site (if user clicks "browser->back" button)?

Here is the trick: add a marker in the url as bookmark.

// Check if its redirected from pageflakes
if( document.location.href.indexOf('#marker') > 0 )
{
       // User clicked the Browser.back(), redirect to referrer site
       document.location.href= document.referrer;
}
else
{
       // From referrer site, redirect to my site
       var redirectUrl = 'mypageX.aspx?<%= Request.RawUrl.Split('?')[1].Replace("'","\\'") %>';
       document.location.href="#marker"
       document.location.href= redirectUrl;
}

Fell free to comment if you have any other ideas.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, January 10, 2007 #

Few days back, I was getting HTTP 404 error in my RSS Reader for some feeds. Some of them are very popular feeds and when I checked the feed XML content, I couldn't find any problem. After doing some step by step debugging I found an interesting thing - the path provided for the DTD in <!DCOTYPE... is no longer valid.

When the XmlTextReader was trying to download the DTD from "http://my.netscape.com/publish/formats/rss-0.91.dtd" it got the exception "HTTP 404 error" and bubbled up to the top level. So, the only option available to me was to tell the XmlTextReader not to try to validate this feed with the provided DTD.

Now, The question comes, how can I tell the XmlTextReader not to validate. While searching for the solution I found a very useful class called "XmlReaderSettings" (in .Net 2.0) where you can do many useful things. but unfortunately the XmlTextReader constructor does not have any overload to pass XmlReaderSettings. You can easily use XmlReaderSettings with XmlReader.

// Create a XmlReaderSettings instance
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;
settings.IgnoreProcessingInstructions = true;
//... and any other rules you like to implement

// Then pass the settings object while creating the XmlReader
XmlReader xmlReader = XmlReader.Create(response.GetResponseStream(), settings);

Although XmlTextReader is a subclass of XmlReader but I was looking for a quick fix and didn't have enough time to change much of my code. Then I found this:

xmlReader.XmlResolver = null;

Yes, if you set XmlResover to null, the XmlTextReader will not try to validate the XML with DTD.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, December 03, 2006 #

Here is a great article explaining the realities of software development:

http://www.dcs-media.com/desdev/Detail.aspx?ArticleId=578

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, October 13, 2006 #

 

Recently, I was trying to delete a windows service. Normally it should not be necessary to manually delete a service. Uninstalling an application should remove its associated service (if any).

However, I installed some beta products and a service created by one of the applications was not removed automatically. Its very easy to remove a service from registry if you know the right path. Here is how I did that:

1. Run Regedit or Regedt32

2. Find the registry entry "HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services"

3. Look for the service there and delete it. You can look at the keys to know what files the service was using and delete them as well (if necessary).

alternatively, you can also use command prompt and delete a service using following command:

sc delete < SERVICE name>

or to create, simply type
sc create <SERVICE name>

Update: 
If you have space in the file path you need to use quotation marks ("). For example: 
sc create "MySQL" binpath= "C:\Archivos de programa\MySQL\MySQL Server 5.1\bin\mysqld.exe"

Thanks to Maya.

NOTE: You may have to reboot the system to get the list updated in service manager.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, October 06, 2006 #

Today, I heard about "Code Search" from a pod cast. Its very useful for developers, specially the advance search option.

see www.google.com/codesearch

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, October 10, 2006 #

After installing the lastest Office 2007 beta 2 technical refresh, I was getting “Document is unavailable” or virus related error message and can not open any old files.

The problem is caused by Norton AntiVirus. To resolve the problem, goto option -> miscellaneus and disable the “How to keep Microsoft Office documents protected” and you can work fine.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, August 24, 2006 #

Recently, Pageflakes released their new RSS Reader. It provides all the features of a good desktop RSS reader and with AJAX, it gives you the smoothness of regular desktop reader. The good thing of a web application is that you don't have to install it in your PC and you can use it from anywhere.

 

The reader has two view modes: Outlook View & Newspaper View. In both view mode, you can resize the panes just like any desktop application. You can also use hotkeys for navigation. At the bottom, there are a number of options for sorting, marking the articles read/unread etc.

          

The reader also has option to save articles. You can save unlimited number of articles (in beta version). Even after few months or even years, you can still keep you feeds. Pageflakes also archives old feeds for a period of time. So, if you are busy for a day and couldn't read your favorite articles, it will be saved there for you. The Forward article option allows you to share your articles with others.

 This RSS Reader is actually a part of the RSS flake. You can import your OPML or add feeds directly into the page or save as bookmark. The pre-caching feature is coming soon. With that, you can configure the reader to download feeds in background and read articles even smoother.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Monday, August 14, 2006 #

Finally I found a simple solution for the FireFox error:

"[Exception... "'Permission denied to set property XULElement.selectedIndex' when calling method: [nsIAutoCompletePopup::selectedIndex]" nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)"

This error occurs when focus() is called. I was reported in https://bugzilla.mozilla.org/show_bug.cgi?id=236791 but still no fix/patch from mozilla.
To avoid this error, you have to turn off autocomplete.

from javascript, you can do that in following way: obj.setAttribute('autocomplete','off');

Or, you can simply set autocomplete="off" in HTML.
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, July 20, 2006 #

I was getting the following error when trying to start IIS from my XP machine:

“Unexpected error 0x8ffe2740 occurred“

You can get more information in MS KB @ http://support.microsoft.com/?id=816944

Finally, I discovered that its caused by Skype. It listens to port 80 for incoming call. Now, most of the time IIS starts before Skype starts. So IIS works but if you restart IIS or try to start IIS after Skype is started then you will get this error message.

There are 2 possible solutions:

1. You can change your IIS settings to run in different port (say 81)
     For IIS 7, go to IIS Manager, select the website from the left tree view; then goto "Bindings..." from the right side "Actions" pane and edit the port number.

2. You can change your Skype settings
     Skype File-> Options -> Connection
     Uncheck Use Port 80 as an alternative for incoming connections.

Restart default website.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Saturday, July 01, 2006 #

Today, I have read a useful article which explains the performance issues for javascript execution on Opera. I think, this is also applicable for regular javascript execution on other browsers too.

http://userjs.org/help/tutorials/efficient-code

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Friday, June 23, 2006 #

Today, I found an interesting change in Visual Studio 2005 JScript debugging. In Visual Studio 2003, to dubug JScript we need to clear the Disable Script Debugging checkbox from Internet Explorer, Tools->Advance Options. But in Visual Studio 2005, we also have to add the key word "debugger" in JScript code. For more details, http://support.microsoft.com/default.aspx?scid=kb;en-us;816173&%20f=11
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati