【问题标题】:Passing WPARAM into DragQueryFile not compatible?将 WPARAM 传递给 DragQueryFile 不兼容?
【发布时间】:2017-05-06 18:04:59
【问题描述】:

我有点困惑。当一个文件被拖到带有 WS_EX_ACCEPTFILES 标志的窗口时,它会将 PostMessage 放入 WndProc 函数中,该函数将 UINT 消息设置为 WM_DROPFILES,并且根据

https://msdn.microsoft.com/en-us/library/windows/desktop/bb774303(v=vs.85).aspx

WPARAM = (WPARAM) (HDROP) hDrop;所以我假设我可以使用 WPARAM 来初始化 HDROP 或者只是将它传递给 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);
}

感谢任何帮助。

【问题讨论】:

  • 为什么要在这里标记c++?这是纯 C。
  • @i486:如果它通过 C++ 编译器传递,它就是 C++。我什至不相信 C 会给出这个错误。
  • @BoundaryImposition C++ 编译器作为.c 源文件的 C 编译器工作,或者可以选择。 Win32 API 是 C 语言,在上面的例子中没有 C++。
  • @i486:如果在 C 模式下运行,GCC 是 C 编译器,而不是 C++ 编译器。您根本无法从上面的小代码 sn-p 判断 OP 是在编写 C 还是 C++,句号。他们选择了c++ 标签这一事实有力地证明了它是 C++,远胜过你的“这是纯 C”断言,没有任何证据支持。
  • @BoundaryImposition 问题中的示例是 C 语言,Win32 API 基于 C,而不是 C++。至少问题的可能答案中的所有内容都将在 C 中。那么 - 为什么要谈论 C++?

标签: c++ windows winapi


【解决方案1】:

您需要将 wparam 转换为 HDROP,然后遍历提供缓冲区的已删除文件路径。

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;
}

但是请注意,尽管处理 WM_DROPFILES 应该可以工作,但处理拖放的首选方法是为您的应用程序实现 IDropTarget interfaceregister it as drop target handler

【讨论】:

    【解决方案2】:

    你快到了。您有正确的答案,但由于与您使用 case 标签有关的不同错误,您将其注释掉。而不是用你的HDROPWPARAM 倒退,你应该修复那个不同的错误;)

    演员表是正确的,但您需要确定案例“主体”的范围(因为事实上,案例没有主体,也没有自己的范围),这就是错误告诉您的内容:

    case WM_DROPFILES: {
        TCHAR FilePath[MAX_PATH];
        HDROP hdrop = (HDROP)wParam; 
        DragQueryFile(hdrop, 0, FilePath, 0);
        return 0;
     }
    

    这里我添加了{} 来引入块作用域。

    【讨论】:

    • 不应该是hdrop作为DragQueryFile的参数吗? lpszFilecch 的参数也不正确。您应该传递一个预分配的缓冲区及其大小,或者传递 NULL for lpszFile 以获得所需的缓冲区大小。
    • 但是 TCHAR 自 windows 2000 以来就没有意义了。
    【解决方案3】:

    添加 VTT 应答。

    您可以将::std::vector&lt; wchar_t &gt; buffer; 替换为std::wstring buffer

    代码

    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      • 2019-06-26
      • 2017-04-06
      • 1970-01-01
      相关资源
      最近更新 更多