Tuesday, July 27, 2010

Rounding in C# Explained

In this post I present you 3 basic functions to round numbers in C#.
Like other mathematical functions they are (logically) part of the class Math.

For "standard" rounding there is the function Round(). This expects as the first parameter the number which is to be rounded and as a second optional one the number of decimal places after rounding. If this parameter is not used, 0 is assumed, meaning the number is rounded to the closest integer.

But there are 2 more interesting functions: Ceiling() and Floor().
Both functions round to integers, the first one to the next highest integer and the second on to the next lowest one.

The following example should make this clear:

            decimal d = (decimal)1.5642; // here "1.5642" has to be converted manually with (decimal) to a decimal value, since C# interprets floating numbers as double by standard

            decimal RoundedIntegerNumber = Math.Round(d); // round to integer = 2
            decimal RoundedDecimalNumber = Math.Round(d, 2); // round with 2 decimal places = 1.56

            decimal NextHigherNumber = Math.Ceiling(d); // round to next highest integer = 2
            decimal NextLowerNumber = Math.Floor(d); // round to next lowest integer = 1

Sunday, July 25, 2010

Create Desktop Shortcut

Shortcuts on the desktop are mostly just "normal" files with the extension ".lnk" (for link). To create such files with C# and to fill them with the right content is after my knowledge a little bit harder and only doable by including the COM object Windows Script Host Object Model.
Therefore in this post I want to show, how to create ".url" files instead of ".lnk" files - they have the same functionality, but are easier to create with .Net.
These files are mainly used to represent links on websites, but they can also be used to create file shortcuts.
The following function creates a shortcut in the path shortcutPath, here shortcutDest represents the path to the program which is to be linked and shortcutIcon the path to the icon, which should be used as symbol for the shortcut:

private void CreateShortcut(string shortcutPath, string shortcutDest, string shortcutIcon)
{
    StreamWriter sw = new StreamWriter(shortcutPath);
    sw.WriteLine("[InternetShortcut]");
    sw.WriteLine("URL=file:///" + shortcutDest);
    sw.WriteLine("IconIndex=0");
    sw.WriteLine("IconFile=" + shortcutIcon);
    sw.Close();
}

To create a shortcut on the desktop, you could call the function as follows:

CreateShortcut(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MyShortcut.url""C:\\Programme\\WinRAR\\WinRAR.exe""C:\\MyIcon.ico");

Saturday, July 24, 2010

Fun App: Take a Screenshot of the Desktop as Wallpaper and Delete all Items - Reverse

So, here the code to reverse the effects done by the program of the last post:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [DllImport("user32.dll")]
        private static extern int FindWindow(string className, string windowText);

        [DllImport("user32.dll")]
        private static extern int ShowWindow(int hwnd, int command);

        private void Form1_Load(object sender, EventArgs e)
        {
            // show taskbar
            int hwnd = FindWindow("Shell_TrayWnd""");
            ShowWindow(hwnd, 1);
       
            string BackupDirectory = @"C:\backupdesktopfun\";

            DirectoryInfo ds = new DirectoryInfo(BackupDirectory);

            string DesktopDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\";

            // recover all files and folders again

            foreach (FileInfo f in ds.GetFiles())
            {
                if (!File.Exists(DesktopDirectory + f.Name))
                    f.MoveTo(DesktopDirectory + f.Name);
            }

            foreach (DirectoryInfo d in ds.GetDirectories())
            {
                if (!Directory.Exists(DesktopDirectory + d.Name))
                    d.MoveTo(DesktopDirectory + d.Name);
            }

            Application.Exit();
        }
    }

Fun App: Take a Screenshot of the Desktop as Wallpaper and Delete all Items

First of all: Attention! With the sample code shown here data might get lost, definitely the ordering of the desktop icons will get lost - I do not take any responsibility for any negative aftermaths.

And now what this is all about: Today I want to present to you a little fun application using a lot of the previous posts, which makes it pretty easy to fool your friends with.
The program takes a screenshot of the desktop, then hides the taskbar and removes all icons from the desktop. Then the program sets this screenshot as the wallpaper, so it looks as everything was as normal, but nothing can be clicked anymore.
The files and symbols from the desktop are not deleted but moved in a backup directory. All this can be reversed with the program from the next post.

All tricks I have used in this application I described in previous post, so I hope you excuse that the source code is not that well documented. You can just copy this code in a Windows Forms - Application overwriting the code of the whole form. On the form a timer has to be placed:

    public partial class Form1 : Form
    {

        [DllImport("user32.dll")]
        private static extern int FindWindow(string className, string windowText);

        [DllImport("user32.dll")]
        private static extern int ShowWindow(int hwnd, int command);


        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni);
        private static UInt32 SPI_SETDESKWALLPAPER = 20;
        private static UInt32 SPIF_UPDATEINIFILE = 0x1;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            // minimize all windows
            Type typeShell = Type.GetTypeFromProgID("Shell.Application");
            object objShell = Activator.CreateInstance(typeShell);
            typeShell.InvokeMember("MinimizeAll", System.Reflection.BindingFlags.InvokeMethod, null, objShell, null);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            int StartX, StartY;
            int Width, Height;

            StartX = 0;
            StartY = 0;
            Width = Screen.PrimaryScreen.Bounds.Width;
            Height = Screen.PrimaryScreen.Bounds.Height;

            Bitmap Screenshot = new Bitmap(Width, Height);

            // wait for all windows to be minimized
            for (int i = 0; i < 1000; i++)
                if (i % 100 == 0)
                    System.Threading.Thread.Sleep(100);

            // take a screenshot from the desktop
            Graphics G = Graphics.FromImage(Screenshot);

            G.CopyFromScreen(StartX, StartY, 0, 0, new Size(Width, Height), CopyPixelOperation.SourceCopy);

            Screenshot.Save("C:\\1.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
            Screenshot.Dispose();

            G.Dispose();

            string filename = "C:\\1.bmp";

            // hide taskbar
            int hwnd = FindWindow("Shell_TrayWnd""");
            ShowWindow(hwnd, 0);

            SystemParametersInfo(20, 0, filename, 0x01 | 0x02);
         
            DirectoryInfo ds = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));

            // backup all files and directories
            string BackupDirectory = @"C:\backupdesktopfun\";

            if (!Directory.Exists(BackupDirectory))
                Directory.CreateDirectory(BackupDirectory);

            foreach (FileInfo f in ds.GetFiles())
            {
                if (!File.Exists(BackupDirectory + f.Name))
                    f.MoveTo(BackupDirectory + f.Name);
            }

            foreach (DirectoryInfo d in ds.GetDirectories())
            {
                if (!Directory.Exists(BackupDirectory + d.Name))
                    d.MoveTo(BackupDirectory + d.Name);
            }

            Application.Exit();
        }
    }

Tuesday, July 20, 2010

Minimize all Windows / Show Desktop

To achieve the same result as the shortcut "Show Desktop" (Win + D), namely minimizing all active windows, with C# we need to go a bit deeper in the system architecture and use an older COM object.
The Component Object Model is a platform technique to manage objects. In .Net these components are normally not used any more, but, as you see, from time to time they are still needed.
COM objects can be accessed by their GUID (Globally Unique Identifier) number, which identifies an object uniquely.
As this number is hard for us humans to use, furthermore there is the ProgID (Programmatic Identifier), which is more easy to understand (for example, names are something like Project.Class).
The ProgIDs are connected to GUIDs in the registry.

To now minimize all programs, we need the COM type Shell.Application. .Net can lookup a corresponding type from the registry with the function Type.GetTypeFromProgID(). Starting from this type we can create an instance of it using Activator.CreateInstance(). With InvokeMember() we can eventually call a function of this object.
But, enough of the theory, here simply the code for minimizing all windows and showing thus the desktop:

Type typeShell = Type.GetTypeFromProgID("Shell.Application");
object objShell = Activator.CreateInstance(typeShell);
typeShell.InvokeMember("MinimizeAll", System.Reflection.BindingFlags.InvokeMethod, null, objShell, null); // Call function MinimizeAll

In the call of InvokeMember() the first parameter says, that the function MinimizeAll is to be used. The 2nd one is a BindingFlag (here it says that the method is to be called). The 4th describes, that the object objShell is to be used for that.

Copy Files / Folders

In the previous posts we have seen, how to check whether files and directories already exist, how they can be moved and how to list the contents of a directory.
Copying files can also be done with one command:

System.IO.File.Copy("C:\\sourcefile.txt""C:\\testfolder\\testfile.txt"true);

The paths have to exist, for example an exception is thrown if the folder "testfolder" does not exist.
The 3rd parameter is and states, whether the targetfile is to be overwritten if it already exists (true means overwriting, the default value for this optional parameter is false).

Ironically, copying folders is much harder than moving them. Moving files is just a small intervention in the file system, just the path of the directory has to be set to the new location.
When copying a file or directory this element has to be duplicated and "registered" in the file system.
When copying folders, this leads to the problem that the complete folder hiearchy including subfolders has to be cloned - in C# there exists no actual function for it.
Therefore we will now write our own. It will work recursive, calling itself with all subdirectories and thus copying the folder structure. Then, all files are copied (using System.IO; required) :

        private void CopyDirectory(string sourceDirectory, string destDirectory)
        {
            DirectoryInfo ds = new DirectoryInfo(sourceDirectory); // this class is needed to read the folder content

            // create target directory if not yet existent
            if (!Directory.Exists(destDirectory))
                Directory.CreateDirectory(destDirectory);

            // recursivly call CoypDirectory() with all subfolders to clone the directory structure
            foreach (DirectoryInfo d in ds.GetDirectories())
            {
                CopyDirectory(d.FullName, destDirectory + "\\" + d.Name);
            }

            // get all files with GetFiles(), which does not return a File object but a FileInfo object
           // but this provides similiar functions, MoveTo() and CopyTo() are available
            foreach (FileInfo f in ds.GetFiles())
            {
                f.CopyTo(destDirectory + "\\" + f.Name, true);
            }
        }

A sample call could like as follows:
CopyDirectory("C:\\sourcefolder""C:\\targetfolder);

Monday, July 19, 2010

List All Files / Folders in Folder

To output all files and folders which are contained in a specific folder we use the C# class System.IO.DirectoryInfo.
This is initialized with the wanted folder and then provides 2 functions to output the folder content: GetFiles() and GetDirectories(). The first one returns an array of System.IO.FileInfo objects, which represent all files in that folder.
The second one returns an array of the type System.IO.DirectoryInfo, which contains all subfolders of the folder.
The following sample application prints all files and subfolders of the directory"C:\testfolder" in the console:

            System.IO.DirectoryInfo ParentDirectory = new System.IO.DirectoryInfo("C:\\testfolder");

            foreach (System.IO.FileInfo f in ParentDirectory.GetFiles())
            {
                Console.WriteLine("File: " + f.Name);
            }

            foreach (System.IO.DirectoryInfo d in ParentDirectory.GetDirectories())
            {
                Console.WriteLine("Folder: " + d.Name);
            }

On Udo's Blog there is further a little extension explaining how to list recursively also files from subdirectories.

Saturday, July 17, 2010

Move File / Folder

To move a file or a folder using C# we need the function Move() of the classes System.IO.File or System.IO.Directory:

System.IO.File.Move("C:\\sourcefile.txt""C:\\testfolder\\targetfile.txt");
System.IO.Directory.Move("C:\\sourcefolder""C:\\testfolder\\targetfolder");

In both variants the first parameter represents the path to the sourcefile / sourcefolder, the second to the targetfile / targetfolder.
The path has to be valid, otherwise the function throws an exception.

Check If File / Directory Exists

In this and the next posts I want to show some basic operations which can be performed on files and directories. In C# we therefor mostly use the classes System.IO.File and System.IO.Directory.
This post shows how to check whether a file or directory already exists:
bool DirectoryExists = System.IO.Directory.Exists("C:\\test");
bool FileExists = System.IO.File.Exists("C:\\testfile.txt");

Thursday, July 15, 2010

Hide Taskbar

If we want to fade the taskbar in or out (most people probably want to hide it), we need the WinAPI.
To get the window handle (the identifier of a window) of the taskbar, we need the function FindWindow(). More to this function and why we here cannot use the .Net class System.Diagnostics.Process, you can read in the previous post.
But with FindWindow(), we can "grab" the taskbar and manipulate it. For showing or hiding it, we need the API function ShowWindow().
It expects 2 parameters: First an integer, which is the windows handle, and second another integer, which describes the desired action. All possible values can be looked up here.
We need the values 0 to hide a window and 1 to show it again, more examples are 3 (maximize) and 6 (minimize).
The following sample application hides the taskbar when loading the form (System.Runtime.InteropServices has to be included via using for the DLL import):

        [DllImport("user32.dll")]
        private static extern int FindWindow(string className, string windowText);

        [DllImport("user32.dll")]
        private static extern int ShowWindow(int hwnd, int command);

        private void Form1_Load(object sender, EventArgs e)
        {
            int TaskbarWindowHandle = FindWindow("Shell_TrayWnd""");
            ShowWindow(TaskbarWindowHandle, 0);
        }

Select Window With FindWindow()

With .Net you can select a specific running process by the functions System.Diagnostics.Process.GetProcessesByName() and System.Diagnostics.Process.GetProcessesById(). You then get an instance of the class Process containig it. This variable then can be manipulated, for example you can termine it or read-out its ID.
Unfortunately these functions do not always suffice.
A process can have multiple windows, as for example a C# application can have many forms. If we want to select a specific window and not just the whole process, we have to use the WinAPI.
This library provides the function FindWindow().
The function expects 2 strings as parameter: The first is called className and specifies the class name of the process / window. The second parameter, windowText, describes the title of the window. If none is given, all windows are selected.
An example will follow in the next post, where this function is used to hide the taskbar.
With System.Diagnostics.Process.GetProcessesByName() this cannot be achieved, since the taskbar is contained in the process "explorer.exe". But with the right parameters in FindWindow(), it can be found and separated.

Wednesday, July 14, 2010

Change Desktop Wallpaper

This post shows, how to change the desktop wallpaper using C#.
For this, one has to include the WinAPI function SystemParametersInfo(). Its signature looks as follows:
SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni)

This function is very all-rounded and make for setting general system parameters, the exact action is set by the first parameter. Possible values can be looked up here here, 4 for example describes activating / deactivating the system alarm tome and 20 change the wallpaper.
As 2nd parameter the function can be given an integer, which is not needed here. But we need the 3rd parameter, which here describes the path to the image, which is to be the new wallpaper. This file has to have the format .bmp.
The last parameter, fWinIni, describes, how the changes are to be made. The here used 0x01 says, that the new value of the parameter is to be written in the user profe. Possible values of this parameter can be viewed here.
Take a look at this sample implementation (using System.Runtime.InteropServices; required):

        [DllImport("user32.dll")]
        private static extern Int32 SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, String pvParam, UInt32 fWinIni);

        private static UInt32 SPI_SETDESKWALLPAPER = 20;
        private static UInt32 SPIF_UPDATEINIFILE = 0x1;

        private void button1_Click(object sender, EventArgs e)
        {
            string Filename = "C:\\1.bmp";
            SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, Filename, SPIF_UPDATEINIFILE);
        }

On Udo's Blog you can find a nice use of this function, namely a program which changes the desktop background depending on the current time.

Tuesday, July 13, 2010

Double Buffering in C#

The standard class for graphical operations in Windows Forms - applications Graphis is unfortunately too slow for larger graphic outputs.
In applications, where a lot has to be drawn, the form starts blurring, the application freezes.
Of course, the with no doubt best and professional solution are external libraries like DirectX or XNA.
Today I do not want to go that far, but instead present you another useful technique for improving the performance: (Double) Buffering.
When drawing traditionally, each element is drawn for itself on the form, the user sees how the form is slowly built up. That means, it can even happen, that the form has to be redrawn during this step, the process slows down even further.
Therefor buffering is a commonly used improvement. In that, a so called Buffer is used, which temporarily saves the elements to be drawn.
The elements are then first drawn in the buffer, eventually the whole buffer is copied to the form.
So all elements are in fact drawn as one big picture, which makes the process much more fluent.
If the buffer is buffered itself, we speak of double buffering.
To demonstrate the effect of this technique, I write a little sample application.
After clicking the button, the program randomly draws circles and text on the form.
The first version uses only standard Graphics functions:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Bounds = Screen.PrimaryScreen.Bounds;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Graphics G = this.CreateGraphics();
            Random Rnd = new Random();

            for (int i = 0; i < 1000; i++)
            {
                G.DrawEllipse(new System.Drawing.Pen(Color.Red), Rnd.Next(this.Width), Rnd.Next(this.Height), Rnd.Next(100), Rnd.Next(100));
            }

            for (int i = 0; i < 1000; i++)
            {
                G.DrawString("Test test test"new System.Drawing.Font("Arial", 12), new SolidBrush(Color.Green), new PointF(Rnd.Next(this.Width), Rnd.Next(this.Height)));
            }
        }
    }
}

Drawing takes its time, you see how the single elements are drawn one after another.

A possibility, to automatically active double buffering, is to add corresponding styles to the form.
The following code can for example be added to Form1_Load():
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);

It enforces, that buffers are used. The process is thereby already speed up a lot.
But if one wants to have more control over the used buffers, they have to be implemented manually.
This last version of the application uses manually created buffer objects. The elements to be drawn are first drawn in the buffers and then copied on the form:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // needed buffer objects
        BufferedGraphicsContext currentContext;
        BufferedGraphics myBuffer;

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Bounds = Screen.PrimaryScreen.Bounds;
     
            // initialize buffer on the form
            currentContext = BufferedGraphicsManager.Current;
            myBuffer = currentContext.Allocate(this.CreateGraphics(), this.DisplayRectangle);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Random Rnd = new Random();

            // first draw elements to the buffer
            for (int i = 0; i < 1000; i++)
            {
                myBuffer.Graphics.DrawEllipse(new System.Drawing.Pen(Color.Red), Rnd.Next(this.Width), Rnd.Next(this.Height), Rnd.Next(100), Rnd.Next(100));
            }

            for (int i = 0; i < 1000; i++)
            {
                myBuffer.Graphics.DrawString("Test test test"new System.Drawing.Font("Arial", 12), new SolidBrush(Color.Green), new PointF(Rnd.Next(this.Width), Rnd.Next(this.Height)));
            }

            // then "render" the buffer, which means that the buffer is drawn to the form
            myBuffer.Render();
        }
    }
}

Monday, July 12, 2010

Matrix Screensaver

With the knowledge from the previous post of how to create screensavers with C# I wrote a screensaver which looks kind of the well known screen from the movie matrix.
In the screensaver all visible letters are instances of a class, which implements a function to draw the letters.
In specific time intervals rows with letters are created and all letters are moved down continiously.
The drawing does not take place directly on the form but in a buffer. Only when all letters are drawn in this, the complete content of the buffer is transfered to the form (this is called rendering).
I would like to just post the complete sourcecode here, hope some of you enjoy trying this.
You can download the commented (in German) sourcecode here,  the executable screensaver file is available here.


Edit: A German video about this post is now also available on Youtube.

Saturday, July 10, 2010

Create A Screensaver

Simply put, a screensaver is just an executable .exe file with ending .scr and some special properties.
This fact we use when creating a screensaver in C#.
The screensaver program expects a parameter on startup, whether the screesaver is to be started ("/s") or configured ("/c").
As it is harder to start Windows forms - applications with parameters, we therefore create a console application.
To this we then add a new element, a form (Windows Form).
In the main function of the console application we then prompt the given parameter, if this is "/s" we show the added form (in my project this is called ScreenSaverForm):
System.Windows.Forms.Application.Run(new ScreensaverForm());

So that the form runs in fullscreen mode as we are used of screensaves, we set the following 3 properties in the function Load() of the form (see the previous post for more details):
        private void ScreensaverForm_Load(object sender, EventArgs e)
        {
            FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Bounds = Screen.PrimaryScreen.Bounds;
            Cursor.Hide(); // hide cursor
            TopMost = true;

        }
When testing the program in this development stage, the console application as well as the taskbar are still visible.
This problem can be fixed, when setting in the project properties (right click on the project in the project explorer) under "Application" the output type as "Windows - Application".
Now we just have to define, when the screensaver should end, of course this is the case when the user starts any input.
Therefore in the functions ScreensaverForm_KeyDown()ScreensaverForm_MouseDown() and private void ScreensaverForm_MouseMove() we execute corresponding actions.
Now the complete source code, first of the console application StartupProgramm.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ScreenSaver
{
    class StartupProgramm
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                // configuration
                if ((args[0].ToLower().Trim().Substring(0, 2) == "/c")) // lconfig - parameter is given in the form "/c:xxxxx"
                {
                    // if wished, create here a form for configuration purposes
                    System.Windows.Forms.MessageBox.Show("No settings available.");
                }
                // Start
                else if (args[0].ToLower() == "/s")
                {
                    // load screensaver form
                    System.Windows.Forms.Application.Run(new ScreensaverForm());
                }
            }
        }
    }
}

Now the sourcecode of the form ScreenSaverForm.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ScreenSaver
{
    public partial class ScreensaverForm : Form
    {

        Point PrevPos; // previous position of the cursor

        public ScreensaverForm()
        {
            InitializeComponent();
        }

        private void ScreensaverForm_Load(object sender, EventArgs e)
        {
            FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;  
            this.Bounds = Screen.PrimaryScreen.Bounds;
            Cursor.Hide();
            TopMost = true;
        }

        private void ScreensaverForm_MouseMove(object sender, MouseEventArgs e)
        {
            // if there was a previous point saved, compare to new point
            if (!PrevPos.IsEmpty)
            {
                // if mouse was moved, exit
                if (PrevPos.X != e.X || PrevPos.Y != e.Y)
                    Close();
            }
            PrevPos = new Point(e.X, e.Y);
        }

        private void ScreensaverForm_MouseDown(object sender, MouseEventArgs e)
        {
            Close();
        }

        private void ScreensaverForm_KeyDown(object sender, KeyEventArgs e)
        {
            Close();
        }
    }
}

The form is still empty, but can be filled with controls and functionality to your heart's desire.
To make windows recognize this screensaver, the .exe - file of the project has to be moved to C:\WINDOWS\system32 and be given the ending ".scr".
In the next post you find a complete screensaver with configuration form, it is a screensaver resembling the Matrix screens.

Run Application in Fullscreen

Some beginners would maybe say, that it is not possible to write "real" applications in C#, as for example with C++, because all C# application look the same, having this predefined border, menu etc.
C# though is a also in professional fields widely used language.
On the one hand WPF is the type of C# application you are looking for if you want to create fancy looking applications.
On the other hand, the mentioned menu and border can easily be hidden and the prorgam can be run in fullscreen mode, so that also the taskbar is hidden.
Therefore 3 properties have to be set (best in Form_Load() or in the constructor of the form), the following example explains these:

private void Form1_Load(object sender, EventArgs e)
{
    this.FormBorderStyle = FormBorderStyle.None; // hide border
    this.TopMost = true// show form in the very front, meaning also in front of the task bar
    this.Bounds = Screen.PrimaryScreen.Bounds; // set form size to screen size
}

Friday, July 9, 2010

Kill A Process

In a previous post I showed how to start processes with C#, today I want to show you how to terminate them again.
In .Net there are two functions, both from the class System.Diagnostics.Process. The first function is CloseMainWindow(). It closes the process in a "soft" way, meaning it is frozen or waiting for user input, the termination is not forced.
This can be done with the function Kill(). These 2 functions can be compared to "Terminate Task" and "Kill Process" from the task manager.
To get access on a running process, you need for example the function Process.GetProcessesByName(). This expects a string as parameter, which specifies the process name, and returns an array of the type System.Diagnostics.Process in which all processes of matching name are contained.
The following code tries to terminate the process first with CloseMainWindow(), waits 500ms and then kills the process with Kill(), if the previous prompt was not successful.

        private void TerminateProcess(string processName)
        {
            Process[] MatchingProcesses = Process.GetProcessesByName(processName);

            foreach (Process p in MatchingProcesses)
            {
                p.CloseMainWindow();
            }

            System.Threading.Thread.Sleep(500);

            MatchingProcesses = Process.GetProcessesByName(processName);

            foreach (Process p in MatchingProcesses)
            {
                p.Kill();
            }
        }

When calling this function, note that the ending ".exe" of the process file must not be given:

private void Form1_Load(object sender, EventArgs e)
{
    TerminateProcess("firefox");
}

Thursday, July 8, 2010

Read-out Screen Resolution

The following code determines the current screen resolution:
int Width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
int Height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
MessageBox.Show("The screen resolution is: " + Width.ToString() + " * " + Height.ToString());

Wednesday, July 7, 2010

Taking Screenshots with C#

Today I want to explain how to take a screenshot with the programming language C#.
I will immediately post the source code, which I will explain afterwards:
private Bitmap TakeScreenshot(bool onlyForm)
{
int StartX, StartY;
int Width, Height;

StartX = (onlyForm) ? (this.Left) : (0);
StartY = (onlyForm) ? (this.Top) : (0);
Width = (onlyForm) ? (this.Width) : (Screen.PrimaryScreen.Bounds.Width);
Height = (onlyForm) ? (this.Height) : (Screen.PrimaryScreen.Bounds.Height);

Bitmap Screenshot = new Bitmap(Width, Height);
Graphics G = Graphics.FromImage(Screenshot);

G.CopyFromScreen(StartX, StartY, 0, 0, new Size(Width, Height), CopyPixelOperation.SourceCopy);
return Screenshot;
}
The function used to take a screenshot is CopyFromScreen() of the class Graphics.
The overloadment used here takes 6 parameters. The first two ones describe the top left corner of the screen area which is supposed to be copied.
As parameter 3 and 4 are here given 0s. These parameters describe the top left corner of the screenshot on the resulting bitmap. Are here given different values, the screenshot is moved about these in the Bitmap.
The 5th parameter describes the size of the screenshot, the 6th one says, that the points are to be copied true to original.
The function TakeScreenshot() expects a boolean variable as parameter. Is it set to false, the complete screen is printed, otherwise only the active form is printed (the canvas size and the coordinates StartX and StartY are set according to the form).
If you are not sure about the meaning of the question marks in the code, check this post out.
With this code, a screenshot of the whole screen can for example be taken and copied to a PictureBox as follows:
pictureBox1.Image = TakeScreenshot(false);

Monday, July 5, 2010

Determine Free Storage Space and Overall Size of a Drive

Listing all drives of the computer can be done like described in the post Enumerate Partitions, using the class DriveInfo. This classes provides also further information on the devices, as for example the size of the drive and the free space on it.
The following application lists all drives, iterates over them, looks for the given drive and outputs the space information then (System.IO has to be included):

DriveInfo[] Drives = DriveInfo.GetDrives(); // read all drives

foreach (DriveInfo d in Drives)
{
if (d.Name == "C:\\"// output size of partition C (replace by any)
Console.WriteLine((d.TotalFreeSpace / (1024 * 1024 * 1024)) + " GB of total " + (d.TotalSize / (1024 * 1024 * 1024)) + " GB available.");
}
The class DriveInfo has on the own hand the property TotalFreeSpace used here, and on the other hand AvailableFreeSpace. The difference is, that the first one saves the available free space in total, whereas the second one just saves the free space reservced for the current user.

Sunday, July 4, 2010

Forwarding Key Inputs to the Form / Key Preview

Suppose, you want to define different key combinations globally on the form. For example, that the program should exit when pressing ESC or that a search function is called when pressing "CTRL + F".
On the form though will probably be controls like textboxes etc. which "take the focus away" from it.
If the user presses "ESC" then and a control has the focus, the key event of that control and not that of the form is triggered.
One possibility would be, to manually forward key events in one function.
Luckily there is a much more comfortable way though, we just have to set the property KeyPreview of the form to true.
Now all key presses are reported to the form as well.
Note though, that this just holds for key events which happen when the application is active, meaning key events which occur when another application has the focus are not treated.
Doing that is much harder, as there a so called KeyHooks is needed, about which I will post some other time.

Saturday, July 3, 2010

Determine RAM Usage

To read-out the RAM usage of the computer using C#, we use the class PerformanceCounter again, which has been introduced in the previous post on how to determine the CPU usage.
To determine the RAM usage though, we use "Memory" as CategoryName and "Available MBytes" as CounterName.
Furthermore, here NextValue() needs no reference point, so a singular call suffices.
A PerformanceCounter with this settings does not read the exact RAM usage though, but the size of the RAM which is not used (in MB).
In the taskmanager we find this value under "System Performance" - "Physical Memory - Available".
Now to the code:
using System.Diagnostics;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        PerformanceCounter RAMCounter = new PerformanceCounter(); // instance of the class PerformanceCounter

        private void Form1_Load(object sender, EventArgs e)
        {
            // initialize with the mentioned values
            RAMCounter.CategoryName = "Memory";
            RAMCounter.CounterName = "Available MBytes";
        }

        // read the RAM usage when clicking
        private void button1_Click(object sender, EventArgs e)
        {
            GetRAMUsage();
        }

        private void GetRAMUsage()
        {
            // call NextValue() and output the result
            MessageBox.Show((RAMCounter.NextValue()).ToString());
        }
    }
}

Friday, July 2, 2010

Determine CPU Usage

To read-out the CPU usage, we use the class PerformanceCounter.
With this class in general performance date can be read-out, by selecting the right parameters then also the CPU can be examined.
When using the class PerformanceCounter, the following properties have to be set to read the CPU usage:
  • CategoryName = "Processor". By doing so we set the general category for the monitoring.
  • CounterName = "% Processor Time". With this property we set the exact name of the performance indicator. 
  • InstanceName = "_Total". Catergories can be split in different instances. The category "_Total" represents always the mostly used data.
To finally get the performance data, we need the function NextValue().
For some performance data, like also in the case of the CPU usage, the function though needs a reference point to compare the current data with that, meaning the function has to be called at least twice.
Since both calls of the function have to be made with some time difference, I moved the reading of the CPU usage to an own thread, so that the run of the main application is not disturbed:
using System.Diagnostics;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }

        PerformanceCounter CPUCounter = new PerformanceCounter(); // instance of the class PerformanceCounter
        Thread CPUWatcher; // thread to read-out the CPU usage

        private void Form1_Load(object sender, EventArgs e)
        {
            // initialisize CPU counter with the value mentioned above
            CPUCounter.CategoryName = "Processor";
            CPUCounter.CounterName = "% Processor Time";
            CPUCounter.InstanceName = "_Total";
         
        }

        // when clicking the button, the CPU usage is determined
        private void button1_Click(object sender, EventArgs e)
        {
            // herefor the thread is (re-)initialized and started
            CPUWatcher = new Thread(new ThreadStart(GetCPUUsage));
            CPUWatcher.Start();
        }

        // the thread starts this function
        private void GetCPUUsage()
        {
            // twice the function NextValue() is called and the result displayed
            CPUCounter.NextValue();
            System.Threading.Thread.Sleep(1000);
            MessageBox.Show(CPUCounter.NextValue().ToString());
        }
    }
}