问题:我正在编写Word 2013加载项/插件/ VSTO,需要拦截来自/到我的插件所在的Word实例的拖放事件运行。
解决方案:我正在尝试将RegisterDragDrop function与IDropTarget的实现一起用于传递到寄存器功能。不幸的是,我的IDropTarget实现中的所有事件都没有触发。我猜我错过了一些东西,或者甚至连插件都没有。
问题:
这是我的代码:
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);
ThisAddIn.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();
}
}
答案 0 :(得分: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());
答案 1 :(得分:0)
您是否检查了RegisterDragDrop调用的返回值?您可能会重新获得DRAGDROP_E_ALREADYREGISTERED,除非您传入的窗口句柄无效,在这种情况下您将获得DRAGDROP_E_INVALIDHWND。不确定你获取窗户的方式是正确的。
Word应该已经将其窗口注册为放置目标,因此您可能需要在注册自己的窗口句柄之前调用RevokeDragDrop。但是,如果您想检查drop上的IDataObject并且只处理某些事情并让Word处理其他内容,这会让您遇到麻烦。 (在这种情况下,你需要做更多的工作)