I've created a toolbar button in OneNote like Daniel Escapa showed. Usually, it works, but sometimes OneNote decides to grey out the toolbar button, making it impossible to click. I can't figure out what state is causing this. How can I prevent this?
I'm careful to return true from the OnEvent and OnClick handlers, but maybe there's a special case that is causing it to return false? Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OneNoteAddin;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;
using OneNote = Microsoft.Office.Interop.OneNote;
namespace NoteTakerPlugin
{
[Guid("792d0410-d53c-402d-92c9-5db9ea29f644")]
public class NoteTakerButton : IOneNoteAddIn
{
// for sending messages to window handles
private struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
// this should be hardcoded in the note taker application
private const string NoteTakerAppClassName = "CubicNoteTaker-792d0410-d53c-402d-92c9-5db9ea29f644::EventReceiver";
private const int WM_COPYDATA = 0x4A;
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);
IntPtr app;
public NoteTakerButton()
{
tellAppSomething("{ \"appStart\": true }", false);
}
public bool OnClick([In] String strActivePageID)
{
// send the click event to the note taker app
tellAppSomething("{ \"click\": { \"pageId\": \"" + strActivePageID + "\" }}", true);
return true;
}
public bool OnEvent([In] OneNote.OneNoteAddIn_Event evt, [In] String strParameter)
{
// send the event to the note taker app
tellAppSomething("{ \"event\": { \"id\": " + (int)evt + ", \"param\": \"" + strParameter + "\" }}", false);
return true;
}
private void tellAppSomething(String message, bool startProgram)
{
// if the process is running
refreshAppStatus();
if( app != IntPtr.Zero )
{
// send a window message to the process telling it the message
sendMessageTo(app, message);
}
else if( startProgram )
{
// start the process with a command line telling it the message
startApp(message);
}
}
private void refreshAppStatus()
{
app = FindWindowByCaption(IntPtr.Zero, NoteTakerAppClassName);
}
private void sendMessageTo(IntPtr hWnd, String msg)
{
int wParam = 0;
int result = 0;
if (hWnd != IntPtr.Zero )
{
byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = IntPtr.Zero;
cds.lpData = msg;
cds.cbData = len + 1;
result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
}
}
private void startApp(String args)
{
string exe = getAppExe();
if (File.Exists(exe))
{
System.Diagnostics.Process.Start(exe, args);
}
else
{
System.Windows.Forms.MessageBox.Show("You need to reinstall the Note Taker application. The installation is corrupted.");
}
}
private string getAppExe()
{
// use the registry to find where the application is installed
RegistryKey noteTakerKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\NoteTaker");
String path = noteTakerKey.GetValue("Path","").ToString();
String exe = noteTakerKey.GetValue("Exe", "").ToString();
if (!Directory.Exists(path))
return "";
String combo = Path.Combine(path, exe);
if( File.Exists(combo) )
return combo;
else // not installed
return "";
}
}
}