Извлечение функции в программировании расширения оболочки - PullRequest
0 голосов
/ 05 апреля 2019

Я хочу извлечь некоторый код DropHandler в отдельную функцию, но не знаю, как это сделать при работе с указателями интерфейса или C ++ в целом. Я хочу получить только первый элемент в DragEnter, используя отдельную функцию.

HRESULT drop_handler::GetFirstItem(IDataObject* p_data_obj, IShellItemArray* items, IShellItem* first_item)
{
    HRESULT hr = SHCreateShellItemArrayFromDataObject(p_data_obj, IID_PPV_ARGS(&items));
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    DWORD item_count;
    items->GetCount(&item_count);
    if (item_count != 1)
    {
        items->Release();
        return E_INVALIDARG;
    }

    hr = items->GetItemAt(0, &first_item);
    if (hr != ERROR_SUCCESS)
    {
        items->Release();
        return E_INVALIDARG;
    }

    return ERROR_SUCCESS;
}

HRESULT drop_handler::DragEnter(IDataObject* p_data_obj, DWORD gtf_key_state, POINTL pt, DWORD* pdw_effect)
{
    IShellItemArray* items = nullptr;
    IShellItem* dragged_item = nullptr;
    HRESULT hr = GetFirstItem(p_data_obj, items, dragged_item);
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    //...use dragged_item

Эта попытка кода приводит к краху Проводника. Я не уверен, какую подпись функции и указатели мне следует использовать, чтобы она работала.

Редактировать : фиксированный ответ для Андерса

HRESULT drop_handler::GetFirstItem(IDataObject* p_data_obj, IShellItemArray*& items, IShellItem*& first_item)
{
    HRESULT hr = SHCreateShellItemArrayFromDataObject(p_data_obj, IID_PPV_ARGS(&items));
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    DWORD item_count;
    hr = items->GetCount(&item_count);
    if (hr != ERROR_SUCCESS || item_count != 1)
    {
        items->Release();
        return E_INVALIDARG;
    }

    hr = items->GetItemAt(0, &first_item);
    if (hr != ERROR_SUCCESS)
    {
        items->Release();
        return E_INVALIDARG;
    }

    return ERROR_SUCCESS;
}

HRESULT drop_handler::DragEnter(IDataObject* p_data_obj, DWORD gtf_key_state, POINTL pt, DWORD* pdw_effect)
{
    IShellItemArray* items;
    IShellItem* dragged_item;
    HRESULT hr = GetFirstItem(p_data_obj, items, dragged_item);
    if (hr != ERROR_SUCCESS)
    {
        return E_INVALIDARG;
    }

    //...use dragged_item

1 Ответ

1 голос
/ 06 апреля 2019

Ваша обработка IShellItemArray* и IShellItem* неверна.GetFirstItem освободит IShellItemArray* при сбое, но при успехе вы утечете, и first_item никогда не будет возвращен правильно.items и first_item в DragEnter никогда не будут действительными.

IShellItemArray* должно быть локальной переменной в GetFirstItem.

Параметр IShellItem* first_item должен быть IShellItem** first_item или IShellItem*& first_item, чтобы значение указателя возвращалось вызывающей стороне корректно.

Никогда не проверяйте возвращаемое значение GetCount.

Поскольку у вас возникают проблемы с указателями, вы можете добавить несколько assert, чтобы убедиться, что указатели интерфейса не являются нулевыми, прежде чем их использовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...