0

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

我打算实现的是允许将控件拖放到 Word 或 Excel 上,并根据目标应用程序,传递适当的文件。

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

@David 感谢您的代码。我用按钮控件(WPF)尝试了类似的事情,并在数据对象中添加了一个文件路径。我遇到了堆栈不平衡异常。

这是代码(在 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

4

3 回答 3

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;
        }
    }
}
于 2013-03-06T20:33:58.047 回答
0

如果您想选择在放置时呈现哪种剪贴板格式,则必须通过实现 IASyncOperation/IDataObjectAsyncCapability来延迟内容的呈现,直到放置发生。但是,Office 没有关于它如何向您的拖动源标识自己的文档。Windows 团队有一条 DDWM_UPDATEWINDOW 消息,但我不确定办公室团队是否使用它。

一般来说,每个程序都有自己对剪贴板格式的偏好。例如,如果您的 IDataObject::GetData 被WordML调用,那么目标可能是 Microsoft Word。如果电子表格ML是首选,那么目标可能是 Microsoft Excel。您不需要实际提供这两种格式的内容,但您可以使用查询的剪贴板格式的模式来确定您的数据被拖放到哪种程序,并在以后提供数据,例如,当 CF_HTML被查询。当然,如果您不介意浪费一些内存,则不需要 IASyncOperation,只需使用 Word 和 Excel 之间不共享的格式填充数据对象,Word 会选择它理解的第一个格式,Excel 会选择第一个它理解的格式。

于 2013-03-06T20:48:12.110 回答
0

问题是范式与您想要的相反。你必须指定你有什么可用的。然后,您放置它的应用程序可以选择它想要采用的内容。

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

此外,对于 excel(我假设是 word),在哪里/当你放下它时会改变它的偏好,例如:

  • 如果您在 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 格式,它将传递数据。我无论如何都找不到使用文件来执行此操作。

于 2013-03-06T20:38:28.533 回答