Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

Creating a Taskbar

4.38/5 (7 votes)
3 Jun 2011CPOL2 min read 43.3K   1.8K  
In this tutorial, I will explain how to create a Windows taskbar in C# with the Merula Shell Library.
Sample Image - maximum width is 600 pixels

Introduction

In this tutorial, I will explain how to create a Windows taskbar in C# with the Merula Shell Library.

You can download the Merula Shell Library here.

First, create a new project in Visual Studio. In the new project window, choose a WPF application. Add the three DLLs from the Merula shell library to the reference of the project.

Creating a Usercontrol

For every window, I want to create a fancy button with an image and the tile, in my taskbar. So let’s create a usercontrol, I called it TaskbarButton.

XML
<UserControl    x:Class="DemoProject.TaskbarButton"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="300">
<Grid    Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image    Name="imgIcon"/>
<TextBlock    Name="lblTitle" Grid.Column="1" Margin="4" />
</Grid>
</UserControl>

In the usercontrol, add an image control and a textblock control.

Add the following code in the codebehind from the usercontrol:

C#
using System;
using System.Windows.Controls;
using Window =    MerulaShell.windows.Window;
namespace DemoProject
{
    /// <summary>
    /// Interaction logic for TaskbarButton.xaml
    /// </summary>
    public partial class TaskbarButton : UserControl
    {
       private    readonly Window    window;
       //Constructor    with a MerulaShell.windows.window as input
       public    TaskbarButton(Window window)
       {
           InitializeComponent();
           this.window    = window;
           window.TitleChanged +=    WindowTitleChanged; 	//when the title of 
							//the window changes
           SetProperties(); //set the window properties
       }
       private    delegate void    DelegateVoid();
       void    WindowTitleChanged(object sender, EventArgs e)
       {
           Dispatcher.Invoke(new DelegateVoid(SetTitle));    //invoke because 
					//merula shell runs in another thread
       }
       private    void SetTitle()
       {
           lblTitle.Text = window.Title; 	// sets the title in the textblock
       }
       private    void SetProperties()
       {
           imgIcon.Source = window.ProgramIcon;   // sets the icon of the window
           lblTitle.Text = window.Title; 	// sets the title in the textblock
       }
    }
}

Your usercontrol will now look something like this:

Sample Image - maximum width is 600 pixels

Loading Windows

The next step is loading the windows in our taskbar. Go to the XAML of the main window and replace the grid with the stackpanel.

My main window XAML is as follows:

XML
<Window    x:Class="DemoProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel    Name="pnlTasks">

</StackPanel>
</Window> 

Add the following code to the codebehind of the mainwindow:

C#
using System;
using System.Windows;
using MerulaShellController.ManageWindows;
namespace DemoProject
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private    ManageWindows windowManager;
        public    MainWindow()
        {
            InitializeComponent();
            windowManager = new ManageWindows();    	//create a new windowmanager  
						//only one needed
            Closed += MainWindow_Closed; 		//on close event
            windowManager.WindowListChanged    += WindowManagerWindowListChanged; //when 
						//the list of windows is changed
            LoadWindows(); //load the windows
        }
        private    delegate void    DelegateVoid();
        void    WindowManagerWindowListChanged(object sender,    EventArgs e)
        {
            //invoke    because merula shell runs in another thread
            Dispatcher.Invoke(new DelegateVoid(LoadWindows));
        }
        void    MainWindow_Closed(object sender, EventArgs e)
        {
            Environment.Exit(0);    			//stops the merula shell
        }
        private    void LoadWindows()
        {
            ClearTasks();				//delete old tasks
            var    windows = windowManager.GetWindows();//windowManager.GetWindows()    
						//returns all the active windows
            foreach    (var window in    windows)
            { //foreach    window add a taskbar button
                pnlTasks.Children.Add(new TaskbarButton(window));
            }
        }
        private    void ClearTasks() 		//delete old tasks
        {
            pnlTasks.Children.Clear();
        }
    }
}

As a result, we now have a window with the current active windows. The list of windows will be updated when the number of windows change and if a tile of a window changes.

Sample Image - maximum width is 600 pixels

Making It Interactive

You still can’t interact with the windows, like minimize or maximize them. Open up the TaskButton usercontrol. Add a MouseUp handler to the usercontrol tag.

C#
MouseUp="UserControlMouseUp"

Add the following code to the codebehind of the usercontrol:

C#
private    bool active;
private    void UserControlMouseUp
	(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    Background = Brushes.LightBlue; 		//set a nice active color
    if(active)    				//when active minimize and maximize
        window.MaximizeMinimize(); 		//minimize or maximize
    else
    {
        active = true; 			//set active
        window.SetToForeground(); 		//set window to foreground
    }
    InvokeActivated(new EventArgs());
}
public    void SetNonActive()
{
    active = false;    			//set active to false
    Background = Brushes.White; 		//reset color to white
}
public    event EventHandler    Activated; 	//event to notify the mainwindow
public    void InvokeActivated(EventArgs    e)
{
    EventHandler    handler = Activated;
    if    (handler != null) handler(this, e);
}

You’ll also have to edit the code behind of the mainwindow. Change the method LoadWindows():

C#
private void    LoadWindows()
{
    ClearTasks();//delete old tasks
    var    windows = windowManager.GetWindows();	//windowManager.GetWindows()    
						//returns all the active windows
    foreach    (var window in    windows)
    { //foreach    window add a taskbar button
        var    button = new TaskbarButton(window);
        button.Activated +=    ButtonActivated; 	//add a event to the taskbarbutton
        pnlTasks.Children.Add(button);
    }
}

Last but not least, you’ll have to create an event handler. Add it to the codebehind of the mainwindow:

C#
void ButtonActivated(object    sender, EventArgs e)
{
    var    senderButton = (TaskbarButton) sender; 	//the sender button
    var    otherButtons = pnlTasks.Children.OfType<TaskbarButton>().Where
		(b    => b != senderButton); 	//select the other buttons
    foreach    (var otherButton in    otherButtons)
    {
        otherButton.SetNonActive(); 		//sets the other buttons to nonactive
    }
} 

As a result, you have a working taskbar.

Merula Shell

More information about merula shell can be found at the following links:

History

  • 3rd June, 2011: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)