Отвечая на мой собственный вопрос: можно восстановить события перетаскивания, которые были проглочены вверх по течению.
Сначала я использовал интерфейс IOleDropTarget, который выглядит следующим образом;
<ComImport, Guid("00000122-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IOleDropTarget
<PreserveSig>
Function OleDragEnter(
<[In], MarshalAs(UnmanagedType.[Interface])> ByVal pDataObj As Object,
<[In], MarshalAs(UnmanagedType.U4)> ByVal grfKeyState As Integer,
<[In], MarshalAs(UnmanagedType.U8)> ByVal pt As Long,
<[In], Out> ByRef pdwEffect As Integer) As Integer
<PreserveSig>
Function OleDragOver(
<[In], MarshalAs(UnmanagedType.U4)> ByVal grfKeyState As Integer,
<[In], MarshalAs(UnmanagedType.U8)> ByVal pt As Long,
<[In], Out> ByRef pdwEffect As Integer) As Integer
<PreserveSig>
Function OleDragLeave() As Integer
<PreserveSig>
Function OleDrop(
<[In], MarshalAs(UnmanagedType.[Interface])> ByVal pDataObj As Object,
<[In], MarshalAs(UnmanagedType.U4)> ByVal grfKeyState As Integer,
<[In], MarshalAs(UnmanagedType.U8)> ByVal pt As Long,
<[In], Out> ByRef pdwEffect As Integer) As Integer
End Interface
Затем, пока мы работаем над интерфейсами, давайте создадим красивые значки, которые Windows Explorer отображает при перетаскивании файла с этим интерфейсом.
Imports IDataObject_Com = System.Runtime.InteropServices.ComTypes.IDataObject
Imports System.Windows.Interop
Imports System.Runtime.InteropServices
Namespace Browser
<StructLayout(LayoutKind.Sequential)>
Public Structure Win32Point
Public x As Integer
Public y As Integer
End Structure
<ComImport>
<Guid("4657278A-411B-11d2-839A-00C04FD918D0")>
Public Class DragDropHelper
End Class
<ComVisible(True)>
<ComImport>
<Guid("4657278B-411B-11D2-839A-00C04FD918D0")>
<InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
Interface IDropTargetHelper
Sub DragEnter(
<[In]> ByVal hwndTarget As IntPtr,
<[In], MarshalAs(UnmanagedType.[Interface])> ByVal dataObject As IDataObject_Com,
<[In]> ByRef pt As Win32Point,
<[In]> ByVal effect As Integer)
Sub DragLeave()
Sub DragOver(
<[In]> ByRef pt As Win32Point,
<[In]> ByVal effect As Integer)
Sub Drop(
<[In], MarshalAs(UnmanagedType.[Interface])> ByVal dataObject As IDataObject_Com,
<[In]> ByRef pt As Win32Point,
<[In]> ByVal effect As Integer)
Sub Show(
<[In]> ByVal show As Boolean)
End Interface
Вам необходимо реализовать интерфейс IOleDropTaget, который затем будет предоставлять событияDragEnter, Over, Leave и Drop.
Чтобы подключить эти события, вам не нужно ничего знать о сообщениях messageloop или wndproc, как было указано выше.Что вам нужно знать, так это то, что одно из окон Chromium с именем класса "Chrome_WidgetWin_0" зарегистрировано для перетаскивания, и его необходимо сначала отозвать, прежде чем вы сможете получить события.
Примеры CefSharp показывают, какуглубиться в окна Chromium, но обычно получается другой класс окон.В этом случае я использую следующее (обратите внимание, я отменяю все окна, которые я нахожу по пути в функции обратного вызова, но кажется, что зарегистрирован только Chrome_WidgetWin_0.
Const Chrome_WidgetWin As String = "Chrome_WidgetWin_0"
Private Function TryFindHandl(ByVal browserHandle As IntPtr, <Out> ByRef chromeWidgetHostHandle As IntPtr) As Boolean
Dim cbXL As New NativeMethodsEx.EnumChildCallback(AddressOf EnumChildProc_Browser)
NativeMethodsEx.EnumChildWindows(browserHandle, cbXL, chromeWidgetHostHandle)
Return chromeWidgetHostHandle <> IntPtr.Zero
End Function
Private Shared Function EnumChildProc_Browser(ByVal hwndChild As Integer, ByRef lParam As Integer) As Boolean
Dim buf As New StringBuilder(128)
NativeMethodsEx.GetClassName(hwndChild, buf, 128)
Dim ret = NativeMethodsEx.RevokeDragDrop(hwndChild)
If ret = NativeMethodsEx.DRAGDROP_E_NOTREGISTERED Then
Debug.Print("")
End If
If buf.ToString = Chrome_WidgetWin Then
lParam = hwndChild
Return False
End If
Return True
End Function
Как только у вас есть этот дескриптор, и вы отменилиэто как целевой объект, тогда вы можете вызвать RegisterDragDrop, передавая дескриптор и ваш класс IOleDropTarget.
Некоторые из моих подписей WinAPI выглядят так
Friend Const DRAGDROP_E_NOTREGISTERED = &H80040100
Friend Const DRAGDROP_E_INVALIDHWND = &H80040102
Friend Const DRAGDROP_E_ALREADYREGISTERED = &H80040101
Friend Const E_OUTOFMEMORY = &H8007000E
Friend Const S_OK = 0
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Shared Function GetClassName(ByVal hWnd As System.IntPtr, ByVal lpClassname As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
End Function
Friend Delegate Function EnumChildCallback(ByVal hwnd As Integer, ByRef lParam As Integer) As Boolean
<DllImport("User32.dll")>
Friend Shared Function EnumChildWindows(ByVal hWndParent As Integer, ByVal lpEnumFunc As EnumChildCallback, ByRef lParam As Integer) As Boolean
End Function
<DllImport("ole32.dll")>
Friend Shared Function RegisterDragDrop(ByVal hwnd As IntPtr, DropTarget As Browser.IOleDropTarget) As IntPtr
End Function
<DllImport("ole32.dll")>
Friend Shared Function RevokeDragDrop(ByVal hwnd As IntPtr) As IntPtr
End Function
Пример события и какиспользовать IDropTargetHelper можно так:
Public Function OleDragEnter(<[In]> <MarshalAs(UnmanagedType.Interface)> pDataObj As Object, <[In]> <MarshalAs(UnmanagedType.U4)> grfKeyState As Integer, <[In]> <MarshalAs(UnmanagedType.U8)> pt As Long, <[In]> <Out> ByRef pdwEffect As Integer) As Integer Implements IOleDropTarget.OleDragEnter
Dim winPT As Win32Point
winPT.x = CInt(pt And &H7FFFFFFF)
winPT.y = CInt((pt >> 32) And &H7FFFFFFF)
Dim eff As DragDropEffects = DragDropEffects.None
'this is my event I am sending back to the browser class to deal with.
RaiseEvent DBDragEnter(eff, New Point(winPT.x, winPT.y))
'you need to pass in the effect
pdwEffect = CInt(eff)
'this is the helper which shows the nice icon you drag around.
ddHelper.DragEnter(targetHwnd, CType(pDataObj, IDataObject_Com), winPT, CInt(eff))
Return NativeMethodsEx.S_OK
End Function
Конечно, что-то, что было бы неплохо увидеть в CefSharp для WinForms, особенно потому, что элемент управления имеет целую кучу или бесполезные свойства (AllowDrop) и события (Drag and Drop) намомент, который не реализован.