Wednesday, December 21, 2005

C# - Resources – Text-Based Typed Resources

.Net supports two types of extended set of resources that includes Multipurpose Internet Mail Extensions (MIME) type information: Text and Binary.

ResX is a .Net specific XML format file for Text-Based Typed Resources. Following is a sample of this file:
<root>
  <xsd:schema id="root" xmlns=""
      xmlns:xsd=http://www.w3.org/2001/XMLSchema
      xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="ResMimeType">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="Version">
    <value>1.0.0.0</value>
  </resheader>
  <resheader name="Reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, 
        Version=1.0.5000.0, Culture=neutral,
        PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="Writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms,
        Version=1.0.5000.0, Culture=neutral, 
        PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <data name="FormCaption">
    <value>Sample Text-Based Resources</value>
  </data>
  <data name="ButtonCaption">
    <value>OK</value>
  </data> 
</root>
The above file can be created manually, but it’s advisable to create it by using Visual Studio, as .resx file is not meant to be read or edited by humans. To add a new .resx file in Visual Studio, select Add New Item from the project menu and choose the Assembly Resource File template. Visual Studio also provide an editor for .resx file.

Most of the codes shown above are schema information. Only the section shown below is for the resources data:
…
<data name="FormCaption">
  <value>Sample Text-Based Resources</value>
</data>
<data name="ButtonCaption">
  <value>OK</value>
</data>
…
Above codes added two entries for the Form Caption and the Button Caption, and both are string entries. If image is require to be added to the .resx resources, the Base64 data encoding will be required. Following is an example for adding an image to the resx file:
<data name="FormBackgroundImage" type="System.Drawing.Bitmap, System.Drawing,
    Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    mimetype="application/x-microsoft.net.object.bytearray.base64">
    <value>
        R0lGODlh5gBlAPYAAAAAAP////7r7P7r7f/q7f3n6/fr7f7o7fzo7fvg6Pvk7fzj7fjT4/nf6vng7fTl
        7ffg7fTZ6vfW7fTY7e/n7fjD7fTO7fHZ7fHN7e/B7e3T7em67enO7ebH7dmo5uCz7dmd7eLB7ePL7c6L
        7du27c6Y7c6i6dav7erl7d3E7eXa7caW7c6l7b2E7cGM7dCw7bN37bd/7cGV7Na97adn7a1w7bmJ7cej
        7cem6MKf7KBh7biU7JRb7byc7KuE6sax7aqN662W7e7uqfLtwffq0fzt4/vp3/3u6P7u6//u7P/u7f7u
        7f3u7fvt7fnt7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAA5gBlAAAH/4BKgoOEhYaHiImK
        SkwICwcLEAYGDhAQlQ4OEpmbEhYWnhYTn58SphKWmQhNTK1Li0xNTU5OBpYTExgYGhkbvh8fIMLCIyUj
        x8gjHw+ICQmL0ItGQtTVQkQJFzc3KSka3d0zKTMlNzMyMzMn6uwzNzYz0fLz8giQCwqW+qmn/aGkGEgJ
        NHXJgQIErVgteYUoFi1bD3Bd2JWhg68NwIaBKMYxmTJmh5zRo4eEiLVq2MSt4OZNhAhw43KYW5Fu3Yl1
        L9zBG8mzp6ABB4IuqEQpFadOmjz9E1jqVCYHCxAsccUQ0dRZtW5NmJih669gwzga8wjiQjMGPhcdGXLy
        WoINN/9Y/JD5koMKly7HrfjxIkeKnOpy5uzhIl7aw9AIEAiKIJ8DW0+TakpaipTSTxNMRUYgtRUTaEuw
        OnkAIeIuDBx6fSUGYqzHESAoICqAFrGhaW2JFBBx4gWOGzJuiJjBQUTxvCn2vmARmB1gGT0M255eSLFQ
        BZRsXfKnWUIFpuCdZlJwYCrVRAkfap3I62LGsB1fX6hKiDb1QSZzJ9CgQcXfdy+8hJcKx6UgwwsI/jWD
        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
        ENobGUGQrVOJjBQIADs=
    </value>
  </data>
Once the .resx file is created, the application can load it and enumerate it using the ResXResourceReader class from System.Resources namespace:
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Resources;
using System.Collections;

namespace TextResourcesApplication {
 public class TextResourcesForm: Form {
  
  // Constructor
  public TextResourcesForm() {
   this.SuspendLayout();

   // Load the resources from the resource file TextResources.resx
   using (ResXResourceReader reader = new ResXResourceReader(@"TextResources.resx")) {
    // Enumerate with a Dictionary object
    foreach (DictionaryEntry entry in reader) {
     string temp = string.Format("
      Name: {0}, // Resource Name (name attribute)
      Value: {1}, // Resoutce Value (value attribute) 
      Type: {2}", // Resource Type (type attribute)
      entry.Key, 
      entry.Value, 
      entry.Value.GetType());
     MessageBox.Show(temp);
    }
   }

   this.ResumeLayout(false);
  }

  public static void Main() {
   Application.Run(new TextResourcesForm());
  }
 }
}
The above codes will loop through each entry in the resources file, and display the entry name, value and type with a message box. The ResXResourceReader class will parse the XML file (.resx file) and return a set of names, typed values, and the value types. The limitation of ResXResourceReader is unable to provides random access to the resources, so in order to access a particular entry, the system have to loop through all the resources and find the matching entry:
…
using (ResXResourceReader reader = new ResXResourceReader(@"TextResources.resx")) {
foreach (DictionaryEntry entry in reader) {
 // if entry is FormCaption, retrieve it's value and cast to string
  if (entry.Key.ToString() == "FormCaption") {
   this.Text = (string) entry.Value;
  }
  // if entry is FormBackgroundImage, retrieve it's value and cast to Bitmap
  if (entry.Key.ToString() == "FormBackgroundImage") {
   this.BackgroundImage = (Bitmap) entry.Value;
  }
 }
}
…
The type information for the resources is embedded along with the data itself, so retrieving the resources just requiring a simple cast to get the typed values of the data. Below is a sample form generated from above codes:

Tuesday, November 15, 2005

C# - Resources – Manifest Resources

Image can be loaded into the application from the file system, for example:
 // Load image from a file path
 Bitmap image = new Bitmap(@"c:\ufo.gif");
But the problem with this method is the application cannot guarantee the file it's looking for will be there. The reasons could be the user removed or moved the file to other location. If the image file the application expecting does not exists, it will cause the application not functioning properly.

The only safe way to make sure that the image, or any file, stays with code is to embed it and load it as a resource, a named piece of data embedded in the assembly itself.

Following command line shows how to embed a file into the assembly:
 csc [source file name.cs] /resource:[resource file name]

 csc ufo.cs /resource:UFOApplication.ufo.gif
The image file will embedded in the assembly’s set of manifest resources. The manifest of an assembly is composed of a set of metadata that’s part of the assembly. Part of that metadata is the name and data associated with each embedded resource.

Following codes shows how to retrieve resources from the assembly manifest:
using System;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using System.Reflection;

namespace UFOApplication {
 public class Form1: Form {

  private Assembly assembly;
  private Bitmap image;

  // Constructor
  public Form1() {

   // Get current object type's assembly.
   this.assembly = this.GetType().Assembly;

   // Load the image binary stream from the assembly manifest.
   // Stream stream = this.assembly.GetManifestResourceStream("UFOApplication.ufo.gif");
   Stream stream = this.assembly.GetManifestResourceStream(this.GetType(), "ufo.gif");

   // Construct the bitmap from stream.
   this.image = new Bitmap(stream);  

   this.Paint += new PaintEventHandler(Form1_Paint);
  }

  private void Form1_Paint(object sender, PaintEventArgs e) {
   // Draw the bitmap on the form.
   e.Graphics.DrawImage(this.image, 0, 0); 
  }

  // The main entry point for the application.
  public static void Main() {
   Application.Run(new Form1());
  }
 }
}
Although manifest resources are useful, but there are some limitations. For example, manifest resources are embedded with no type information. So there will be no difference to the Bitmap class for ufo.gif, ufo.jpg, or ufo.xyz, which looking for data itself for the type like JPEG, PNG, GIF and etc.

The proper type of object will be needed to load the relevant type of each resource.

Monday, November 14, 2005

C# - Graphics – Double Buffering

The codes below is to load a gif image from the local path and draw it on the form, and the image will “animated” by moving 1 step down and right at certain interval. The image must exist in the same path as the application executable. This program has a timer component that executes the codes to increase the X and Y values (for the image), and refresh the screen by calling the form’s Invalidate method. Invalidate will trigger the form’s Paint Event to redraw the form’s client area. The Paint Event will draw the image on the form’s client area with the newly updated X and Y values (the horizontal point, X-axis, and the vertical point, Y-axis).
using System;
using System.Windows.Forms;
using System.Drawing;

public class Form1: Form {
 private Timer timer1;
 private Image imgUFO;

 private int x = 0;
 private int y = 0;

 // Constructor
 public Form1() {
  this.SuspendLayout();

  // Load UFO bitmap from the same path as the running application.
  this.imgUFO = new Bitmap(@"ufo.gif");

  // Setting up the Timer control.
  this.timer1 = new Timer();
  this.timer1.Interval = 50;
  this.timer1.Enabled = true;
  this.timer1.Tick += new EventHandler(timer1_Tick);

  // Setting up Form control.
  this.Text = "UFO Program";
  this.BackColor = Color.White;
  this.Paint += new PaintEventHandler(Form1_Paint);

  this.ResumeLayout(false);
 }

 private void timer1_Tick(object sender, EventArgs e) {
  // Update image position
  newPositions();

  // Refresh screen
  Invalidate();
 }

 private void Form1_Paint(object sender, PaintEventArgs e) {
  // Draw bitmap on the form.
  Graphics g = e.Graphics;
  g.DrawImage(this.imgUFO, this.x, this.y); 
 }

 private void newPositions() {
  // Move Right & Down for 1 step.
  this.x += 1;
  this.y += 1;
 }

 // The main entry point for the application.
 public static void Main() {
  Application.Run(new Form1());
 }
}
The program seems to work perfectly. But when notice carefully, the image draw on screen will look a bit flickering. The image flashes on and off most unpleasantly. This is due to the way that the screen is drawn. When the Paint Event redraws the form, the screen is drawn with white, and then the image is drawn separately. This process is very visible and looks terrible.

This problem can be solved by a technique known as double buffering. The idea is that the program doesn't draw on the frame the user can see. Instead, it draws on a buffer in memory. Then, when the picture is complete, it is copied into the visible screen. The copy process is very quick, and the flicker is removed.

The following codes create another bitmap area, draw onto that, and then copy the new bitmap into position:
using System;
using System.Windows.Forms;
using System.Drawing;

public class Form1: Form {
 private Timer timer1;
 private Image imgUFO;

 private int x = 0;
 private int y = 0;

 // Constructor
 public Form1() {
  this.SuspendLayout();

  // Load UFO bitmap from the same path as the running application.
  this.imgUFO = new Bitmap(@"ufo.gif");

  // Setting up the Timer control.
  this.timer1 = new Timer();
  this.timer1.Interval = 50;
  this.timer1.Enabled = true;
  this.timer1.Tick += new EventHandler(timer1_Tick);

  // Setting up Form control.
  this.Text = "UFO Program";
  this.BackColor = Color.White;
  this.Paint += new PaintEventHandler(Form1_Paint);

  this.ResumeLayout(false);
 }

 private void timer1_Tick(object sender, EventArgs e) {
  // Update image position
  newPositions();

  // Refresh screen
  Invalidate();
 }

 // This is a very important method overriding for double buffering.
 // By overriding this method, it will disable the background painting.
 protected override void OnPaintBackground(PaintEventArgs e) {
 }

 private void Form1_Paint(object sender, PaintEventArgs e) {
  // Temporary bitmap to hold the backbuffer image
  Bitmap backBuffer = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);

  using (Graphics g = Graphics.FromImage(backBuffer)) {
   g.Clear(Color.White);
   g.DrawImage(this.imgUFO, this.x, this.y);
  }

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

 private void newPositions() {
  // Move Right & Down for 1 step.
  this.x += 1;
  this.y += 1;
 }

 // The main entry point for the application.
 public static void Main() {
  Application.Run(new Form1());
 }
}

Saturday, October 01, 2005

Poser - Dynamic Clothing – Getting Started

Dynamic clothing simulation enables cloth drapes naturally on the figure. This guide provides the basic steps setting up the Poser Cloth Room for dynamic clothing.

1) Create a new scene. Load the figure into the scene, if required set to Zero Figure. (In this example V3 is loaded).


2) Open Props Library, and load the dynamic cloth. (In this example, dynamic empire waist dress from Stegy is loaded). Set the parent object of the dynamic cloth to the figure's hip.

3) Move Animation Control slider to the last frame (by default, last frame should be frame 30).

4) Pose the figure. (Unlike conforming clothes, the dynamic clothes will not pose according to the figure).

5) Move the Animation Control slider back to the first frame, and switch to Cloth Room.

6) Click the New Simulation button.

7) The Simulation Setting dialog will appear. Set the Drape frames to 10. This will add 10 frames to the simulation before it move the figure, and will make the final result look more realistic.

8) Click the Clothify button, and select the dynamic cloth from the drop down.

9) Click on Collide Against button, the Cloth Collision Objects dialog will appear. Click the Add/Remove button to add objects.

10) Select the figure. A point to note, the more selected parts, and the longer calculation time will be required. If the cloth touches only certain parts of the body, select those parts will be enough.

11) Final step. Click the Calculate Simulation to start calculation. This will take quite some time depending on the settings.

12) The result.

Friday, September 16, 2005

So, this is the begining?

Hi, I am a very forgetful person. I always forgot what I have learned. So, I decided to document whatever I learn in this blog, in a summarized format, and with my poor English. In case one day, I want to recall some tips, techniques, or whatever, I can come back to this place and hopefully I can find what I am looking for.