Программно удалить файлы в корзину

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 13 май 2024.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Мне нужно было реализовать удаления файлов в корзину методом - Drag and Drop

    Для того чтобы понять смысл алгоритма для себя сделал показательную программу

    При запуске появляется окно в которое методом перетаскивания
    файла или группы файлов без разницы
    эти файлы перемещаются в корзину

    Алгоритм:

    При создании окна в сообщении - WM_CREATE
    мы инициализируем определёнными значениями структуру - SHFILEOPSTRUCT

    И когда окно обрабатывает сообщение - WM_DROPFILES
    в параметре - wParam
    возвращается дескриптор внутренней структуры
    в этой структуре первым параметром прописано смещение
    на символьные пути файла или файлов в формате - UNICODE
    адрес первого файла мы записываем в объект (pFrom) структуры - SHFILEOPSTRUCT

    скармливаем адресом этой структуры функцию - SHFileOperationW
    после освобождаем выделенную память функцией - DragFinish

    Проект:

    Код (ASM):
    1.  
    2. ;=====================================================================
    3. lib Shell32
    4. ;---------------------------------------------------------------------
    5. Window -1,-1,200,200,0,'Корзина',0,0,WS_EX_ACCEPTFILES,11,0,hWnd,1
    6. Message
    7. Exit
    8. ;=====================================================================
    9. proc hWnd ; процедурная функция окна
    10. ;--------------------------------------
    11. case WM_CREATE
    12. global sfs:SHFILEOPSTRUCT
    13. dword sfs.hwnd = hWin
    14. mov sfs.wFunc,FO_DELETE
    15. mov sfs.pTo,0
    16. mov sfs.fFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION
    17. mov sfs.fAnyOperationsAborted,0
    18. mov sfs.hNameMappings,0
    19. mov sfs.lpszProgressTitle,0
    20. ;--------------------------------------
    21. case WM_DROPFILES
    22. fun DragAcceptFiles,hWin,0  ; на время удаления отключим принятие файлов
    23. dword eax = [&wParam]
    24. dword sfs.pFrom = eax+[eax] ; адрес символов файлов в формате - UNICODE
    25. fun SHFileOperationW,&sfs   ; соответственно только функция - UNICODE
    26. fun DragFinish,wParam       ; освободим память выделенную системой
    27. fun DragAcceptFiles,hWin,1  ; после удаления включим принятие файлов
    28. ;--------------------------------------
    29. case WM_DESTROY
    30. fun PostQuitMessage,0
    31. ;--------------------------------------
    32. end
    33. ;=====================================================================
    34. end
    35.  
    Синтаксис кода я думаю интуитивно понятен
    но если кому интересно

    Мой транслятор под капотом создаёт - Ассемблерный листинг
    и скармливает его основному компилятору - ml.exe

    Код (ASM):
    1.  
    2. .686
    3. .mmx
    4. .xmm
    5. .model flat,stdcall
    6. option casemap :none
    7. option dotname
    8. include \masm32#\library\base\base.inc
    9. include \masm32#\library\structure\structure.inc
    10. includelib /masm32#/lib/kernel32.lib
    11. GetModuleHandleA PROTO :DWORD
    12. GetProcessHeap PROTO
    13. ExitProcess PROTO :DWORD
    14. includelib /masm32#/lib/user32.lib
    15. GetSystemMetrics PROTO :DWORD
    16. TranslateMessage PROTO :DWORD
    17. DispatchMessage EQU <DispatchMessageA>
    18. DispatchMessageA PROTO :DWORD
    19. GetMessage EQU <GetMessageA>
    20. GetMessageA PROTO :DWORD,:DWORD,:DWORD,:DWORD
    21. DefWindowProc EQU <DefWindowProcA>
    22. DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD
    23. CallWindowProc EQU <CallWindowProcA>
    24. CallWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
    25. PostQuitMessage PROTO :DWORD
    26. includelib /masm32#/lib/msvcr120.lib
    27. rand_s PROTO C:VARARG
    28. includelib /masm32#/lib/shell32.lib
    29. DragAcceptFiles PROTO :DWORD,:DWORD
    30. SHFileOperationW PROTO :DWORD
    31. DragFinish PROTO :DWORD
    32. WS_EX_ACCEPTFILES EQU 010h
    33. WM_CREATE EQU 01h
    34. FO_DELETE EQU 03h
    35. FOF_ALLOWUNDO EQU 040h
    36. FOF_NOCONFIRMATION EQU 010h
    37. WM_DROPFILES EQU 0233h
    38. WM_DESTROY EQU 02h
    39. .code
    40. start:
    41. assume es:nothing,ss:nothing,fs:nothing,gs:nothing
    42. .shar segment SHARED
    43. .const
    44. ?XmmXorps oword 80000000800000008000000080000000h
    45. ?XmmXorpd oword 80000000000000008000000000000000h
    46. ?MmxNeg qword 08000000080000000h
    47. ?MmxNot qword 0ffffffffffffffffh
    48. ?XmmQword qword 0,41f0000000000000h
    49. ?FpuReal tbyte 1.8446744073709551616e19
    50. .data?
    51. ?R dq 128 dup(?)
    52. ?Q dq 128 dup(?)
    53. ?F dd 128 dup(?)
    54. ?D dd 128 dup(?)
    55. ?W dw 128 dup(?)
    56. ?B db 128 dup(?)
    57. hInstance dd ?
    58. hHeap dd ?
    59. dScreenW dd ?
    60. dScreenH dd ?
    61. tmp dd ?
    62. ?Ind dd ?
    63. ?Rnd dd ?
    64. ?Dwd dd ?
    65. ?Dd dd ?
    66. ?Dw dw ?
    67. ?Db db ?
    68. .code
    69. push 0
    70. call GetModuleHandleA
    71. mov hInstance,eax
    72. call GetProcessHeap
    73. mov hHeap,eax
    74. push 0
    75. call GetSystemMetrics
    76. mov dScreenW,eax
    77. push 1
    78. call GetSystemMetrics
    79. mov dScreenH,eax
    80. push $hWnd
    81. .data?
    82. hWnd dd ?
    83. .code
    84. push offset hWnd
    85. push 0
    86. push 10080000h
    87. push WS_EX_ACCEPTFILES
    88. push 0
    89. push 0
    90. .const
    91. align 16
    92. dd 0,0,0,7
    93. ??__0 db 202,238,240,231,232,237,224,0,0,0,0,0
    94. .code
    95. push offset ??__0
    96. push 0
    97. push 200
    98. push 200
    99. push 0FFFFFFFFh
    100. push 0FFFFFFFFh
    101. push 13
    102. call ?FunWindow
    103. add esp,56
    104. .data?
    105. ??MsgStr? dword 8 dup(?)
    106. .code
    107. ??Msg_loop:
    108. push 0
    109. push 0
    110. push 0
    111. push offset ??MsgStr?
    112. call GetMessageA
    113. test eax,eax
    114. je ??Msg_Exit
    115. push offset ??MsgStr?
    116. call TranslateMessage
    117. push offset ??MsgStr?
    118. call DispatchMessageA
    119. jmp ??Msg_loop
    120. ??Msg_Exit:
    121. push 0
    122. call ExitProcess
    123. align 16
    124. $hWnd proc hWin,uMsg,wParam,lParam
    125. cmp uMsg,WM_CREATE
    126. jnz ??L_3
    127. .data?
    128. sfs SHFILEOPSTRUCT <>
    129. .code
    130. mov eax,hWin
    131. mov sfs.hwnd,eax
    132. mov sfs.wFunc,FO_DELETE
    133. mov sfs.pTo,0
    134. mov sfs.fFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION
    135. mov sfs.fAnyOperationsAborted,0
    136. mov sfs.hNameMappings,0
    137. mov sfs.lpszProgressTitle,0
    138. xor eax,eax
    139. ret
    140. ??L_3:
    141. cmp uMsg,WM_DROPFILES
    142. jnz ??L_5
    143. push 0
    144. push hWin
    145. call DragAcceptFiles
    146. mov eax,wParam
    147. mov eax,dword ptr [eax]
    148. add eax,dword ptr [eax]
    149. mov sfs.pFrom,eax
    150. push offset sfs
    151. call SHFileOperationW
    152. push wParam
    153. call DragFinish
    154. push 1
    155. push hWin
    156. call DragAcceptFiles
    157. xor eax,eax
    158. ret
    159. ??L_5:
    160. cmp uMsg,WM_DESTROY
    161. jnz ??L_7
    162. push 0
    163. call PostQuitMessage
    164. xor eax,eax
    165. ret
    166. ??L_7:
    167. push lParam
    168. push wParam
    169. push uMsg
    170. push hWin
    171. call DefWindowProcA
    172. ret
    173. $hWnd endp
    174. include \masm32#\func\base.asm
    175. include \masm32#\func\window.asm
    176. end start
    177.  
    Работает этот метод выше всяких похвал

    Начиная с операционной системы - Vista
    Майкрософт
    рекомендует это делать интерфейсом - IFileOperation

    В интернете я нашёл информацию и реализовал код

    Здесь будет показана только обработка сообщения - WM_DROPFILES

    Код (ASM):
    1.  
    2. ;--------------------------------------
    3. case WM_DROPFILES
    4. fun DragAcceptFiles,hWin,0  ; на время удаления отключим принятие файлов
    5. ;------------------
    6. global CLSID_FileOperation = g'3ad05575-8857-4850-9277-11b85bdb8e09'
    7. global IID_IFileOperation  = g'947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8'
    8. global IID_IShellItem      = g'43826D1E-E718-42EE-BC55-A1E261C37BFE'
    9. ;------------------
    10.         ; Инициализировать COM-объект
    11. fun CoInitialize,0
    12. ;------------------
    13.         ; Создать объект
    14. fun CoCreateInstance,&CLSID_FileOperation,0,CLSCTX_INPROC_SERVER,
    15.                      &IID_IFileOperation,&&pIFoDisp
    16. ;------------------
    17.         ; Установить флаги выполняемой операции
    18. fun pIFoDisp.IFileOperation.SetOperationFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION
    19. ;------------------
    20.         ; Создать объект IShellItem
    21. dword eax = [&wParam]
    22. dword eax = eax+[eax] ; адрес символов файлов в формате - UNICODE
    23. fun SHCreateItemFromParsingName,eax,0,&IID_IShellItem,&&deleteItem
    24. ;------------------
    25.         ; Подготовить операцию удаления
    26. fun pIFoDisp.IFileOperation.DeleteItem,deleteItem,0
    27. ;------------------
    28.         ; Выполнить операцию
    29. fun pIFoDisp.IFileOperation.PerformOperations
    30. ;------------------
    31. fun DragFinish,wParam       ; освободим память выделенную системой
    32. fun DragAcceptFiles,hWin,1  ; после удаления включим принятие файлов
    33. ;--------------------------------------
    34.  
    Закрытие интерфейсов я пока не стал делать

    Этот метод работает но к сожелению только для одного файла
    если передать в окно несколько файлов в корзину переместится только один

    Кто знаком с этими методами интерфейса подскажите пожалуйста
    как реализовать множественное перемещение файлов
     
  2. Research

    Research Member

    Публикаций:
    1
    Регистрация:
    6 янв 2024
    Сообщения:
    88
    Делал на другом языке погромирования множественное перемещение, обрабатывается WM_DROPFILES:
    Код (Text):
    1.  
    2. var
    3.   Files: TStrings;
    4.   i: Integer;
    5.   FileName: string;
    6.   hDrop: THandle;
    7.   FileCount: Integer;
    8.   FileNameLength: Integer;
    9. begin
    10.   if Msg.message = WM_DROPFILES then
    11.   begin
    12.     Files := TStringList.Create;
    13.     // Получаем дескриптор списка файлов
    14.     hDrop := THandle(Msg.wParam);
    15.  
    16.     // Получаем количество файлов, переданных через Drag-and-Drop
    17.     FileCount := DragQueryFile(hDrop, $FFFFFFFF, nil, 0);
    18.  
    19.     Files.Clear;
    20.  
    21.     // Обрабатываем каждый файл
    22.     for i := 0 to FileCount - 1 do
    23.     begin
    24.       // Получаем размер буфера для имени файла
    25.       FileNameLength := DragQueryFile(hDrop, i, nil, 0) + 1;
    26.  
    27.       // Выделяем память для имени файла
    28.       SetLength(FileName, FileNameLength);
    29.  
    30.       // Получаем имя файла
    31.       DragQueryFile(hDrop, i, PChar(FileName), FileNameLength);
    32.  
    33.       // Выводим имя файла
    34.       //ShowMessage(FileName);
    35.       Files.Add(FileName);
    36.     end;
    37.  
    38.     // Освобождаем ресурсы
    39.     DragFinish(hDrop);
    40.     Files.Free;
    41.  
    42.     Handled := True;
    43.   end;
    44. end;
    Воз можно поможет удалить ненавистные файлы в корзину
     
    Последнее редактирование: 13 май 2024
  3. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Спасибо Research, но мне нужно интерфейсом - IFileOperation
     
  4. CaptainObvious

    CaptainObvious Member

    Публикаций:
    0
    Регистрация:
    18 янв 2024
    Сообщения:
    53
    assch, можно чату гпт(или you.com) задать вопрос об IFileOperation
     
  5. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.339
    Можно мсдн открыть и увидеть, что в интерфейсе IFileOperation кроме метода DeleteItem, есть DeleteItems, принимающий не одиночный IShellItem, а энумератор IEnumShellItems.
     
    Mikl___ нравится это.
  6. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    То что он есть rmn, я знаю но вот как это обыграть пока что у меня не получается
     
  7. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.339
    В чем проблема? В обработчике WM_DROPFILES вызываешь DragQueryFile с индексом -1, чтобы получить количество файлов в наборе, затем в цикле от 0 до count вызываешь DragQueryFile чтобы получить имя очередного файла, создаешь из него IShellItem и сохраняешь в динамический массив. Пишешь методы интерфейса IEnumShellItems, которые будут возвращать элементы этого динамического массива, заносишь их адреса в lpVtbl и передаешь этот псевдообъект в IFileOperation:: DeleteItems.
    --- Сообщение объединено, 14 май 2024 ---
    Или, раз уже решил использовать COM, делаешь как спец :) : создаешь класс, реализующий IDropTarget и привязываешь его к окну вызовом RegisterDragDrop. Система будет вызывать методы этого интерфейса, когда над окном будут водить разными шелл-объектами и в методе IDropTarget:: Drop ты получишь готовый IDataObject. представляющий список файлов, который сразу можно будет передать в IFileOperation:: DeleteItems. WM_DROPFILES тут будет не нужон.
     
    Mikl___ нравится это.
  8. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Не совсем разобрался rmn, но попробую покапаться
     
  9. Research

    Research Member

    Публикаций:
    1
    Регистрация:
    6 янв 2024
    Сообщения:
    88
    Не знаю насколько адекватный ответ выдала неровная сеть:
    Код (Text):
    1. #include <windows.h>
    2. #include <shobjidl.h>
    3.  
    4. // Функция для обработки Drag and Drop событий
    5. HRESULT HandleDragAndDrop(HWND hWnd, IDataObject* pDataObj)
    6. {
    7.     // Получаем интерфейс IFileOperation
    8.     IFileOperation* pFileOperation;
    9.     HRESULT hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation));
    10.     if (SUCCEEDED(hr))
    11.     {
    12.         // Получаем интерфейс IEnumShellItems
    13.         IEnumShellItems* pEnumShellItems;
    14.         hr = pDataObj->EnumFormatEtc(DATADIR_GET, &pEnumShellItems);
    15.  
    16.         if (SUCCEEDED(hr))
    17.         {
    18.             // Перебираем все выбранные файлы
    19.             ULONG fetched;
    20.             while (pEnumShellItems->Next(1, &pItem, &fetched) == S_OK && fetched == 1)
    21.             {
    22.                 // Добавляем файлы в операцию
    23.                 hr = pFileOperation->DragEnter(hWnd, pDataObj, pt, *pdwEffect);
    24.                 if (FAILED(hr))
    25.                 {
    26.                     // Обработка ошибок при добавлении файлов
    27.                     break;
    28.                 }
    29.             }
    30.  
    31.             // Выполняем операцию
    32.             hr = pFileOperation->PerformOperations();
    33.             if (FAILED(hr))
    34.             {
    35.                 // Обработка ошибок при выполнении операции
    36.             }
    37.  
    38.             // Освобождаем ресурсы
    39.             pEnumShellItems->Release();
    40.         }
    41.  
    42.         // Освобождаем ресурсы
    43.         pFileOperation->Release();
    44.     }
    45.  
    46.     return hr;
    47. }
    48.  
    49. // Функция обработки сообщений окна
    50. LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    51. {
    52.     switch (uMsg)
    53.     {
    54.         case WM_DROPFILES:
    55.         {
    56.             // Получаем IDataObject из HDROP
    57.             HDROP hDrop = (HDROP)wParam;
    58.             IDataObject* pDataObj = NULL;
    59.             HRESULT hr = ::DragQueryFile(hDrop, 0, &pDataObj);
    60.             if (SUCCEEDED(hr))
    61.             {
    62.                 // Обрабатываем Drag and Drop
    63.                 HandleDragAndDrop(hWnd, pDataObj);
    64.                 pDataObj->Release();
    65.             }
    66.  
    67.             // Освобождаем ресурсы
    68.             ::DragFinish(hDrop);
    69.  
    70.             return 0;
    71.         }
    72.  
    73.         // Обработка других сообщений
    74.         // ...
    75.  
    76.         default:
    77.             return DefWindowProc(hWnd, uMsg, wParam, lParam);
    78.     }
    79. }
    80.  
    81. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
    82. {
    83.     // Создаем окно
    84.     HWND hWnd = CreateWindowEx(0, L"STATIC", L"Drag and Drop Window", WS_OVERLAPPEDWINDOW,
    85.                                CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInstance, NULL);
    86.  
    87.     // Регистрируем оконный класс
    88.     WNDCLASSEX wcex;
    89.     wcex.cbSize = sizeof(WNDCLASSEX);
    90.     wcex.style = 0;
    91.     wcex.lpfnWndProc = WindowProc;
    92.     wcex.cbClsExtra = 0;
    93.     wcex.cbWndExtra = 0;
    94.     wcex.hInstance = hInstance;
    95.     wcex.hIcon = NULL;
    96.     wcex.hCursor = NULL;
    97.     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    98.     wcex.lpszMenuName = NULL;
    99.     wcex.lpszClassName = L"DragAndDropWindow";
    100.     wcex.hIconSm = NULL;
    101.  
    102.     RegisterClassEx(&wcex);
    103.  
    104.     // Показываем окно
    105.     ShowWindow(hWnd, nShowCmd);
    106.     UpdateWindow(hWnd);
    107.  
    108.     // Запускаем цикл обработки сообщений
    109.     MSG msg;
    110.     while (GetMessage(&msg, NULL, 0, 0))
    111.     {
    112.         TranslateMessage(&msg);
    113.         DispatchMessage(&msg);
    114.     }
    115.  
    116.     return (int)msg.wParam;
    117. }
    118.  
     
    Последнее редактирование: 14 май 2024
  10. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Спасибо Research, посмотрю
     
  11. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    С кодом так и ничего не получилось странный он какой то

    Чтобы получить указатель интерфейса - IFileOperation
    достаточно например знать его - CLSID_FileOperation
    у функция (CoCreateInstance) вернёт его указатель
    А вот как например получить указатель интерфейса - IEnumShellItems
    ведь нет такого - CLSID_IEnumShellItems

    В этом странном коде вроде это прописано но наверное там что то не неправильно

    Не подскажите как получить указатель интерфейса - IEnumShellItems
     
  12. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.339
    Этот интерфейс тебе надо не получить, а создать самому.
     
  13. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Спасибо rmn, за уточнение
    как я полагаю методом другого интерфейса или я ошибаюсь
    а если да то например какого интерфейса
     
  14. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.339
    Нет. Создать методом написания функций:
    QueryInterface
    AddRef
    Release
    Clone
    Next
    Reset
    Skip
     
  15. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Это как
    прости за наглость можно пример
     
  16. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.339
    Код (C):
    1.  
    2. #include <windows.h>
    3. #include <tchar.h>
    4. #include <shlwapi.h>
    5. #include <shobjidl.h>
    6.  
    7. #pragma comment(lib, "shlwapi.lib")
    8.  
    9. /* -------------------------------------------------------------------------- */
    10.  
    11. static HRESULT WINAPI IEnumShellItems_QueryInterface    (IEnumShellItems* This, REFIID riid, LPVOID* ppvObject);
    12. static HRESULT WINAPI IEnumShellItems_AddRef            (IEnumShellItems* This);
    13. static HRESULT WINAPI IEnumShellItems_Release           (IEnumShellItems* This);
    14. static HRESULT WINAPI IEnumShellItems_Clone             (IEnumShellItems* This, IEnumShellItems** ppenum);
    15. static HRESULT WINAPI IEnumShellItems_Next              (IEnumShellItems* This, ULONG celt, IShellItem** rgelt, ULONG* pceltFetched);
    16. static HRESULT WINAPI IEnumShellItems_Reset             (IEnumShellItems* This);
    17. static HRESULT WINAPI IEnumShellItems_Skip              (IEnumShellItems* This, ULONG celt);
    18.  
    19. static const IEnumShellItemsVtbl CEnumShellItemsVtbl =
    20. {
    21.     IEnumShellItems_QueryInterface,
    22.     IEnumShellItems_AddRef,
    23.     IEnumShellItems_Release,
    24.     IEnumShellItems_Clone,
    25.     IEnumShellItems_Next,
    26.     IEnumShellItems_Reset,
    27.     IEnumShellItems_Skip,
    28. };
    29.  
    30. typedef struct _CEnumShellItems
    31. {
    32.     const IEnumShellItemsVtbl* lpVtbl;
    33.  
    34.     LONG refCount;
    35.  
    36.     IShellItem** items;
    37.     UINT count;
    38.     UINT pos;
    39. }CEnumShellItems;
    40.  
    41. /* -------------------------------------------------------------------------- */
    42.  
    43. static void FreeEnumShellItemsInstance (CEnumShellItems* en)
    44. {
    45.     UINT i;
    46.  
    47.     if (en)
    48.     {
    49.         if (en->items)
    50.         {
    51.             for (i=0; i<en->count; i++)
    52.                 if (en->items[i])
    53.                     en->items[i]->lpVtbl->Release (en->items[i]);
    54.          
    55.             HeapFree (GetProcessHeap(), 0, en->items);
    56.         }
    57.      
    58.         HeapFree (GetProcessHeap(), 0, en);
    59.     }
    60. }
    61.  
    62. /* -------------------------------------------------------------------------- */
    63.  
    64. static HRESULT CreateEnumShellItemsInstance (HDROP hDrop, IEnumShellItems** ppenum)
    65. {
    66.     CEnumShellItems* en;
    67.     WCHAR fileName[MAX_PATH];
    68.     UINT i;
    69.     HRESULT hr;
    70.  
    71.     if (!ppenum)
    72.         return E_POINTER;
    73.  
    74.     *ppenum = NULL;
    75.  
    76.     en = (CEnumShellItems*)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CEnumShellItems));
    77.     if (!en)
    78.         return E_OUTOFMEMORY;
    79.  
    80.     en->lpVtbl = &CEnumShellItemsVtbl;
    81.     en->refCount = 1;
    82.  
    83.     en->count = DragQueryFileW (hDrop, (UINT)-1, NULL, 0);
    84.     if (en->count == 0)
    85.     {
    86.         FreeEnumShellItemsInstance (en);
    87.  
    88.         return E_FAIL;
    89.     }
    90.  
    91.     en->items = (IShellItem**)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellItem*) * en->count);
    92.     if (!en->items)
    93.     {
    94.         FreeEnumShellItemsInstance (en);
    95.  
    96.         return E_OUTOFMEMORY;
    97.     }
    98.  
    99.     for (i=0; i<en->count; i++)
    100.     {
    101.         if (DragQueryFileW (hDrop, i, fileName, MAX_PATH) == 0)
    102.         {
    103.             FreeEnumShellItemsInstance (en);
    104.  
    105.             return E_FAIL;
    106.         }
    107.  
    108.         hr = SHCreateItemFromParsingName (fileName, NULL, &IID_IShellItem, &en->items[i]);
    109.         if (FAILED (hr))
    110.         {
    111.             FreeEnumShellItemsInstance (en);
    112.  
    113.             return hr;
    114.         }
    115.     }
    116.  
    117.     *ppenum = (IEnumShellItems*)en;
    118.  
    119.     return S_OK;  
    120. }
    121.  
    122. /* -------------------------------------------------------------------------- */
    123.  
    124. static HRESULT WINAPI IEnumShellItems_QueryInterface (IEnumShellItems* This, REFIID riid, LPVOID* ppvObject)
    125. {
    126.     CEnumShellItems* en;
    127.  
    128.     en = (CEnumShellItems*)This;
    129.  
    130.     if (!ppvObject)
    131.         return E_POINTER;
    132.  
    133.     *ppvObject = NULL;
    134.  
    135.     if (!memcmp (riid, &IID_IUnknown, sizeof(GUID)) ||
    136.         !memcmp (riid, &IID_IEnumShellItems, sizeof(GUID)))
    137.     {
    138.         This->lpVtbl->AddRef (This);
    139.         *ppvObject = This;
    140.  
    141.         return S_OK;
    142.     }
    143.  
    144.     return E_NOINTERFACE;
    145. }
    146.  
    147. /* -------------------------------------------------------------------------- */
    148.  
    149. static HRESULT WINAPI IEnumShellItems_AddRef (IEnumShellItems* This)
    150. {
    151.     CEnumShellItems* en;
    152.  
    153.     en = (CEnumShellItems*)This;
    154.  
    155.     InterlockedIncrement (&en->refCount);
    156.  
    157.     return S_OK;
    158. }
    159.  
    160. /* -------------------------------------------------------------------------- */
    161.  
    162. static HRESULT WINAPI IEnumShellItems_Release (IEnumShellItems* This)
    163. {
    164.     CEnumShellItems* en;
    165.     LONG refCount;
    166.  
    167.     en = (CEnumShellItems*)This;
    168.  
    169.     refCount = InterlockedDecrement (&en->refCount);
    170.     if (refCount == 0)
    171.         FreeEnumShellItemsInstance (en);
    172.  
    173.     return S_OK;
    174. }
    175.  
    176. /* -------------------------------------------------------------------------- */
    177.  
    178. static HRESULT WINAPI IEnumShellItems_Clone (IEnumShellItems* This, IEnumShellItems** ppenum)
    179. {
    180.     CEnumShellItems* en;
    181.     en = (CEnumShellItems*)This;
    182.  
    183.     if (!ppenum)
    184.         return E_POINTER;
    185.  
    186.     *ppenum = NULL;
    187.  
    188.     return E_NOTIMPL;
    189. }
    190.  
    191. /* -------------------------------------------------------------------------- */
    192.  
    193. static HRESULT WINAPI IEnumShellItems_Next (IEnumShellItems* This, ULONG celt, IShellItem** rgelt, ULONG* pceltFetched)
    194. {
    195.     CEnumShellItems* en;
    196.     IShellItem* item;
    197.     UINT i;
    198.  
    199.     en = (CEnumShellItems*)This;
    200.  
    201.     if (!rgelt)
    202.         return E_POINTER;
    203.  
    204.     if (!pceltFetched && celt > 1)
    205.         return E_INVALIDARG;
    206.  
    207.     if (en->pos >= en->count)
    208.         celt = 0;
    209.     else if (en->count - en->pos < celt)
    210.         celt = en->count - en->pos;
    211.  
    212.     for (i=0; i<celt; i++)
    213.     {
    214.         item = en->items[en->pos + i];
    215.         item->lpVtbl->AddRef (item);
    216.         rgelt[i] = item;
    217.     }
    218.  
    219.     en->pos += celt;
    220.  
    221.     if (pceltFetched)
    222.         *pceltFetched = celt;
    223.  
    224.     return (celt != 0 ? S_OK : S_FALSE);
    225. }
    226.  
    227. /* -------------------------------------------------------------------------- */
    228.  
    229. static HRESULT WINAPI IEnumShellItems_Reset (IEnumShellItems* This)
    230. {
    231.     CEnumShellItems* en;
    232.  
    233.     en = (CEnumShellItems*)This;
    234.  
    235.     en->pos = 0;
    236.  
    237.     return S_OK;
    238. }
    239.  
    240. /* -------------------------------------------------------------------------- */
    241.  
    242. static HRESULT WINAPI IEnumShellItems_Skip (IEnumShellItems* This, ULONG celt)
    243. {
    244.     CEnumShellItems* en;
    245.  
    246.     en = (CEnumShellItems*)This;
    247.  
    248.     if (en->pos >= en->count)
    249.         celt = 0;
    250.     else if (en->count - en->pos < celt)
    251.         celt = en->count - en->pos;
    252.  
    253.     en->pos += celt;
    254.  
    255.     return S_OK;
    256. }
    257.  
    258. /* -------------------------------------------------------------------------- */
    259.  
    260. static LRESULT WINAPI WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    261. {
    262.     IFileOperation* fileOper;
    263.     IEnumShellItems* enumItems;
    264.     HRESULT hr;
    265.  
    266.     switch (msg)
    267.     {
    268.         ...
    269.         case WM_DROPFILES:
    270.             hr = CreateFileOperationInstance (&fileOper);
    271.             if (SUCCEEDED (hr))
    272.             {
    273.                 hr = CreateEnumShellItemsInstance ((HDROP)wParam, &enumItems);
    274.                 if (SUCCEEDED (hr))
    275.                 {
    276.                     fileOper->lpVtbl->DeleteItems (fileOper, (IUnknown*)enumItems);
    277.                     fileOper->lpVtbl->PerformOperations (fileOper);
    278.  
    279.                     enumItems->lpVtbl->Release (enumItems);
    280.                 }
    281.  
    282.                 fileOper->lpVtbl->Release (fileOper);
    283.             }
    284.  
    285.             DragFinish ((HDROP)wParam);
    286.  
    287.             return 0;
    288.      
    289.         ...
    290.         default:
    291.             return DefWindowProc (hwnd, msg, wParam, lParam);
    292.     }
    293. }
    294.  
    295. /* -------------------------------------------------------------------------- */
    296.  
     
  17. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Большое спасибо rmn, за участие и за пример.
    Буду изучать.

    Век живи век учись.
    --- Сообщение объединено, 15 май 2024 ---
    мой Microsoft Visual Studio 12
    Ошибка 1 error C3861: CreateFileOperationInstance: идентификатор не найден
    Ошибка 2 error C3861: CreateEnumShellItemsInstance: идентификатор не найден

    ругается на синтаксис
    Код (Text):
    1.  
    2. static const IEnumShellItemsVtbl CEnumShellItemsVtbl =
    3. {
    4.     IEnumShellItems_QueryInterface,
    5.     IEnumShellItems_AddRef,
    6.     IEnumShellItems_Release,
    7.     IEnumShellItems_Clone,
    8.     IEnumShellItems_Next,
    9.     IEnumShellItems_Reset,
    10.     IEnumShellItems_Skip,
    11. };
    12.  
    и
    Код (Text):
    1.  
    2. typedef struct _CEnumShellItems
    3. {
    4.     const IEnumShellItemsVtbl* lpVtbl;
    5.     LONG refCount;
    6.     IShellItem** items;
    7.     UINT count;
    8.     UINT pos;
    9. }CEnumShellItems;
    10.  
     
  18. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.339
    Первую тебе самому написать надо и перенести туда код, создающий IFileOperation. Вторая должна быть перед WndProc, потому что она без прототипа.

    У AddRef и Release тип возвращаемого значения надо на ULONG поменять (и в прототипе и в реализации). И, возможно, надо заголовки дополнительные подключить. где все используемые интерфейсы объявлены.
     
  19. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Чтобы тема не повисла
    выкладываю своё решение

    Для удаления группы файлов нужен метод - DeleteItems
    у этого метода только один параметр это указатель на интерфейс - IShellItemArray

    Этот интерфейс можно получить функцией - SHCreateShellItemArrayFromIDLists
    у неё три параметра:
    1 - количество указателей в массиве
    2 - адрес указателя на массив указателей - ITEMIDLIST
    3 - адрес лексемы которая получит указатель на интерфейс - IShellItemArray

    Но чтобы сделать массив указателей - ITEMIDLIST
    нам придётся в ручную парсить список файлов

    Когда окно обрабатывает сообщение - WM_DROPFILES
    в параметре - wParam
    возвращается дескриптор внутренней структуры
    в этой структуре первым параметром прописано смещение
    на символьные пути файла или файлов в формате - UNICODE

    Этот список нам и нужно полностью прогнать до финальных четырёх нулей
    каждый символьный путь к файлу мы будем скармливать функции - SHParseDisplayName
    а она будет записывать в адрес третьего параметра указатель - ITEMIDLIST

    Этих указателей может быть много по этому нам нужна отдельная память
    куда мы последовательно будем записывать указатели (по сути адреса)

    Я нашёл оригинальный выход мы воспользуемся памятью которую выделила сама система
    это та память где она прописала символьные пути файлов
    которые мы собственно говоря и будем парсить
    а после обработки мы вернём эту память системе функцией - DragFinish

    Код (ASM):
    1.  
    2. ;---------------------------------------------------------------------
    3. lib Shell32,ole32
    4. ;---------------------------------------------------------------------
    5. global CLSID_FileOperation = g'3AD05575-8857-4850-9277-11B85BDB8E09'
    6. global IID_IFileOperation = g'947AAB5F-0A5C-4C13-B4D6-4BF7836FC9F8'
    7. global pOperation::IFileOperation
    8. global pArray::IShellItemArray
    9. global pIdl ; адрес указателя на массив указателей - ITEMIDLIST
    10. ;---------------------------------------------------------------------
    11. include interface.asm
    12. ;---------------------------------------------------------------------
    13. Window -1,-1,200,200,0,'Корзина',0,0,0,11,0,hWnd,1
    14. Message
    15. Exit
    16. ;=====================================================================
    17. proc hWnd ; процедурная функция окна
    18. ;--------------------------------------
    19. case WM_CREATE
    20. fun CoInitialize,0
    21. fun DragAcceptFiles,hWin,1
    22. ;--------------------------------------
    23. case WM_DROPFILES
    24. fun DragAcceptFiles,hWin,0
    25. fun CoCreateInstance,&CLSID_FileOperation,0,CLSCTX_ALL,
    26.                      &IID_IFileOperation,&pOperation
    27. fun pOperation.SetOperationFlags,FOF_ALLOWUNDO or FOF_NOCONFIRMATION
    28. ;------------------
    29. pushad
    30. dword edi = [&wParam]
    31. mov pIdl,edi
    32. dword esi = edi+[edi]
    33. xor ebx,ebx
    34. Loc__lop:
    35. if dw[esi]
    36. inc ebx
    37. fun SHParseDisplayName,esi,0,edi,0,0
    38. Loc__smv:
    39. add esi,2
    40. mov eax,[esi]
    41. if ax
    42. jmp Loc__smv
    43. endif
    44. add edi,4
    45. add esi,2
    46. jmp Loc__lop
    47. endif
    48. fun SHCreateShellItemArrayFromIDLists,ebx,pIdl,&pArray
    49. popad
    50. ;------------------
    51. fun pOperation.DeleteItems,pArray
    52. fun pOperation.PerformOperations
    53. fun pOperation.Release
    54. fun pArray.Release
    55. fun DragFinish,wParam
    56. fun DragAcceptFiles,hWin,1
    57. ;--------------------------------------
    58. case WM_DESTROY
    59. fun CoUninitialize
    60. fun PostQuitMessage,0
    61. ;--------------------------------------
    62. end
    63. ;=====================================================================
    64. end
    65.  
    В проекте подключен файл - interface.asm
    это файл где описаны используемые интерфейсы

    Код (ASM):
    1.  
    2. ;------------------------------------------------------
    3. interface IFileOperation
    4.    QueryInterface,DWORD,DWORD
    5.    AddRef
    6.    Release
    7.    Advise,DWORD,DWORD
    8.    Unadvise,DWORD
    9.    SetOperationFlags,DWORD
    10.    SetProgressMessage,DWORD
    11.    SetProgressDialog,DWORD
    12.    SetProperties,DWORD
    13.    SetOwnerWindow,DWORD
    14.    ApplyPropertiesToItem,DWORD
    15.    ApplyPropertiesToItems,DWORD
    16.    RenameItem,DWORD,DWORD,DWORD
    17.    RenameItems,DWORD,DWORD
    18.    MoveItem,DWORD,DWORD,DWORD,DWORD
    19.    MoveItems,DWORD,DWORD
    20.    CopyItem,DWORD,DWORD,DWORD,DWORD
    21.    CopyItems,DWORD,DWORD
    22.    DeleteItem,DWORD,DWORD
    23.    DeleteItems,DWORD
    24.    NewItem,DWORD,DWORD,DWORD,DWORD,DWORD
    25.    PerformOperations
    26.    GetAnyOperationsAborted,DWORD
    27. end
    28. ;------------------------------------------------------
    29. interface IShellItemArray
    30.    QueryInterface,DWORD,DWORD
    31.    AddRef
    32.    Release
    33.    BindToHandler,DWORD,DWORD,DWORD,DWORD
    34.    GetPropertyStore,DWORD,DWORD,DWORD
    35.    GetPropertyDescriptionList,DWORD,DWORD,DWORD
    36.    GetAttributes,DWORD,DWORD,DWORD
    37.    GetCount,DWORD
    38.    GetItemAt,DWORD,DWORD
    39.    EnumItems,DWORD
    40. end
    41. ;------------------------------------------------------
    42.  
    В проекте эти интерфейсы привязаны к определённым лексемам

    Код (ASM):
    1.  
    2. global pOperation::IFileOperation
    3. global pArray::IShellItemArray
    4.  
    Но в принципи можно не подключать этот файл интерфейсов
    а просто объявить лексемы

    Код (ASM):
    1.  
    2. global pOperation
    3. global pArray
    4.  
    А в коде вместо методов

    Код (ASM):
    1.  
    2. fun pOperation.DeleteItems,pArray
    3.  
    Прописывать их числовые смещения

    Код (ASM):
    1.  
    2. fun pOperation.68,pArray
    3.  
    Что в принципи одно и тоже
    Только в этом случае за количество прописанных аргументов
    вся ответственность на программисте

    Это удаление реализованно на интерфейсах
    но по скорости исполнения оно работает точно так же
    как и способ с гораздо меньшим байт-кодом без интерфейсов
    описанный в первом посте

    Но чёрт его знает может быть интерфейсы более надёжны или безопасны
    а может быть и нет

    Век живи век учись
     
  20. CaptainObvious

    CaptainObvious Member

    Публикаций:
    0
    Регистрация:
    18 янв 2024
    Сообщения:
    53
    …И век последний, ужасней всех,
    Увидим и вы, и я:
    Всё файлы скроет грусный смех,
    Тоска небытия.
     
    q2e74 нравится это.