Click here to Skip to main content
15,886,724 members
Articles / Programming Languages / C#

Creating a postit control in C# (.Net 3.5)

Rate me:
Please Sign up or sign in to vote.
4.50/5 (5 votes)
8 Aug 2012CPOL3 min read 39.9K   877   15   20
A postit control

Introduction

This tutorial describes an approach for creating a postit control in C# (.NET 3.5). It started when I was experimenting in Paint to draw a postit. At some point, I decided to make a control out of it. This could be used, for instance, in a virtual SCRUM-board or in a todo-application.

a simple postit

a postit with more text

multiple postits

Features 

Before I started, I defined a short list of features to implement. Other features will be certainly added in future versions.

Properties to set at creation:

  • Message: The message itself 
  • Font: The font type and size
  • TextColor: The text color of the message
  • PostitColor: The color of the postit
  • Urgency: A flag that indicates whether the task is urgent or not

Actions to perform on the postit:

  • Move: moving the postit around
  • Change size: making the postit larger or smaller with the mouse wheel
  • Reset size: Setting the postit to its original size

Using the code

This section first describes the implementation of the control and then the implementation of a sample client using the control.

Step 1: Create an image

After some experimentation, I created a bitmap that was good enough. You can of course use the image that is available in the attachments.

Step 2: Project creation

Create a project of type Windows Forms Application in Visual Studio.

Step 3: Add image as resource

  • Open the project properties and go to the Resources tab
  • Select Add Resource and then Add Existing File.
  • Select the bitmaps attached to this article (‘lightyellow.bmp’, ‘flatyellow.bmp’)

Step 4: Add user control

Add a new user control via the Solution Explorer and name it Postit.

Step 5: Implementing the control

The following properties are defined here: 

C#
private string message;  // the message
private Size postitSize; // the size of the postit
private Bitmap postitBitMap; // the bitmap

private int sizeDiff = 20; // the diff for resizing the postit
private int maxWidth = 750; // the maximum width
private int maxHeigth = 750; // the maximum height
private int minWidth = 150; // the minimum width
private int minHeigth = 150; // the minimum width

private int blackBorderWidth = 50; // the width to avoid a black border around the bitmap
private int blackBorderHeight = 70; // the height to avoid a black border around the bitmap

private int messageLeft = 5; // the left position of the message
private int messageTop = 100; // the top position of the message

private bool isUrgent = false; // the urgency flag
private int urgencyFlagLeft = 5; // the left position of the urgency flag
private int urgencyFlagTop = 5; // the top position of the urgency flag

private Size originalSize; // the original size
private Font messageFont = new Font("Tahoma", 20); // the font
private Brush messageColor = Brushes.Black; // the font color
private PostitColor postitColor; // the color of the postit

The postit control has three different constructors:

C#
public Postit(String message)
{
    this.message = message;
    this.postitColor = PostitColor.FlatYellow;
    this.init();
}

public Postit(String message, Font messageFont, Brush messageColor, PostitColor postitColor)
{              
    this.message = message;
    this.messageFont = messageFont;
    this.messageColor = messageColor;
    this.postitColor = postitColor;
    this.init();            
}

public Postit(String message, Font messageFont, Brush messageColor, PostitColor postitColor, bool isUrgent)
{            
    this.message = message;
    this.messageFont = messageFont;
    this.messageColor = messageColor;
    this.postitColor = postitColor;
    this.isUrgent = isUrgent;
    this.init();
}

All constructors call the init()-method, that does all the general initialization, i. e. it creates the bitmap, defines the size of the postit and the original size and sets the event handlers:

C#
private void init()
{
    //set the control styles
    SetStyle(ControlStyles.OptimizedDoubleBuffer | 
        ControlStyles.UserPaint | 
        ControlStyles.OptimizedDoubleBuffer, true);
    
    InitializeComponent();
    
    // set the postit bitmap
     if (this.postitColor == PostitColor.LightYellow)
         this.postitBitMap = PostitDemo.Properties.Resources.lightyellow;
     else
         this.postitBitMap = PostitDemo.Properties.Resources.flatyellow;
                
    //set the size
    this.postitSize = this.postitBitMap.Size;
    this.originalSize = this.Size;                        
                
    // set the event handlers
    this.MouseWheel += new MouseEventHandler(this.OnMouseWheel);
    this.DoubleClick += new EventHandler(this.OnDoubleClick);
}

The postit control is painted with the help of the OnPaint and OnPaintBackground methods. Both methods are overridden: 

C#
protected override void OnPaint(PaintEventArgs e)
{
    this.drawPostit(e.Graphics);                
}

private void drawPostit(Graphics controlGraphics)
{
    // define a rectangle to draw the image in. 
    // NOTE: Make the rectangle slightly larger than the original bitmap to avoid a black border.
    Rectangle imageRect = new Rectangle(0, 0, this.postitSize.Width+this.blackBorderWidth, 
        this.postitSize.Height+this.blackBorderHeight);
    controlGraphics.DrawImage(this.postitBitMap, imageRect);            
    
    // draw the text
    RectangleF textRect = new RectangleF(this.messageLeft, this.messageTop, this.postitSize.Width, 
        this.postitSize.Height);
    StringFormat drawFormat = new StringFormat();
    drawFormat.Alignment = StringAlignment.Center;            
    controlGraphics.DrawString(this.message, this.messageFont, this.messageColor, textRect,
        drawFormat);

    // draw the emergency flag if necessary
    if (this.isUrgent)
    {
        RectangleF urgentRect = new RectangleF(this.urgencyFlagLeft, this.urgencyFlagTop, 
            this.postitSize.Width / 10, 100);
        controlGraphics.DrawString("!", new Font("Tahoma", 50,FontStyle.Bold), Brushes.Red, 
            urgentRect);
    }
}

The drawPostit method first paints the bitmap. Thereafter, the message is painted with the given font. At last, the urgency flag is painted, if the flag is set. 

The OnPaintBackground-method is empty to avoid that the background is painted. This minimizes problems with flickering when the postit is moved. 

C#
protected override void OnPaintBackground(PaintEventArgs pevent)
{
    //Don't allow the background to paint
}

Resizing of the postit is handled by the OnMouseWheel method:

C#
protected void OnMouseWheel(object sender, MouseEventArgs e)
{
    this.resize(e);
}

private void resize(MouseEventArgs e)
{
    int width = this.Size.Width;
    int height = this.Size.Height;

    // make it larger
    if (e.Delta > 0)
    {
        if ((width + this.sizeDiff <= this.maxWidth)
        && (height + this.sizeDiff <= this.maxHeigth))
        {
            width += this.sizeDiff;
            height += this.sizeDiff;
        }
    }
    else // make it smaller
    {
        if ((width - this.sizeDiff >= this.minWidth)
        && (height - this.sizeDiff >= this.minHeigth))
        {
            width -= this.sizeDiff;
            height -= this.sizeDiff;
        }
    }

    // set the new size
    this.Size = new Size(width, height);
    this.postitSize = new Size(width - 25, height - 35);
}

As stated above, the size of the postit shall be reset through a double click:

C#
protected void OnDoubleClick(object sender, EventArgs e)
{
    this.resetSize();
}

private void resetSize()
{
    this.Size = this.originalSize;
    this.postitSize = this.postitBitMap.Size;
}

Step 6: Implement the form

Now the postit control is ready and the following describe the creation of a Windows Form that uses the postit control:

The form contains the following controls:

  • a groupbox  (name=grpPostitSettings)
  • a label (name=lblMessageText)
  • a textbox (name=txtMessage)
  • ...and a button (name=btnCreatePostit)

Besides, the form has the following properties:

C#
private Postit currentPostit = null;  // represents the currently selected postit
private List<Postit> postitList = new List<Postit>();

private Point ptStartPosition; // the start position of the postit when moving
private Point ptEndPosition; // the end position of the postit when moving

When the button is clicked, a new postit is created, event handlers are set and the control is added to the form: 

C#
private void btnCreatePostit_Click(object sender, EventArgs e)
{
    Postit postit = new Postit(this.txtMessage.Text, new Font("Comic", 20), 
        Brushes.Green, PostitColor.FlatYellow, this.chkUrgent.Checked);
    postit.Location = new Point(5, 100);
    postit.MouseDown += new MouseEventHandler(this.OnMouseDown);
    postit.MouseMove += new MouseEventHandler(this.OnMouseMove);
    postit.BackColor = Color.FromKnownColor(KnownColor.Transparent);
    this.Controls.Add(postit);

    this.currentPostit = postit;
    this.postitList.Add(postit);
}

The mouse events MouseDown and MouseMove are handled here as well:

C#
private void OnMouseDown(object sender, MouseEventArgs e)
{
    this.currentPostit = sender as Postit;
    this.ptStartPosition = this.PointToScreen(e.Location);
}

private void OnMouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Cursor.Current = Cursors.SizeAll;
        this.ptEndPosition = this.currentPostit.PointToScreen(e.Location);
        ptEndPosition.Offset(-ptStartPosition.X, -ptStartPosition.Y);
        this.currentPostit.Location = ptEndPosition;
        this.Invalidate();
    }
}

History  

  • 2012-07-30: This is the first version.
  • 2012-08-09: Added the postit color as new property.

Helpful resources

License

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


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionProblem displaying message Pin
carlosvela114-Apr-14 14:27
carlosvela114-Apr-14 14:27 
AnswerRe: Problem displaying message Pin
martinbaeumer198122-Apr-14 5:51
martinbaeumer198122-Apr-14 5:51 
BugBug while compiling Pin
Wrangly15-Apr-13 3:51
Wrangly15-Apr-13 3:51 
GeneralRe: Bug while compiling Pin
martinbaeumer198115-Apr-13 5:14
martinbaeumer198115-Apr-13 5:14 
GeneralRe: Bug while compiling Pin
martinbaeumer198115-Apr-13 12:35
martinbaeumer198115-Apr-13 12:35 
GeneralRe: Bug while compiling Pin
Wrangly15-Apr-13 23:50
Wrangly15-Apr-13 23:50 
GeneralRe: Bug while compiling Pin
martinbaeumer198116-Apr-13 1:13
martinbaeumer198116-Apr-13 1:13 
GeneralRe: Bug while compiling Pin
Wrangly16-Apr-13 1:54
Wrangly16-Apr-13 1:54 
GeneralRe: Bug while compiling Pin
martinbaeumer198116-Apr-13 3:31
martinbaeumer198116-Apr-13 3:31 
GeneralRe: Bug while compiling Pin
Wrangly16-Apr-13 3:46
Wrangly16-Apr-13 3:46 
GeneralRe: Bug while compiling Pin
martinbaeumer198116-Apr-13 4:58
martinbaeumer198116-Apr-13 4:58 
GeneralRe: Bug while compiling Pin
martinbaeumer198122-Apr-13 0:54
martinbaeumer198122-Apr-13 0:54 
GeneralRe: Bug while compiling Pin
Wrangly22-Apr-13 6:22
Wrangly22-Apr-13 6:22 
QuestionGood article! Pin
Volynsky Alex9-Aug-12 5:59
professionalVolynsky Alex9-Aug-12 5:59 
QuestionComplete lack of Aesthetics Pin
JoseMenendez30-Jul-12 5:21
JoseMenendez30-Jul-12 5:21 
Though good, whenever working with this kind of controls, assistance of a designer is of vital importance.

The colors and fonts are "oh my eyes!" bad. If no designer at hand, a quick google images search would help:

Google search for postit[^]
J

AnswerRe: Complete lack of Aesthetics Pin
martinbaeumer198130-Jul-12 8:42
martinbaeumer198130-Jul-12 8:42 
GeneralRe: Complete lack of Aesthetics Pin
Pete O'Hanlon30-Jul-12 21:32
mvePete O'Hanlon30-Jul-12 21:32 
QuestionNo download links? Pin
cp2008042829-Jul-12 21:39
cp2008042829-Jul-12 21:39 
AnswerRe: No download links? Pin
martinbaeumer198129-Jul-12 22:28
martinbaeumer198129-Jul-12 22:28 
AnswerRe: No download links? Pin
martinbaeumer198130-Jul-12 4:23
martinbaeumer198130-Jul-12 4:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.