Tracking global mouse events for drag/drop handling
Possible Duplicate:
Drag Drop from .NET application to Explorer
In my application it's required that users can have ability of drag & drop from files from ListView
on the from to Windows Explorer. This files locates on server so I need download them to place which user point. For this I decided to set hook WH_MOUSE_LL
for tracking global mouse events to get handle of folder where user drop his files and then using it to get it's absolute path for loading files. Here is id DLL with HOOK function:
[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);
}
}
}
Then I register it with SetWindowsHookEx
:
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
IntPtr pDll = LoadLibrary(@"C:UsersвоваDocumentsvisual studio 2010ProjectsMouseHookMouseHookbinDebugMouseHook.dll");
MouseHookProcedure = new HookProc(msHookObj.LowLevelMouseProc);
hHook = SetWindowsHookEx(WH_MOUSE,
MouseHookProcedure,
pDll,
0);
In result my app doesn't track global events. Please help, what I do wrong?
Thanks
I decided to use your advice regrding drag&drop, so i came to using Shell API. but i have problems with it: since my files not in system i can't use CF_HDROP format for their transfer. So as i anderstand i have to use CFSTR_FILECONTENTS.
Here are my code:
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);
}
In row: IStream iStream = (IStream)GetFileContents(item);- function GetFileContents(item)- connect to server and sends request on file downloading
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();
}
I've never done something like this and only approximately understand how it works. I get next errors:
-Type passed must be an interface. Parameter name: t. on this row: medium.unionmember = Marshal.GetComInterfaceForObject(iStream, typeof(MemoryStream));
-The method or operation is not implemented. on this row:((System.Runtime.InteropServices.ComTypes.IDataObject)ob).SetData(ref formatetc, ref medium, true);
From last error as i understand - i mast inmplement method SetDate, but i didn't find any info i internet. As for first error i think it's connected with bad parameter type(MemoryStram insted Istream)
Anybody have ideas how to resolve them?
Thenaks
链接地址: http://www.djcxy.com/p/61732.html上一篇: Windows热键来调用应用程序
下一篇: 跟踪全局鼠标事件以进行拖放处理