Как самому управлять рисованием меню?

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

Как самому управлять рисованием меню?

Сообщение arthur2 » 25.04.2008 (Пт) 19:48

В свойе программе всё ясно - при создании пункта указываю MF_OWNERDRAW, затем ставлю субклассинг на то окно, которому будут отправляться сообщения и делаю с меню всё, что угодно.

Но в данном случае меню - это подпункты в конеткстом меню проводника:
http://bbs.vbstreets.ru/viewtopic.php?t=36449

Есть у кого-нибудь идеи, как узнать, кому оно посылает свои сообщения?

Есть стандартный способ - использовать вместо IContextMenu то ли IContextMenu2, то ли IContextMenu3. Но ни одного примера на бейсике я не нашёл. Да и сами эти интерфейсы где взять - не понятно.
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 26.04.2008 (Сб) 9:29

Есть у кого-нибудь идеи, как узнать, кому оно посылает свои сообщения?
Эксплореру :roll:
Есть стандартный способ - использовать вместо IContextMenu то ли IContextMenu2, то ли IContextMenu3. Но ни одного примера на бейсике я не нашёл. Да и сами эти интерфейсы где взять - не понятно.
Интерфейсы здесь (olelib.tlb) и здесь (ISHF_Ex.Tlb). Возможно на акселераторе найдутся и примеры.
Лучший способ понять что-то самому — объяснить это другому.

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

Сообщение arthur2 » 26.04.2008 (Сб) 22:01

Antonariy
Спасибо большое, уже что-то! Правда, примеров там я так и не нашёл. Все примеры на IContextMenu (их разных у меня уже три штуки)

А тлб-шки вроде те. Правда, без примеров всё равно не понятно, как ими пользоваться :(

Э-эх, попробую поковыряться.

Эксплореру :roll:

Ага, мне почему-то тоже так кажется. Хотя, фиг его знает, может и блокноту :lol:
А вообще - хоть калькулятору - хендл бы как получить
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 27.04.2008 (Вс) 8:55

Хендл чего и зачем? Если для сабклассинга - невозможно сабклассить окна чужих процессов.
Лучший способ понять что-то самому — объяснить это другому.

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

Сообщение Хакер » 27.04.2008 (Вс) 10:46

Сабклассить то можно, но код WindowProc-а должен попасть в АП чужого процесса. И всё, что этим WindowProc-ом юзается, тоже.
—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 » 28.04.2008 (Пн) 14:00

Мне казалось, что раз проводник это меню вызывает, то весь код в его процесс и попадет. По крайней мере, IContextMenu2 и IContextMenu3 какой-то же хендл должны возвращать. Вопрос в том, как их прицепить.

В olelib.tlb оказались правильные интерфейсы - IContextMenu оттуда работает. Но логики того, как цепляетя IContextMenu, я не понимаю, а механическая замена IContextMenu на IContextMenu2 ничего не дала -код просто перестал действовать.

В ISHF_Ex.Tlb интерфейсы не те - они вообще отказываются имплементиться. И внутри у них лишние процедуры. Настоящий IContextMenu требует реализовать три процедуры, а тот, что в этой тлб, содержит их аж шесть штук.
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 28.04.2008 (Пн) 14:14

По крайней мере, IContextMenu2 и IContextMenu3 какой-то же хендл должны возвращать.
Интерфейсы ничего не возвращают, они описывают правила, по которым реализуются классы.
Но логики того, как цепляетя IContextMenu, я не понимаю
IContextMenu - интерфейс, четко определенный разработчиками винды для присобачивания своих пунктов в контекстное меню проводника. Проводник перед отображением меню просматривает реестр на предмет классов, которые имеют желание прицепить свои пункты. Найдя все эти классы, он у каждого запрашивает интерфейс IContextMenu. Если интерфейс получен, добавляется пункт, если нет, игнорируется.

И вообще, начни с изучения основ технологии COM, осознай смысл интерфейсов, после этого тебе будет очевидно, почему механическая замена не работает.
Лучший способ понять что-то самому — объяснить это другому.

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

Сообщение arthur2 » 29.04.2008 (Вт) 13:31

Antonariy
Я может чего не так сформулировал, но то, что ты написал, я как раз правильно понимаю. В интерфейсе все процедуры пустые. После того, как я его имплементю и реализую, мой класс становится опозноваемым снаружи - он теперь соответсвует нужным правилам, и по этим правилам к нему теперь можно обращаться.

Интерфейсы ничего не возвращают

В IContextMenu2 реализуется процедура:
Private Sub IContextMenu2_HandleMenuMsg(ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
End Sub
Через которую проводник мне возвращает нужные значения. Может, слово "возвращает" здесь не вполне подходит, но я это имел ввиду.

Кстати, пока не увидил этот присловутый IContextMenu2, мне казалось, что через него мне дадут хендл для субклассинга. А оказалось, что субклассинг происходит где-то там за кулисами, а мне возвращают уже готовые сообщения. Это, кстати, означает, что с помощью IContextMenu2 я смогу только подровнять пункты, но чтобы самому их перерисовывать, нужен IContextMenu3. А его я так и не нашёл.

Найдя все эти классы, он у каждого запрашивает интерфейс IContextMenu. Если интерфейс получен, добавляется пункт, если нет, игнорируется.

Э-эх, если бы было всё так просто... Тогда Implements IContextMenu2 было бы достаточно. Но увы:
Бейсик то ли не может самостояетльно реализовать QueryContextMenu, то ли делает это как-то не так, то ли ещё чего (не силён в инглише, в связи с чем комментарии не очень понял). Поэтому при инициализации класса делается такая фишка:

Код: Выделить всё
Dim pImp As Long
Dim oImp As IContextMenu
Set oImp = Me
Call CopyMemory(pImp, oImp, 4)
pOldFunction = ReplaceVtableEntry(pImp, 4, AddressOf sc_QueryContextMenu)


И после этого всё, что должно было бы прийти в IContextMenu_QueryContextMenu, перенаправляется в sc_QueryContextMenu.

Логика этого способа мне не вполне понятна. Проделать то же самое для IContextMenu2 мне не удалось (не заработало).

И вообще, начни с изучения основ технологии COM
Внятно по-русски для бейсика ничего нет. А других языков (кроме русского и бейсика) я не знаю :lol:
Артур
 
   

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

Сообщение Хакер » 29.04.2008 (Вт) 13:38

Таки ты не понял суть интерфейсов классов и реализации. Бейсик (и никакой другой язык) вообще не должен самостоятельно ничего реализовывать.

Прочитать про COM на русском можно много-где. И ничего языко-специфичного там нет. Ну, по крайней мере, очень мало.
—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 » 29.04.2008 (Вт) 14:21

Хакер
Ну чего ты опять без конкретики? Много где - это где? Теория обычно иллюстрируется примерами, а если пример на си - то мне это как на санскрите.

Суть интерфейсов я понял. По крайней мере, на столько, чтобы то, где я ими польюзуюсь, работало. (И кстати, спасибо именно тебе!) Если я формулирую не на твоём профессиональном сленге, а так, как понимаю - это не значит, что я вообще не понимаю.

Бейсик (и никакой другой язык) вообще не должен самостоятельно ничего реализовывать.
Поясни? Интерфейсы и нужны, чтобы их реализовывать. Вероятно, мы опять про что-то разное (термин "реализация" значит что-то сугубо сокральное? но я использовал не термин, а просто слово на русском)

А вообще - мне бы хотелось просто нарисовать иконки у меню так, чтобы они не инвертировались. А ещё лучше - слямзить на эту тему готовый кусок кода. И после этого забыть об IContextMenu навсегда.
Артур
 
   

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

Сообщение arthur2 » 30.04.2008 (Ср) 0:18

Бейсик то ли не может самостояетльно реализовать QueryContextMenu, то ли делает это как-то не так, то ли ещё чего

Так, с этим стало понятно. QueryContextMenu - это процедура, а нужно, чтобы была функция. ReplaceVtableEntry как раз и превращает процедуру в функцию. Этот приём есть во всех трёх примерах, найденых мной по теме. Но оказалось, не очень-то и нужно - код работает и без этого. В общем, Antonariy, по отношению к IContextMenu ты прав - Implements оказалось достаточно. Но вот IContextMenu2 не сработал ни разу!

Вот прикладываю полную минималку кода, добавляющего контекстное меню к файлам. Специально выброшено всё, что связано с обработкой действий над пунктами - есть только добавление пункта и всё.

В классе объявлены IContextMenu и IContextMenu2. IContextMenu работает нормально. Но из IContextMenu2 ни одна процедура не вызывается.
Вложения
cntMnMin.zip
Минимальный код, добавляющий пункт в меню проводника
(194.64 Кб) Скачиваний: 77
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 30.04.2008 (Ср) 9:07

QueryContextMenu - это процедура, а нужно, чтобы была функция. ReplaceVtableEntry как раз и превращает процедуру в функцию.
Как я недавно узнал, вернуть значения из процедуры можно через Err.Raise, пользуйся ею. Вполне возможно, что проводник не запрашивает IContextMenu2 потому что не получает какой-то результат из IContextMenu.

Вот тебе Idiot's gude для IContextMenu2 - увы, мало того, что по-английски, так еще и на с++. translate.ru поможет с первым, со вторым придется шевелить мозгами, понять смысл кода ты по идее способен.

Изучай английский, хотя бы до уровня "перевожу со словарем", без него в прогаммировании делать нечего. Разве что податься в 1С.
Лучший способ понять что-то самому — объяснить это другому.

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

Сообщение arthur2 » 30.04.2008 (Ср) 11:56

Antonariy
Я уже долго бьюсь с IContextMenu2, но, насколько я знаю (как раз и руководства для идиота), он мне довольно бесполезен, а нужен IContextMenu3. Но третьего я даже найти не могу.

Руководство идиота переведено на русский:
http://www.rsdn.ru/summary/390.xml
И я его уже облазил вдоль и поперёк в меру понимания.

Как я недавно узнал, вернуть значения из процедуры можно через Err.Raise
Спасибо! А как?
Код: Выделить всё
On Error Resume Next
Err.Raise rez
В этом случае процедура вернёт проводнику rez? Или я не правильно понял? А On Error тут наверное, лишний?

Этот приём я уже встречал в примерах расширений, которые нашёл (сути, правда, не понял, пока ты не сказал).
Код: Выделить всё
Private Sub IDropTarget_DragLeave()
    Err.Raise E_NOTIMPL
End Sub

Но вот что интересно - у того же автора в обработке контекстного меню всё же используется приём с перенаправлением процедуры на функцию. Тем более загадочно, что у меня всё работает вообще без возвращения значения.

Изучай английский, хотя бы до уровня "перевожу со словарем"
Ну, на уровне промта я, пожалуй, со словарём перевожу :lol: Только такое перевожение сильно выматывает (где-то так же, как и попытка читать машинный перевод, так что я обычно всё-же сам).


[/code]
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 30.04.2008 (Ср) 12:52

В этом случае процедура вернёт проводнику rez? Или я не правильно понял? А On Error тут наверное, лишний?
Да, правильно, х.з., лучше убрать.
Но вот что интересно - у того же автора в обработке контекстного меню всё же используется приём с перенаправлением процедуры на функцию. Тем более загадочно, что у меня всё работает вообще без возвращения значения.
Абсолютно с теми же самыми приёмами и загадками я ознакомился при решении этой проблемы. Автор один и тот же.
Ну, на уровне промта я, пожалуй, со словарём перевожу Только такое перевожение сильно выматывает (где-то так же, как и попытка читать машинный перевод, так что я обычно всё-же сам).
Я хотел сказать "без". То, что выматывает, не беда. Помню, 10 лет назад "Легенды Кирандии" и прочие квесты проходил со словарем. :) Где-то через полгода в словаре отпала необходимость, наблатыкался. :) До сих пор предпочитаю игры на английском.
Лучший способ понять что-то самому — объяснить это другому.

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

Сообщение arthur2 » 30.04.2008 (Ср) 18:29

Автор один и тот же

Дело в том, что у меня есть три действующих примера на IContextMenu. И это - уже почти смею утверждать - все примеры, которые вообще есть в сети на бейсике.

Так вот, приём с подменой на функцию используется во всех трёх. :roll:

Код: Выделить всё
' Don't even ask about this procedure... I've basically ripped it out of the
' original source code; I certainly couldn't write it myself, but I do understand it.
' Basically, it rips out the reference to the class' function that needs to
' be replaced, and replaces it with the address of another function.
' It actually alters memory inside the VB workings of the VTable, and I really
' suggest that you stay away from it as far as possible...


Э-эх... Очевидно, что один не раскопаю. А тема, кажется, особым вниманием у публики не пользуется Изображение
Артур
 
   


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

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

Сейчас этот форум просматривают: Yandex-бот и гости: 31

    TopList