在允许放下之前检查目标窗口

时间:2013-03-06 19:10:02

标签: c# drag-and-drop target

在允许丢弃之前,有没有办法检查目标(它属于哪个.exe)?

我打算实现的目标是让控件成为一种阻力。放在Word或Excel上,取决于哪个目标应用程序,传递相应的文件。

编辑: 这是我在VB中尝试的代码

@David感谢您的代码。我尝试使用Button控件(WPF)并在dataobject中添加文件路径。我得到了Stack Imbalance异常。

这是代码(在VB.Net中尝试) - 这给了我这个错误: 对PInvoke函数'TestApplication!TestApplication.MainWindow :: GetCursorPos'的调用使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

我忘记了什么吗?

EDIT 进行了一些更改,现在可以正常使用。


    

Imports System.Diagnostics Imports System.Runtime.InteropServices Imports System.Collections.Specialized Class MainWindow <DllImport("user32.dll")> _ Private Shared Function WindowFromPoint(ByVal xPoint As Integer, ByVal yPoint As Integer) As IntPtr End Function <DllImport("user32.dll")> _ Private Shared Function GetCursorPos(lpPoint As Point) As Boolean End Function <DllImport("kernel32.dll", SetLastError:=True)> _ Private Shared Function GetProcessId(hWnd As IntPtr) As Integer End Function <DllImport("user32.dll", SetLastError:=True)> _ Private Shared Function GetWindowThreadProcessId(hWnd As IntPtr, lpdwProcessId As Integer) As UInteger End Function Private MouseIsDown As Boolean = Nothing Private Sub DropButton_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles DropButton.PreviewMouseLeftButtonDown MouseIsDown = True End Sub Private Sub DropButton_MouseMove(sender As Object, e As MouseEventArgs) Handles DropButton.MouseMove If MouseIsDown Then Dim data As New DataObject() Dim DropList As New StringCollection DropList.Add("c:\file.txt") data.SetFileDropList(DropList) DragDrop.DoDragDrop(CType(e.OriginalSource, DependencyObject), data, DragDropEffects.Move) End If End Sub Private Sub DropButton_GiveFeedback(sender As Object, e As GiveFeedbackEventArgs) Handles DropButton.GiveFeedback Dim a = Mouse.GetPosition(Me) If a <> Nothing Then Dim hWnd As IntPtr = WindowFromPoint(a.X, a.Y) If hWnd <> Nothing Then Dim processId As Integer GetWindowThreadProcessId(hWnd, processId) Dim proc As Process = Process.GetProcessById(processId) label1.Content = proc.MainWindowTitle End If End If End Sub End Class

3 个答案:

答案 0 :(得分:0)

不确定。您可以通过在GiveFeedback事件中为执行拖放操作的控件实现一些互操作来实现此目的。我制作了一个示例应用程序,并使用树形视图控件和表单上的标签进行测试。

using System.Diagnostics;
using System.Runtime.InteropServices;

[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(Point Point);

[DllImport("user32.dll")]
static extern bool GetCursorPos(out Point lpPoint);

[DllImport("kernel32.dll", SetLastError = true)]
static extern int GetProcessId(IntPtr hWnd);

[DllImport("user32.dll", SetLastError=true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);


private void treeView1_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
    Point p;

    if (GetCursorPos(out p))
    {
        IntPtr hWnd = WindowFromPoint(p);

        if (hWnd != null)
        {
            int processId;
            GetWindowThreadProcessId(hWnd, out processId);

            Process proc = Process.GetProcessById(processId);
            label1.Text = proc.MainWindowTitle;
        }
    }
}

答案 1 :(得分:0)

问题在于范式与你想要的相反。您必须指定可用的内容。然后你放下它的应用程序可以选择它想要的东西。

不幸的是,如果你在DataFormats.FileDrop中放入多个文件,Excel将打开这两个文件(我假设Word也会这样)。

另外,对于excel(我假设单词),你放弃的地方/当它改变了它的偏好,例如:

  • 如果您在Excel没有打开文件时删除它,则首选FileDrop,拒绝其他所有文件
  • 如果你放在标题栏上,它会更喜欢FileDrop,拒绝其他所有内容
  • 如果你放在一张打开的工作表上,它会更喜欢StringFormat(即使我认为它更喜欢CSV)。
  • Excel如何更喜欢Rtf到CSV,所以如果你把两个都放在你的数据中,Word会把Rtf和Excel带到CSV

所以,执行此操作的代码是......

  DataObject d = new DataObject();
  d.SetData(DataFormats.CommaSeparatedValue, csvValue);
  d.SetData(DataFormats.Rtf, rtfValue);
  DoDragDrop(d, DragDropEffects.Copy);

因此,如果您可以在调用之前将数据转换为csv和rtf格式,它将传递数据。无论如何我都找不到使用文件来做这件事。

答案 2 :(得分:0)

如果要选择要在放置时呈现的剪贴板格式,则必须延迟内容的呈现,直到implementing IASyncOperation/IDataObjectAsyncCapability发生丢弃为止。但Office没有关于如何识别拖动源的文档。有一个来自Windows团队的DDWM_UPDATEWINDOW消息,但我不确定办公室团队是否使用它。

一般来说,each program have its own preference of clipboard formats。例如,如果使用WordML调用了IDataObject :: GetData,则目标可能是Microsoft Word。如果首选SpreadsheetML,则目标可能是Microsoft Excel。您不需要实际提供这两种格式的内容,但您可以使用查询的剪贴板格式模式来确定数据被删除的程序类型,并在以后提供数据,例如,当CF_HTML时被查询。当然,如果你不介意浪费一些内存,你不需要IASyncOperation,只需用Word和Excel之间不共享的格式填充数据对象,Word会选择它理解的第一种格式,Excel会选择第一种格式格式它理解。