Monday, April 29, 2013

Visual C# Lesson 3: Using ListBoxes, arrays, and the string.Split( ) method

Introduction


In this tutorial, I'll go over another user interface ListBox control, which allows us to display items in a scrollable or drop-down style list.  We will also see how to split a string into separate strings that are stored in a string array, using the Split( ) method.

The ListBox and TextBox Controls

For this project, you should do the following:
  1. Create a new Windows Forms Application named Lesson3
  2. Resize the form so it is a little bit wider
  3. Place the following controls onto the form:
  • ListBox
  • TextBox
  • Button
ListBox
For this control, do the following:
  • Change the (Name) property to lstNameBox
  • Resize the height of listbox to make it a little bit taller than the default
TextBox
For the textbox, do the following:
  • Change the (Name) property to txtInput
  • Resize the width of the textbox so it is about as long as the form

Button
  • Change the (Name) property to btnPerformAction
  • Change the Text property to Perform Action
  • Make the button longer so it can accomodate the text

Programming the Event Handler

Again, we're going to make use of an event handler, which will respond to the button's Click event.  In the Design View, double click the btnPerformAction button to generate the event handler, and show you the Code View.

I'll show you the code, and then we'll discuss it.  Try to see if you can understand what's going on.  Pay close attention to the array declaration and the use of the for loop.


       private void btnPerformAction_Click(object sender, EventArgs e)
        {
            string[] nameArray;

            nameArray = txtInput.Text.Split();

            for (int i = 0; i < nameArray.Length; i++)
            {
                lstNameBox.Items.Add(nameArray[i]);
            }//end for
        }

First, look at the array declaration.  Notice that it is slightly different than an array declaration in a language like C++.  You put the brackets, [ ], after the data type instead of after the identifier.

Below that, we use the string class's Split( ) method on the txtInput's Text property, which, by default splits the large text string into individual strings, delimited by spaces.

The for loop is very interesting.  In C#, arrays are classes and have properties.  The Length property is extremely useful, because it tells us how many items are in the array.

Inside the for loop, we access the lstNameBox's Items property, which is a collection, an array-like structure that can hold items in its own right.  Item-by-item, we call the Add(  ) method of the Items property, to add these individual items to the list box.

Running the Program - Round 1

To use this program, simply type a list of names, separated by spaces, in the textbox.  Then, click the Perform Action button.  Watch the magic.

 

It is pretty straightforward, but there is what could be considered a simple bug.  Click the button more than once and observe what happens.  It adds the list multiple times.

Fixing the Multiple Listing Bug and Running the Program - Round 2


So, how do we remedy this so that only what is in the textbox is split and displayed once?  We use the Clear( ) method of the listbox's Items collection each time before we enter the for loop.  Let's see our new code.


    private void btnPerformAction_Click(object sender, EventArgs e)
        {
            string[] nameArray;

            nameArray = txtInput.Text.Split();

            lstNameBox.Items.Clear();
            for (int i = 0; i < nameArray.Length; i++)
            {
                lstNameBox.Items.Add(nameArray[i]);
            }//end for
        }

Run the program again and try clicking the button multiple times.

This solves the problem.  One simple line of code.  We tell the listbox's Items property to empty itself before we go into the loop to add the items from the text box.

Summary

In this tutorial, we got our feet wet with yet another Windows Forms control.  This time, the ListBox.  We learned how to add elements to the listbox's Items property, which is a member of the ListBox class, and is an object collection.  Clearing the list was a piece of cake, with only one line of code being necessary.

We also learned about arrays - how to declare the array, and then assign it to another array.  In this case, the Split( ) method of the string class returned an array for us.

Visual C# Lesson 2: Labels and TextBoxes

Introduction

In this tutorial, we will explore adding and interacting with labels and textboxes in Visual Studio 2012. 

I assume you know how to create a Windows Forms Application, as described in Visual C# Lesson 1.


Adding a Button, a Label and a TextBox

A label is a user interface control that is typically used for displaying information.  This information could be static information - like a basic "signpost" telling the user "hey, here is where you enter your name:", or it can be used to output information to the user in a more complex fashion.

A textbox is a control that is typically used to obtain user input.  The user types something in it, then sometime later, your program makes use of this input.

Before we proceed, let's add the two user interface controls. 

  1. Create a new Windows Forms Application in C# and name it Lesson2
  2. Drag a Label control from the Toolbox onto the form
  3. Drag a TextBox control onto the form
  4. Move the textbox so it is near the top of the form, and make it a little wider using the sizing handles
  5. Move the label so it's a little bit under the textbox
  6. Add a Button onto the form and put it near the bottom of the label and textbox
It should look something like the following when you're done with the above steps:


 

Now we need to modify the properties in the Properties window.  For each of the controls, make the following modifications:

The label1 label
  • Change the (Name) property to lblOutput
  • Remove the text in the Text property entirely
Don't be afraid that you can't "grab" the label easily on the form in Design View anymore.  It's actually very easy to select it again.  You just go to the drop-down above the Properties window and select the control you want.


The textBox1 textbox
  • Change the (Name) property to txtInput
Since textboxes do not contain text by default, you don't have to modify the Text property

The button1 button
  • Change the (Name) property to btnExecute
  • Change the Text property to Click Me!

Generating the Event Handler

Just like we did in Lesson 1, double click the btnExecute button to generate the event handler.  You are now in the Code view.  Inside the event handler, you will add statements to simply set the lblOutput label's Text property equal to the Text property of txtInput.

Let's look at the code I've added:


       private void btnExecute_Click(object sender, EventArgs e)
        {
            lblOutput.Text = txtInput.Text;
        }

This code is fairly straightforward.  I'm saying, "When the user clicks the button btnExecute, set the lblOutput's Text property equal to the Text property of the txtInput text box."

So, all three of our controls are playing a part in this.  The button is used as the "signaller" to the program to say "do this...".  The label lblOutput has its Text property changed to whatever text string is in the txtInput text box's Text property.

Observing the Output


Build and run the application and then put your name in the text box, and click the button.  The label will echo the text in the text box.  You can keep modifying the text in the text box and clicking the button and it will update the label's text.

 
 

Summary

 

This very simply application gives us insight into the inner-workings of a Windows Forms application.  Specifically, we looked at how we can use labels, textboxes, and buttons to interact with the user.  If you're coming from a programming language where you wrote Console applications, then you're used to writing code and having it execute in a realitvely sequential manner (with slight variations due to our selection and repetition control structures like if-statements and while-loops.)

This paradigm of programming we're using is called event-driven programming.  Event-driven programs respond to, well, events!  An event can be a number of different things - clicking a button, typing in a text box, the selected item in a drop-down menu (ListBox).  The sky is the limit.  We will explore more as I write more tutorials.



Visual C# Lesson 1: Introduction to Windows Forms Applications in Visual Studio 2012

Introduction

In this tutorial, I will be showing you how to create a basic Windows Forms application using C# in Visual Studio 2012.  If you have an earlier version of Visual Studio, or a different edition, don't worry.  Many of the steps are very similar and some are even identical.

Creating a New Windows Forms Application


Before we get started, a couple basic concepts if you're new to Visual Studio:
  • A project is a collection of source code files and resources (configuration files, images, etc.)
  • A solution is a collection of one or more projects.
Thus, a project lives inside a solution, and source code and resources live inside a project.  Simple enough for now?  Ok let's get going.


To create a new Windows Forms application:

  1. Open up Visual Studio
  2. Click on File
  3. Hover over New
  4. Click Project
 

When the New Project window is displayed, you should make sure you are under C# as the language.  Then, you should do the following:

  1. Verify you have Windows Forms Application selected
  2. Change the name of the project to something meaningful
  3. [optional]  Select the Browse button and move the location of the project to some location you want to keep your solution.
  4. Click the OK button


This will generate the configuration and setup files necessary for your solution.  You should now see the basic Design View for a Windows Forms application as the largest area in the visible interface.  Before we move on, I want you to add one more thing.  You need the toolbox, so we can actually add items to the form.  If you already see it, then ignore these steps:

  1. Go to View
  2. Click Toolbox
 
 
Usually, I like to dock my toolbox as a tab along with Solution Explorer.  Visual Studio has kind of a strange docking mechanism that you have to get used to.  Click and drag the Toolbox that appears over the Solution Explorer and then hover over the center docking control and release the mouse.  It should look something like this (note I've moved my tabs around a bit.)
 




  Now, there are four major "parts" I want you to be aware of are:
  • The Design View
  • The Solution Explorer
  • The Toolbox
  • The Properties Window
The Design View contains the area where you can place and select controls, such as buttons, text boxes, labels, and other user interface objects.

The Solution Explorer contains the projects in your solution.  You'll start out with one project, and it is often the case that you will only have one projects, even for many medium sized software applications you'll work on.

The Toolbox, in the docking format I selected, is available by clicking on the botton tab to switch back and forth between our Solution Explorer and Toolbox.  It contains the controls that we can add to our form.

The Properties Window contains various properties of a control, such as the programmatic name (the variable's identifier), the display text, the color, styles, and many others.  This window is also where you can view various events associated with the various user controls.

A Simple Example with a Button

Let's create a very simple application that simply allows the user to click a button, and says "Hello!" to the user.

  1. From the Toolbox, drag a Button control (which is under All Windows Forms) onto the form in Design View.
  2. In the Properties Window, change the (Name) property to btnPressMe, which will be the name of the button used in the actual code we are about to write.  It is a convention, but not required to start a button control identifier's name with btn.
  3. Change the Text property to Click Me
Your form should now look something like the following:



Now we have our basic button ready.

Build and Run the application as follows:

  1. Go to Build
  2. Click Build Solution
  3. Go to Debug
  4. Click Start without Debugging
Now click the button.  But wait.  It doesn't do anything.  Why is this?

This is because you haven't added an event handler to it.  Close the executing Form1 application and go back into Visual Studio.

Adding an Event Handler to the Button

In Design View in Visual Studio, double click the button on the form.  It will generate an event handler for the button and link it automatically.  There are many different events to choose from.  For buttons, the default event is Click.  This code that you will write in this method is what will execute when a user of your application clicks the button.

So what can we do?  Since we don't know too much just yet, let's just have a Message Box pop up and tell the user "Hello!"

Make your button's event handler match the code inside the body of mine:


      private void btnPressMe_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello!");
        }

Now build and run the application in the same manner you did before (Build --> Build Solution, then Debug --> Start without Debugging.)

See?  If you click on the button, you now get a message!

 



Sunday, April 28, 2013

Android Game Case Study 1: Getting an image to display using Android Canvas class

Introduction


Using Android's Canvas to display images on the screen is crucial for anyone wanting to program games or similar content.  In this tutorial, I'll take you through some of the basics. 
Assumptions:
  • I assume you have Eclipse downloaded and ready to use.
  • I also assume you have the Android SDKs installed - click here to see the instructions for installing the Eclipse plugin.
  • You have the emulator ready to go (See here for more details.)
It would be very helpful if you've had some experience with Eclipse before attempting this tutorial, but if you follow along carefully, you should be okay.

The version of Eclipse I am using might be slightly different from yours.  I'm using Indigo Service Release 2.  (Build ID 20120216-1857)

Creating a New Android Application

Well, first things first - we need to create a new Android application.
  1. Go to File
  2. Go to New
  3. Click Android Application Project
 
The next thing you do is name your project, and change the package name to something meaningful.  You should have something similar to what I have below:
 


 
 
I chose to set the minimum, target, and compile with to API 10, which is Gingerbread (specifically, Android 2.3.3)  Note that if you use an earlier version of Android like I am, you must set the Theme to None.
 
Click Next, and continue to do so, accepting the default options.  Then, finally click Finish.  You could rename your Main_Activity, but for this example, I chose not to.
 
Once you create the project, you may have an XML file pop up.  You can close it.  Expand the src directory so you can see the package, and then expand the package so you can see the Main_Activity java file.
 
The code should look similar to the following:
 
package com.profjpbaugh.gametest1;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
}
 
 

Creating a SurfaceView that Implements Runnable

In order to correctly and efficiently draw to the canvas, we have to create a class that extends (inherits from) Android's SurfaceView class.  Additionally, we will implement threading in our application.
 
To create a new class:
  1. Right click the com.profjpbaugh.gametest1 package (or whatever you named yours)
  2. Name the class CustomView
  3. Click Finish
 
 
 
 
 
Once the class is created, you should:
 
  1. Add the code extends SurfaceView implements Runnable after the class name
  2. Once you do this, you'll receive errors, which you can fix automatically by hovering over the errors and selecting the appropriate fix.  This would include the missing class references and method and constructor that are to be implemented. 


The code should look something like the following:

package com.profjpbaugh.gametest1;

import android.content.Context;
import android.view.SurfaceView;

public class CustomView extends SurfaceView implements Runnable
{

 public CustomView(Context context) {
  super(context);
  // TODO Auto-generated constructor stub
 }

 @Override
 public void run() {
  // TODO Auto-generated method stub
  
 }

}
CustomView.java

Adding a Bitmap Asset and Implementing the getBitmapFromFile() method

The major point of this tutorial is to display an image on the canvas.  We can do this in a number of ways.  However, putting images in the drawable directories is not always the best idea.  You cannot make subdirectories in the drawable directories for one, which can cause organizational nightmares.  In my own applications, I typically leave the basic UI components and icons in drawable directories, and put sprites and other game-related objects in the assets directory (or subdirectories.)

But, getting the images out of the assets directory is not as nice as just being able to reference them easily, as with drawables they are indexed and given identifiers in the R.java file.

First thing is to add the bitmap to the assets directory.
  1. Create an image in a paint program
  2. Save it to the assets directory inside of your Eclipse project
I created a file named mr_stickman.png in Adobe Photoshop.  I gave it transparency by creating a new Layer, and deleting the background.  When I saved it as a .png file, it was automatically created with the transparency information in it.



mr_stickman.png - my glorious work of art


Then refresh your navigation pane from inside Eclipse
  1. From inside Eclipse, right click assets directory
  2. Choose Refresh
  3. Expand the assets directory and you should see the image


The above screenshot shows our mr_stickman.png file sitting in the folder.

The next thing we need to do is implement a method that can read the data from the assets directory, and create a Bitmap from it, and allow us to capture the image.  The entire code is as follows:

package com.profjpbaugh.gametest1;

import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.view.SurfaceView;



public class CustomView extends SurfaceView implements Runnable
{
 private AssetManager assets = null;
 
 public CustomView(Context context) {
  super(context);
  assets = context.getAssets();
 }

 @Override
 public void run() {
  // TODO Auto-generated method stub
  
 }
 
 
 
 private Bitmap getBitmapFromFile(String fileName)
 {
  Bitmap bmp = null;
  
  Config config = Config.ARGB_8888;
  
  Options options = new Options();
  options.inPreferredConfig = config;
  
  InputStream inputStream = null;
  
  try
  {
   inputStream = assets.open(fileName);
   bmp = BitmapFactory.decodeStream(inputStream);
   if(bmp == null)
   {
    throw new RuntimeException("Couldn't load bitmap from asset '" + fileName + "'");
   }
   
  }
  catch(IOException e)
  {
   throw new RuntimeException("Couldn't load bitmap from asset '" + fileName + "'");
  }
  finally
  {
   if(inputStream != null)
   {
    try
    {
     inputStream.close();
    }
    catch(IOException e)
    {
     //do nothing
    }
   }
  }
  return bmp;
 }//end getBitmapFromFile

}
If you just cut and paste the code without the imports at the top, you're going to get a bunch of unresolved errors.  Just hover over each of them and correct them.  For example, you will need to include (import) the package references for the following:

  • Bitmap
  • Config
  • Options
  • InputStream
  • BitmapFactory
  • IOException
If you copy and paste the entire code above, then the only thing you'll need to change is the package name at the top.  For example, change com.profjpbaugh.gametest1 to com.somename.gametest1 or whatever you chose to name it.

So, what does the code do?  First, pay attention that I added an AssetManager variable assets to the top and initialized it in the constructor.

As far as the getBitmapFromFile( ) method is concerned, in a nutshell, the inputStream variable reads a byte stream from file (it doesn't really have knowledge of what the data in the fileName represents.  We take that data, and we create a bitmap using the BitmapFactory method decodeStream( ) on the inputStream variable.  If we are successful, we have a beautiful bitmap, which we return to the caller.

So basically, from a "black box" perspective - you give the method getBitmapFromFile( ) the name of the bitmap, and it returns that bitmap in the appropriate Bitmap class format.

Implementing the resume() and pause() methods

Okay, so now we've got our method to load data from a file and convert it to the appropriate format so that we can use it.  Now we have to add a little bit more code to our CustomView class so that it can paint our image to the screen.
 
Firstly, we'll add the following variable declarations to the top of the CustomView class:
  • private SurfaceHolder holder = null;
  • private boolean running = false;
  • private Thread renderThread = null;
  • private Bitmap stickman = null;
The SurfaceHolder is an interface that we will use to gain access to draw to the screen.
The boolean variable running is to keep track as to whether or not the thread of execution is running or not.
The Thread class allows us to create actual threads and start their execution.
The Bitmap class allows us to create variables to hold a compatible image.
 
Once we have the variables declared (and the appropriate imports placed at the top of the file), we can make use of them, initializing them in the constructor.
 
 public CustomView(Context context) {
  super(context);
  
  this.holder = getHolder();
  this.assets = context.getAssets();
  this.stickman = getBitmapFromFile("mr_stickman.png");
 }
 
 Once we've initialized these variables, we can continue to work by adding the resume() and pause() methods, which will be called from our MainActivity's onResume( ) and onPause( ) methods, respectively.

Below the run( ) method, add the following code:
 
 
public void resume()
 {
  running = true;
  renderThread = new Thread(this);
  renderThread.start();
 }
 

 public void pause()
 {
  running = false;
  while(true)
  {
   try
   {
    renderThread.join();
    break;
   }
   catch(InterruptedException e)
   {
    
   }
  }//end while(true)
 }
 
The resume( ) method essentially just sets the running variable to true, then creates and starts a new thread (renderThread).
The pause( ) method sets the running to false, and then attempts to perform a join( ) and continue execution.   
 
Once these are implemented, we can move back to our run ( ) method and implement that.
 

Implementing the run( ) method

 Now, we see where the real magic happens.  The run( ) method is called when the thread starts.  As long as our running variable is true, we continue running the thread.

 @Override
 public void run() {
  while(running)
  {
   synchronized(this)
   {
    if(!holder.getSurface().isValid())
    {
     continue;
    }//end if isValid() call
    
    Canvas canvas = holder.lockCanvas();
    
    canvas.drawBitmap(stickman, 0, 0, null);
    holder.unlockCanvasAndPost(canvas);
   }
  }//end while
  
 }


Notice that here, we test to see if the surface is valid, and if it is not we continue (in other words, go to the next iteration of the loop, skipping what is below the continue statement.)  As long as the surface is valid, we lock the canvas for drawing using our SurfaceHolder interface, then draw the bitmap using the drawBitmap( ) method.  In this particular version of drawBitmap( ), the parameters are as follows:

  • Bitmap bitmap - the bitmap to be drawn
  • int x - x coordinate of the upper left corner of the image
  • int y - y coordinate of the upper left corner of the image
  • Paint paint - the paint object to use to paint the bitmap.  We can just leave this null.
When we're done drawing, we unlock the canvas and post a message indicating this fact.


The MainActivity Class updates

In the MainActivity class, we must:

  • Create an instance of the CustomView class
  • Set that instance as the Content View for this activity
  • Call the pause() method of the CustomView class from onPause()
  • Call the resume() method of the CustomView class from onResume()
The full code for the final MainActivity class is as follows:

package com.profjpbaugh.gametest1;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

 private CustomView cv = null;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        cv = new CustomView(this);
        setContentView(cv);
    }

    @Override
    public void onResume()
    {
     super.onResume();
     cv.resume();
     
    }
    
    @Override
    public void onPause()
    {
     super.onPause();
     cv.pause();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
      
}





And the full code for the CustomView class is as follows:

package com.profjpbaugh.gametest1;

import java.io.IOException;
import java.io.InputStream;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;



public class CustomView extends SurfaceView implements Runnable
{
 private AssetManager assets = null;
 private SurfaceHolder holder = null;
 private boolean running = false;
 private Thread renderThread = null;
 private Bitmap stickman = null;
 
 public CustomView(Context context) {
  super(context);
  
  this.holder = getHolder();
  this.assets = context.getAssets();
  this.stickman = getBitmapFromFile("mr_stickman.png");
 }

 @Override
 public void run() {
  while(running)
  {
   synchronized(this)
   {
    if(!holder.getSurface().isValid())
    {
     continue;
    }//end if isValid() call
    
    Canvas canvas = holder.lockCanvas();
    
    canvas.drawBitmap(stickman, 0, 0, null);
    holder.unlockCanvasAndPost(canvas);
   }
  }//end while
  
 }

 public void resume()
 {
  running = true;
  renderThread = new Thread(this);
  renderThread.start();
 }
 
 public void pause()
 {
  running = false;
  while(true)
  {
   try
   {
    renderThread.join();
    break;
   }
   catch(InterruptedException e)
   {
    
   }
  }//end while(true)
 }
 
 
 private Bitmap getBitmapFromFile(String fileName)
 {
  Bitmap bmp = null;
  
  Config config = Config.ARGB_8888;
  
  Options options = new Options();
  options.inPreferredConfig = config;
  
  InputStream inputStream = null;
  
  try
  {
   inputStream = assets.open(fileName);
   bmp = BitmapFactory.decodeStream(inputStream);
   if(bmp == null)
   {
    throw new RuntimeException("Couldn't load bitmap from asset '" + fileName + "'");
   }
   
  }
  catch(IOException e)
  {
   throw new RuntimeException("Couldn't load bitmap from asset '" + fileName + "'");
  }
  finally
  {
   if(inputStream != null)
   {
    try
    {
     inputStream.close();
    }
    catch(IOException e)
    {
     //do nothing
    }
   }
  }
  return bmp;
 }//end getBitmapFromFile

}


If you run this project as an Android Application, you should see something like the following:



Closing Remarks

In this tutorial, we went over the basics of displaying an image using the canvas.  In brief, we implemented a custom called CustomView, which inherits from (extends) the SurfaceView class.  This class also implements the Runnable interface, which is involved in threading.

Once we created the CustomView class, we created an instance of it in the MainActivity class, and set it as the content View of the MainActivity.  Additionally, we called the CustomView's pause() and resume() methods from the MainActivity's onPause( ) and onResume( ) activities, respectively.