:: Visual Foxpro, Foxpro for DOS
Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
Для целей документирования приложения пытаюсь получить структуру меню главного окна. Но для пунктов POPUP меню получаю пустую строку:
*--- API для работы с меню
Declare Integer GetMenu In WIN32API ;
integer HWnd

Declare Integer GetMenuItemInfo In WIN32API ;
integer hMenu,;
integer uItem,;
integer fByPosition,;
string @ MENUITEMINFO

Declare Integer GetProcessHeap In WIN32API

Declare Integer HeapAlloc In WIN32API ;
integer iHeap, ;
integer uFlags, ;
integer dwBytes

Declare Integer HeapFree In WIN32API ;
integer iHeap, ;
integer uFlags, ;
integer hGlobal

Declare Integer GetMenuItemCount In WIN32API Integer hMenu

Declare Integer GetSubMenu In WIN32API ;
integer hMenu,;
integer nPos

*--- API для работы с меню - дополнение
Declare Integer GlobalAlloc In WIN32API ;
integer uFlags, ;
integer dwBytes

Declare Integer GlobalFree In WIN32API ;
integer hGlobal

Declare Integer SendMessage In user32.Dll Integer, Integer, Integer, String @


_hWnd = _vfp.HWnd
_hMenu = GetMenu(_hWnd) && Хэндл меню

=mm_get_sub_menu(_hMenu,_hWnd)

Procedure mm_get_sub_menu
Lparameters _hMenu, _hWnd
LOCAL _count_item, _i, cCaption
*--- количество пунктов меню
_count_item = GetMenuItemCount(_hMenu)
If _count_item > 0
For _i=0 To _count_item - 1
cCaption = get_item_Caption(_hMenu ,_i, _hWnd)
? cCaption
*--- проверка на субменю
_hMenu_sub = GetSubMenu(_hMenu, _i) && дескриптор "выскакивающего" меню или подменю, активизированного пунктом меню.
*--- Если пункт меню не активизирует "выскакивающее" меню или подменю, величина возвращаемого значения - ПУСТО (NULL)
If !Isnull(_hMenu_sub) &&
If Vartype(_hMenu_sub) = 'N' And _hMenu_sub # 0
mm_get_sub_menu(_hMenu_sub, _hWnd)
Endif
Endif

Endfor
Endif
Return

Procedure get_item_Caption
Lparameters hMenu ,_num_item, _hWnd
*--- hMenu - дескриптор меню
*--- _num_item - номер пункта
*--- _hWnd - дескриптор окна, содержащего меню
#Define MF_BYCOMMAND 0x00000000
#Define MF_BYPOSITION 0x00000040
#Define MF_STRING 0x00000000
#Define MFT_OWNERDRAW 0x00000100
#Define MFT_SEPARATOR 0x00000800

#Define MIIM_STRING 0x00000040
*--- Retrieves or sets the fType and dwTypeData members. MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
#Define MIIM_TYPE 0x00000010
*--- fMask с этим значением возвращает значение fType
*--- который нужно анализировать
#Define MIIM_FTYPE 0x00000100

#Define LEN_MENU_CAPTION 254
*-- для второй вариант
#Define GPTR 0x00000040
#Define WM_INITMENUPOPUP 0x0117
Local pCaption, MII, nCaptionLen, cCaption, hMenu
_hMenu = hMenu
If .T.
*--- второй вариант

*!* Структура MENUITEMINFO
*!* cbSize As Long
*!* fMask As Long
*!* fType As Long
*!* fState As Long
*!* wID As Long
*!* hSubMenu As Long
*!* hbmpChecked As Long
*!* hbmpUnchecked As Long
*!* dwItemData As Long
*!* dwTypeData As String - Это указатель
*!* cch As Long
*!* hbmpItem As Long

*!* struct tagMENUITEMINFOA {
*!* UINT cbSize;
*!* UINT fMask;
*!* UINT fType;
*!* UINT fState;
*!* UINT wID;
*!* HMENU hSubMenu;
*!* HBITMAP hbmpChecked;
*!* HBITMAP hbmpUnchecked;
*!* ULONG_PTR dwItemData;
*!* LPSTR dwTypeData;
*!* UINT cch;
*!* HBITMAP hbmpItem;
*!* } MENUITEMINFOA, *LPMENUITEMINFOA;

Local cdwTypeData, nlendwTypeData, _nGlobaldwTypeData, MII, cbSize,;
fMask,fType,fState, wID,hSubMenu,hbmpChecked,hbmpUnchecked, dwItemData,;
dwTypeData, cch,hbmpItem, resMII

cdwTypeData = Space(254)
nlendwTypeData = Len(cdwTypeData )
_nGlobaldwTypeData = GlobalAlloc(GPTR,nlendwTypeData )
=Sys(2600, _nGlobaldwTypeData , nlendwTypeData, cdwTypeData )
*!* Чтобы получить элемент меню типа MFT_STRING, сначала найдите размер строки, установив член dwTypeData MENUITEMINFO равным NULL,
*!* а затем вызовите GetMenuItemInfo. Значение cch+1 - это необходимый размер.
*!* Затем выделите буфер такого размера, поместите указатель на буфер в dwTypeData, увеличьте cch на единицу, а затем снова вызовите GetMenuItemInfo,
*!* чтобы заполнить буфер строкой.
*** !В примерах берется размер с запасом 254 и не аналазируется первым вызовом.
*!* !Если извлеченный элемент меню имеет какой-то другой тип, то GetMenuItemInfo устанавливает член dwTypeData в значение,
*!* тип которого задается членом fTypefType, и устанавливает cch в 0.
*MII - переменная, в которой формируем структуру MENUITEMINFO
MII=Space(48)
cbSize = 48 && размер структуры 12*4
*--- MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
fMask = MIIM_TYPE && MIIM_STRING && Retrieves or sets the dwTypeData member
fType = MF_STRING && MFT_STRING - 0x00000000L Отображает пункт меню с помощью текстовой строки. Элемент dwTypeData-это указатель на строку с нулевым окончанием, а элемент cch - это длина строки. MFT_STRING заменяется на MIIM_STRING
fState =0
wID =0
hSubMenu =0
hbmpChecked =0
hbmpUnchecked =0
dwItemData =0
dwTypeData = _nGlobaldwTypeData
cch = 254
hbmpItem =0

MII = BinToC(cbSize , '4RS') &&cbSIZE
MII = MII+BinToC(fMask, '4RS' )
MII = MII+BinToC(fType , '4RS' )
MII = MII+BinToC(fState , '4RS' )
MII = MII+BinToC(wID , '4RS' )
MII = MII+BinToC(hSubMenu , '4RS' )
MII = MII+BinToC(hbmpChecked , '4RS' )
MII = MII+BinToC(hbmpUnchecked , '4RS' )
MII = MII+BinToC(dwItemData , '4RS' )
MII = MII+BinToC(dwTypeData , '4RS' )
MII = MII+BinToC(cch , '4RS' )
MII = MII+BinToC(hbmpItem , '4RS' )
*--- неудачная попытка
*!* MN_GETHMENU = 0x01E1
*!* SendMessage(_hWnd, WM_INITMENUPOPUP, hMenu, BinToC(_num_item , '2RS')+ BinToC(0, '2RS'))

resMII =GetMenuItemInfo(_hMenu ,_num_item ,MF_BYPOSITION ,@MII)
If resMII #0
*--- извлечение результата
cbSize =CToBin(Substr(MII,1,4),'4RS')
fMask =CToBin(Substr(MII,5,4),'4RS')
fType =CToBin(Substr(MII,9,4),'4RS')
fState =CToBin(Substr(MII,13,4),'4RS')
wID =CToBin(Substr(MII,17,4),'4RS')
hSubMenu =CToBin(Substr(MII,21,4),'4RS')
hbmpChecked =CToBin(Substr(MII,25,4),'4RS')
hbmpUnchecked= CToBin(Substr(MII,29,4),'4RS')
dwItemData =CToBin(Substr(MII,33,4),'4RS')
nGlobaldwTypeData =Strconv( (Substr(MII,37,4)),6)

cch =CToBin(Substr(MII,41,4),'4RS')
hbmpItem =CToBin(Substr(MII,44,4),'4RS')
nGlobaldwTypeData =Alltrim(Sys(2600, CToBin(Substr(MII,37,4),'4RS'), cch ))
nCaptionLen = CToBin(Substr(MII,41,4),'4RS')
cCaption = Sys( 2600, CToBin( Substr( MII, 37, 4 ), '4RS' ), nCaptionLen )
*--- конец извлечения результата
If cch # 0
Return cCaption

Else
*--- cch = 0 - значит тип отличается от MIIM_STRING
DO CASE
CASE MFT_SEPARATOR = fType &&
cCaption = '---- Разделитель ----'
CASE MFT_OWNERDRAW = fType &&
*!* Назначает ответственность за рисование элемента меню окну, которому принадлежит меню.
*!* Окно получает сообщение WM_MEASUREITEM перед первым отображением меню, а также сообщение WM_DRAWITEM всякий раз,
*!* когда необходимо обновить внешний вид элемента меню.
*!* Если это значение указано, то элемент dwTypeData содержит определенное приложением значение.
MII=Space(48)
cbSize = 48 && размер структуры 12*4
*--- Retrieves the fType and dwTypeData members. MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
fMask = MIIM_TYPE && MIIM_STRING && Retrieves or sets the dwTypeData member
fType = MFT_OWNERDRAW && Назначает ответственность за рисование элемента меню окну, которому принадлежит меню. Окно получает сообщение WM_MEASUREITEM перед первым отображением меню, а также сообщение WM_DRAWITEM всякий раз, когда необходимо обновить внешний вид элемента меню. Если это значение указано, то элемент dwTypeData содержит определенное приложением значение.
fState =0
wID =0
hSubMenu =0
hbmpChecked =0
hbmpUnchecked =0
dwItemData =0
dwTypeData = _nGlobaldwTypeData &&CHR(0) &&.null. &&
cch = 254
hbmpItem =0

MII = BinToC(cbSize , '4RS') &&cbSIZE
MII = MII+BinToC(fMask, '4RS' )
MII = MII+BinToC(fType , '4RS' )
MII = MII+BinToC(fState , '4RS' )
MII = MII+BinToC(wID , '4RS' )
MII = MII+BinToC(hSubMenu , '4RS' )
MII = MII+BinToC(hbmpChecked , '4RS' )
MII = MII+BinToC(hbmpUnchecked , '4RS' )
MII = MII+BinToC(dwItemData , '4RS' )
MII = MII+BinToC(dwTypeData , '4RS' )
MII = MII+BinToC(cch , '4RS' )
MII = MII+BinToC(hbmpItem , '4RS' )

resMII =GetMenuItemInfo(_hMenu ,_num_item ,MF_BYPOSITION ,@MII)
If resMII #0
cbSize =CToBin(Substr(MII,1,4),'4RS')
fMask =CToBin(Substr(MII,5,4),'4RS')
fType =CToBin(Substr(MII,9,4),'4RS')
fState =CToBin(Substr(MII,13,4),'4RS')
wID =CToBin(Substr(MII,17,4),'4RS')
hSubMenu =CToBin(Substr(MII,21,4),'4RS')
hbmpChecked =CToBin(Substr(MII,25,4),'4RS')
hbmpUnchecked= CToBin(Substr(MII,29,4),'4RS')
dwItemData =CToBin(Substr(MII,33,4),'4RS')
nGlobaldwTypeData =Strconv( (Substr(MII,37,4)),6)

cch =CToBin(Substr(MII,41,4),'4RS')
hbmpItem =CToBin(Substr(MII,44,4),'4RS')
nGlobaldwTypeData =Alltrim(Sys(2600, CToBin(Substr(MII,37,4),'4RS'), cch ))
nCaptionLen = CToBin(Substr(MII,41,4),'4RS')
cCaption = Sys( 2600, CToBin( Substr( MII, 37, 4 ), '4RS' ), nCaptionLen )

If cch # 0
Return cCaption

Else
Return 'Не определен'
Endif
Endif
ENDCASE
Endif
Endif
*--- освобождаю память
=GlobalFree(_nGlobaldwTypeData)

Else
*--- тоже рабочий вариант - без анализа
*--- выделение памяти внутри процесса
pCaption = HeapAlloc(GetProcessHeap(),0, LEN_MENU_CAPTION )

MII = ;
BINTOC( 48 , '4RS') + ; && cbSIZE
BinToC( MIIM_STRING, '4RS' )+ ; && fMask
Replicate( Chr(0), 28 ) + ;
BinToC( pCaption, '4RS' ) + ;
BinToC( LEN_MENU_CAPTION, '4RS' ) + ; && cch
Replicate( Chr(0), 4 )

If GetMenuItemInfo(hMenu ,_num_item ,MF_BYPOSITION ,@MII) <> 0
nCaptionLen = CToBin(Substr(MII,41,4),'4RS')
cCaption = Sys( 2600, CToBin( Substr( MII, 37, 4 ), '4RS' ), nCaptionLen )
Else
cCaption = "<<error>>"
Endif
*--- освобождаю память
=HeapFree( GetProcessHeap(), 0, pCaption )
Endif
Return cCaption

VFP меню POPUP создает в MFT_OWNERDRAW и не возвращает названия пунктов.
Подскажите пожалуйста - Какими средствами получить структуру системного меню, желательно с содержанием иконок?
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
po2

Сообщений: 2864
Откуда: Иркутск
Дата регистрации: 22.12.2001
Я уж забыл все. Помнится, есть одна тонкость. Состоит в том, что позиций меню, до его активизации, считай нет. Только каркас. Проверьте, что вернет ваш код, если вызвать его из пользовательской функции помещенной в секцию skip любой из позиций popup.
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
Заменив _hWnd на хэндл главного окна приложения запустил код из секции SKIP FOR команды DEFINE BAR. Результат тот же - наименования пунктов линейки главного меню возвращаются, наименования пунктов POPUP меню нет.
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Зачем такие мучения? Зачем АПИ? Нет исходного кода проекта, где это меню описано?

И, опять же, безотносительно к первому - меню штука совершенно динамическая - там и пункты и подменю могут добавляться/убираться сколь угодно гибко. Открыл форму - добавились пункты для работы с ней, закрыл - пропали. Вполне типичное поведение.
Не думаю что "документирование приложения" должно опираться на пункты меню.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
Абсолютно объективное, профессиональное рассуждение. Спасибо, что обратили внимание. «Мучения» – в моем случае это точное и емкое определение. Для чего мне они нужны? Да конечно не в получении результата, выраженного в виде текста с картинками в HTL формате. Тактическое решение, не претендующее на оригинальность, при наличии времени «заглянуть за горизонт своих познаний». Какие Win Msg необходимо связывать?
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Яковлев Игорь
Какие Win Msg необходимо связывать?

Добавлю немного для пояснения сказанного выше.
Просто в фокспро меню - вещь несколько специфическая. В широком смсле слова - это вообще не виндовский объект. Для его создания не используются никакие библиотеки, как это обычно делается где-то в других средах. А свои собственные, встроенные средства. Создается же оно при этом в программе через определенный набор команд, выполняемых в рантайме.
Т.е. отсюда видимо и нестоятельность попыток его "считывания" как стандартного виндовского объекта.
Как выше уже и было упомянуто, если есть рабочие коды запускаемой программы, можно например попытаться автоматизировать выборку его создания из них. Но только, если оно не создается там динамически, иначе придется анализировать код его создания-изменения уже вручную.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
Извинюсь заранее, если настойчивость в достижении понимания предмета вопроса выглядит как спор неразумного пятиклассника с учителем математики.

В результате работы приведенного кода очевидно, что «в фокспро меню - вещь несколько специфическая.»
А именно: fType = MFT_OWNERDRAW «Assigns responsibility for drawing the menu item to the window that owns the menu. The window receives a WM_MEASUREITEM message before the menu is displayed for the first time, and a WM_DRAWITEM message whenever the appearance of the menu item must be updated. If this value is specified, the dwTypeData member contains an application-defined value.» Назначает ответственность за рисование элемента меню окну, которому принадлежит меню. Окно получает сообщение WM_MEASUREITEM перед первым отображением меню, а также сообщение WM_DRAWITEM всякий раз, когда необходимо обновить внешний вид элемента меню. Если это значение указано, то элемент dwTypeData содержит определенное приложением значение. Но VFP не позаботился определить это значение или я его неправильно определяю.

Экспертное мнение могло бы прояснить «смутные сомнения». Но даже если текстового вида извлечь невозможно, то «нарисованный» пункт меню потенциально извлекаем.
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
ssa

Сообщений: 13008
Откуда: Москва
Дата регистрации: 23.03.2005
Crispy
Яковлев Игорь
Какие Win Msg необходимо связывать?

Добавлю немного для пояснения сказанного выше.
Просто в фокспро меню - вещь несколько специфическая. В широком смсле слова - это вообще не виндовский объект.
А вот и нет. Наоборот, это чисто виндовый объект, к тому же как бы "системный", создаваемый самой виндой.
Цитата:
Для его создания не используются никакие библиотеки, как это обычно делается где-то в других средах. А свои собственные, встроенные средства.
Угу, непосредственное обращение к API.
Цитата:
Создается же оно при этом в программе через определенный набор команд, выполняемых в рантайме.
Т.е. отсюда видимо и нестоятельность попыток его "считывания" как стандартного виндовского объекта.
Не так. Несостоятельность попыток читать его как фоксовый объект.
А это таки объект операционной системы. И читать его надо из ресурсов операционной системы. Ибо куда-то туда она его пихает по командам от прикладной проги.


------------------
Лень - это неосознанная мудрость.
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
Яковлев Игорь
«заглянуть за горизонт своих познаний».

Красиво сказано.
Только не похож ваш копипаст на горизонт.
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
lulgu
Яковлев Игорь
«заглянуть за горизонт своих познаний».

Красиво сказано.
Только не похож ваш копипаст на горизонт.

Свои горизонты я открываю на этом форум.
копипаст по мотиву автора beobachter
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
Яковлев Игорь
lulgu
Яковлев Игорь
«заглянуть за горизонт своих познаний».

Красиво сказано.
Только не похож ваш копипаст на горизонт.

Свои горизонты я открываю на этом форум.
копипаст по мотиву автора beobachter

Сейчас не 2006 год.
Вынесите свои Api-функции и структуры в отдельные обертки, и с каждой разбирайтесь отдельно.
Если хотите расширить свои познания, возьмите их описания в MSDN, там все есть.
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
ssa
А это таки объект операционной системы. И читать его надо из ресурсов операционной системы. Ибо куда-то туда она его пихает по командам от прикладной проги.

Может конечно и так. Специально в эту тему не углублялся, не было нужды.
Хотя у меня всегда, когда доводилось иметь дело с фоксовским меню, складывалось впечатление, что оно какое-то "не настоящее". Как и форма, и грид, и еще ряд фоксовских контролов.
Но те хотя бы визуальны. Меню же и близко не визуально на этапе разработке. Т.е. это всего лишь тупо набор команд. Причем почти не изменившихся со времен DOS-а.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
lulgu
Сейчас не 2006 год.
Это как-то отразилось на VFP 9.0? Освежите в свой памяти дату релиза

lulgu
Вынесите свои Api-функции и структуры в отдельные обертки, и с каждой разбирайтесь отдельно.
Api-функции и структуры в отдельных обертках.
См. правила конференции:
"Старайтесь создавать репро, которое спокойно запускается из .PRG файла без изменений"

lulgu
Если хотите расширить свои познания, возьмите их описания в MSDN, там все есть.
Без комментария ... Копипаст содержит выдержки из MSDN. Вы вероятно не прочитали



Исправлено 1 раз(а). Последнее : Яковлев Игорь, 17.06.20 19:37
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
PaulWist

Сообщений: 14625
Дата регистрации: 01.04.2004
2Яковлев Игорь

Не надо дальше ;)


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
Яковлев Игорь
Без комментария ...

+
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Яковлев Игорь
Экспертное мнение могло бы прояснить «смутные сомнения». Но даже если текстового вида извлечь невозможно, то «нарисованный» пункт меню потенциально извлекаем.
Не думаю что кто либо из тут присутствующих занимался декомпиляцией кода собственно VFP для глубокого понимания как же именно он обрабатывает команды DEFINE PAD/BAR/MENU, ON [SELECTION], ACTIVATE MENU и всё прочее Это попросту не нужно никому и никогда. В фоксе есть все команды необходимые для управления меню и есть некоторый набор функции для "получения его структуры" - всякие CNTBAR()/PRMBAR()/GETBAR() Но т.к. эти возможности не симметричны (не всё что можно задать/создать в меню можно потом прочитать) то иногда в программах используют те или иные объектные или ещё какие-то (на основе массивов, или таблиц с метаданными) обёртки - чтобы иметь возможность во время исполнения программы как поменять что-либо в системе меню (добавить/убрать/спрятать пункт, поменять надпись или картинку) так и "прочитать структуру" - т.е. определить какие пункты и подменю активны, какие у них картинки, надписи, условия пропуска и т.п. И ни одно из этих решений не спускается до уровня АПИ функций - просто потому что это не нужно

ssa
А вот и нет. Наоборот, это чисто виндовый объект, к тому же как бы "системный", создаваемый самой виндой.
В фоксе есть и "классическое" досовское меню - при том управляемое/создаваемое теми же самыми командами. Так что далеко не всегда меню в фоксе это "виндовое меню" (хотя использовать этот унаследованный ужас FPD-BAR меню в здравом уме вряд ли кто-то будет).
ssa
И читать его надо из ресурсов операционной системы. Ибо куда-то туда она его пихает по командам от прикладной проги.
Не знаю про какие именно "ресурсы ОС" ты тут написал, фоксовое меню никогда не было статическим, как во многих сишных программах, где оно хранится как "ресурс" в специальной секции exe файла... Но в общем-то АПИ функции GetMenu и т.д. и позволяют получить доступ к тому "виндовому меню" которое фокс делает на основе фоксовых команд управления меню. Но т.к. подменю у фокса "саморисованные", то как таковых их по простому не вынуть - с чем и столкнулся автор темы.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
Igor Korolyov
Но т.к. подменю у фокса "саморисованные", то как таковых их по простому не вынуть - с чем и столкнулся автор темы.

Интересно, кроме ссылки на ТС, как вы еще можете подтвердить это утверждение?
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
lulgu

Сообщений: 1838
Дата регистрации: 30.11.2016
lulgu
Igor Korolyov
Но т.к. подменю у фокса "саморисованные", то как таковых их по простому не вынуть - с чем и столкнулся автор темы.

Интересно, кроме ссылки на ТС, как вы еще можете подтвердить это утверждение?

ТС в рамках своей задачи получил ответ еще в первом же совете (второй пост сверху) и в принципе, тему на этом можно было и закрывать.
(Признаюсь, я не сразу обратил на него внимание).
ИК это важное замечание проигнорировал и начал привычно выдумывать "саморисованную" теорию.
Хотя кроме GetMenu() есть еще функции для работы с меню.
И, конечно, практическая ценность тематики довольно специфична.



Исправлено 2 раз(а). Последнее : lulgu, 19.06.20 12:21
Ratings: 0 negative/0 positive
Re: Инвентаризация меню
Яковлев Игорь
Автор

Сообщений: 9
Откуда: Кингисепп
Дата регистрации: 20.10.2017
Встав на твердые основания MSDN появилось ощущение похожее на понимание. Огромная благодарность всем, принявших участие в обсуждении.

*--- API для работы с меню
Declare Integer GetMenu In WIN32API ;
integer HWnd

Declare Integer GetMenuItemInfo In WIN32API ;
integer hMenu,;
integer uItem,;
integer fByPosition,;
string @ MENUITEMINFO

Declare Integer GetProcessHeap In WIN32API

Declare Integer HeapAlloc In WIN32API ;
integer iHeap, ;
integer uFlags, ;
integer dwBytes

Declare Integer HeapFree In WIN32API ;
integer iHeap, ;
integer uFlags, ;
integer hGlobal

Declare Integer GetMenuItemCount In WIN32API Integer hMenu

Declare Integer GetSubMenu In WIN32API ;
integer hMenu,;
integer nPos

_hWnd = _vfp.HWnd
_hMenu = GetMenu(_hWnd) && Хэндл меню

=mm_get_sub_menu(_hMenu,_hWnd)

Procedure mm_get_sub_menu
Lparameters _hMenu, _hWnd
LOCAL _count_item, _i, cCaption
*--- количество пунктов меню
_count_item = GetMenuItemCount(_hMenu)
If _count_item > 0
For _i=0 To _count_item - 1
cCaption = get_item_Caption(_hMenu ,_i, _hWnd)
? cCaption
*--- проверка на субменю
_hMenu_sub = GetSubMenu(_hMenu, _i) && дескриптор "выскакивающего" меню или подменю, активизированного пунктом меню.
*--- Если пункт меню не активизирует "выскакивающее" меню или подменю, величина возвращаемого значения - ПУСТО (NULL)
If !Isnull(_hMenu_sub) &&
If Vartype(_hMenu_sub) = 'N' And _hMenu_sub # 0
mm_get_sub_menu(_hMenu_sub, _hWnd)
Endif
Endif

Endfor
Endif
Return

Procedure get_item_Caption
Lparameters hMenu ,_num_item, _hWnd
*--- hMenu - дескриптор меню
*--- _num_item - номер пункта
*--- _hWnd - дескриптор окна, содержащего меню
#Define MF_BYCOMMAND 0x00000000
#Define MF_BYPOSITION 0x00000040
#Define MF_STRING 0x00000000
#Define MFT_OWNERDRAW 0x00000100
#Define MFT_SEPARATOR 0x00000800

#Define MIIM_STRING 0x00000040
*--- Retrieves or sets the fType and dwTypeData members. MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
#Define MIIM_TYPE 0x00000010
#Define MIIM_FTYPE 0x00000100 && Retrieves or sets the fType member.
#Define MIIM_DATA 0x00000020
*--- fMask с этим значением возвращает значение fType
*--- который нужно анализировать
#Define MIIM_FTYPE 0x00000100

#Define LEN_MENU_CAPTION 254
*-- для второй вариант
#Define GPTR 0x00000040
#Define WM_INITMENUPOPUP 0x0117
Local pCaption, MII, nCaptionLen, cCaption, hMenu
_hMenu = hMenu
If .T.
Local cdwTypeData, nlendwTypeData, _nGlobaldwTypeData, MII, cbSize,;
fMask,fType,fState, wID,hSubMenu,hbmpChecked,hbmpUnchecked, dwItemData,;
dwTypeData, cch,hbmpItem, resMII

cdwTypeData = Space(254)
nlendwTypeData = Len(cdwTypeData )
_nGlobaldwTypeData = HeapAlloc(GetProcessHeap(),0, LEN_MENU_CAPTION ) &&GlobalAlloc(GPTR,nlendwTypeData )
=Sys(2600, _nGlobaldwTypeData , nlendwTypeData, cdwTypeData )

MII=Space(48)
cbSize = 48 && размер структуры 12*4
*--- MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
fMask = MIIM_TYPE && MIIM_STRING && Retrieves or sets the dwTypeData member
fType = MF_STRING && MFT_STRING - 0x00000000L Отображает пункт меню с помощью текстовой строки. Элемент dwTypeData-это указатель на строку с нулевым окончанием, а элемент cch - это длина строки. MFT_STRING заменяется на MIIM_STRING
fState =0
wID =0
hSubMenu =0
hbmpChecked =0
hbmpUnchecked =0
dwItemData = 0
dwTypeData = _nGlobaldwTypeData
cch = 254
hbmpItem =0

MII = BinToC(cbSize , '4RS') &&cbSIZE
MII = MII+BinToC(fMask, '4RS' )
MII = MII+BinToC(fType , '4RS' )
MII = MII+BinToC(fState , '4RS' )
MII = MII+BinToC(wID , '4RS' )
MII = MII+BinToC(hSubMenu , '4RS' )
MII = MII+BinToC(hbmpChecked , '4RS' )
MII = MII+BinToC(hbmpUnchecked , '4RS' )
MII = MII+BinToC(dwItemData , '4RS' )
MII = MII+BinToC(dwTypeData , '4RS' )
MII = MII+BinToC(cch , '4RS' )
MII = MII+BinToC(hbmpItem , '4RS' )
resMII =GetMenuItemInfo(_hMenu ,_num_item ,MF_BYPOSITION ,@MII)
If resMII #0
*--- извлечение результата
cbSize =CToBin(Substr(MII,1,4),'4RS')
fMask =CToBin(Substr(MII,5,4),'4RS')
fType =CToBin(Substr(MII,9,4),'4RS')
fState =CToBin(Substr(MII,13,4),'4RS')
wID =CToBin(Substr(MII,17,4),'4RS')
hSubMenu =CToBin(Substr(MII,21,4),'4RS')
hbmpChecked =CToBin(Substr(MII,25,4),'4RS')
hbmpUnchecked= CToBin(Substr(MII,29,4),'4RS')
dwItemData =CToBin(Substr(MII,33,4),'4RS')
nGlobaldwTypeData =Strconv( (Substr(MII,37,4)),6)

cch =CToBin(Substr(MII,41,4),'4RS')
hbmpItem =CToBin(Substr(MII,44,4),'4RS')
nGlobaldwTypeData =Alltrim(Sys(2600, CToBin(Substr(MII,37,4),'4RS'), cch ))
nCaptionLen = CToBin(Substr(MII,41,4),'4RS')
cCaption = Sys( 2600, CToBin( Substr( MII, 37, 4 ), '4RS' ), nCaptionLen )
*--- конец извлечения результата
If cch # 0
Return cCaption

Else
DO CASE
CASE MFT_SEPARATOR = fType &&
cCaption = '---- Разделитель ----'
CASE MFT_OWNERDRAW = fType &&
*!* Назначает ответственность за рисование элемента меню окну, которому принадлежит меню.
*!* Окно получает сообщение WM_MEASUREITEM перед первым отображением меню, а также сообщение WM_DRAWITEM всякий раз,
*!* когда необходимо обновить внешний вид элемента меню.
*!* Если это значение указано, то элемент dwTypeData содержит определенное приложением значение.
MII=Space(48)
cbSize = 48 && размер структуры 12*4
fMask = MIIM_DATA
fType = 0 &&MF_STRING
fState =0
wID =0
hSubMenu =0
hbmpChecked =0
hbmpUnchecked =0
dwItemData = 0
dwTypeData = _nGlobaldwTypeData
cch = 254
hbmpItem =0

MII = BinToC(cbSize , '4RS') &&cbSIZE
MII = MII+BinToC(fMask, '4RS' )
MII = MII+BinToC(fType , '4RS' )
MII = MII+BinToC(fState , '4RS' )
MII = MII+BinToC(wID , '4RS' )
MII = MII+BinToC(hSubMenu , '4RS' )
MII = MII+BinToC(hbmpChecked , '4RS' )
MII = MII+BinToC(hbmpUnchecked , '4RS' )
MII = MII+BinToC(dwItemData , '4RS' )
MII = MII+BinToC(dwTypeData , '4RS' )
MII = MII+BinToC(cch , '4RS' )
MII = MII+BinToC(hbmpItem , '4RS' )
resMII =GetMenuItemInfo(_hMenu ,_num_item ,MF_BYPOSITION ,@MII)
If resMII #0
cbSize =CToBin(Substr(MII,1,4),'4RS')
fMask =CToBin(Substr(MII,5,4),'4RS')
fType =CToBin(Substr(MII,9,4),'4RS')
fState =CToBin(Substr(MII,13,4),'4RS')
wID =CToBin(Substr(MII,17,4),'4RS')
hSubMenu =CToBin(Substr(MII,21,4),'4RS')
hbmpChecked =CToBin(Substr(MII,25,4),'4RS')
hbmpUnchecked= CToBin(Substr(MII,29,4),'4RS')
dwItemData =CToBin(Substr(MII,33,4),'4RS')
nGlobaldwTypeData =Strconv( (Substr(MII,37,4)),6)

cch =CToBin(Substr(MII,41,4),'4RS')
hbmpItem =CToBin(Substr(MII,44,4),'4RS')
nGlobaldwTypeData =Alltrim(Sys(2600, CToBin(Substr(MII,37,4),'4RS'), cch ))
nCaptionLen = CToBin(Substr(MII,41,4),'4RS')
cCaption = Sys( 2600, CToBin( Substr( MII, 37, 4 ), '4RS' ), nCaptionLen )
IF !EMPTY(dwItemData) && ?
_cCaption = STRCONV(SUBSTR(Sys(2600, dwItemData, 80),15),6)
_len = LEN(_cCaption)
IF AT(CHR(4),_cCaption) > 0
_len = MIN(_len,AT(CHR(4),_cCaption))
ENDIF
IF AT(CHR(63),_cCaption) > 0
_len = MIN(_len,AT(CHR(63),_cCaption))
ENDIF
cCaption = SUBSTR(_cCaption,1,_len-1)
_len = _len
Else
Return 'Не определен'
Endif
Endif
ENDCASE
Endif
Endif
*--- освобождаю память
=HeapFree( GetProcessHeap(), 0, _nGlobaldwTypeData )
Endif
Return cCaption
[code][/code]
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 32 (Гостей: 32)

© 2000-2024 Fox Club 
Яндекс.Метрика