C++ 用C+发送WM#u dropfile+;和WinAPI到第三方应用程序

C++ 用C+发送WM#u dropfile+;和WinAPI到第三方应用程序,c++,winapi,drag-and-drop,automation,windows-messages,C++,Winapi,Drag And Drop,Automation,Windows Messages,因此,我一直在拼命地尝试自动化拖放功能,并将我对解决方案的搜索范围缩小到了相当精细的代码块: // DragAndDrop.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <Windows.h> #include <Shlobj.h> #include <tchar.h> int main(int argc, char*

因此,我一直在拼命地尝试自动化拖放功能,并将我对解决方案的搜索范围缩小到了相当精细的代码块:

// DragAndDrop.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <Shlobj.h>
#include <tchar.h>


int main(int argc, char* argv[]) {

    for (int i = 0; i <= WM_DROPFILES; i++)
    {
        ChangeWindowMessageFilter (i, MSGFLT_ADD);
    }

    if (HWND hwnd = FindWindow ("OpusApp", NULL)) {

    //HGLOBAL hGlobal = GlobalAlloc (GMEM_FIXED,
    //sizeof ("d:\\DragMe.txt") + 2);
    //char *strFile = (char*) GlobalLock
    //(hGlobal);
    //strcpy (strFile, "d:\\DragMe.txt");
    //strFile [strlen ("d:\\DragMe.txt") +
    //1] = NULL;
    char filename[] = "d:\\DragMe.txt";

    POINT point;
    point.x = 480;
    point.y = 480;

    HGLOBAL hMem = GlobalAlloc(GHND, sizeof(DROPFILES) + strlen(filename)+2);

    DROPFILES *dfiles = (DROPFILES*) GlobalLock(hMem);
    if (!dfiles)
    {
        GlobalFree(hMem);
        return NULL;
    }

    dfiles->pFiles = sizeof(DROPFILES);
    dfiles->pt = point;
    dfiles->fNC = TRUE;
    dfiles->fWide = FALSE;
    memcpy(&dfiles[1], filename, strlen(filename));
    GlobalUnlock(hMem);

    printf ("Sending Message...\n");

    if (!PostMessage(hwnd, WM_DROPFILES, (WPARAM)hMem, 0)) {
        printf("Error Posting Message!");
        GlobalFree(hMem);
    }
    }

    int temp = 0;
    scanf("&d", temp);
    return 0;
}
//DragAndDrop.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
#包括
#包括
int main(int argc,char*argv[]){
for(int i=0;i pFiles=sizeof(DROPFILES);
dfiles->pt=点;
dfiles->fNC=TRUE;
dfiles->fWide=FALSE;
memcpy(&d文件[1],文件名,strlen(文件名));
GlobalUnlock(hMem);
printf(“发送消息…\n”);
if(!PostMessage(hwnd,WM_DROPFILES,(WPARAM)hMem,0)){
printf(“发布错误消息!”);
全球自由度(hMem);
}
}
内部温度=0;
scanf(“&d”,温度);
返回0;
}
…我为我的代码中的任何不好的词道歉…它们只是为了调试目的。无论如何,上面的内容非常简单,它可以与Microsoft Word、Excel和记事本一起使用…但是对于许多应用程序来说,它根本不起作用(Spy++甚至不记录WM_DROPFILES消息在这些情况下,系统范围内的,这很奇怪…).我甚至尝试过为有问题的应用程序将代码编译为x64或x86,但没有改变

我觉得我可能错误地使用了FindWindow(我使用了与AutoIT捆绑的窗口信息工具来获取窗口类,因为我发现Spy++非常混乱)。无论如何,我设置了一个悬赏,因为我真的需要弄清楚这一点

我需要使用的应用程序名为Dartfish,它是Windows 7上的32位应用程序…我需要将视频文件列表发送到其界面的特定区域(特定窗格),我正在尝试使用上述代码执行此操作


有什么帮助吗?我非常感谢!!

ChangeWindowMessageFilter/Ex()
不授予您将指定消息发送给其他进程的权利。它授予其他进程(特别是较低完整性进程)将该消息发送给您的权利。因此,请摆脱它,这对您没有好处

下一步,尝试发送Unicode文件名,并将
dfiles->fWide
设置为TRUE,然后查看是否有区别。某些应用程序不处理Ansi数据。Windows是基于Unicode的操作系统。用于了解给定HWND是否需要Ansi或Unicode窗口消息


最后,一些应用程序根本不实现
WM\u DROPFILES
(它们不调用
dragaacceptfiles()
或启用
WS\u EX\u ACCEPTFILES
)。在现代Windows版本中,处理拖放操作的首选方法是实现该界面,并使用将其与HWND关联。没有API可检索HWND的
IDropTarget
,但可以手动执行:

(改编自本次讨论:)


如果HWND具有
IDropTarget
,则可以使用
IDataObject
包装
DROPFILES
数据,并将其传递给
IDropTarget::Drop()
方法。如果
Drop()
接受数据,不要发布
WM\u DROPFILES
消息。但是,诀窍是
IDropTarget*
指针由
GetProp()返回
与拥有HWND的进程相关,因此您必须将其封送到您的进程中,或者将代码注入HWND的进程中,以便实际使用接口指针。

我使用了与您的代码几乎相同的代码,并在许多应用程序中取得了很好的效果。我认为您的问题在于您找到的窗口FindWindow()是一个顶级窗口,它可能不是在目标应用中启用拖放的窗口。某些应用仅启用选定的子窗口进行拖放。问题当然是找到该窗口。我还没有找到任何简单的解决方案。您可以递归枚举顶部窗口的所有子窗口使用EnumChildWindows()并尝试识别正确的窗口(即,按类、ID、窗口样式或其他参数),但这很糟糕。我使用SpyXX,但这也不是一个很好的解决方案。

祝你好运。

你的目标窗口是否有WS_EX_ACCEPTFILES样式?看,这就是问题所在……它是第三方、封闭源代码的应用程序。我不知道。因此完全有可能我选错了树,应用程序甚至可能没有WM_DROPFILES的事件处理程序?或者所有windows应用程序都处理此消息吗默认情况下?要检测WS_EX_ACCEPTFILES样式,您可以将GetWindowLong与GWL_EXSTYLE参数一起使用。
WS_EX_ACCEPTFILES
只是一种快捷方式,以避免调用
DragAcceptFiles()
。但不,默认情况下,所有应用程序都不会处理
WM DROPFILES
放弃它。单个应用程序必须处理
WM_DROPFILES
来决定如何使用拖动的文件名。好的,谢谢你清理这些文件名。请参阅下文;我一直在研究你的解决方案。检索
IDropTarget
的代码看起来无法跨进程工作(至少,检索到的值没有意义)。如果目标应用程序注册了drop target(如上所述),您可以使用它。如果您阅读了我链接到的讨论,则通过分析
DoDragDrop()的内部工作来确定
IDropTarget
检索代码
,它与
IDropTarget
一起跨流程边界工作。其他在线来源,包括和,确认了这一点。在您的第一个链接中,建议使用此方法的评论者也说(在后面的评论中)您需要在相同的地址空间中运行。我知道
DoDragDrop
可以跨进程运行;我还知道它使用在每个进程中运行的OLE代码。最后,如何可能每个注册的
IDropTarget
指针在每个进程的地址空间中都有效?Remy,您的答案与建议一致我还有一个相关的问题,我有一个“半生不熟的”
IDropTarget* GetRegisteredDropTargetFromWnd (HWND hWnd) 
{ 
    IUnknown *pBuffer = (IUnknown *) GetProp (hWnd, TEXT("OleDropTargetInterface")); 
    if (pBuffer != NULL) 
    { 
        IDropTarget *pRetVal = NULL; 
        if (SUCCEEDED(pBuffer->QueryInterface(IID_IDropTarget, (void **) &pRetVal)))
            return pRetVal;     
    }
    return NULL; 
}