Jesper Niedermann's .NET Blog
about .NET and related technologies RSS 2.0
# Friday, 13 November 2009

In the Day View project I needed to open a Windows 7 Sticky Note programmatically and write to it. Unfortunately I found out that there is not an API for the Sticky Notes application. At least not a managed one.

So I had to fake it and make my own API. I have made a small class that basicly uses Process.Start to open the program, and SendKeys to write to the Note.

Here it is:

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace DayView
{
public class StickyNote
{
private const string m_ProcessName = "StikyNot";
private readonly string m_ProcessFileName = Path.Combine(Environment.SystemDirectory, "StikyNot.exe");
private event EventHandler m_Activated = delegate { };
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

public void Activate()
{
bool makeNewNote = true;
Process p = FindProcess();
if (p == null)
{
p = StartProcess();
if (!NoteContainsText(p.MainWindowHandle))
{
makeNewNote = false;
}
}
var state = new StickyNoteState();
state.MakeNewNote = makeNewNote;
state.StickyNoteProcess = p;
ThreadPool.QueueUserWorkItem(Activate, state);
}

private void Activate(object state)
{
var stickyNoteState = state as StickyNoteState;
if (stickyNoteState.MakeNewNote)
{
NewNote(stickyNoteState.StickyNoteProcess);
}
OnActivated();
}

private Process StartProcess()
{
var startInfo = new ProcessStartInfo(m_ProcessFileName);
Process p = Process.Start(startInfo);
Thread.Sleep(200); //This is an annoying hack. I haven't been able to find another way to be sure the process is started.
return p;
}

private void NewNote(Process p)
{
SetForegroundWindow(p.MainWindowHandle);
Signal("^n");
}

/// <summary>
/// Weird hack to find out if note contains text.
/// </summary>
/// <returns></returns>
private bool NoteContainsText(IntPtr handle)
{
string textOfClipboard = Clipboard.GetText();
Signal("^a");
Signal("^c");
Signal("{RIGHT}");
string noteText = Clipboard.GetText().Trim();
if (textOfClipboard == null)
{
Clipboard.SetText(textOfClipboard);
}
return !string.IsNullOrEmpty(noteText);
}

private Process FindProcess()
{
Process[] processes = Process.GetProcessesByName(m_ProcessName);
if(processes != null && processes.Length > 0)
{
return processes[0];
}
return null;
}

internal void OnActivated()
{
m_Activated(this, new EventArgs());
}

public event EventHandler Activated
{
add { m_Activated += value; }
remove { m_Activated -= value; }
}

public void Signal(string message)
{
SendKeys.SendWait(message);
SendKeys.Flush();
}
}

public class StickyNoteState
{
public bool MakeNewNote { get; set; }
public Process StickyNoteProcess { get; set; }

}
}

It works OK. The only really buggy thing in the code is in line 47, where I have to use a Thread.Sleep in order to make sure the note is loaded before I write to it. Unfortunately this is necessary because the Process class does not provide an event to signal when it has finished loading. I arbitrarily chose 200 milliseconds for the Sleep. Larger values might be necessary on slower computers.

In order to use the class you have to configure SendKeys in your app.config like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="SendKeys" value="SendInput"/>
</appSettings>
</configuration>
Friday, 13 November 2009 23:28:10 (GMT Standard Time, UTC+00:00)  #    Comments [4] -
.NET | Tips & Tricks | Windows 7
Wednesday, 23 June 2010 15:28:03 (GMT Daylight Time, UTC+01:00)
Great article...
I need to create a note with some text inside.
Is there a way to do this?
Wednesday, 23 June 2010 20:44:00 (GMT Daylight Time, UTC+01:00)
Hi Bruno,

Well I guess it is not that obvious how to use my API. Sorry...

Here is an example:

public void NewNote(string someText)
{
var note = new StickyNote();
note.Activate();
note.Activated += (s, e) => { note.Signal(someText); };
}

Just use \n in the text string for lineshifts.
Jesper
Saturday, 14 July 2012 21:37:40 (GMT Daylight Time, UTC+01:00)
Great and valuable work done by you.Can you tell how to delete or update existing notes?
shoaib
Tuesday, 24 July 2012 18:52:51 (GMT Daylight Time, UTC+01:00)
Hi Shoaib,

Thank you.

Since there is really no API for Sticky Notes you would have to emulate a user like I did in the StickyNote class. E.g. Delete is possible by sending Ctrl+D to the App. I have not tried this, you are on your own :)

Not elegant but I think that is the only way unless Microsoft has come up with an API since I wrote the article.

Good luck.
Jesper
Comments are closed.
Archive
<2017 December>
SunMonTueWedThuFriSat
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456
About the author/Disclaimer
I am a software architect with focus on Microsoft Technologies. I have been working with these in different large companies since 1995. I am currently employed at UVdata A/S.
Here is my View Jesper Niedermann's profile on LinkedIn

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Privacy policy
The privacy policy of this site.

© Copyright 2017
Jesper Niedermann
Sign In
Statistics
Total Posts: 28
This Year: 0
This Month: 0
This Week: 0
Comments: 32
All Content © 2017, Jesper Niedermann
DasBlog theme 'Niedermann' created by Jesper Niedermann, based on 'Business' created by Christoph De Baene (delarou)