簡體   English   中英

如何使用CefSharp Winform接收拖動移動和拖放事件

[英]How to receive drag move and drag drop events using CefSharp winforms

我正在使用windowsformshost並嘗試獲取拖動和放置事件。

我在WPF窗口,Windowsformshost和ChromiumWebBrowser上設置了allowdrop。 我可以理解,由於windowsformshost的空域問題,WPF窗口將無法獲取事件。 但是我不明白為什么Windowsformshost或ChromiumWebBrowser沒有得到任何事件。 看來它們被CEF / CefSharp吞沒了並且沒有被傳遞。 如何處理事件和/或需要在CEF / CefSharp中禁用什么?

當我從純WPF CefSharp遷移時,我已經使用WPF ChromiumWebBrowser(不使用IDragHandler)實現了Dragenter,Dragmove和Dragdrop。

我想要實現的是根據鼠標拖動的位置顯示不同的拖動效果,其次,我希望能夠攔截drop事件,以便首先檢查用戶將鼠標放在文件上載類型元素上的文件類型。

禁用或調用RevokeDragDrop有什么作用 ?從Cefsharp的角度來看,應該調用哪個Hwnd(窗口)?

回答我自己的問題:可以恢復已被上游吞噬的拖放事件。

首先,我使用了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資源管理器顯示的漂亮圖標。

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消息的信息。 您需要知道的是,其中一個類名為“ Chrome_WidgetWin_0”的Chromium窗口已注冊用於拖放,必須首先將其吊銷,然后才能獲取事件。

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

一旦擁有此句柄並將其吊銷為吊銷目標,則可以調用句柄和IOleDropTarget類來調用RegisterDragDrop。

我的一些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 for WinForms中看到一些東西,特別是因為該控件具有一堆或無用的屬性(AllowDrop)和事件(拖放)目前尚未實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM