【问题标题】:Tracking global mouse events for drag/drop handling [duplicate]跟踪全局鼠标事件以进行拖放处理[重复]
【发布时间】:2012-09-25 12:20:11
【问题描述】:

可能重复:
Drag Drop from .NET application to Explorer

在我的应用程序中,要求用户能够从 ListView 的文件拖放到 Windows 资源管理器。该文件位于服务器上,因此我需要下载它们以放置哪个用户点。为此,我决定设置挂钩WH_MOUSE_LL 用于跟踪全局鼠标事件以获取用户放置文件的文件夹的句柄,然后使用它来获取加载文件的绝对路径。这是带有 HOOK 功能的 id DLL:

        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public POINT pt;
            public int hwnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }


        private enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_MOUSEMOVE = 0x0200,
            WM_MOUSEWHEEL = 0x020A,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205
        }


        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode,
        IntPtr wParam, IntPtr lParam);

        public int LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            //Marshall the data from the callback.
            //MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));

            MSLLHOOKSTRUCT MyMouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));

            if (nCode >= 0 &&
            MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
            {
                String strCaption = "x = " +
                        MyMouseHookStruct.pt.x.ToString("d") +
                        "  y = " +
                MyMouseHookStruct.pt.y.ToString("d");
                //You must get the active form because it is a static function.
                Console.WriteLine(strCaption);

            }
            return CallNextHookEx(hHook, nCode, wParam, lParam);


        }
    }
}

然后我用SetWindowsHookEx注册:

[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
IntPtr pDll = LoadLibrary(@"C:\Users\вова\Documents\visual studio    2010\Projects\MouseHook\MouseHook\bin\Debug\MouseHook.dll");
MouseHookProcedure = new HookProc(msHookObj.LowLevelMouseProc);

hHook = SetWindowsHookEx(WH_MOUSE,
            MouseHookProcedure,
            pDll, 
            0);

结果我的应用程序不跟踪全局事件。请帮忙,我做错了什么?

谢谢

【问题讨论】:

  • 我只是在代码中更改了一行 hHook = SetWindowsHookEx(7, MouseHookProcedure,pDll, 0);现在它正在跟踪窗口中的所有鼠标事件,但有时它会给我错误:CallBackCollected 委托。这是什么意思?最后一个问题:我怎样才能知道它的句柄得到文件夹的完整路径?谢谢
  • 如果您实际使用 WH_MOUSE_LL 而不是 WH_MOUSE,您可能会对此有所尝试。但是利用 Windows 中内置的拖放支持。

标签: c# events mouse hook


【解决方案1】:

我决定使用你关于拖放的建议,所以我开始使用 Shell API。但我有问题:因为我的文件不在系统中,所以我不能使用 CF_HDROP 格式进行传输。 所以我认为我必须使用 CFSTR_FILECONTENTS。

这是我的代码:

    public class DataObjectEx :
        DataObject, System.Runtime.InteropServices.ComTypes.IDataObject
    {
        private static readonly TYMED[] ALLOWED_TYMEDS =
            new TYMED[] { 
            TYMED.TYMED_ENHMF,
            TYMED.TYMED_GDI,
            TYMED.TYMED_HGLOBAL,
            TYMED.TYMED_ISTREAM, 
            TYMED.TYMED_MFPICT};
        public void FormDataObject(ListViewItem item)
        {
            var formatmumber=(Int16)DataFormats.GetFormat(NativeMethods.CFSTR_FILECONTENTS).Id;

            //формируем структуру для shell
            formatetc = new FORMATETC();
            formatetc.cfFormat = formatmumber;
            formatetc.ptd = IntPtr.Zero;
            formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT;
            formatetc.lindex = -1;
            formatetc.tymed = TYMED.TYMED_ISTREAM;

            //формируем структуру для передачи данных в shell
            medium = new STGMEDIUM();
            medium.tymed = TYMED.TYMED_ISTREAM;
            MemoryStream = GetFileContents(item);
            //IStream ob1;
            medium.unionmember = Marshal.GetComInterfaceForObject(iStream, typeof(MemoryStream));
            //medium.unionmember = iStream;


            ((System.Runtime.InteropServices.ComTypes.IDataObject)ob).SetData(ref formatetc, ref medium, true);

        }

行中:IStream iStream = (IStream)GetFileContents(item);- 函数 GetFileContents(item)- 连接到服务器并发送文件下载请求

public static MemoryStream  get_file_Istream(string file_id)
    {
        string data = "cmd=get_file&id=" + file_id + "&token=" + Token.curent_token;
        string Uri = URL.address;

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Uri);

        request.Method = "POST";
        request.AllowAutoRedirect = true;
        request.ContentType = "application/x-www-form-urlencoded";
        byte[] EncodedPostParams = Encoding.UTF8.GetBytes(data);
        request.ContentLength = EncodedPostParams.Length;
        request.GetRequestStream().Write(EncodedPostParams, 0, EncodedPostParams.Length);
        request.GetRequestStream().Close();


        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

        MemoryStream mm = new MemoryStream();
        response.GetResponseStream().CopyTo(mm);

        return mm;
        //ResponseStream = response.GetResponseStream();
    }

我从来没有做过这样的事情,只是大致了解它是如何工作的。 我得到下一个错误:

- 传递的类型必须是接口。 参数名称:t。在这一行:medium.unionmember = Marshal.GetComInterfaceForObject(iStream, typeof(MemoryStream));

- 方法或操作未实现。在这一行:((System.Runtime.InteropServices.ComTypes.IDataObject)ob).SetData(ref formatetc, ref medium, true);

据我了解,从上一个错误开始 - 我使用了 SetDate 方法,但我没有在互联网上找到任何信息。至于第一个错误,我认为它与错误的参数类型有关(MemoryStram insted Istream)

有人知道如何解决它们吗?

Thenaks

【讨论】:

    猜你喜欢
    • 2012-07-21
    • 2017-06-05
    • 2022-11-10
    • 2020-05-10
    • 2011-05-25
    • 2011-09-01
    • 2019-12-15
    • 2014-06-01
    • 2014-11-22
    相关资源
    最近更新 更多