【问题标题】:Using Microsoft Word Plug-in/VSTO to intercept Drag/Drop Events使用 Microsoft Word 插件/VSTO 拦截拖放事件
【发布时间】:2015-10-30 19:18:29
【问题描述】:

问题:我正在编写一个 Word 2013 加载项/插件/VSTO,需要拦截从/到我的插件所在的 Word 实例的拖放事件跑步。

解决方案:我正在尝试使用RegisterDragDrop functionIDropTarget 的实现来传递到寄存器函数。不幸的是,我的 IDropTarget 实现中的所有事件都没有触发。我猜我遗漏了一些东西,或者这可能根本无法通过插件实现。

问题:

  1. 如果可能,我应该将什么句柄传递给 RegisterDragDrop 方法?是插件的句柄吗? MS-Word 实例本身的句柄?
  2. 如果这是不可能的,使用Windows Procedures(挂钩Windows 调用)会是一个潜在的解决方案吗?

这是我的代码:

NativeMethods.cs:

// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms678405(v=vs.85).aspx
[DllImport("ole32.dll")]
public static extern int RegisterDragDrop(IntPtr hwnd, IDropTarget pDropTarget);

这个AddIn.cs:

private void ThisAddIn_Startup(object sender, EventArgs e)
{
    int temp = 0;
    Process[] pWords = Process.GetProcessesByName("WINWORD");
    foreach (Process process in pWords)
    {
        temp = process.Id;
    }

    NativeMethods.RegisterDragDrop(Process.GetProcessById(temp).Handle, new MyDropTarget())
}

MyDropTarget.cs:

public class MyDropTarget : IDropTarget
{
    public void OnDragDrop(DragEventArgs e)
    {
        throw new NotImplementedException();
    }

    public void OnDragEnter(DragEventArgs e)
    {
        throw new NotImplementedException();
    }

    public void OnDragLeave(EventArgs e)
    {
        throw new NotImplementedException();
    }

    public void OnDragOver(DragEventArgs e)
    {
        throw new NotImplementedException();
    }
}

【问题讨论】:

    标签: c# .net ms-word drag-and-drop vsto


    【解决方案1】:

    可以使用RegisterDragDrop函数,但在此之前,需要调用RevokeDragDrop,可以这样获取句柄:

      [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
     private  static IntPtr GetCurrentWindowHandle()
        {
            IntPtr windowHandle = IntPtr.Zero;
    
            windowHandle = FindWindow("OpusApp", null);
    
            windowHandle = FindWindowEx(windowHandle, IntPtr.Zero, "_WwF", null);
            windowHandle = FindWindowEx(windowHandle, IntPtr.Zero, "_WwB", null);
            windowHandle = FindWindowEx(windowHandle, IntPtr.Zero, "_WwG", null);
    
            return windowHandle;
        }
    

    这是我的代码:

       [ComImport, Guid("00000122-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleDropTarget
    {
        [PreserveSig]
        int OleDragEnter([In, MarshalAs(UnmanagedType.Interface)] object pDataObj, [In, MarshalAs(UnmanagedType.U4)] int grfKeyState, [In, MarshalAs(UnmanagedType.U8)] long pt, [In, Out] ref int pdwEffect);
        [PreserveSig]
        int OleDragOver([In, MarshalAs(UnmanagedType.U4)] int grfKeyState, [In, MarshalAs(UnmanagedType.U8)] long pt, [In, Out] ref int pdwEffect);
        [PreserveSig]
        int OleDragLeave();
        [PreserveSig]
        int OleDrop([In, MarshalAs(UnmanagedType.Interface)] object pDataObj, [In, MarshalAs(UnmanagedType.U4)] int grfKeyState, [In, MarshalAs(UnmanagedType.U8)] long pt, [In, Out] ref int pdwEffect);
    }
    
    internal class MyDropTarget : IOleDropTarget
    {
        [DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern int RegisterDragDrop(IntPtr hwnd, IOleDropTarget target);
    
        [DllImport("ole32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern int RevokeDragDrop(IntPtr hwnd);
        public int OleDragEnter(object pDataObj, int grfKeyState, long pt, ref int pdwEffect)
        {
            throw new NotImplementedException();
        }
    
        public int OleDragOver(int grfKeyState, long pt, ref int pdwEffect)
        {
            throw new NotImplementedException();
        }
    
        public int OleDragLeave()
        {
            throw new NotImplementedException();
        }
    
        public int OleDrop(object pDataObj, int grfKeyState, long pt, ref int pdwEffect)
        {
            throw new NotImplementedException();
        }
    }
    

    像这样使用它:

      var hwnd = GetCurrentWindowHandle();
                MyDropTarget.RevokeDragDrop(hwnd);
                var rtn = MyDropTarget.RegisterDragDrop(hwnd, new MyDropTarget());
    

    【讨论】:

      【解决方案2】:

      您是否检查了 RegisterDragDrop 调用的返回值?您很有可能会返回 DRAGDROP_E_ALREADYREGISTERED,除非您传入的窗口句柄无效,在这种情况下您将获得 DRAGDROP_E_INVALIDHWND。不确定您获取窗户的方式是否正确。

      Word 应该已经将其窗口注册为放置目标,因此您可能需要在注册自己的窗口句柄上调用 RevokeDragDrop。但是,如果您想在放置时检查 IDataObject 并且只处理某些事情而让 Word 处理其他所有事情,这会给您带来麻烦。 (在这种情况下你需要做更多的工作)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-13
        相关资源
        最近更新 更多