问题
I'm kinda confused. When a file is dragged onto a window with WS_EX_ACCEPTFILES flagged it places a PostMessage into the WndProc function, which sets UINT message to WM_DROPFILES and, according to
https://msdn.microsoft.com/en-us/library/windows/desktop/bb774303(v=vs.85).aspx
the WPARAM = (WPARAM) (HDROP) hDrop; So am I wrong to assume that I can use the WPARAM to initialize the HDROP or just pass it into the DragQueryFile ??
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE:
return 0;
case WM_DROPFILES:
TCHAR* FilePath;
HDROP hDrop = wParam; //wParam cannot be used to ini. an entity of type HDROP
//HDROP hdrop = (HDROP)wParam; initialization of hDrop is skipped by case label
DragQueryFile(wParam, 0, FilePath, 0); //wParam not compatible
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Every kind of help is appreciated.
回答1:
You need to cast wparam to HDROP and then iterate over dropped file paths supplying buffer.
case WM_DROPFILES:
{
auto const drop_handle{reinterpret_cast< ::HDROP >(wParam)};
auto const dropped_files_count
{
::DragQueryFileW(drop_handle, 0xFFFFFFFF, nullptr, 0)
};
::std::vector< wchar_t > buffer;
for(::UINT dropped_file_index{0}; dropped_files_count != dropped_file_index; ++dropped_file_index)
{
auto const file_path_symbols_count_excluding_terminating_null
{
::DragQueryFileW(drop_handle, dropped_file_index, nullptr, 0)
};
if(0 < file_path_symbols_count_excluding_terminating_null)
{
auto const buffer_size{file_path_symbols_count_excluding_terminating_null + 1};
buffer.resize(buffer_size);
auto const copied_symbols_count_excluding_terminating_null
{
::DragQueryFileW(drop_handle, dropped_file_index, buffer.data(), buffer_size)
};
if(copied_symbols_count_excluding_terminating_null == file_path_symbols_count_excluding_terminating_null)
{
buffer.back() = L'\0'; // just in case....
// buffer now contains file path...
}
}
}
break;
}
However note that even though handling WM_DROPFILES
should work, the preffered way to handle drag-and drop is to implement IDropTarget interface and register it as drop target handler for your application.
回答2:
You're nearly there. You had the right answer, but you commented it out, due to a different error relating to your use of case
labels. Instead of going backwards with your HDROP
and WPARAM
, you should just have fixed that different error ;)
The cast is correct, but you need to scope your case "body" (because, in fact, a case has no body, or scope of its own), and that's what the error's telling you:
case WM_DROPFILES: {
TCHAR FilePath[MAX_PATH];
HDROP hdrop = (HDROP)wParam;
DragQueryFile(hdrop, 0, FilePath, 0);
return 0;
}
Here I've added {
and }
to introduce a block scope.
回答3:
add VTT answered.
you can replace ::std::vector< wchar_t > buffer;
with std::wstring buffer
code
case WM_DROPFILES:
{
auto const drop_handle{ reinterpret_cast<::HDROP>(wParam) };
auto const dropped_files_count
{
::DragQueryFileW(drop_handle, 0xFFFFFFFF, nullptr, 0)
};
::std::wstring buffer;
for (::UINT dropped_file_index{ 0 }; dropped_files_count != dropped_file_index; ++dropped_file_index)
{
auto const file_path_symbols_count_excluding_terminating_null
{
::DragQueryFileW(drop_handle, dropped_file_index, nullptr, 0)
};
if (0 < file_path_symbols_count_excluding_terminating_null)
{
auto const buffer_size{ file_path_symbols_count_excluding_terminating_null + 1 };
buffer.resize(buffer_size);
auto const copied_symbols_count_excluding_terminating_null
{
::DragQueryFileW(drop_handle, dropped_file_index, &buffer[0], buffer_size)
};
if (copied_symbols_count_excluding_terminating_null == file_path_symbols_count_excluding_terminating_null)
{
buffer.back() = L'\0'; // just in case....
// buffer now contains file path...
MessageBox(0, buffer.c_str(), buffer.c_str(), MB_OK);
}
}
}
break;
}
来源:https://stackoverflow.com/questions/43823771/passing-wparam-into-dragqueryfile-not-compatible