Tuesday, July 29, 2008

Nokia N95 MAC Address

To check the MAC address of the WLAN adapter for phones running on the S60 operating systems (for example, the Nokia N95), type the following code in the standby mode:

*#62209526#

The MAC address of some phone can also be obtained on the label under the battery.

Monday, July 28, 2008

Synchronize Timezone for Windows Mobile 5.0 devices in C# and .Net Compact Framework

Synchronize Timezone for Windows Mobile 5.0 devices in C# and .Net Compact Framework

Many forums on the web have the issue of timezone synchronization for the WM5.0 devices posted and unanswered. Changing the timezone information on a Windows Mobile 5.0 device is not as straight forward as a Windows CE 5.0 one. The latter keep all the different timezones in the device registry, while the former has the timezones in a file on its file system.

To correctly change current timezone for applications in C# running on the Windows Mobile 5.0 platform, the PInvoke calls can be used. To make life easier, I would recommend the OpenNETCF library as it already wraps the PInvoke calls and their complexity in managed classes.

In the OpenNETCF.Win32 namespace, the TimeZoneCollection class exposes the Initialize() method that loads an array of timezone structures into memory. The Initialize() method of the TimeZoneCollection class uses the PInvoke call

[DllImport("citydb")]
extern static IntPtr ClockGetTimeZoneDataByOffset(int nOffset);

to get all the different timezones available on the device.

Once all the different timezones have been loaded, it is easy to loop through the collection and pick up the appropriate timezone and then call the SetTimeZoneInformation() method found in the DateEx class within the same namespace.

However, when the TimeZoneCollection is instantiated and initialized, a native exception is thrown on the device, similar to the following:

TimeZoneCollection tzc = new TimeZoneCollection();
tzc.Initialize();





Chris Tacke mentioned about a bug in the OpenNETCF code in his blog, and to get over this exception, the PInvoke definition must be changed so that it accepts a second parameter that is a ref int (the original only has one parameter, which is incorrect). Hence, the PInvoke definition will be as follows:

[DllImport("citydb")]
extern static IntPtr ClockGetTimeZoneDataByOffset(int nOffset, ref int fix);

If you need further information or still having problems, please do not hesitate to let me know.

Last but not the least, talking about the real synchronization, my application's server tier already handled all the complexity (i.e. determining the correct time, and timezone for the device and providing the timezone bias), so I just had to set the timezone and time correctly using the provided bias.

Saturday, July 26, 2008

N95 Barcode Reader

Nokia N95 allows creation, sharing and scanning of barcodes. Yes barcodes!!!

1. Create the barcode
The barcode can be created by using different kind of generators. And there are many free online generators as well. For example, here or here. I will use the Nokia's Mobile Codes service.

The barcode below is one for this blog's url http://moiashvin-tech.blogspot.com:



These barcodes can also be used in websites, emails, or documents and at the same time protect the data from spambots.

2. Reading the barcode

Now to read the barcode, there are various readers available for the S60 mobile phones. For example, Kaywa Reader, Glass Reader, UpCode Reader and Semacode Reader, just to name a few.

Here, I will use the Nokia Barcode Reader that comes with the mobile phone by default.







Updated on 30/Jul/08:
Why is this needed? A comment posted from one of the nokia forums:

Actually this is a massive usage in Japan that is spreading across the globe. In Japan you find adverts, posters, magazines etc with them and more commonly, every businessman has one on his business card so the recipient can scan it straight into the phone!

For a real practical situation, imagine this:
You see poster for a gig you are interested in. The poster has a QR code (2D barcode), you scan it and the resulting link takes the phone browser straight to a secure site where you buy tickets!

It really does have a lot of potential. It is also useful if you want to view a web page on your phone to save typing in a long address. I have a firefox plugin which generates the barcode for the page you are on when you hover over a status bar icon. You can then scan that straight off the screen for future use on your phone!

Source: http://www.allaboutsymbian.com/

C# 3.0 Object and Collection Initializers

In this article, I will talk about Object and Collection Initializers in C# 3.0.

Object initializers let us assign values to any accessible fields or properties of an object at the time of creation without having to explicitly invoke a constructor.

When using .Net 2.0, to initialize an instance of a User, we would (1) either overload the constructors, (2) or create an instance first and assign values accordingly.

User oldUser = new User();
oldUser.UserId = "OUSR";
oldUser.UserName = "Old User";
oldUser.UserEmail = "old.user@somewhere.com";
oldUser.UserLevel = 3;


Now, with C# 3.0 and .NET 3.5, we will be able to initialize the object by creating the instance and assigning the values to the properties in a single statement. Using this new syntax, the code will look like:

User test = new User { UserId = "NUSR", UserName = "New User",
 UserEmail = "new.user@anywhere.com", UserLevel = 3};


Similarly, if we had to create a list of users in .NET 2.0, we would first create the list and then add the users one by one.

User oldUser = new User();
oldUser.UserId = "OUSR";
oldUser.UserName = "Old User";
oldUser.UserEmail = "old.user@somewhere.com";
oldUser.UserLevel = 5;
 
User newIser = new User();
newIser.UserId = "NUSR";
newIser.UserName = "New User";
newIser.UserEmail = "new.user@anywhere.com";
newIser.UserLevel = 3;
 
List<User> users = new List<User>();
users.Add(oldUser);
users.Add(newIser);


And now, with C# 3.0 and .NET 3.5, this can be achieved in just one single statement:

List<User> users = new List<User> {
    new User { UserId = "OUSR", UserName = "Old User",
        UserEmail = "old.user@somewhere.com", UserLevel = 5},
    new User { UserId = "NUSR", UserName = "New User",
        UserEmail = "new.user@anywhere.com", UserLevel = 3}
};

C# 3.0 Automatic Properties

The C# 3.0 has a very interesting feature: Automatic Properties.

So far, with C# 2.0 and Visual Studio 2005, we have enjoyed the 'Right-Click --> Refactor --> Encapsulate Field' option to automatically generate properties in the classes. And hence, as an example, a User class will look like:

    public class User
    {
        private string userId;
 
        /// <summary>
        /// Gets or sets the user id.
        /// </summary>
        /// <value>The user id.</value>
        public string UserId
        {
            get { return userId; }
            set { userId = value; }
        }
 
        private string userName;
 
        /// <summary>
        /// Gets or sets the name of the user.
        /// </summary>
        /// <value>The name of the user.</value>
        public string UserName
        {
            get { return userName; }
            set { userName = value; }
        }
 
        private string userEmail;
 
        /// <summary>
        /// Gets or sets the user email.
        /// </summary>
        /// <value>The user email.</value>
        public string UserEmail
        {
            get { return userEmail; }
            set { userEmail = value; }
        }
 
        private int userLevel;
 
        /// <summary>
        /// Gets or sets the user level.
        /// </summary>
        /// <value>The user level.</value>
        public int UserLevel
        {
            get { return userLevel; }
            set { userLevel = value; }
        }
    }


Now, with C# 3.0, the User class will look as follows:

    public class User
    {
        /// <summary>
        /// Gets or sets the user id.
        /// </summary>
        public string UserId { get; set; }
 
        /// <summary>
        /// Gets or sets the user name.
        /// </summary>
        public string UserName { get; set; }
 
        /// <summary>
        /// Gets or sets the user email.
        /// </summary>
        public string UserEmail { get; set; }
 
        /// <summary>
        /// Gets or sets the user level.
        /// </summary>
        public int UserLevel { get; set; }
    }


When the code is compiled, the compiler will automatically generate the appropriate fields when encountering the empty get and/or set blocks. However, note that these automatic properties are normally used in situations where no body is in the get or set blocks.

And, going one step further, the compiler generated code for these automatic properties is as follows:

LINQ - Restriction Operator 'where'

The .NET Framework 3.5 version extends the .NET Framework 2.0 and 3.0 versions. One of the new features is the Language-Integrated Query (LINQ) and this extends powerful query capabilities to the C# language syntax (and VB as well) in the form of standard easily-learned query patterns.

A very simple program that displays the odd digits in LINQ:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace TestLinQ
{
    class Program
    {
        static void Main(string[] args)
        {
           // declare an array of integers
           int[] digits = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 
           // find all odd digits
           var oddDigits = from n in digits where n % 2 == 1 select n;

           // display all odd digits
           foreach(var x in oddDigits)
           {
              Console.WriteLine(x);
           }
        }
    }
}
 
This is indeed my first LINQ experience ;-), more precisely with the restriction operation 'where' ...

Wednesday, July 16, 2008

Projects targeting .NET Compact Framework 1.0 require version 1.1 of the .NET Framework, which is not detected on this machine.

I tried to compile a C# solution, containing one Smartphone 2003 .NET Compact Framework 1.1 project, in Visual Studio 2005 and got the following error:

Projects targeting .NET Compact Framework 1.0 require version 1.1 of the .NET Framework, which is not detected on this machine.

This has been explained on the MSDN page here.

Apparently, the .NET Framework 1.1 was not installed on my machine. This framework can be downloaded here.

One thing worth noting is that having the .NET Framework 2.0 is not sufficient to build the .NET Framework 1.1 projects. We need to get it installed on the machine first!

Saturday, July 12, 2008

Determine if a computer is 32-bit or 64-bit Microsoft Windows XP

There are different ways to determine a computer is running a 32-bit or 64-bit Microsoft Windows operating system. In this post, I will talk only for the Windows XP Professional operating system.

Right-click My Computer --> Select Properties --> In General tab,

for a 32-bit version, the operating system will appear as "Microsoft Windows XP Professional Version " (e.g. 2002) under the System section and,

for a 64-bit version, the operating system will appear as "Microsoft Windows XP Professional x64 Edition Version ".


More information here.

Troubleshooting the Realtek HD Audio Sound Manager

Following a full format of my machine, I have re-installed the Realtek HD Audio Sound Manager. The rear speakers and front panel mic jack wasn't working for some reasons and it seems there was no easy way to fix this problem - no obvious configuration in the Sound Manager panels, the devices were working properly on the Device Manager, the installation of latest drivers doesn't change anything... and many other users having the same problem on the internet technical forums.

However, I have solved this issue months back when first installing the drivers, and I have solved it once again for a second time. So, if you having the same problem, try the following:

1. Open the Realtek HD Audio Sound Manager and click the Connector Settings option;


2. Check (or select) the Disable front panel jack detection.



And, it works!!

Sunday, July 6, 2008

Embed image in HTML message in .NET Framework

Adding an image to an email message in .NET Framework is quite simple by using the attachment features. However doing so, the receiver of the email will have to explicitly open the image (or download it first) when opening the message.

An alternative way would be to use an HTML-formatted message and embed the image in the message. In this way, as the receiver opens the message, the image will appear automatically.

How is it achieved in .NET Framework? Very simple.

1. Create an email message, setting the from address, to address and subject text accordingly.
2. Create an html body, and use the img tag to embed the image. Set the content id (cid) in the src attribute correctly.
3. Create an alternative view for the html message.
4. Create linked resource object for the image to be embedded. Set the content id.
5. Add the newly created linked resource object to the html alternative view.
6. Add the alternative view to the email message.
7. Set the IsBodyHtml property to true.


8. Send the email message using SmtpClient (not in this post).

Saturday, July 5, 2008

HelloWorld example illustrating Globalization feature in .NET Framework

In this simple example, I will illustrate globalization feature of .NET Framework via the ResourceManager and the CultureInfo classes.

Step 1: Create a console application. Under the Properties folder, there exists one resource file, namely Resources.resx.

Open the file and add a new entry:

HelloTest > Hello World. Welcome to my blog.

Step 2: Now, right click the Properties folder and add a new resource file using the Add -> Add New Item. Name it as Resources.it.resx.

Open the newly created resource file and add a new entry:

HelloTest > Ciao mondo. Benvenuto al mio blog.

Step 3: Repeat Step 2, by adding a new resource file. Name it Resources.fr.resx and add a new entry:

HelloTest > Bonjour monde. Bienvenue à mon blog.

So far,

Step 4: Instantiate the ResourceManager class. Use the GetString() method to get the correct text to be displayed based on the desired culture.

The ResourceManager picks up the correct text for the culture.

Output:

Registration and Persistance of Custom Culture in .NET Framework

Writing the previous post about Creating a Custom Culture in .NET Framework, one question came in my mind: where the information about this new custom culture is stored on the computer? what the register method does with the CultureAndRegionInfoBuilder instance? And after some research work, I have got the needed details.

Registration of Custom Culture
The registration process, when calling the Register() method, does the following:

1. An .nlp file is created. This file contains all information defined in the CultureAndRegionInfoBuilder instance.

2. Next, the .nlp file is stored in the %WINDIR%\Globalization system directory on the computer (i.e. C:\WINDOWS\Globalization\). Hence, the culture information will still be available when the computer is restarted at a later time.

Note: Since the .nlp file is stored in a system directory, to register a custom culture you must have administrative priviledges on the computer.

3. The final step is the preparation of the .NET Framework to search the %WINDIR%\Globalization system directory the next time there is a request to create a new custom culture. An InvalidOperationException will be thrown if an attempt to register a culture more than once is made.

Persistance of Custom Culture
Another interesting feature about the CultureAndRegionInfoBuilder is its ability to write an XML representation of the object to a specified file. This can be achieved using the Save() method.

// save the new culture
// for instantiation of the infoBuilder object, see previous post
infoBuilder.Save("c:/en-mu.xml");

Creating a Custom Culture in .NET Framework

Another interesting topic on cultures in .NET Framework is creating a custom culture. This is very useful if the predefined cultures in .NET Framework or the underlying windows operating system do not provide the required information.

The CultureAndRegionInfoBuilder class allows the creating of custom cultures from scratch or based on existing cultures.

For instance, if we try to create a CultureInfo object for "en-MU", an exception is thrown.

CultureInfo muCultureInfo = new CultureInfo("en-MU");



I will now create this custom "en-MU" culture by using the existing cultures.

Step 1: Add a reference to sysglobl.dll in the project. This library can be found in the Microsoft .NET folder (e.g. C:\Windows\Microsoft.NET\Framework\v2.0.50727\).

Step 2: Add the namespaces System and System.Globalization

using System;
using System.Globalization;

Step 3: Create an instance of the CultureAndRegionInfoBuilder

CultureAndRegionInfoBuilder infoBuilder
= new CultureAndRegionInfoBuilder("en-MU", CultureAndRegionModifiers.None);


The CultureAndRegionModifiers.None is used since the custom culture is a specific one. More information about the CultureAndRegionModifiers enumeration here.

Step 4: To keep the new custom culture simple, I will use a combination of the existing en-GB and fr-FR cultures. Hence, in this step, the culture and region details will be loaded in the new culture.

CultureInfo frCulture = new CultureInfo("fr-FR");
CultureInfo gbCulture = new CultureInfo("en-GB");
infoBuilder.LoadDataFromCultureInfo(frCulture);
infoBuilder.LoadDataFromRegionInfo(new RegionInfo(gbCulture.LCID));

Step 5: The new custom culture is now ready. However, additional details can be further changes to have more precise information.

For example,

infoBuilder.CultureEnglishName = "Mauritius";
infoBuilder.CurrencyEnglishName = "Mauritian Rupees";
infoBuilder.TwoLetterISORegionName = "MU";
infoBuilder.NumberFormat.CurrencySymbol = "Rs";


Step 6: Register the new custom culture on the local computer and makes the culture available to the application(s).

infoBuilder.Register();



Now, the culture "en-MU" can be successfully instantiated.

CultureInfo muCultureInfo = new CultureInfo("en-MU");



Note: To unregister the custom culture, the Unregister() method can be used.

CultureAndRegionInfoBuilder.Unregister("en-MU");

Cultures in .NET Framework

The .NET Framework provides the CultureInfo class in System.Globalization namespace that allows manipulation and retrieval of information about the cultural context in which an application is running.

First of all, it is important to elaborate on the different culture categories available. The cultures in .NET can be grouped into three categories:

1. Invariant Culture
This culture category is culture-insensitive and is used as a default culture when consistency is desired.

2. Neutral Culture
A neutral culture is associated with a language but has no relationship to countries or regions. For example, the English spoken in UK is different from that spoken in the US. English (en), French (fr) and Spanish (sp) are examples of neutral cultures. This culture category will be designated by the first two characters in the CultureInfo class of .NET. If only the two letters are specified, they will be the Neutral class.

3. Specific Culture
This category is the most precise and is represented by a neutral culture, a hyphen, and then a specific culture abbreviation. For instance, in "fr-FR", fr is the neutral culture (French) and FR represents the specific culture (France).

CultureInfo in .NET Framework
The current culture information can be obtained via the CurrentCulture property of the executing thread's CurrentThread property.

CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;









Enumerating all available cultures
To get hold of all the different cultures available, the following code can be used:

CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.AllCultures);

The GetCultures() method accept the CultureTypes enum as an input parameter.



Windows XP Regional Options
Go to Control Panel --> Regional and Language Options --> Regional Options Tab



RegionInfo in .NET Framework
CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
RegionInfo regionInfo = new RegionInfo(cultureInfo.LCID);

Wednesday, July 2, 2008

C# Form Keyboard Events - KeyPreview property

If you encounter a situation where you want your C# form to see the key events that happen on its controls, then set the Form.KeyPreview property to true.

We have been working on one of the Symbol devices, namely, WT4090 and there was the need to close the form when the user presses the ESC button. The KeyDown event is triggered correctly as long as the form is without any control, and once a control is added, the KeyDown event stopped being triggered. The solution was to set:

Form.KeyPreview = true

Remarks from MSDN
When this property is set to true, the form will receive all KeyPress, KeyDown, and KeyUp events. After the form's event handlers have completed processing the keystroke, the keystroke is then assigned to the control with focus. For example, if the KeyPreview property is set to true and the currently selected control is a TextBox, after the keystroke is handled by the event handlers of the form the TextBox control will receive the key that was pressed. To handle keyboard events only at the form level and not allow controls to receive keyboard events, set the KeyPressEventArgs.Handled property in your form's KeyPress event handler to true.

You can use this property to process most keystrokes in your application and either handle the keystroke or call the appropriate control to handle the keystroke. For example, when an application uses function keys, you might want to process the keystrokes at the form level rather than writing code for each control that might receive keystroke events.


Source: here