Здравствуйте, alexqc, Вы писали:
[]
P>>Так бы и говорил сразу, а то я понял так, что тебе нужно засунуть все это дело в clipboard, дабы потом можно было в проводнике сделать paste...
A>Про клипбоард я вообще ни слова не говорил.
Ну это я почему-то так понял
[]
A>Я для проверки делал
A> int size=strlen(lpDroppedText)+2+sizeof(DROPFILES);
A> HGLOBAL drop_data = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
A> struct DROP_DATA{
A> DROPFILES df;
A> char names[1];
A> } *hal=(DROP_DATA*)GlobalLock(drop_data);
A> memset(hal,0,size); // не нужно, у тебя же GMEM_ZEROINIT
hal->>df.fNC=sizeof(DROPFILES);
A> strcpy(hal->names,lpDroppedText);
A> GlobalUnlock(drop_data); // Думается это надо делать после DragQueryFile
A> int ret=DragQueryFile(HDROP (drop_data)
A> ,UINT(0xFFFFFFFF), NULL,0);
A> GlobalFree(drop_data);
A>получаю ret=0, т.е. ошибку.
A>Точно ли drop_data в этом случае тот самый HDROP? (об этом как раз в TFM нет ни слова
)
Дык я же приводил цитату из TFM. К тому же реальность данная мне в ощущениях это подтверждает.
P>>ЗЗЫ Хотя ежели ты сообщение шлешь в другое приложение, тогда скорее всего в clipboard таки пихать придется, а в SendMessage отдавать то, что вернет SetClipboardData.
A>Что-то извратом пахнет, да и clipboard портить...
Ну clipboard то ты не испортишь, бо таким образом copy\paste в explorer (или еще куда) проще всего сделать.
Правда для WM_DROPFILES это не работает, собст. как я и думал из-за границ процесса.
Вобщем лови. Писано в MFC'ях, но думается под голое API переделать труда не составит. Запускаешь 2 экземпляра приложения и тащиш мышой из одного в другое.
class drop_names
{
std::vector<TCHAR> drop_data_;
size_t cur_index;
bool locked_;
public:
drop_names() : cur_index(0), locked_(false) { }
bool add(const TCHAR* name)
{
_ASSERTE(!locked_);
if (locked_)
return false;
const size_t name_size = lstrlen(name);
drop_data_.resize(cur_index + name_size + 1);
memcpy(&drop_data_[0] + cur_index, name, name_size * sizeof(TCHAR));
cur_index += name_size;
drop_data_[cur_index] = _T('\0');
++cur_index;
return true;
}
const TCHAR* lock()
{
_ASSERTE(!locked_);
if (!locked_)
{
drop_data_.push_back(_T('\0'));
++cur_index;
locked_ = true;
}
return &drop_data_[0];
}
size_t size() const { return cur_index * sizeof(TCHAR); }
};
void CNewView::OnLButtonDown(UINT nFlags, CPoint point)
{
SetCapture();
}
void CNewView::OnLButtonUp(UINT nFlags, CPoint point)
{
drop_names d_names;
const TCHAR* name1 = "c:\\temp\\mycoolfile1.txt";
const TCHAR* name2 = "c:\\temp\\mycoolfile2.txt";
const TCHAR* name3 = "c:\\temp\\mycoolfile3.txt";
d_names.add(name1);
d_names.add(name2);
d_names.add(name3);
const TCHAR* names = d_names_.lock();
const size_t names_size = d_names_.size();
DROPFILES drop_struct = { sizeof(drop_struct), { 0, 0 }, 0, 0 };
const size_t drop_size = sizeof(drop_struct) + names_size;
std::vector<unsigned char> drop_data(drop_size);
memcpy(&drop_data[0], &drop_struct, sizeof(drop_struct));
memcpy(&drop_data[0] + sizeof(drop_struct), names, names_size);
ClientToScreen(&point);
CWnd* found_wnd = WindowFromPoint(point);
_ASSERTE(found_wnd);
DWORD process_id = 0;
GetWindowThreadProcessId(found_wnd->GetSafeHwnd(), &process_id);
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
_ASSERTE(process);
LPVOID address = VirtualAllocEx(process, NULL, drop_size, MEM_COMMIT, PAGE_READWRITE);
_ASSERTE(address);
SIZE_T bytes_written = 0;
BOOL res = WriteProcessMemory(process, address, &drop_data[0], drop_size, &bytes_written);
_ASSERTE(res && bytes_written == drop_size);
found_wnd->SendMessage(WM_DROPFILES, (WPARAM)address, 0);
res = VirtualFreeEx(process, address, 0, MEM_RELEASE);
_ASSERTE(res);
ReleaseCapture();
}
void CNewView::OnDropFiles(HDROP drop_info)
{
CClientDC dc(this);
int item_count = DragQueryFile(drop_info, 0xFFFFFFFF, NULL, 0);
CString text;
text.Format("Dropped %d files", item_count);
dc.TextOut(100, 100, text);
for (int i = 0; i < item_count; ++i)
{
TCHAR buffer[MAX_PATH] = { 0 };
int buffer_size = DragQueryFile(drop_info, i, NULL, 0);
DragQueryFile(drop_info, i, buffer, MAX_PATH);
dc.TextOut(100, 120 + 20 * i, buffer);
}
}
ЗЫ Ежели надо чтоб работало и под w9x, то придеться вместо VirtualAllocEx\WriteProcessMemory использовать внедрение dll. Подробнее об этом полно инфы тут на сайте, ну иеще конечно у Рихтера.