#winapi #visual-c
#winapi #visual-c
Вопрос:
Я хочу извлечь некоторый код 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(amp;items));
if (hr != ERROR_SUCCESS)
{
return E_INVALIDARG;
}
DWORD item_count;
items->GetCount(amp;item_count);
if (item_count != 1)
{
items->Release();
return E_INVALIDARG;
}
hr = items->GetItemAt(0, amp;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*amp; items, IShellItem*amp; first_item)
{
HRESULT hr = SHCreateShellItemArrayFromDataObject(p_data_obj, IID_PPV_ARGS(amp;items));
if (hr != ERROR_SUCCESS)
{
return E_INVALIDARG;
}
DWORD item_count;
hr = items->GetCount(amp;item_count);
if (hr != ERROR_SUCCESS || item_count != 1)
{
items->Release();
return E_INVALIDARG;
}
hr = items->GetItemAt(0, amp;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:
Ваша обработка IShellItemArray*
и IShellItem*
неверна. GetFirstItem
освободится IShellItemArray*
при сбое, но при успехе вы пропустите его и first_item
никогда не будете возвращены правильно. items
и first_item
в DragEnter
никогда не будут действительными.
IShellItemArray*
вероятно, должна быть локальная переменная в GetFirstItem
.
IShellItem* first_item
Параметр должен быть IShellItem** first_item
или IShellItem*amp; first_item
, чтобы значение указателя правильно возвращалось вызывающей стороне.
Вы никогда не проверяете возвращаемое значение GetCount
.
Поскольку у вас возникли проблемы с указателями, вы можете захотеть добавить некоторые assert
s, чтобы убедиться, что указатели вашего интерфейса не равны нулю, прежде чем использовать их.
Комментарии:
1. Спасибо! Используя
IShellItem*amp;
в качестве аргумента, он компилируется и отлично работает! Причина, по которой мне нужно принестиIShellItemArray*
извне, заключается в том, что я могу выпустить ее позже.