Thursday, 9 July 2009

Form based Windows Mobile splash screen

I thing, an application is looks like more professional, if it's got splash screen. It's just an optical tuning for an application, but marketing is very important in the mobile programming. So, I show you, how can you create a form based splash screen create.

First of all, you can create two forms. One, to your main application, and one, to your splash screen. The main form's properties are your business, do what you want to your app. But your slash screen has a very important property. Set the WindowState property Maximized. Take another important step, and delete the MainMenu control. Now you get a clear form without header and menu. This is the base of your splash screen. Take a picture, label, progress bar, little animation, or other design thing into your splash form, but never take buttons, textboxes, or other user interaction needed controls.

Next, set your shiny splash. Open your main form class, and create a private splash form member. Create a new instance in the main form's constructor, and show it:

private
Splash _splashScreen;


 


public MainForm()

{

_splashScreen = new
Splash();

_splashScreen.Owner = this;

_splashScreen.Show();


Application.DoEvents();


 

InitializeComponent();


this.Enabled = false;

}


 

When you start your application, your splash screen is shown, but never close. Next step, close your splash screen, when your main form finished the initialization. Open the main form's load event handler, and write the splash screen closer commands into the end of the block:

private
void MainForm_Load(object sender, EventArgs e)

{

// other code end


this.Enabled = true;


this.Visible = true;

_splashScreen.Close();

}


 

Now you've got a nice splash screen, it's not a big magic, just a little trick, but your application looks like more professional.

Monday, 6 July 2009

Own designed button in Windows Mobile

I hate Windows mobile standard user controls design. If you would like to create a nice application you can't do it with these controls. The worst control is the button, for the point of design. I think, if you would like to make a shiny design, first of all you need a good background and some good buttons. Other controls are not so important. The background is just an image box, everybody can take is to a form. What about with the buttons. Now I show you, how I can create designable buttons. Look at it!

First of all, Create a UserControl, for example BaseButton, or OwnDesignableButton. Then next add a PictureBox and set the next properties. Dock = Fill, SizeMode = StrechImage. These properties sets can take resizable to your button. After you need two pictures. Once for the button image. And once for the pushed button image. Create two picture properties:

private
Image _unpushedImage;


 


public
Image UnpushedImage

{


get { return _unpushedImage; }


set { _unpushedImage = value; }

}


 


private
Image _pushedImage;


 


public
Image PushedImage

{


get { return _pushedImage; }


set { _pushedImage = value; }

}


 

When you take add somewhere to your new ButtonControl, you can find two properties into the property list. A PushedImage, and an UnpushedImage. Next modify the setter of UnpushedImage, and set the _unpushedImage into the image of PictureBox:

set

{

_unpushedImage = value;


if (_unpushedImage != null)

{

ButtonImage.Image = _unpushedImage;

}

}


 

Now, when we are set the UnpushedImage properties, we can find, the controls image can sets. Next Catch two events one the ButtonImage.MouseUp and one the ButtonImage.MouseDown and create the change of image.


 

private
void ButtonImage_MouseUp(object sender, MouseEventArgs e)

{


if(_unpushedImage != null)

ButtonImage.Image = _unpushedImage;

}


 


private
void ButtonImage_MouseDown(object sender, MouseEventArgs e)

{


if (_pushedImage != null)

ButtonImage.Image = _pushedImage;

}


 

Now you have a Control, which looks like a button. Next you can create an event, which rise when somebody push your button. Than the event is created, Invoke this event into the ButtonImage.MouseUp event handler.

public
event
MouseEventHandler ButtonClick;


 


private
void ButtonImage_MouseUp(object sender, MouseEventArgs e)

{


if(_unpushedImage != null)

ButtonImage.Image = _unpushedImage;


 


if(ButtonClick != null)

ButtonClick.Invoke(sender, e);

}


 

If you would like a really nice button, you could make the got focus event, when you show another image like selected control image.

Now you need a cool designer, how create some cool button picture to you.

Friday, 3 July 2009

AppConfig style xml based configuration in Windows Mobile

My first surprise when I start to learn Windows Mobile programming was the lack of Application configuration. So, I would like to show a solution to this problem.

First of all, you can create a new Windows mobile Class library. Then add a new xml file into library. Set the xml file Copy to Output Directory property Copy always.

Rename the Class1.cs for example Configuration.cs. Now you've got a class library with an empty xml file and a public class file which is also empty.

Next step to write the application configuration like xml file. Use configuration and appSettings tags, like appConfig. Look at my example below:

<?xml
version="1.0"
encoding="utf-8" ?>

<configuration>

<appSettings>


 

...


 

<add
key="url"
value="http://test.test:8080/example" />


 

...


 

</appSettings>

</configuration>


 

Next step to write the configuration class, which will be use the xml. Firs I use singleton pattern, to guarantee only one config of application.


public
class
Configuration

{

#region singleton


 


static
Configuration instance = null;


static
readonly
object padlock = new
object();


 

Configuration()

{

InitConfiguration();

}


 


public
static
Configuration Instance

{


get

{


lock (padlock)

{


if (instance == null)

{

instance = new
Configuration();

}


return instance;

}

}

}


 

#endregion


 

#region Constructor


///
<summary>


/// I use this init function to separate


/// singleton logic and constuctor logic


///
</summary>


private
void InitConfiguration()

{


 

}


 

#endregion

}


 

After this we need a NameValueCollection, which is hold setting into the memory. Some public property, which is good to read and write settings and a Load and Save method, which is load settings information from xml tom memory and save back, if we change something.

So these are the private fields, on for NameValuePair and one for the path of xml file:

#region private fields


 


private
NameValueCollection _settings;


private
string _settingsPath;


 

#endregion


 

These are the properties which are gets or sets information from the NameValuePair:

#region config fields


 


public
string ServerUri

{


get { return _settings.Get("url"); }


set { _settings.Set("url", value); }

}


 

#endregion


 

These are the operations which are creating date transfer between memory and xml file:

#region operators


 


///
<summary>


/// Gets settings fields from xml file


///
</summary>


public
static
void Load()

{


// Get the path of the settings file.

_settingsPath = Path.GetDirectoryName(

System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase);

_settingsPath += @"\Settings.xml";


 


if (!File.Exists(_settingsPath))


throw
new FileNotFoundException(

_settingsPath + " could not be found.");


 

System.Xml.XmlDocument xdoc = new XmlDocument();

xdoc.Load(_settingsPath);

XmlElement root = xdoc.DocumentElement;

System.Xml.XmlNodeList nodeList = root.ChildNodes.Item(0).ChildNodes;


 


// Add settings to the NameValueCollection.

_settings = new
NameValueCollection();

_settings.Add("url", nodeList.Item(4).Attributes["value"].Value);

}


 


///
<summary>


/// Save modified settings fields to xml file


///
</summary>


public
static
void Save()

{

XmlTextWriter tw = new XmlTextWriter(_settingsPath,

System.Text.UTF8Encoding.UTF8);

tw.WriteStartDocument();

tw.WriteStartElement("configuration");

tw.WriteStartElement("appSettings");


 


for (int i = 0; i < _settings.Count; ++i)

{

tw.WriteStartElement("add");

tw.WriteStartAttribute("key", string.Empty);

tw.WriteRaw(_settings.GetKey(i));

tw.WriteEndAttribute();


 

tw.WriteStartAttribute("value", string.Empty);

tw.WriteRaw(_settings.Get(i));

tw.WriteEndAttribute();

tw.WriteEndElement();

}


 

tw.WriteEndElement();

tw.WriteEndElement();


 

tw.Close();

}


 

#endregion


 

Don't forget, xml file is a string file, if you would like to hold another type value, for example integer, you always need type validation and explicit conversation.

It's more comfortable, if you call load method into the constructor, and call Save method into all of property setter:

#region Constructor


///
<summary>


/// I use this init function to separate


/// singleton logic and constuctor logic


///
</summary>


private
void InitConfiguration()

{

Load();

}


 

#endregion


 

#region config fields


 


public
string ServerUri

{


get { return _settings.Get("url"); }


set

{

_settings.Set("url", value);

Save();

}

}


 

#endregion


 

This solution is takes to me very comfortable to programming Windows Mobile. I hope you enjoy it, and it was useful to you!

This solution is not full of my work, some part of this solution I find on the net forums, and other blogs long time before.

Wednesday, 1 July 2009

Windows Mobile user friendly exception handler

When I got an unhandled exception into my own application, I always think, what a terrible window is this. If you are thinking the same, this solution is helps to make the unhandled exception is a little bit nicer.
If you would like to catch all of unhandled exceptions, you must sign in the AppDomain.CurrentDomain.UnhandledException event.


AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);


private static void OnUnhandledException(Object sender,
UnhandledExceptionEventArgs e)
{
//Implement universal exception handling
}


The best way if you do this on the main entry point of your application on the Program.cs file, before you run your main form.


[MTAThread]
static void Main()
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(OnUnhandledException);

Application.Run(new MainForm());
}


On the event handler, first of all you must find the exception. This is on the event argument. After find the exception, you can run another form, which is shows a user friendly picture, or message to the exception.


private static void OnUnhandledException(Object sender,
UnhandledExceptionEventArgs e)
{
Exception ex = e.ExceptionObject as Exception;
if (ex != null)
{
Application.Run(new ExceptionHandler(ex, e.IsTerminating));
}
finally
{

}

}
}


My Exception handler form is a very simple form, I just create an overloadaed constructor, when I get the exception, and write exception message like a text message.


public partial class ExceptionHandler : Form
{
public ExceptionHandler(Exception ex)
{
InitializeComponent();
lblExceptionMessage.Text = ex.Message;
}

public ExceptionHandler()
{
InitializeComponent();
lblExceptionMessage.Text = String.Empty;
}
}


The other thing, what I usually do, when I catch an unhandled exception, I create a little logger, and take a log message to my log file. I implement this solution at the same place, on the OnUnhandledException event handler.


if (ex != null)
{
FileStream fs = new FileStream("MyTrafficError.log", FileMode.Append,
FileAccess.Write, FileShare.None, 1000, false);
StreamWriter sw = new StreamWriter(fs);
try
{
sw.WriteLine("DateStamp: " + DateTime.Now.ToString());
sw.WriteLine("ToString(): " + ex.ToString());
sw.WriteLine("Message: " + ex.Message);
sw.WriteLine("StackTrace: " + ex.StackTrace);

sw.WriteLine("THE END");
sw.Flush();
Application.Run(new ExceptionHandler(ex, e.IsTerminating));
}
finally
{
if (sw != null)
{
fs.Close();
sw.Close();
}
}


This is a good way, to find bugs, when other people tests to your application. When they finished the test, just need to see the log, and you could seen, if something does’nt work perfect.

Tuesday, 30 June 2009

Double Buffering in Windows Mobile

When you draw a custom image, or control, and you would like to resize or move that, you can find,the graphical object is flickering. You can stop this flickering, if you use double buffer technic.
Double buffer works with two layer. The front layer, what you see int he screen, the background layer, is, whar you paint. If the paint method is finish, you just change the background and front layers.
The .NET windows forms control has a built-in double buffering. The Control base class has a SetStyle method. You can set here the double buffer layering.


public partial class DoubleLayerBuffering : UserControl
{
public DoubleLayerBuffering()
{
InitializeComponent();

//Set double buffering in the constructor
SetStyle(ControlStyles.AllPaintingInWmPaint
ControlStyles.OptimizedDoubleBuffer, true);
}

private void DoubleLayerBuffering_Paint(object sender,
PaintEventArgs e)
{
//You can do coustom painting, if use e.Graphics.
//For example:
e.Graphics.DrawRectangle(new SolidBrush(Color.Black),
new Rectangle(10, 10, 20, 20));
}
}


To use double buffering .NET Framework is very simple, and clear, you cant do anything, just set the control style int the constructor.
In .NET Compact Framework you cant find SetStyle method. You must write your own double buffering algorithm. The next example shown, how to do that.


private void Form1_Paint(object sender, PaintEventArgs e)
{
Bitmap doubleBuffer = new Bitmap(Width, Height);
Graphics graphics = Graphics.FromImage(doubleBuffer);

DrawMyCustomControl(graphics);

e.Graphics.DrawImage(doubleBuffer, 0, 0);
}

private void DrawMyCustomControl(Graphics graphics)
{
//You can do coustom painting, if use graphics.
//For example:
graphics.DrawRectangle(new SolidBrush(Color.Black),
new Rectangle(10, 10, 20, 20));

}


The double layer buffeing is not a big magic, but if you use, you get a nicer applications, smooth moveing, and not flickering.

updating:

So, I try to use double layer buffering, and I fing, something is not ok. When my control is refreshing, I find a short white flickering.
If you override OnPaintBackground this flickering is stop.


protected override void OnPaintBackground(PaintEventArgs e)
{
//Do nothing!
}


So, if you want a totaly smooth and flickerless application, first of all override OnPaintBackground, where do nothing. After override OnPaint, and use double layer buffering. On the OnPaint first paint the background, then paint the forground.

updating 2:

I find, my Double layer buffering application tip has a memory leak. After draw backgound layer, you must dispose tihis. The correct solution is:


private void Form1_Paint(object sender, PaintEventArgs e)
{
Bitmap doubleBuffer = new Bitmap(Width, Height);
Graphics graphics = Graphics.FromImage(doubleBuffer);

DrawMyCustomControl(graphics);

e.Graphics.DrawImage(doubleBuffer, 0, 0);

doubleBuffer.Dispose();
graphics.Dispose();
}

Monday, 29 June 2009

And the blog is starting

Hi everyone,



I would like to see you the issues and solutions, what I find into my job. I hope you find some help to your problems.



Tamas Maksa