简体   繁体   English

将文件从我的应用程序拖放到另一个应用程序的Win32 API过程

[英]The Win32 API procedure of drag-and-dropping a file from my app to another app

In short, trying to do what the following two lines of C# code do without using System.Windows.Forms , because it is .NET Core and not a WinForms project. 简而言之,请尝试不使用System.Windows.Forms而执行以下两行C#代码,因为它是.NET Core,而不是WinForms项目。

var data = new System.Windows.Forms.DataObject(
    System.Windows.Forms.DataFormats.FileDrop, new string[] { @"C:\test.txt"});
dummyControl.DoDragDrop(data, System.Windows.Forms.DragDropEffects.Copy);

But it does not work. 但这行不通。 What have I done wrong? 我做错了什么? My procedure was, 我的程序是

  1. When mouse is down on a UI control, call SetCapture to capture the event. 在UI控件上按下鼠标时,调用SetCapture捕获事件。
  2. The IDropSource 's QueryContinueDrag keep returning S_OK until the mouse button is up, and then DRAGDROP_S_DROP . IDropSourceQueryContinueDrag一直返回S_OK直到鼠标按钮向上,然后DRAGDROP_S_DROP
  3. My "DataObject" implementing IDataObject has EnumFormatEtc . 我实现IDataObject “ DataObject”具有EnumFormatEtc In which I return only one FORMATETC . 我只返回一个FORMATETC

      new FORMATETC() { cfFormat = CF_HDROP, ptd = IntPtr.Zero, dwAspect = DVASPECT.DVASPECT_ICON, lindex = -1, tymed = TYMED.TYMED_FILE } 
    1. In QueryGetData , if the format 's tymed is TYMED_FILE , return S_OK meaning I am dragging a file. QueryGetData ,如果formattymedTYMED_FILE ,则返回S_OK表示我正在拖动文件。 Otherwise return DV_E_TYMED meaning I don't have that type of data. 否则返回DV_E_TYMED表示我没有该类型的数据。

    2. In GetData , if the format 's tymed is TYMED_FILE , I set a file like this GetData ,如果formattymedTYMED_FILE ,则我将这样设置一个文件

        medium = new STGMEDIUM(); medium.tymed = TYMED.TYMED_FILE; medium.unionmember = Marshal.StringToHGlobalUni(@"C:\\test.txt"); medium.pUnkForRelease = IntPtr.Zero; 

I tried to drag-and-drop to Notepad. 我试图将其拖放到记事本中。 Problems are, 问题是

  1. When DoDragDrop is not called on the mouse down event, mouse is captured and mouse up event is received. 当在鼠标按下事件上未调用DoDragDrop时,将捕获鼠标并接收鼠标按下事件。 But when DoDragDrop is called, QueryContinueDrag is endlessly called and I don't get the mouse up event, even after I released the mouse. 但是,当调用DoDragDrop时,会无休止地调用QueryContinueDrag ,即使释放了鼠标,我也没有发生鼠标向上事件。 I tried to call DoDragDrop in another thread, but that did not work. 我试图在另一个线程中调用DoDragDrop ,但这没有用。
  2. I get callbacks like QueryGetData(TYMED_HGLOBAL) or QueryGetData(TYMED_HGLOBAL, TYMED_ISTREAM, TYMED_GDI, TYMED_MFPICT, TYMED_ENHMF) , but not for TYMED_FILE . 我收到了类似QueryGetData(TYMED_HGLOBAL)QueryGetData(TYMED_HGLOBAL, TYMED_ISTREAM, TYMED_GDI, TYMED_MFPICT, TYMED_ENHMF) ,但没有TYMED_FILE Why isn't Notepad requesting that? 为什么记事本不要求?

The drag and drop seems unnecessarily complex, but for now, I am only interested in dragging a file, so I did not want to implement parts other than that. 拖放似乎不必要地复杂,但是目前,我仅对拖动文件感兴趣,因此我不想实现除此以外的其他部分。 What in the above procedure or assumptions are wrong? 上述程序或假设中有哪些错误?

When DoDragDrop is not called on the mouse down event, mouse is captured and mouse up event is received. 当在鼠标按下事件上未调用DoDragDrop时,将捕获鼠标并接收鼠标按下事件。 But when DoDragDrop is called, QueryContinueDrag is endlessly called and I don't get the mouse up event, even after I released the mouse. 但是,当调用DoDragDrop时,会无休止地调用QueryContinueDrag,即使释放了鼠标,我也没有发生鼠标向上事件。

You don't get a mouse up event because DoDragDrop() blocks your UI message loop until the drag operation is completed. 您不会发生鼠标上DoDragDrop()事件,因为DoDragDrop()阻塞UI消息循环,直到完成拖动操作为止。 So you need to use the input flags given to your QueryContinueDrag() implementation to decide whether to continue dragging, perform the drop, or abort the operation. 因此,您需要使用提供给QueryContinueDrag()实现的输入标志来确定是继续拖动,执行放置还是中止操作。

If you start the drag on a left mouse down, return S_OK if the grfKeyState parameter includes the MK_LBUTTON flag, and return DRAGDROP_S_DROP if the MK_LBUTTON flag is cleared. 如果你开始在鼠标左键拖动下,返回S_OK如果grfKeyState参数包括MK_LBUTTON标志,并返回DRAGDROP_S_DROP如果MK_LBUTTON标志被清除。 Return DRAGDROP_S_CANCEL if the fEscapePressed parameter is true. 如果fEscapePressed参数为true,则返回DRAGDROP_S_CANCEL This is documented on MSDN: 这记录在MSDN上:

IDropSource::QueryContinueDrag method IDropSource :: QueryContinueDrag方法

Parameters 参数

fEscapePressed

Indicates whether the Esc key has been pressed since the previous call to QueryContinueDrag or to DoDragDrop if this is the first call to QueryContinueDrag . 指示自上次调用QueryContinueDragDoDragDrop如果这是对QueryContinueDrag的第一次调用)以来,是否已按下Esc键 A TRUE value indicates the end user has pressed the escape key; TRUE值表示最终用户已按下退出键; a FALSE value indicates it has not been pressed. FALSE值表示尚未按下。

grfKeyState

The current state of the keyboard modifier keys on the keyboard. 键盘上键盘修饰键的当前状态。 Possible values can be a combination of any of the flags MK_CONTROL, MK_SHIFT, MK_ALT, MK_BUTTON, MK_LBUTTON , MK_MBUTTON, and MK_RBUTTON. 可能的值可以是标志MK_CONTROL,MK_SHIFT,MK_ALT,MK_BUTTON, MK_LBUTTON ,MK_MBUTTON和MK_RBUTTON中任何一个的组合。

Return Value 返回值

This method can return the following values. 此方法可以返回以下值。

S_OK S_OK
The drag operation should continue. 拖动操作应继续。 This result occurs if no errors are detected, the mouse button starting the drag-and-drop operation has not been released , and the Esc key has not been detected. 如果未检测到任何错误, 尚未释放开始拖放操作的鼠标按钮 ,也未检测到Esc键,则会出现此结果。

DRAGDROP_S_DROP DRAGDROP_S_DROP
The drop operation should occur completing the drag operation. 放置操作应完成拖动操作。 This result occurs if grfKeyState indicates that the key that started the drag-and-drop operation has been released. 如果grfKeyState指示开始拖放操作的键已释放,则会出现此结果。

DRAGDROP_S_CANCEL DRAGDROP_S_CANCEL
The drag operation should be canceled with no drop operation occurring. 拖动操作应被取消,而不会发生拖放操作。 This result occurs if fEscapePressed is TRUE, indicating the Esc key has been pressed. 如果fEscapePressed为TRUE(表示已按下Esc键),则会出现此结果。

Remarks 备注

The DoDragDrop function calls QueryContinueDrag whenever it detects a change in the keyboard or mouse button state during a drag-and-drop operation. 每当DoDragDrop函数在拖放操作期间检测到键盘或鼠标按钮状态发生变化时,就会调用QueryContinueDrag QueryContinueDrag must determine whether the drag-and-drop operation should be continued, canceled, or completed based on the contents of the parameters grfKeyState and fEscapePressed . QueryContinueDrag必须基于参数grfKeyStatefEscapePressed的内容来确定拖放操作是应该继续,取消还是完成。


I get callbacks like QueryGetData(TYMED_HGLOBAL) or QueryGetData(TYMED_HGLOBAL, TYMED_ISTREAM, TYMED_GDI, TYMED_MFPICT, TYMED_ENHMF), but not for TYMED_FILE. 我收到了类似QueryGetData(TYMED_HGLOBAL)或QueryGetData(TYMED_HGLOBAL,TYMED_ISTREAM,TYMED_GDI,TYMED_MFPICT,TYMED_ENHMF)的回调,但没有TYMED_FILE的回调。 Why isn't Notepad requesting that? 为什么记事本不要求?

You can't use TYMED_FILE for CF_HDROP , you must use TYMED_HGLOBAL . 您不能将TYMED_FILE用于CF_HDROP ,而必须使用TYMED_HGLOBAL And the content of the allocated HGLOBAL must be a DROPFILES struct followed by a double-null-terminated list of file paths. 并且已分配的HGLOBAL的内容必须是DROPFILES结构,后跟一个双空终止的文件路径列表。 This is documented on MSDN: 这记录在MSDN上:

Shell Clipboard Formats Shell剪贴板格式

CF_HDROP CF_HDROP

This clipboard format is used when transferring the locations of a group of existing files. 传输一组现有文件的位置时使用此剪贴板格式。 Unlike the other Shell formats, it is predefined, so there is no need to call RegisterClipboardFormat . 与其他Shell格式不同,它是预定义的,因此无需调用RegisterClipboardFormat The data consists of an STGMEDIUM structure that contains a global memory object. 数据由包含全局存储对象的STGMEDIUM结构组成。 The structure's hGlobal member points to a DROPFILES structure as its hGlobal member. 该结构的hGlobal成员指向DROPFILES结构作为其hGlobal成员。

The pFiles member of the DROPFILES structure contains an offset to a double null-terminated character array that contains the file names. DROPFILES结构的pFiles成员包含一个双零终止字符数组的偏移量,该字符数组包含文件名。 If you are extracting a CF_HDROP format from a data object, you can use DragQueryFile to extract individual file names from the global memory object. 如果要从数据对象中提取CF_HDROP格式,则可以使用DragQueryFile从全局内存对象中提取单个文件名。 If you are creating a CF_HDROP format to place in a data object, you will need to construct the file name array. 如果要创建CF_HDROP格式以放置在数据对象中,则需要构造文件名数组。

The file name array consists of a series of strings, each containing one file's fully qualified path, including the terminating NULL character. 文件名数组由一系列字符串组成,每个字符串包含一个文件的标准路径,包括终止NULL字符。 An additional null character is appended to the final string to terminate the array. 在最终字符串后附加一个空字符以终止数组。 For example, if the files c:\\temp1.txt and c:\\temp2.txt are being transferred, the character array looks like this: 例如,如果正在传输文件c:\\temp1.txtc:\\temp2.txt ,则字符数组如下所示:

c:\\temp1.txt'\\0'c:\\temp2.txt'\\0''\\0'

Note 注意
In this example, '\\0' is used to represent the null character, not the literal characters that should be included. 在此示例中, '\\0'用于表示空字符,而不是应包括的文字字符。

If the object was copied to the clipboard as part of a drag-and-drop operation, the pt member of the DROPFILES structure contains the coordinates of the point where the object was dropped. 如果作为拖放操作的一部分将对象复制到剪贴板,则DROPFILES结构的pt成员将包含放置对象的点的坐标。 You can use DragQueryPoint to extract the cursor coordinates. 您可以使用DragQueryPoint提取光标坐标。

If this format is present in a data object, an OLE drag loop simulates WM_DROPFILES functionality with non-OLE drop targets. 如果数据对象中存在此格式,则OLE拖动循环会使用非OLE放置目标来模拟WM_DROPFILES功能。 This is important if your application is the source of a drag-and-drop operation on a Windows 3.1 system. 如果您的应用程序是Windows 3.1系统上的拖放操作的来源,则这一点很重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我的Win32 App如何从UWP App窃取焦点? - How Can My Win32 App Steal Focus From My UWP App? 外部应用程序中文本框的 SetText。 Win32 API - SetText of textbox in external app. Win32 API 在启动时从Metro应用程序进入Win32桌面 - enter win32 desktop from metro app at its startup LaunchFullTrustProcessForCurrentAppAsync 杀死 win32 应用程序 - LaunchFullTrustProcessForCurrentAppAsync kills win32 app 从我的操作系统的任何文件夹中检测文件删除,并防止c#或win32 api删除 - File deletion detect from any folder of my operating system and prevent the deletion by c# or win32 api 记录到自定义事件日志(C#应用程序,但使用win32 API) - logging to custom event log (C# app, but using win32 API) 如何在 C#/Win32 api 中找到 Windows 应用程序执行别名的目标? - How do I find the target of a Windows App Execution Alias in C#/Win32 api? 将C#win32应用程序连接到Access数据库 - Connecting C# win32 app to Access Database 从主UWP进程终止UWP应用的Win32进程,或向其发送消息 - Terminate the win32 process of UWP app from main UWP process, or send message to it 如何从 UWP 应用程序中使用命令行 arguments 实现启动 win32 exe? - How do you implement Launching a win32 exe with command line arguments from an UWP app?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM