0

我在 OneNote 中创建了一个工具栏按钮,如Daniel Escapa 所示。通常,它可以工作,但有时 OneNote 决定将工具栏按钮变灰,使其无法单击。我无法弄清楚是什么状态导致了这种情况。我怎样才能防止这种情况?

我很小心地从 OnEvent 和 OnClick 处理程序返回 true,但也许有一种特殊情况导致它返回 false?这是我的代码:

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 ""; 
        }
    }
}
4

2 回答 2

1

在我的项目属性 Build 选项卡中,我忘记在 Release 模式下检查“Register for COM interop”。这导致了间歇性错误。

于 2010-10-27T10:18:59.070 回答
1

编辑:我现在记得这个问题!当您关闭 OneNote 时,检查它的实例是否仍在 taskman 中运行,我认为这种锁定插件在未来实例中并将它们变灰,确保您没有任何代码留下运行会导致实例停留活。

于 2010-10-25T09:45:41.583 回答