Greg Dolley’s Weblog

A Blog about Graphics Programming, Game Programming, Tips and Tricks

Archive for the ‘C# Programming’ Category

Managed DirectX C# Graphics Tutorial 1: Getting Started

Posted by gregd1024 on February 26, 2008

I’m going to demonstrate the same principles as my last post (DirectX 9 C++ Graphics Tutorial 1), how to fill a form with a solid color – except this time it’ll be in .NET using C# and Managed DirectX (MDX 1.1). MDX 1.1 is meant to expose most of the functionality as native DirectX 9.

Requirements

Everything in this tutorial is based on Visual Studio 2008 Express.

You’ll also need the DirectX SDK. You can download it from Microsoft’s site with this link. Note that this is the June 2007 release. I purposely didn’t link to the latest (November 2007 at the time of this writing) because Microsoft has removed the Managed DirectX samples and documentation from that release. If you read my last post, then you know that Microsoft has moved MDX’s functionality into the XNA framework, but threw out all features which were not simultaneously supported by both Xbox and Windows.

Tutorial Source and Project Files

To get the finished result of what this tutorial teaches – project files, binaries, and source – use this link:

Download C# Sources and Binaries [~10k]

Step 1: Create and Setup Your Project

We’re going to start from absolute scratch – that means no wizards and no auto-generated code. So start out by creating an empty C# project. You can name it whatever you like and place it in any directory.

Now add the following references:

  • Microsoft.DirectX
  • Microsoft.DirectX.Direct3D
  • System
  • System.Drawing
  • System.Windows.Forms

Go into your project settings and change the output type from “Console Application” to “Windows Application.”

managed_directx_tutorial_1_project_settings

Add one source file called “main.cs” (actually, you can use a different name but I’m going to refer to this file as “main.cs” throughout the tutorial).

Step 2: Create the Form

Inside “main.cs” you’re going to add the following “using” statements:

using System;

using System.Windows.Forms;

using Microsoft.DirectX;

using Microsoft.DirectX.Direct3D;

To make the form, copy the following code snippet and paste it directly underneath the “using” statements:

namespace MDX_Tutorial1
{
   class MainClass:Form
   {
      MainClass()
      {
         this.Text = “Managed DirectX Tutorial 1”;
      }

 

      static void Main()
      {
         MainClass MainForm = new MainClass();
         Application.Run(MainForm);
      }
   }
}

Step 3: Create the Device Object

Just like the previous post’s C++ example, you’ll have to create a device object. Since we’ll be accessing this object in multiple functions, it must be a class member variable. Add the following declaration inside “MainClass”:

private Device m_device = null;

Also add a method called “InitGraphics()” – this is where we’ll create and initialize the device object. The initialization code is only a few lines:

void InitGraphics()
{
   PresentParameters present_params = new PresentParameters();
  

   present_params.Windowed = true;
   present_params.SwapEffect = SwapEffect.Discard;
  

   m_device = new Device(0, DeviceType.Hardware, this,

                         CreateFlags.SoftwareVertexProcessing, present_params);
}

First, we create the “PresentParameters” object. This object describes how DirectX should behave in our application. We want the application to be a window and we’ll let the device handle the back buffer (“Windowed” and “SwapEffect”). Next, we actually create the device. There are several overloads for the constructor of “Device” but the one we’re interested in takes five arguments as described below:

  • Parameter 1: “int adapter”
  • Parameter 2: “DeviceType deviceType”
  • Parameter 3: “Control renderWindow”
  • Parameter 4: “CreateFlags behaviorFlags”
  • Parameter 5: “params PresentParameters[] presentationParameters”

For the adapter we used “0” since this designates the default. We chose hardware rendering as opposed to software emulation. Our main application class is also our render target form (hence the “this” keyword). We wanted software vertex processing instead of hardware calculated transforms. Lastly, we passed in our “present_params” object as the fifth parameter.

Now we must call “InitGraphics()” from somewhere. Add the following line in “Main()”:

static void Main()
{
   MainClass MainForm = new MainClass();
   MainForm.InitGraphics(); // <— ADD THIS LINE
   Application.Run(MainForm);
}

Step 4: Draw on the Form

In order to draw on the form we must override the “OnPaint()” function. In this function we use the “m_device” member to call “Clear()” and “Present()” like this:

protected override void OnPaint(PaintEventArgs e)
{
   m_device.Clear(ClearFlags.Target,
                  System.Drawing.Color.FromArgb(0, 0, 255).ToArgb(), 1.0f, 0);
   m_device.Present();
}

The “Clear()” function fills one or more buffers with a single value. The first parameter specifies which buffer, or series of buffers, to fill. It can be the rendering target buffer (Target), depth buffer (ZBuffer), or stencil buffer (Stencil). You can specify more than one by combining their values via a bitwise “OR” operation. The second parameter specifies what color to use in clearing the render target surface. In our case we chose blue. The third parameter specifies what value to use for clearing the depth buffer. Lastly, the fourth parameter specifies what value to use for clearing the stencil buffer.

The “Present()” function displays everything to the screen. It is equivalent to calling the C++ version with four NULL parameters.

Run the Program!

Our first managed DirectX program is done! Now compile and run the program. You should see output similar to this:

managed_directx_tutorial_1_output

Conclusion

While this program is rather boring, in the next tutorial we’ll cover how to draw a 2D triangle with different colored vertices.

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Advertisements

Posted in .NET Graphics, C# Programming, DirectX | 35 Comments »

Can I Use Typedef’s in C#?

Posted by gregd1024 on February 15, 2008

When moving from C++ to C#, the following question often arises: does C# support typedef’s? Unfortunately, no. However, you can get pretty close. Consider this code:

using GLenum = System.UInt32;

The “using GLenum” statement makes the symbol “GLenum” equivalent to a “System.UInt32” name. Now you can use “GLenum” to declare identifiers instead of “UInt32.” In this way, it’s acting exactly like a C or C++ typedef. What’s actually happening is that you’re creating a C# alias – a mechanism which allows the renaming of a class, struct, or namespace. While this may seem pretty flexible, consider what happens when you try the following:

using GLfloat = float; // ERROR!

This line results in a compile error because “float” is a keyword. Why weren’t C# aliases built to support this as well? When you consider the original purpose of aliases it kind of makes sense. They were meant to save the programmer from lots of typing by providing a mechanism to shorten long qualifiers. We all know some namespaces and classes in C# are much longer than what you would typically see in a C++ program, so providing renaming support was practically a necessity. But do you really think a lot of programmers are going to shorten “float” or “int”? So when I said you can “get pretty close” to a C++ typedef, I was specifically referring to limitations such as this.

Another big limitation is that aliases are limited in scope. Only the namespace in which they’re declared can see them and their scope cannot cross multiple source files. The last part is severely limiting – it forces you to include the same declaration in every file. At least it’s better than nothing.

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Posted in C# Programming, Tips and Tricks | 8 Comments »

How to Make a C# Application Without the Wizard

Posted by gregd1024 on February 14, 2008

Most C++ programmers know how to start coding from an empty project without the wizard’s assistance. But how many tutorials show a way to do this in C#? Questions arise like what references you need, what should the default project settings be, etc.

In this post I’m going to create a Windows Form application starting from scratch (just an empty project). It’s actually quite easy if you’re making a DLL, Console application, or Forms application. Plus, you can be certain that your application doesn’t contain any useless references or dependencies.

Note: this tutorial is applicable to Visual Studio 2008.

Step 1 – Create an Empty Project

Start Visual Studio and select “File->New Project.” When the “New Project” dialog appears, select the “Empty Project” template and name it whatever you like. Click OK.

c_sharp_app_from_scratch_new_project_dialog

Step 2 – Modify Project Settings

At this point you’ll have an empty project loaded in Solution Explorer without any source files or references listed. Now, go to the “Project” menu and select “Properties.” Under the “Application” tab, click the “Output type” combo box and change it from “Console Application” to “Windows Application.” This makes the project into a regular Windows Form app.

c_sharp_app_from_scratch_project_settings

Save this configuration (hit CTRL-S or click “File->Save”) and close the “Project Settings” window.

Step 3 – Add References

Now right click on the “References” folder in Solution Explorer and click “Add Reference” (you can also select the same option from the “Project” menu). Which references you’ll need will depend on what kind of project you’re building, but in our case we need “System,” “System.Windows.Forms,” and “System.Drawing.” They are located in the .NET tab of the “Add Reference” dialog:

c_sharp_app_from_scratch_system_reference

After you’ve selected all three references, click OK. Now your project should look like this in Solution Explorer:

 c_sharp_app_from_scratch_solution_explorer_references

FYI: for almost any project you’ll at least need the “System” reference, so I add this one right away no matter what kind of project I’m creating. If your project was extremely simple, had no dependencies, and you didn’t care about fully qualifying your types, then you could get away with not adding this reference.

Step 4 – Add a Source File

You’ll notice from the last screenshot that we don’t have any source files in our project. Well that’s easy to fix – click on “Add New Item” located under the “Project” menu. When the “Add New Item” dialog appears, select “Code File.” Name it whatever you like and click OK.

c_sharp_app_from_scratch_add_code_file

Step 5 – Add Code

We didn’t want to select the “Class” template because that would cause Visual Studio to create a class skeleton and add useless references to the project.  Selecting “Code File” ensures that nothing is done which isn’t completely necessary. It also gives us an entirely blank source file. Here is the minimum amount of code you’ll have to add for some meaningful output:

  1. Type the “using” directives for “System,” “System.Windows.Forms,” and “System.Drawing.”
  2. Type a namespace declaration.
  3. In that namespace type a class declaration deriving from “Form”.
  4. Type a “static void Main()” function into the class.
  5. Inside the Main() function type this line: “Application.Run(new MyClass());”

After following the steps above, your code should look similar to this:

using System;
using System.Windows.Forms;

using System.Drawing;

 

namespace MyProject
{
   class MyClass:Form
   {
      static void Main()
      {
         Application.Run(new MyClass());
      }
   }
}

You can actually compile and run the project in this state, but it will just produce a blank form and you won’t be able to add controls in the Designer. We’ll take care of this problem in the next step.

Step 6 – Add Controls to Form

You may be wondering how to associate your hand-written code with Visual Studio’s Designer. Believe it or not, there’s no need to do this. In fact, Visual Studio automatically detects whenever you derive a class from “System.Windows.Forms.Form” and links the associated source file to the Designer.

Now, right click on your source file in Solution Explorer and select “View Designer.” When the Designer comes up you’ll see an empty form. Drag a button control on it and switch back to code-view. You’ll notice that Visual Studio has added this function to your class:

private void InitializeComponent()
{
   this.button1 = new System.Windows.Forms.Button();
   this.SuspendLayout();
   //
   // button1
   //
   this.button1.Location = new System.Drawing.Point(104, 93);
   this.button1.Name = “button1”;
   this.button1.Size = new System.Drawing.Size(75, 23);
   this.button1.TabIndex = 0;
   this.button1.Text = “button1”;
   this.button1.UseVisualStyleBackColor = true;
   //
   // MyClass
   //
   this.ClientSize = new System.Drawing.Size(284, 264);
   this.Controls.Add(this.button1);
   this.Name = “MyClass”;
   this.ResumeLayout(false);

}

Visual Studio automatically keeps InitializeComponent() up-to-date. It contains all the code for creating and positioning the form’s controls. However, we still have to call the function. For this, we turn to the class’s constructor. Since we haven’t defined a constructor yet, we’ll do it now and add the call to InitializeComponent():

MyClass()
{
   InitializeComponent();
}

By now, your source code should look like this:

using System;
using System.Windows.Forms;
using System.Drawing;

 

namespace MyProject
{
   class MyClass:Form
   {
      private Button button1;
     

      MyClass()
      {
         InitializeComponent();
      }
     

      static void Main()
      {
         Application.Run(new MyClass());
      }

     

      private void InitializeComponent()
      {
         this.button1 = new System.Windows.Forms.Button();
         this.SuspendLayout();
         //
         // button1
         //
         this.button1.Location = new System.Drawing.Point(104, 93);
         this.button1.Name = “button1”;
         this.button1.Size = new System.Drawing.Size(75, 23);
         this.button1.TabIndex = 0;
         this.button1.Text = “button1”;
         this.button1.UseVisualStyleBackColor = true;
         //
         // MyClass
         //
         this.ClientSize = new System.Drawing.Size(284, 264);
         this.Controls.Add(this.button1);
         this.Name = “MyClass”;
         this.ResumeLayout(false);

      }
   }
}

Step 7 – Compiled and Run

Now try running the project! Hopefully you see something similar to my output:

c_sharp_app_from_scratch_output_form

Congratulations! You just created a Windows Forms application from scratch!

Optional Things

You may be thinking, “but what about the extra code the wizard adds in forms like Dispose() and the “components” member? Don’t I need that stuff too?” The short answer: it depends.

In certain situations you’ll need the “components” member, but it’s not necessary to define it. The Designer will add the declaration when it’s needed. Try placing a Notify Icon or Timer control and you’ll see what I mean. The “components” member is used for most of the non-visual controls available in the Designer. If you drag a control on a form and it gets added to the container bar (on the bottom of the design window) instead of making some visual appearance on the form itself, then there’s a good chance it’ll use this variable.

You’ll need the Dispose() function only if you must explicitly free resources that can’t otherwise be managed by the Garbage Collector. These resources might be unmanaged memory, file handles, database connections, or similar objects who’s destruction is non-deterministic. Given that our example program allocated objects only from the managed heap, having a Dispose() would be pointless.

If you find that your class will eventually need the “components” member and a Dispose() method, here’s the minimum amount of code you’ll need to get started:

// Special Designer variable
private System.ComponentModel.IContainer components = null;

 

// Used to explicitly free any resources not
// managed by the Garbage Collector
protected override void Dispose(bool disposing)
{
   if (disposing && (components != null))
   {
      components.Dispose();
   }
   base.Dispose(disposing);
}

Also, you may have noticed that when using the wizard to generate a project, it creates a separate form class instead of using the application’s main class as the container. This results in two extra source files being added to the solution. You can do this yourself by creating one source file giving it a “.cs” extension (such as “Form.cs”) and creating another file with the same name but giving it a “.Designer.cs” extension (such as “Form.Designer.cs”). Visual Studio will automatically associate these two files together and you’ll see “Form.Designer.cs” underneath “Form.cs” in Solution Explorer’s tree view:

c_sharp_app_from_scratch_manual_form_files

Conclusion

I hope that this post has given you insight into rolling your own Windows Forms project from scratch. While it will always be faster to use the wizard, at least now you don’t have to rely on it. You also know what parts of the wizard’s code can be deleted if your program doesn’t require it.

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Posted in C# Programming, General Programming, Tips and Tricks | 6 Comments »

How to Convert a Console App into a Windows App in C# – Part Two

Posted by gregd1024 on February 9, 2008

As I promised in yesterday’s post, I’m now going to show you an even easier way to convert a C# console application into a regular Windows application. Since the steps are nearly identical, I’m just going to focus on the key points instead of writing the same thing as before.

First, perform the following steps:

  • Create a regular C# console application or open one of your own.
  • Add the following two references to your project and the corresponding “using” statements on top of the main source file:

using System.Drawing

using System.Windows.Forms

  • Remove the “args” string array parameter from the Main() function.
  • Add “Application.EnableVisualStyles();” as the first call in the Main() function.
  • Change the “Output type” of your project from “Console Application” to “Windows Application.”

Now for the fun part (the part that’s different from my last post). Do the following:

  • Change the “Program” class to derive from “System.Windows.Forms.Form.”
  • Add “Application.Run(new Program());” as the last call in the Main() function.

At this point your “Program” class should look like this:

class Program:System.Windows.Forms.Form

{

   static void Main()

   {

      Application.EnableVisualStyles();

      Application.Run(new Program());

   }

}

We’re almost done. In fact, you can run the program now and you’ll see a blank form. But you won’t be able to place any controls on it. Well, actually that’s not true – you can place controls, but the form will still be blank at runtime. The last step is:

  • Add a constructor to the “Program” class and call “InitializeComponent()” inside it:

class Program:System.Windows.Forms.Form

{

   Program() // ADD THIS CONSTRUCTOR

   {

      InitializeComponent();

   }

 

   static void Main()

   {

      Application.EnableVisualStyles();

      Application.Run(new Program());

   }

}

“InitializeComponent()” will not be defined yet. However, the Form Designer will create this function as soon as any control is placed on the form or its layout is modified. You may have noticed that the icon next to “Program.cs” (in Solution Explorer) has changed to a form instead of the one representing a code file:

console_convert_2_icon_change 

This means you can double-click on it and Visual Studio will open the Form Designer instead of going to the source. Try this:

  1. Double click on Program.cs.
  2. Change the form’s size in the Designer.
  3. Go back to the source window of Program.cs.

Now you should see the “InitializeComponent()” function defined underneath “Main().” Your “Program” class will now look like this:

class Program:System.Windows.Forms.Form
{
   Program()
   {
      InitializeComponent();
   }
     
   static void Main()
   {
      Application.EnableVisualStyles();
      Application.Run(new Program());
   }

 

   private void InitializeComponent() // DESIGNER WILL ADD THIS FUNCTION
   {
      this.SuspendLayout();
      //
      // Program
      //
      this.ClientSize = new System.Drawing.Size(367, 188);
      this.Name = “Program”;
      this.ResumeLayout(false);

 

   }
}

You’re done! 🙂 Everything is contained in this one source file. The designer will keep on modifying “InitializeComponent()” whenever something changes in the form itself. It will also add the necessary member variables to the “Program” class whenever controls are placed on the form.

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Posted in C# Programming, General Programming, Tips and Tricks | 22 Comments »

How to Convert a Console App into a Windows App in C#

Posted by gregd1024 on February 8, 2008

In this post I’m going to demonstrate how you can easily take a simple C# console application and convert it into a regular Windows application. It will involve just a few code changes and one project settings change. There are actually two methods to do it – a method in which you end up with almost the same code the wizard normally generates, and a method in which your application class becomes the main form. I’m only going to demonstrate the first method in this post; I’ll cover the second method in my next post.

The instructions presented in this post are for Visual Studio 2008, but most should work in a similar way with previous versions. I’m also going to use Express for the programmers who don’t have full blown Visual Studio.

Step 1: Create a C# Console Application

For demonstration purposes I’m creating a C# console application from the wizard. Of course, if you already have a console app you want to convert, open your project instead.

console_app_conversion_new_project

Step #2: Add References

Add the following references to the project:

  1. “System.Drawing”
  2. “System.Windows.Forms”

console_convert_add_references

These references are not added by the console app generator wizard, so we must add them manually. Also, add the corresponding “using” statements to your application’s main source file (the file that contains the Main() function):

  1. “using System.Drawing”
  2. “using System.Windows.Forms”

Step Three: Modify the Main() Function

Perform the following steps to the Main() function:

  1. Remove the “args” parameter from Main().
  2. Add the following two lines:

static void Main()

{

   Application.EnableVisualStyles(); // <– ADD THIS LINE

  

   // your existing code goes here (if any)

 

   Application.Run(new Form1()); // <– ADD THIS LINE

}

You can optionally add “Application.SetCompatibleTextRenderingDefault(false);” right under the EnableVisualStyles() call, but it’s not required. I mention it because this is what the wizard adds when auto-generating a project, but its purpose is beyond me (if you know what this function does, please leave a comment).

Step Four: Add a New Form Resource to the Project

Add a new form to the project and keep the name as Form1.cs:

console_convert_add_form

Step Five: Modify Project Settings

To modify the project settings go to the Project menu and click on Properties. Under the first tab (Application), click the Output type drop-down box and change it from “Console” to “Windows Application.”

console_convert_project_settings

Step Six: Compile and Run!

We’re done! 🙂 Now try running the project. You should see a blank form without any console box:

console_convert_up_and_running

Conclusion

In my next post I’m going to show you an even simpler way of doing this very same thing. Instead of explicitly adding a Form resource to the project, we’ll just take the class which houses Main() and turn it into a form programmatically. You’ll even be able to use the Form Designer to add controls and modify layouts.

-Greg Dolley

*Get new posts automatically! Grab the RSS feed here. Want email updates instead? Click here.

Posted in C# Programming, General Programming, Tips and Tricks | 17 Comments »