Поэтому я отчаянно пытался автоматизировать функциональность перетаскивания, и сузил свой поиск решений до довольно изысканного куска кода:
// 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;
}
… Я прошу прощения за любые плохие слова в моем коде … они только для целей отладки. В любом случае, вышеприведенное очень просто и работает с Microsoft Word, Excel и Notepad … но для ряда приложений оно вообще не работает (Spy ++ даже не регистрирует сообщение WM_DROPFILES общесистемного в этих случаях, что странно …). Я даже пытался скомпилировать код как x64 или x86 для проблемных приложений, но без изменений …
Мне кажется, что я неправильно использую FindWindow (я использую Window Info Tool в комплекте с AutoIT, чтобы получить класс окна, так как Spy ++ довольно запутанный). В любом случае, я назначаю вознаграждение, потому что мне действительно нужно выяснить это.
Приложение, с которым мне нужно будет это использовать, называется Dartfish, и это 32-разрядное приложение в Windows 7 … Мне нужно отправить список видеофайлов в определенную область его интерфейса (определенную панель), и я Я пытаюсь сделать это с помощью приведенного выше кода.
Любая помощь? Я очень ценю это!
ChangeWindowMessageFilter/Ex()
не дает вам права отправлять указанное сообщение другим процессам. Он предоставляет другим процессам (в частности, процессам с более низкой целостностью) право отправлять это сообщение вам. Так что избавься от этого, это тебе не выгодно.
Затем попробуйте отправить имена файлов Unicode с помощью dfiles->fWide
установите в TRUE и посмотрите, будет ли это иметь значение. Некоторые приложения не обрабатывают данные Ansi. Windows — это ОС на основе Юникода. использование IsWindowUnicode()
знать, ожидает ли данный HWND сообщения окна Ansi или Unicode.
Наконец, некоторые приложения просто не реализуют WM_DROPFILES
(они не звонят DragAcceptFiles()
или включить WS_EX_ACCEPTFILES
). Предпочтительный способ обработки перетаскивания&падение в современных версиях Windows заключается в реализации IDropTarget
вместо этого, и связать его с HWND, используя RegisterDragDrop()
. Там нет API для получения HWND IDropTarget
, но это можно сделать вручную:
(адаптировано из этого обсуждения: Как получить для HWND это IDropTarget?)
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;
}
Если HWND имеет IDropTarget
Вы можете обернуть DROPFILES
данные с IDataObject
и передать его IDropTarget::Drop()
метод. Если Drop()
принимает данные, не размещайте WM_DROPFILES
сообщение. Однако хитрость в том, что IDropTarget*
указатель возвращается GetProp()
относится к процессу, которому принадлежит HWND, так что вам придется встроить его в свой процесс или добавить код в процесс HWND, чтобы фактически использовать указатель интерфейса.
Я использовал код, почти идентичный вашему, с хорошими результатами во многих приложениях. Я думаю, что ваша проблема в том, что окно, которое вы найдете с помощью FindWindow (), является верхний уровень окно, которое может не быть активным окном для добавления в целевое приложение. Некоторые приложения включают только выбранные дочерние окна для удаления. Проблема, конечно, в том, чтобы найти это окно. Я не нашел простого решения этой проблемы. Вы мог рекурсивно перечислять все дочерние элементы верхнего окна, используя EnumChildWindows () и пытаясь определить правильное окно (то есть по классу, ID, стилю окна или другому параметру), но это брутто. Я использую SpyXX, но это тоже не очень хорошее решение.
Удачи.