2012-09-25 70 views
0

Possible Duplicate:
Drag Drop from .NET application to Explorer用于拖动跟踪全球鼠标事件/放处理

在我的应用它要求用户可以在具有ListView从Windows资源管理器从文件拖放&下降的能力。这些文件位于服务器上,因此我需要下载它们以放置哪个用户点。为此,我决定设置钩子WH_MOUSE_LL来跟踪全局鼠标事件,以获取用户放置文件的文件夹句柄,然后使用它获取加载文件的绝对路径。这里是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); 

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

感谢

+0

我只是改变一列代码 HHOOK = SetWindowsHookEx函数(7,MouseHookProcedure,PDLL,0); 现在它跟踪窗口中的所有鼠标事件,但有时会给我错误:CallBackCollected委托。这是什么意思? 而最后一个问题: 我怎样才能得到知道它的处理文件夹的完整路径? 谢谢 –

+0

如果您实际使用WH_MOUSE_LL而不是WH_MOUSE,则可能会出现此情况。但是* *要利用Windows中内置的拖放支持。 –

回答

0

我决定用你的建议regrding拖&下降,所以我来到了使用壳牌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(项目); - 功能GetFileContents(项目) - 连接到服务器和文件下载发送请求

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