Мне нужно было реализовать удаления файлов в корзину методом - Drag and Drop Для того чтобы понять смысл алгоритма для себя сделал показательную программу При запуске появляется окно в которое методом перетаскивания файла или группы файлов без разницы эти файлы перемещаются в корзину Алгоритм: При создании окна в сообщении - WM_CREATE мы инициализируем определёнными значениями структуру - SHFILEOPSTRUCT И когда окно обрабатывает сообщение - WM_DROPFILES в параметре - wParam возвращается дескриптор внутренней структуры в этой структуре первым параметром прописано смещение на символьные пути файла или файлов в формате - UNICODE адрес первого файла мы записываем в объект (pFrom) структуры - SHFILEOPSTRUCT скармливаем адресом этой структуры функцию - SHFileOperationW после освобождаем выделенную память функцией - DragFinish Проект: Код (ASM): ;===================================================================== lib Shell32 ;--------------------------------------------------------------------- Window -1,-1,200,200,0,'Корзина',0,0,WS_EX_ACCEPTFILES,11,0,hWnd,1 Message Exit ;===================================================================== proc hWnd ; процедурная функция окна ;-------------------------------------- case WM_CREATE global sfs:SHFILEOPSTRUCT dword sfs.hwnd = hWin mov sfs.wFunc,FO_DELETE mov sfs.pTo,0 mov sfs.fFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION mov sfs.fAnyOperationsAborted,0 mov sfs.hNameMappings,0 mov sfs.lpszProgressTitle,0 ;-------------------------------------- case WM_DROPFILES fun DragAcceptFiles,hWin,0 ; на время удаления отключим принятие файлов dword eax = [&wParam] dword sfs.pFrom = eax+[eax] ; адрес символов файлов в формате - UNICODE fun SHFileOperationW,&sfs ; соответственно только функция - UNICODE fun DragFinish,wParam ; освободим память выделенную системой fun DragAcceptFiles,hWin,1 ; после удаления включим принятие файлов ;-------------------------------------- case WM_DESTROY fun PostQuitMessage,0 ;-------------------------------------- end ;===================================================================== end Синтаксис кода я думаю интуитивно понятен но если кому интересно Мой транслятор под капотом создаёт - Ассемблерный листинг и скармливает его основному компилятору - ml.exe Код (ASM): .686 .mmx .xmm .model flat,stdcall option casemap :none option dotname include \masm32#\library\base\base.inc include \masm32#\library\structure\structure.inc includelib /masm32#/lib/kernel32.lib GetModuleHandleA PROTO :DWORD GetProcessHeap PROTO ExitProcess PROTO :DWORD includelib /masm32#/lib/user32.lib GetSystemMetrics PROTO :DWORD TranslateMessage PROTO :DWORD DispatchMessage EQU <DispatchMessageA> DispatchMessageA PROTO :DWORD GetMessage EQU <GetMessageA> GetMessageA PROTO :DWORD,:DWORD,:DWORD,:DWORD DefWindowProc EQU <DefWindowProcA> DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD CallWindowProc EQU <CallWindowProcA> CallWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD PostQuitMessage PROTO :DWORD includelib /masm32#/lib/msvcr120.lib rand_s PROTO C:VARARG includelib /masm32#/lib/shell32.lib DragAcceptFiles PROTO :DWORD,:DWORD SHFileOperationW PROTO :DWORD DragFinish PROTO :DWORD WS_EX_ACCEPTFILES EQU 010h WM_CREATE EQU 01h FO_DELETE EQU 03h FOF_ALLOWUNDO EQU 040h FOF_NOCONFIRMATION EQU 010h WM_DROPFILES EQU 0233h WM_DESTROY EQU 02h .code start: assume es:nothing,ss:nothing,fs:nothing,gs:nothing .shar segment SHARED .const ?XmmXorps oword 80000000800000008000000080000000h ?XmmXorpd oword 80000000000000008000000000000000h ?MmxNeg qword 08000000080000000h ?MmxNot qword 0ffffffffffffffffh ?XmmQword qword 0,41f0000000000000h ?FpuReal tbyte 1.8446744073709551616e19 .data? ?R dq 128 dup(?) ?Q dq 128 dup(?) ?F dd 128 dup(?) ?D dd 128 dup(?) ?W dw 128 dup(?) ?B db 128 dup(?) hInstance dd ? hHeap dd ? dScreenW dd ? dScreenH dd ? tmp dd ? ?Ind dd ? ?Rnd dd ? ?Dwd dd ? ?Dd dd ? ?Dw dw ? ?Db db ? .code push 0 call GetModuleHandleA mov hInstance,eax call GetProcessHeap mov hHeap,eax push 0 call GetSystemMetrics mov dScreenW,eax push 1 call GetSystemMetrics mov dScreenH,eax push $hWnd .data? hWnd dd ? .code push offset hWnd push 0 push 10080000h push WS_EX_ACCEPTFILES push 0 push 0 .const align 16 dd 0,0,0,7 ??__0 db 202,238,240,231,232,237,224,0,0,0,0,0 .code push offset ??__0 push 0 push 200 push 200 push 0FFFFFFFFh push 0FFFFFFFFh push 13 call ?FunWindow add esp,56 .data? ??MsgStr? dword 8 dup(?) .code ??Msg_loop: push 0 push 0 push 0 push offset ??MsgStr? call GetMessageA test eax,eax je ??Msg_Exit push offset ??MsgStr? call TranslateMessage push offset ??MsgStr? call DispatchMessageA jmp ??Msg_loop ??Msg_Exit: push 0 call ExitProcess align 16 $hWnd proc hWin,uMsg,wParam,lParam cmp uMsg,WM_CREATE jnz ??L_3 .data? sfs SHFILEOPSTRUCT <> .code mov eax,hWin mov sfs.hwnd,eax mov sfs.wFunc,FO_DELETE mov sfs.pTo,0 mov sfs.fFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION mov sfs.fAnyOperationsAborted,0 mov sfs.hNameMappings,0 mov sfs.lpszProgressTitle,0 xor eax,eax ret ??L_3: cmp uMsg,WM_DROPFILES jnz ??L_5 push 0 push hWin call DragAcceptFiles mov eax,wParam mov eax,dword ptr [eax] add eax,dword ptr [eax] mov sfs.pFrom,eax push offset sfs call SHFileOperationW push wParam call DragFinish push 1 push hWin call DragAcceptFiles xor eax,eax ret ??L_5: cmp uMsg,WM_DESTROY jnz ??L_7 push 0 call PostQuitMessage xor eax,eax ret ??L_7: push lParam push wParam push uMsg push hWin call DefWindowProcA ret $hWnd endp include \masm32#\func\base.asm include \masm32#\func\window.asm end start Работает этот метод выше всяких похвал Начиная с операционной системы - Vista Майкрософт рекомендует это делать интерфейсом - IFileOperation В интернете я нашёл информацию и реализовал код Здесь будет показана только обработка сообщения - WM_DROPFILES Код (ASM): ;-------------------------------------- case WM_DROPFILES fun DragAcceptFiles,hWin,0 ; на время удаления отключим принятие файлов ;------------------ global CLSID_FileOperation = g'3ad05575-8857-4850-9277-11b85bdb8e09' global IID_IFileOperation = g'947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8' global IID_IShellItem = g'43826D1E-E718-42EE-BC55-A1E261C37BFE' ;------------------ ; Инициализировать COM-объект fun CoInitialize,0 ;------------------ ; Создать объект fun CoCreateInstance,&CLSID_FileOperation,0,CLSCTX_INPROC_SERVER, &IID_IFileOperation,&&pIFoDisp ;------------------ ; Установить флаги выполняемой операции fun pIFoDisp.IFileOperation.SetOperationFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION ;------------------ ; Создать объект IShellItem dword eax = [&wParam] dword eax = eax+[eax] ; адрес символов файлов в формате - UNICODE fun SHCreateItemFromParsingName,eax,0,&IID_IShellItem,&&deleteItem ;------------------ ; Подготовить операцию удаления fun pIFoDisp.IFileOperation.DeleteItem,deleteItem,0 ;------------------ ; Выполнить операцию fun pIFoDisp.IFileOperation.PerformOperations ;------------------ fun DragFinish,wParam ; освободим память выделенную системой fun DragAcceptFiles,hWin,1 ; после удаления включим принятие файлов ;-------------------------------------- Закрытие интерфейсов я пока не стал делать Этот метод работает но к сожелению только для одного файла если передать в окно несколько файлов в корзину переместится только один Кто знаком с этими методами интерфейса подскажите пожалуйста как реализовать множественное перемещение файлов
Делал на другом языке погромирования множественное перемещение, обрабатывается WM_DROPFILES: Код (Text): var Files: TStrings; i: Integer; FileName: string; hDrop: THandle; FileCount: Integer; FileNameLength: Integer; begin if Msg.message = WM_DROPFILES then begin Files := TStringList.Create; // Получаем дескриптор списка файлов hDrop := THandle(Msg.wParam); // Получаем количество файлов, переданных через Drag-and-Drop FileCount := DragQueryFile(hDrop, $FFFFFFFF, nil, 0); Files.Clear; // Обрабатываем каждый файл for i := 0 to FileCount - 1 do begin // Получаем размер буфера для имени файла FileNameLength := DragQueryFile(hDrop, i, nil, 0) + 1; // Выделяем память для имени файла SetLength(FileName, FileNameLength); // Получаем имя файла DragQueryFile(hDrop, i, PChar(FileName), FileNameLength); // Выводим имя файла //ShowMessage(FileName); Files.Add(FileName); end; // Освобождаем ресурсы DragFinish(hDrop); Files.Free; Handled := True; end; end; Воз можно поможет удалить ненавистные файлы в корзину
Можно мсдн открыть и увидеть, что в интерфейсе IFileOperation кроме метода DeleteItem, есть DeleteItems, принимающий не одиночный IShellItem, а энумератор IEnumShellItems.
В чем проблема? В обработчике WM_DROPFILES вызываешь DragQueryFile с индексом -1, чтобы получить количество файлов в наборе, затем в цикле от 0 до count вызываешь DragQueryFile чтобы получить имя очередного файла, создаешь из него IShellItem и сохраняешь в динамический массив. Пишешь методы интерфейса IEnumShellItems, которые будут возвращать элементы этого динамического массива, заносишь их адреса в lpVtbl и передаешь этот псевдообъект в IFileOperation:: DeleteItems. --- Сообщение объединено, 14 май 2024 --- Или, раз уже решил использовать COM, делаешь как спец : создаешь класс, реализующий IDropTarget и привязываешь его к окну вызовом RegisterDragDrop. Система будет вызывать методы этого интерфейса, когда над окном будут водить разными шелл-объектами и в методе IDropTarget:: Drop ты получишь готовый IDataObject. представляющий список файлов, который сразу можно будет передать в IFileOperation:: DeleteItems. WM_DROPFILES тут будет не нужон.
Не знаю насколько адекватный ответ выдала неровная сеть: Код (Text): #include <windows.h> #include <shobjidl.h> // Функция для обработки Drag and Drop событий HRESULT HandleDragAndDrop(HWND hWnd, IDataObject* pDataObj) { // Получаем интерфейс IFileOperation IFileOperation* pFileOperation; HRESULT hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)); if (SUCCEEDED(hr)) { // Получаем интерфейс IEnumShellItems IEnumShellItems* pEnumShellItems; hr = pDataObj->EnumFormatEtc(DATADIR_GET, &pEnumShellItems); if (SUCCEEDED(hr)) { // Перебираем все выбранные файлы ULONG fetched; while (pEnumShellItems->Next(1, &pItem, &fetched) == S_OK && fetched == 1) { // Добавляем файлы в операцию hr = pFileOperation->DragEnter(hWnd, pDataObj, pt, *pdwEffect); if (FAILED(hr)) { // Обработка ошибок при добавлении файлов break; } } // Выполняем операцию hr = pFileOperation->PerformOperations(); if (FAILED(hr)) { // Обработка ошибок при выполнении операции } // Освобождаем ресурсы pEnumShellItems->Release(); } // Освобождаем ресурсы pFileOperation->Release(); } return hr; } // Функция обработки сообщений окна LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_DROPFILES: { // Получаем IDataObject из HDROP HDROP hDrop = (HDROP)wParam; IDataObject* pDataObj = NULL; HRESULT hr = ::DragQueryFile(hDrop, 0, &pDataObj); if (SUCCEEDED(hr)) { // Обрабатываем Drag and Drop HandleDragAndDrop(hWnd, pDataObj); pDataObj->Release(); } // Освобождаем ресурсы ::DragFinish(hDrop); return 0; } // Обработка других сообщений // ... default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // Создаем окно HWND hWnd = CreateWindowEx(0, L"STATIC", L"Drag and Drop Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, NULL); // Регистрируем оконный класс WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = 0; wcex.lpfnWndProc = WindowProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = NULL; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"DragAndDropWindow"; wcex.hIconSm = NULL; RegisterClassEx(&wcex); // Показываем окно ShowWindow(hWnd, nShowCmd); UpdateWindow(hWnd); // Запускаем цикл обработки сообщений MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; }
С кодом так и ничего не получилось странный он какой то Чтобы получить указатель интерфейса - IFileOperation достаточно например знать его - CLSID_FileOperation у функция (CoCreateInstance) вернёт его указатель А вот как например получить указатель интерфейса - IEnumShellItems ведь нет такого - CLSID_IEnumShellItems В этом странном коде вроде это прописано но наверное там что то не неправильно Не подскажите как получить указатель интерфейса - IEnumShellItems
Спасибо rmn, за уточнение как я полагаю методом другого интерфейса или я ошибаюсь а если да то например какого интерфейса
Код (C): #include <windows.h> #include <tchar.h> #include <shlwapi.h> #include <shobjidl.h> #pragma comment(lib, "shlwapi.lib") /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_QueryInterface (IEnumShellItems* This, REFIID riid, LPVOID* ppvObject); static HRESULT WINAPI IEnumShellItems_AddRef (IEnumShellItems* This); static HRESULT WINAPI IEnumShellItems_Release (IEnumShellItems* This); static HRESULT WINAPI IEnumShellItems_Clone (IEnumShellItems* This, IEnumShellItems** ppenum); static HRESULT WINAPI IEnumShellItems_Next (IEnumShellItems* This, ULONG celt, IShellItem** rgelt, ULONG* pceltFetched); static HRESULT WINAPI IEnumShellItems_Reset (IEnumShellItems* This); static HRESULT WINAPI IEnumShellItems_Skip (IEnumShellItems* This, ULONG celt); static const IEnumShellItemsVtbl CEnumShellItemsVtbl = { IEnumShellItems_QueryInterface, IEnumShellItems_AddRef, IEnumShellItems_Release, IEnumShellItems_Clone, IEnumShellItems_Next, IEnumShellItems_Reset, IEnumShellItems_Skip, }; typedef struct _CEnumShellItems { const IEnumShellItemsVtbl* lpVtbl; LONG refCount; IShellItem** items; UINT count; UINT pos; }CEnumShellItems; /* -------------------------------------------------------------------------- */ static void FreeEnumShellItemsInstance (CEnumShellItems* en) { UINT i; if (en) { if (en->items) { for (i=0; i<en->count; i++) if (en->items[i]) en->items[i]->lpVtbl->Release (en->items[i]); HeapFree (GetProcessHeap(), 0, en->items); } HeapFree (GetProcessHeap(), 0, en); } } /* -------------------------------------------------------------------------- */ static HRESULT CreateEnumShellItemsInstance (HDROP hDrop, IEnumShellItems** ppenum) { CEnumShellItems* en; WCHAR fileName[MAX_PATH]; UINT i; HRESULT hr; if (!ppenum) return E_POINTER; *ppenum = NULL; en = (CEnumShellItems*)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CEnumShellItems)); if (!en) return E_OUTOFMEMORY; en->lpVtbl = &CEnumShellItemsVtbl; en->refCount = 1; en->count = DragQueryFileW (hDrop, (UINT)-1, NULL, 0); if (en->count == 0) { FreeEnumShellItemsInstance (en); return E_FAIL; } en->items = (IShellItem**)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellItem*) * en->count); if (!en->items) { FreeEnumShellItemsInstance (en); return E_OUTOFMEMORY; } for (i=0; i<en->count; i++) { if (DragQueryFileW (hDrop, i, fileName, MAX_PATH) == 0) { FreeEnumShellItemsInstance (en); return E_FAIL; } hr = SHCreateItemFromParsingName (fileName, NULL, &IID_IShellItem, &en->items[i]); if (FAILED (hr)) { FreeEnumShellItemsInstance (en); return hr; } } *ppenum = (IEnumShellItems*)en; return S_OK; } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_QueryInterface (IEnumShellItems* This, REFIID riid, LPVOID* ppvObject) { CEnumShellItems* en; en = (CEnumShellItems*)This; if (!ppvObject) return E_POINTER; *ppvObject = NULL; if (!memcmp (riid, &IID_IUnknown, sizeof(GUID)) || !memcmp (riid, &IID_IEnumShellItems, sizeof(GUID))) { This->lpVtbl->AddRef (This); *ppvObject = This; return S_OK; } return E_NOINTERFACE; } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_AddRef (IEnumShellItems* This) { CEnumShellItems* en; en = (CEnumShellItems*)This; InterlockedIncrement (&en->refCount); return S_OK; } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_Release (IEnumShellItems* This) { CEnumShellItems* en; LONG refCount; en = (CEnumShellItems*)This; refCount = InterlockedDecrement (&en->refCount); if (refCount == 0) FreeEnumShellItemsInstance (en); return S_OK; } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_Clone (IEnumShellItems* This, IEnumShellItems** ppenum) { CEnumShellItems* en; en = (CEnumShellItems*)This; if (!ppenum) return E_POINTER; *ppenum = NULL; return E_NOTIMPL; } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_Next (IEnumShellItems* This, ULONG celt, IShellItem** rgelt, ULONG* pceltFetched) { CEnumShellItems* en; IShellItem* item; UINT i; en = (CEnumShellItems*)This; if (!rgelt) return E_POINTER; if (!pceltFetched && celt > 1) return E_INVALIDARG; if (en->pos >= en->count) celt = 0; else if (en->count - en->pos < celt) celt = en->count - en->pos; for (i=0; i<celt; i++) { item = en->items[en->pos + i]; item->lpVtbl->AddRef (item); rgelt[i] = item; } en->pos += celt; if (pceltFetched) *pceltFetched = celt; return (celt != 0 ? S_OK : S_FALSE); } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_Reset (IEnumShellItems* This) { CEnumShellItems* en; en = (CEnumShellItems*)This; en->pos = 0; return S_OK; } /* -------------------------------------------------------------------------- */ static HRESULT WINAPI IEnumShellItems_Skip (IEnumShellItems* This, ULONG celt) { CEnumShellItems* en; en = (CEnumShellItems*)This; if (en->pos >= en->count) celt = 0; else if (en->count - en->pos < celt) celt = en->count - en->pos; en->pos += celt; return S_OK; } /* -------------------------------------------------------------------------- */ static LRESULT WINAPI WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { IFileOperation* fileOper; IEnumShellItems* enumItems; HRESULT hr; switch (msg) { ... case WM_DROPFILES: hr = CreateFileOperationInstance (&fileOper); if (SUCCEEDED (hr)) { hr = CreateEnumShellItemsInstance ((HDROP)wParam, &enumItems); if (SUCCEEDED (hr)) { fileOper->lpVtbl->DeleteItems (fileOper, (IUnknown*)enumItems); fileOper->lpVtbl->PerformOperations (fileOper); enumItems->lpVtbl->Release (enumItems); } fileOper->lpVtbl->Release (fileOper); } DragFinish ((HDROP)wParam); return 0; ... default: return DefWindowProc (hwnd, msg, wParam, lParam); } } /* -------------------------------------------------------------------------- */
Большое спасибо rmn, за участие и за пример. Буду изучать. Век живи век учись. --- Сообщение объединено, 15 май 2024 --- мой Microsoft Visual Studio 12 Ошибка 1 error C3861: CreateFileOperationInstance: идентификатор не найден Ошибка 2 error C3861: CreateEnumShellItemsInstance: идентификатор не найден ругается на синтаксис Код (Text): static const IEnumShellItemsVtbl CEnumShellItemsVtbl = { IEnumShellItems_QueryInterface, IEnumShellItems_AddRef, IEnumShellItems_Release, IEnumShellItems_Clone, IEnumShellItems_Next, IEnumShellItems_Reset, IEnumShellItems_Skip, }; и Код (Text): typedef struct _CEnumShellItems { const IEnumShellItemsVtbl* lpVtbl; LONG refCount; IShellItem** items; UINT count; UINT pos; }CEnumShellItems;
Первую тебе самому написать надо и перенести туда код, создающий IFileOperation. Вторая должна быть перед WndProc, потому что она без прототипа. У AddRef и Release тип возвращаемого значения надо на ULONG поменять (и в прототипе и в реализации). И, возможно, надо заголовки дополнительные подключить. где все используемые интерфейсы объявлены.
Чтобы тема не повисла выкладываю своё решение Для удаления группы файлов нужен метод - DeleteItems у этого метода только один параметр это указатель на интерфейс - IShellItemArray Этот интерфейс можно получить функцией - SHCreateShellItemArrayFromIDLists у неё три параметра: 1 - количество указателей в массиве 2 - адрес указателя на массив указателей - ITEMIDLIST 3 - адрес лексемы которая получит указатель на интерфейс - IShellItemArray Но чтобы сделать массив указателей - ITEMIDLIST нам придётся в ручную парсить список файлов Когда окно обрабатывает сообщение - WM_DROPFILES в параметре - wParam возвращается дескриптор внутренней структуры в этой структуре первым параметром прописано смещение на символьные пути файла или файлов в формате - UNICODE Этот список нам и нужно полностью прогнать до финальных четырёх нулей каждый символьный путь к файлу мы будем скармливать функции - SHParseDisplayName а она будет записывать в адрес третьего параметра указатель - ITEMIDLIST Этих указателей может быть много по этому нам нужна отдельная память куда мы последовательно будем записывать указатели (по сути адреса) Я нашёл оригинальный выход мы воспользуемся памятью которую выделила сама система это та память где она прописала символьные пути файлов которые мы собственно говоря и будем парсить а после обработки мы вернём эту память системе функцией - DragFinish Код (ASM): ;--------------------------------------------------------------------- lib Shell32,ole32 ;--------------------------------------------------------------------- global CLSID_FileOperation = g'3AD05575-8857-4850-9277-11B85BDB8E09' global IID_IFileOperation = g'947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8' global pOperation::IFileOperation global pArray::IShellItemArray global pIdl ; адрес указателя на массив указателей - ITEMIDLIST ;--------------------------------------------------------------------- include interface.asm ;--------------------------------------------------------------------- Window -1,-1,200,200,0,'Корзина',0,0,0,11,0,hWnd,1 Message Exit ;===================================================================== proc hWnd ; процедурная функция окна ;-------------------------------------- case WM_CREATE fun CoInitialize,0 fun DragAcceptFiles,hWin,1 ;-------------------------------------- case WM_DROPFILES fun DragAcceptFiles,hWin,0 fun CoCreateInstance,&CLSID_FileOperation,0,CLSCTX_ALL, &IID_IFileOperation,&pOperation fun pOperation.SetOperationFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION ;------------------ pushad dword edi = [&wParam] mov pIdl,edi dword esi = edi+[edi] xor ebx,ebx Loc__lop: if dw[esi] inc ebx fun SHParseDisplayName,esi,0,edi,0,0 Loc__smv: add esi,2 mov eax,[esi] if ax jmp Loc__smv endif add edi,4 add esi,2 jmp Loc__lop endif fun SHCreateShellItemArrayFromIDLists,ebx,pIdl,&pArray popad ;------------------ fun pOperation.DeleteItems,pArray fun pOperation.PerformOperations fun pOperation.Release fun pArray.Release fun DragFinish,wParam fun DragAcceptFiles,hWin,1 ;-------------------------------------- case WM_DESTROY fun CoUninitialize fun PostQuitMessage,0 ;-------------------------------------- end ;===================================================================== end В проекте подключен файл - interface.asm это файл где описаны используемые интерфейсы Код (ASM): ;------------------------------------------------------ interface IFileOperation QueryInterface,DWORD,DWORD AddRef Release Advise,DWORD,DWORD Unadvise,DWORD SetOperationFlags,DWORD SetProgressMessage,DWORD SetProgressDialog,DWORD SetProperties,DWORD SetOwnerWindow,DWORD ApplyPropertiesToItem,DWORD ApplyPropertiesToItems,DWORD RenameItem,DWORD,DWORD,DWORD RenameItems,DWORD,DWORD MoveItem,DWORD,DWORD,DWORD,DWORD MoveItems,DWORD,DWORD CopyItem,DWORD,DWORD,DWORD,DWORD CopyItems,DWORD,DWORD DeleteItem,DWORD,DWORD DeleteItems,DWORD NewItem,DWORD,DWORD,DWORD,DWORD,DWORD PerformOperations GetAnyOperationsAborted,DWORD end ;------------------------------------------------------ interface IShellItemArray QueryInterface,DWORD,DWORD AddRef Release BindToHandler,DWORD,DWORD,DWORD,DWORD GetPropertyStore,DWORD,DWORD,DWORD GetPropertyDescriptionList,DWORD,DWORD,DWORD GetAttributes,DWORD,DWORD,DWORD GetCount,DWORD GetItemAt,DWORD,DWORD EnumItems,DWORD end ;------------------------------------------------------ В проекте эти интерфейсы привязаны к определённым лексемам Код (ASM): global pOperation::IFileOperation global pArray::IShellItemArray Но в принципи можно не подключать этот файл интерфейсов а просто объявить лексемы Код (ASM): global pOperation global pArray А в коде вместо методов Код (ASM): fun pOperation.DeleteItems,pArray Прописывать их числовые смещения Код (ASM): fun pOperation.68,pArray Что в принципи одно и тоже Только в этом случае за количество прописанных аргументов вся ответственность на программисте Это удаление реализованно на интерфейсах но по скорости исполнения оно работает точно так же как и способ с гораздо меньшим байт-кодом без интерфейсов описанный в первом посте Но чёрт его знает может быть интерфейсы более надёжны или безопасны а может быть и нет Век живи век учись