Почему не вызываете ни одна процедура из интерфейса?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Почему не вызываете ни одна процедура из интерфейса?

Сообщение arthur2 » 02.05.2008 (Пт) 17:29

Пишу расширение проводника - контекстное меню файлов. В классе объявлены интерфейсы IContextMenu и IContextMenu2 (к проекту подключена olelib.tlb). Первый вызывается нормально А второй не вызывается ни разу. Почему?

Код: Выделить всё
Option Explicit

Implements IContextMenu
Implements IContextMenu2
Implements IShellExtInit

'______________________________________________

Private Sub IContextMenu_GetCommandString(ByVal idCmd As Long, ByVal uType As olelib.GetCommandStringFlags _
                                        , pwReserved As Long, ByVal pszName As Long, ByVal cchMax As Long)
End Sub
'______________________________________________

Private Sub IContextMenu_InvokeCommand(lpici As olelib.CMINVOKECOMMANDINFO)
End Sub
'______________________________________________

Private Sub IContextMenu_QueryContextMenu(ByVal hMenu As Long, ByVal indexMenu As Long, ByVal idCmdFirst As Long _
                                        , ByVal idCmdLast As Long, ByVal uFlags As olelib.QueryContextMenuFlags)
'Это нормально срабатывает:
    InsertMenu hMenu, indexMenu, MF_BYPOSITION Or MF_OWNERDRAW, 1, ByVal "ЛЯ-ЛЯ-ЛЯ"
End Sub
'______________________________________________

Private Sub IContextMenu2_HandleMenuMsg(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
'А это - не вызывается ни разу
   debugLog "IContextMenu2_HandleMenuMsg"
End Sub
'______________________________________________

Private Sub IContextMenu2_GetCommandString(ByVal idCmd As Long, ByVal uType As olelib.GetCommandStringFlags _
                                          , pwReserved As Long, ByVal pszName As Long, ByVal cchMax As Long)
End Sub
'______________________________________________

Private Sub IContextMenu2_InvokeCommand(lpici As olelib.CMINVOKECOMMANDINFO)
End Sub
'______________________________________________

Private Sub IContextMenu2_QueryContextMenu(ByVal hMenu As Long, ByVal indexMenu As Long, ByVal idCmdFirst As Long _
                                           , ByVal idCmdLast As Long, ByVal uFlags As olelib.QueryContextMenuFlags)
   debugLog "IContextMenu2_QueryContextMenu"
End Sub
'______________________________________________

Private Sub IShellExtInit_Initialize(ByVal pidlFolder As Long, ByVal lpIDataObject As olelib.IDataObject, ByVal hkeyProgID As Long)
'Подозреваю, что что-то нужно добавить сюда. Но что? Или не сюда?
'Err.Raise S_OK
End Sub
'______________________________________________

Public Sub debugLog(ByVal sMsg As String)
    Dim hFile As Integer
    hFile = FreeFile
    Open App.Path & "\debug.log" For Append As #hFile
    Write #hFile, sMsg
    Close #hFile
End Sub


То же самое файлом: http://bbs.vbstreets.ru/download.php?id=6663
[Хакер] :: Исправлено. При публикации ссылок на ресурсы форума, настоятельно рекомендуется вырезать из них параметр &sid=xxxxxxxxxxxxxx.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 19:59

В классе объявлены интерфейсы IContextMenu и IContextMenu2

В классе не объявлены интерфейсы IContextMenu и IContextMenu2. Они объявлены в olelib.tlb, а в классе реализованы.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 02.05.2008 (Пт) 20:39

Хакер
Хорошо, не объявлены, а реализованы. Ну а почему IContextMenu2 недореализовался?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 20:40

С чего ты взял, что он недореализовался?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 02.05.2008 (Пт) 21:35

"недореализовался" - не более, чем ирония. Считай, что я написал его в кавычках.

Мне кажется, что я уже всех задолбал этим IContextMenu2. Помог бы, чтоли? Что нужно дописать, чтобы сработало-таки IContextMenu2_HandleMenuMsg?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 21:39

arthur2
Ничего. Если его код в нём ни разу не выполнился, значит его не вызывают, а если его не вызывают, то дело не в нём, и значит, писать в нём ничего не нужно.

Возможно, что класс реализует какой-то не тот интерфейс (например в TLB указали левый IID, да, в TLB бывают ошибки...).

Возможно, что с интерфейсом всё ОК, но работа метода обламывается где-то на прологе. Поэтому советую поставить CC в начало метода и посмотреть, что будет.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 02.05.2008 (Пт) 21:55

Хакер
То есть, в принципе, если бы IContextMenu2 был правильным, то в таком варианте должно работать?

Что такое СС?

А вообще - для своего же меню проводник вызывает IContextMenu2 - на сколько я знаю, подменю Отправить и Создать через него рисуются.

Если я правильно понимаю, надобность в HandleMenuMsg возникает, только если меню рисуется самостоятельно. Может я создаю пункт не со всеми нужными флагами? (Хотя в обычной программе MF_OWNERDRAW, вроде, достаточно...)
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 21:58

СС это 16-ричное представление числа 204, которое в свою очередь является опкодом инструкции int3.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 02.05.2008 (Пт) 22:04

Хакер
Ты же знаешь, что я не специалист. Куда вписать-то? И на что потом смотреть?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 22:08

arthur2
Найти первый байт в EXE файле, где начинается интересующий метод и вписать туда число 204 (размером байт). После чего запустить библу. Если упадёт (хотя я против этого термина. Программы не падают - они лишь выбрасывают исключения, которые никто не обрабатывает. Так вот, если выбросит отладочное исключение...) - то значит метод всё-таки вызывается, и проблема уже в VB.

Если же всё будет работать так же, несмотря на то, что был вставлен int3, значит можно смело утверждать, что эксплорер не действительно по каким-то причинам не вызывает твой метод.

Ну и, соответственно, в зависимости от результата, копать дальше.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 02.05.2008 (Пт) 22:12

Понятно. А как найти этот байт? (а то вдруг библа выбросит исключение не потому, что метод вызывается, а потому, что я байт не там поменял?)
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 22:18

Вставь внутри метода вызов kernel32!DebugBreak. Скомпилируй. Вызови метод интерфейса вручную (например, из специальной тест-программы), словишь вышеописанное исключение. В диалоге, который предлагает "Отправить отчёт" выбери "Отладка". В отладчике увидишь код функции DebugBreak:
Код: Выделить всё
int3
retn 0


Дошагай до retn 0 и возвратись из функции. Окажешься в окрестности метода. Тогда иди по коду вверх пока не увидишь nop-паддинг, идущий непосредственно перед первым байтом кода метода.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 02.05.2008 (Пт) 22:52

Вызвать метод я могу, скажем, так:

Dim icm2 as IContextMenu2
set icm2=me
icm2.HandleMenuMsg 0,0,0

(После этого IContextMenu2_HandleMenuMsg вызывается и лог пишется)

Куда ставить DebugBreak? в IContextMenu2_HandleMenuMsg ? Или во все четыре метода?

В общих чертах я, вроде как, представил (если правильно представил). Не понятно только - если метод не вызывается, он всё равно немного вызывается, чтоли?

Попробую. Терра инкогнита... Ну, я пошёл. Надеюсь, винда не умрёт.
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.05.2008 (Пт) 22:58

Куда ставить DebugBreak?

Начало каких методов ты хочешь найти и в начало каких методов ты хочешь поставить CC - туда и ставь. (А поставить CC ты хочешь в начало тех методов, которые, как тебе кажется, у тебя не вызываются)

В общих чертах я, вроде как, представил (если правильно представил). Не понятно только - если метод не вызывается, он всё равно немного вызывается, чтоли?

Нет.

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

Потому что если ты думаешь, что метод, содержащий MsgBox "Hello!", после компиляции будет содержать только код вызова MsgBox-а, то ты ошибаешься. Он будет содержать ещё и так называемый пролог, который, например, кроме всего, устанавливает SEH-хэндлер. Вот возможно что-то во-время выполнения пролога происходит не так, и до твоего кода дело не доходит.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 03.05.2008 (Сб) 0:11

Ну вот - после того, как проводник выдаёт предложение подебагиться, точно с таким же предложением умирает и сам доктор Ватсон :cry:

Э-эх, руки мои крюки :lol:
Артур
 
   

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 03.05.2008 (Сб) 0:42

Чтобы вызывать библиотеку не из проводника, а из другой программы, сделал так:

В классе создал процедуру для вызова метода из интерфейса:
Код: Выделить всё
Public Sub debugBr()
Dim icm2 As IContextMenu2
Set icm2 = Me
icm2.HandleMenuMsg 0, 0, 0
End Sub
'____________________________
Private Sub IContextMenu2_HandleMenuMsg(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
   DebugBreak
'   debugLog "IContextMenu2_HandleMenuMsg"
End Sub

В отладочной программе сделал вызов этого метода:

Код: Выделить всё
Dim b As Object
Set b = CreateObject("cntMn.clsContextMenu")
b.debugBr


Вместо предпологаемого предложения подебагиться программа выдаёт:
Run-time error '-2147417848 (80010108)':
Method '~' of object '~' failed

Если запустить библу из бейсика, то всё идёт как и предпологалось, до самого DebugBreak (на нём ставлю точку останова и затем пропускаю, иначе умирает уже бейсик).

Что я опять делаю не так?
Артур
 
   


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot, Google-бот и гости: 18

    TopList