Blog. Just Blog

Обработка перетаскивания ссылок в окно приложения

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Обработка перетаскивания ссылок в окно приложения
Обработка перетаскивания ссылок в окно приложения

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

Делается это средствами интерфейсов OLE (Object Linking and Embedding). Но сперва нам понадобится несколько структур, которых, как вы уже догадались, в FASM изначально нет.
  1. ; Интерфейс IDropTarget
  2. struct IDropTargetStruct
  3.         QueryInterface  dd ?
  4.         AddRef          dd ?
  5.         Release         dd ?
  6.         DragEnter       dd ?
  7.         DragOver        dd ?
  8.         DragLeave       dd ?
  9.         Drop            dd ?
  10.         refcount        dd ?
  11. ends
  12.  
  13. ; Интерфейс IDropTarget
  14. struct IDataObjectStruct
  15.         QueryInterface  dd ?
  16.         AddRef          dd ?
  17.         Release         dd ?
  18.         GetData         dd ?
  19.         GetDataHere     dd ?
  20.         QueryGetData    dd ?
  21.         GetCanonicalFormatEtc dd ?
  22.         SetData         dd ?
  23.         EnumFormatEtc   dd ?
  24.         DAdvise         dd ?
  25.         DUnadvise       dd ?
  26.         EnumDAdvise     dd ?
  27.         refcount        dd ?
  28. ends
  29.  
  30. ; Структуры, используемые для получения переданных строк
  31. struct STGMEDIUM
  32.         tymed           dd ?
  33.         hGlobal         dd ?
  34.         pUnkForRelease  dd ?
  35. ends
  36.  
  37. struct FORMATETC
  38.         cfFormat        dd ?
  39.         lptd            dd ?
  40.         dwAspect        dd ?
  41.         lindex          dd ?
  42.         tymed           dd ?
  43. ends
При создании окна, которое должно обрабатывать перетаскивание ссылок, первым делом надо инициализировать OLE и заполнить ссылки на методы интерфейса IDropTarget, сами функции вы увидите чуть ниже. Когда все параметры будут заполнены, функцией RegisterDragDrop назначается захват перетаскивания данных нужному окну.
  1. wminitdialog:
  2.         ; Инициализация OLE
  3.         invoke  OleInitialize,NULL
  4.  
  5.         ; Настроить структуру IDropTarget для окна
  6.         mov     [IDropTarget.QueryInterface],IDropTarget_QueryInterface
  7.         mov     [IDropTarget.AddRef],IDropTarget_AddRef
  8.         mov     [IDropTarget.Release],IDropTarget_Release
  9.         mov     [IDropTarget.DragEnter],IDropTarget_DragEnter
  10.         mov     [IDropTarget.DragOver],IDropTarget_DragOver
  11.         mov     [IDropTarget.DragLeave],IDropTarget_DragLeave
  12.         mov     [IDropTarget.Drop],IDropTarget_Drop
  13.  
  14.         ; Разрешить окну принимать объекты
  15.         mov     [pDropTarget],IDropTarget
  16.         invoke  RegisterDragDrop,[hwnddlg],pDropTarget
При закрытии окна или при завершении работы приложения надо освободить захват и разорвать соединение с OLE.
  1. wmclose:
  2.         ; Освободить захват перетаскивания
  3.         invoke  RevokeDragDrop,[hwnddlg]
  4.         invoke  OleUninitialize
Теперь основное - реализация методов интерфейса. Я оставил только минимально необходимый код для обработки. Метод DragEnter активируется, когда курсор с захваченными данными из окна другого приложения переходит на окно нашего приложения. На этом этапе уже можно проверить, что за данные нам передают, а на основании этого принять решение, будем ли мы их обрабатывать или не будем. Метод Drop, соответственно, отвечает за обработку броска данных на окно. Именно в этом методе наше приложение должно выполнять все запланированные действия с полученной строкой.
  1. ; Строка названия формата, который будет обрабатывать окно приложения
  2. CFSTR_INETURL du 'UniformResourceLocatorW',0
  1. proc IDropTarget_QueryInterface pthis:DWORD, iid:DWORD, ppvObject:DWORD
  2.         ; S_OK
  3.         xor     eax,eax
  4.         ret
  5. endp
  6.  
  7. proc IDropTarget_AddRef pthis:DWORD
  8.         lea     eax,[pthis]
  9.         inc     [eax+IDropTargetStruct.refcount]
  10.         mov     eax,[eax+IDropTargetStruct.refcount]
  11.         ret
  12. endp
  13.  
  14. proc IDropTarget_Release pthis:DWORD
  15.         lea     eax,[pthis]
  16.         dec     [eax+IDropTargetStruct.refcount]
  17.         mov     eax,[eax+IDropTargetStruct.refcount]
  18.         ret
  19. endp
  20.  
  21. ;---------------------------------------------------------
  22. ; Метод DragEnter - курсор заходит на форму
  23. ;---------------------------------------------------------
  24. proc IDropTarget_DragEnter pthis:DWORD,lpDataObject:DWORD,grfKeyState:DWORD,\
  25.                            pt.x:DWORD,pt.y:DWORD,lpdwEffect:DWORD
  26.         locals
  27.            medium STGMEDIUM
  28.            fmte   FORMATETC
  29.         endl
  30.  
  31.         push    ebx esi
  32.  
  33.         ; DROPEFFECT_MOVE
  34.         lea     eax,[lpdwEffect]
  35.         mov     dword [eax],2
  36.  
  37.         ; Проверить перетаскиваемую информацию на соответствие
  38.         ; формату ссылки
  39.         lea     eax,[medium]
  40.         push    eax
  41.  
  42.         lea     ebx,[fmte]
  43.         invoke  RegisterClipboardFormat,CFSTR_INETURL
  44.         mov     [ebx+FORMATETC.cfFormat],eax
  45.         mov     [ebx+FORMATETC.lptd],NULL
  46.         mov     [ebx+FORMATETC.dwAspect],1
  47.         mov     [ebx+FORMATETC.lindex],-1
  48.         mov     [ebx+FORMATETC.tymed],1
  49.         push    ebx
  50.  
  51.         mov     esi,[lpDataObject]
  52.         mov     eax,[esi]
  53.         stdcall [eax+IDataObjectStruct.GetData],esi
  54.         or      eax,eax
  55.         jz      @f
  56.  
  57.         ; Перетаскиваемые данные не соответствуют формату
  58.         ; E_INVALIDARG
  59.         mov     eax,80070057h
  60. @@:
  61.         pop     esi ebx
  62.         ret
  63. endp
  64.  
  65. ;---------------------------------------------------------
  66. ; Метод DragOver - курсор перемещается над формой
  67. ;---------------------------------------------------------
  68. proc IDropTarget_DragOver pthis:DWORD,grfKeyState:DWORD,\
  69.                           pt.x:DWORD,pt.y:DWORD,lpdwEffect:DWORD
  70.         ; DROPEFFECT_MOVE
  71.         lea     eax,[lpdwEffect]
  72.         mov     dword [eax],2
  73.         ; S_OK
  74.         xor     eax,eax
  75.         ret
  76. endp
  77.  
  78. ;---------------------------------------------------------
  79. ; Метод DragLeave - курсор покинул форму
  80. ;---------------------------------------------------------
  81. proc IDropTarget_DragLeave pthis:DWORD
  82.         ; S_OK
  83.         xor     eax,eax
  84.         ret
  85. endp
  86.  
  87. ;---------------------------------------------------------
  88. ; Метод Drop - данные сброшены на форму
  89. ;---------------------------------------------------------
  90. proc IDropTarget_Drop pthis:DWORD,lpDataObject:DWORD,grfKeyState:DWORD,\
  91.                       pt.x:DWORD,pt.y:DWORD,lpdwEffect:DWORD
  92.         locals
  93.            medium STGMEDIUM
  94.            fmte   FORMATETC
  95.         endl
  96.  
  97.         pusha
  98.  
  99.         ; DROPEFFECT_MOVE
  100.         lea     eax,[lpdwEffect]
  101.         mov     dword [eax],2
  102.  
  103.         lea     eax,[medium]
  104.         push    eax
  105.  
  106.         lea     ebx,[fmte]
  107.         invoke  RegisterClipboardFormat,CFSTR_INETURL
  108.         mov     [ebx+FORMATETC.cfFormat],eax
  109.         mov     [ebx+FORMATETC.lptd],NULL
  110.         mov     [ebx+FORMATETC.dwAspect],1
  111.         mov     [ebx+FORMATETC.lindex],-1
  112.         mov     [ebx+FORMATETC.tymed],1
  113.         push    ebx
  114.  
  115.         mov     esi,[lpDataObject]
  116.         mov     eax,[esi]
  117.         stdcall [eax+IDataObjectStruct.GetData],esi
  118.  
  119.         lea     eax,[medium]
  120.         mov     eax,[eax+STGMEDIUM.hGlobal]
  121.         mov     eax,[eax]
  122.         ; EAX - указатель на переданную строку
  123.         ;---------------------------------------------
  124.         ; действия с переданной строкой
  125.         ;---------------------------------------------
  126.  
  127.         popa
  128.  
  129.         ; S_OK
  130.         xor     eax,eax
  131.         ret
  132. endp
Если окно должно принимать через drag'n'drop не только ссылки, а вообще любую текстовую информацию, то надо будет немного модифицировать методы DragEnter и Drop. В этом случае больше не надо проверять формат данных при заходе курсора и при броске данных на окно. Остальные методы остаются без изменений.
  1. ;---------------------------------------------------------
  2. ; Метод DragEnter - курсор заходит на форму
  3. ;---------------------------------------------------------
  4. proc IDropTarget_DragEnter pthis:DWORD,lpDataObject:DWORD,grfKeyState:DWORD,\
  5.                            pt.x:DWORD,pt.y:DWORD,lpdwEffect:DWORD
  6.         ; DROPEFFECT_MOVE
  7.         lea     eax,[lpdwEffect]
  8.         mov     dword [eax],2
  9.         ; S_OK
  10.         xor     eax,eax
  11.         ret
  12. endp
  13.  
  14. ;---------------------------------------------------------
  15. ; Метод Drop - данные сброшены на форму
  16. ;---------------------------------------------------------
  17. proc IDropTarget_Drop pthis:DWORD,lpDataObject:DWORD,grfKeyState:DWORD,\
  18.                       pt.x:DWORD,pt.y:DWORD,lpdwEffect:DWORD
  19.         locals
  20.            medium STGMEDIUM
  21.            fmte   FORMATETC
  22.         endl
  23.  
  24.         pusha
  25.  
  26.         ; DROPEFFECT_MOVE
  27.         lea     eax,[lpdwEffect]
  28.         mov     dword [eax],2
  29.  
  30.         lea     eax,[medium]
  31.         push    eax
  32.  
  33.         lea     eax,[fmte]
  34.         mov     [eax+FORMATETC.cfFormat],0Dh
  35.         mov     [eax+FORMATETC.lptd],NULL
  36.         mov     [eax+FORMATETC.dwAspect],1
  37.         mov     [eax+FORMATETC.lindex],-1
  38.         mov     [eax+FORMATETC.tymed],1
  39.         push    eax
  40.  
  41.         mov     esi,[lpDataObject]
  42.         mov     eax,[esi]
  43.         stdcall [eax+IDataObjectStruct.GetData],esi
  44.  
  45.         lea     eax,[medium]
  46.         mov     eax,[eax+STGMEDIUM.hGlobal]
  47.         mov     eax,[eax]
  48.         ; EAX - указатель на переданную строку
  49.         ;---------------------------------------------
  50.         ; действия с переданной строкой
  51.         ;---------------------------------------------
  52.  
  53.         popa
  54.  
  55.         ; S_OK
  56.         xor     eax,eax
  57.         ret
  58. endp
Этот способ передачи данных окну приложения не поддерживает передачу файлов, ее надо будет реализовывать отдельно, как указано в начале статьи. Если к этому добавить еще и обработку параметров командной строки, то приложение станет по-настоящему "всеядным".

В приложении примеры программ с исходными текстами, одна из которых позволяет перетаскивать в свое окно только ссылки, а вторая принимает любые строковые данные из приложений.

Примеры программ с исходными текстами (FASM)Примеры программ с исходными текстами (FASM)

Drag.n.Drop.URL.Data.Demo.zip (6,349 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 999 | Комментариев: 0

Метки: Assembler, окна, COM
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2021
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0069 сек.) / Память: 4.75 Mb
Наверх