![]() |
|
|
![]()
|
|
| suvolod |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 56 Регистрация: 20.8.2005 Репутация: 1 Всего: 1 |
Всем доброе время суток. Вопрос такой. У меня главное окно программы - диалого. К нему прицеплено меню, которое я создал в ресурсах.
В этом меню одно из подменю имеет динамически создаваемые итемы. Т.е оно представлет из себя менюшку вида Пользователи=> Новый пользователь Удалить пользователя ---------------------------- (сепаратор) Иван v Максим Женя ... и т.д. Т.е по кнопке "Новый пользователь" появляется новый элемент меню, по кнопке "Удалить пользователя" удаляется текущий. Текущий выбранный пользователь помечается флажком. В общем-то, у меня пока два вопроса. 1. Как сохранить такое изменное меню? - на ум приходит пока только создание какой-нибудь сохраняемой в файл структуры, в которую при закрытии программы скидываются дополнительные элементы с именами пользователей, а при открытии - сначала загружается базовое меню, а затем в него добавляются элементы из этой структуры. 2. Не совсем понятно, как работать с таким динамическим элементом. Мне надо пометить "галочкой" элемент, на котором щелкнули, и соответственно снять галочку с предыдущего. Но ведь элементы-то динамические. Во первых, я не могу заранее задать для них обработчик для вызова CheckMenuItem, потому-что на момент загрузки программы может не быть вообще ни одного динамически созданного элемента меню. А во вторых, как-то неправильно наверное на каждый элемент (а их может быть и 20 штук) писать один и тот-же обработчик, который фактически делает лишь одно - ставит галочку на текущем элементе и проверяет/снимает галочку с остальных. Это сообщение отредактировал(а) suvolod - 1.11.2010, 11:54 |
|||
|
||||
| Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
1. Да, именно так. Или в реестр.
2. Почему же не можешь? Другое дело, что нужно заранее выделить пл команд для этих итемов - ты же не будешь присваивать идентификаторы какие попало? Выдели диапазон команд заранее, скажем :
А потом используй цикл по этим элементам: если элемент с заданным номером существует, делай с ним что-нибудь. Хотя гораздо удобнее использовать обработчики команд с макросами ON_COMMAND_RANGE и ON_UPDATE_COMMAND_UI. Соответственно, обработчик для установки галки может выглядеть так:
-------------------- ... |
||||
|
|||||
| suvolod |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 56 Регистрация: 20.8.2005 Репутация: 1 Всего: 1 |
Earnest, большое спасибо. Теперь хоть в голове стало проясняться
|
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Сериализация - это по-определению лишь "расплющивание" динамических структур данных. Как бы ты не записывал свои меню в файл - это по любому будет сериализация.
CMenu - не потомок CWnd, но потомок CObject, так что метод Serialize у него тоже есть. Только толку-то. В оболочку вызов (для меню) не встроен, так что верхнюю голову напрячь придется. И придумать, куда это дело вставить. Кроме того, стандартная сериализация удобна для сохранения\загрузки документов. Вот если состав меню нужно записать именно в документ, тогда другое дело. Но и тогда удобнее делать "руками": в документ включить список этих юзеров, обновлять и поддерживать его именно в документе, а меню модифицировать, скажем, на OnUpdate, тем более что технология в MFC отработана: проще всего списать слова в MFC, где модифицируется меню MRU-документов. Дело в том, что там есть некоторые неочевидные хитрости, так что чем ковыряться самому, проще слова списать. -------------------- ... |
|||
|
||||
| suvolod |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 56 Регистрация: 20.8.2005 Репутация: 1 Всего: 1 |
Earnest, добрый вечер. Наконец-то все заработало через ON_COMMAND_RANGE и ON_UPDATE_COMMAND_UI_RANGE
Два вопроса еще есть, подскажи, очень нужно. 1. Во первых, я так и не понял, как сделать это-же без этих макросов. ты писала...
... поясни подробнее, как это происходит. Создавая новый элемент меню, я вызываю что-то типа cMenu->AppendMenuW(MF_STRING,ID_USER_FIRST+count, s); ... то есть идентификатор элементу я присваиваю, а функцию обработки - нет. Если заранее прописать идентификаторы в ON_COMMAND_RANGE - тут все ясно, но я понял, что есть возможность назначить обработчик сообщения без этого макроса. Т.е каждому новому элементу меню будет присваиваться некая фция (одна?), в ней крутиться цикл (хотя, имхо тут уместнее будет switch), и в зависимости от id текущего итема выполняются те или иные действия.. Я правильно понял? 2. Я прошу совета - как лучше организовать такой функционал. Каждый пункт меню (с именем юзера)должен хранить какие-то доп. данные. Если быть точнее - в списке может быть один и тот-же юзер, но работающий с разными базами. Соответственно по выбору другого пункта должны произойти изменения - юзер остаться прежним, а база - старая закрыться и загрузиться новая.. Как это лучше сделать? На ум приходит пока только задавать текстовое значение итема вида "Юзер База", а затем читать и разбирать эту строку... но может есть способ лучше? Так как имя базы, например, может быть коротким, а путь до нее - очень длинным и выводить полный путь в менюшке нереально.. Это сообщение отредактировал(а) suvolod - 2.11.2010, 14:54 |
|||
|
||||
| Earnest |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Нет, динамически добавить функцию-обработчик нельзя. Можно без макросов, переопределив OnCmdMsg. Примерно то же самое, что в обработчике, но нужно проверять, что пришло обновление и номер ид-ра. А про цикл я имела в виду, когда ты спрашивал про CheckMenuItem: можно переопределить обработчик OnInitMenuPopup (откуда все это вызывается), и там в цикле пройтись по пунктам меню и всем поставить Check. Но это самый плохой способ. Через макросы и обработчике лучше, да и проще в данном случае. Самый гибкий - через OnCmdMsg, но пока это для тебя сложновато, да и задача вполне решаема через макросы. С пунктом меню можно связать некоторое значение целого типа, не больше. Это может быть индекс данных или указатель. Но сами данные должны жить где-то еще. Хранить динамические данные только в пункте меню не стоит - задолбаешься за временем жизни следить. Я бы сделала так: Где-то - в приложении, документе или как-то еще - зависит от структуры приложения - хранится список или массив пар "юзер" + "данные". Юзер, разумеется, должен представляться не именем, а каким-то ид-ром, чтобы не дублировать бесконечно строки.
Меню составляем из данных контейнера CUserData. Добавлять строки меню лучше через InsertMenuItem, это гибче. Как формировать строку, чтобы они отличались для одинаковых юзеров - дело хозяйское, но не в коем случае не для того, чтобы впоследствие ее разбирать - нафик, у нас ведь вся инфа есть. Смысл в том, чтобы получив определенную команду из нашего пула найти соответствующий элемент данных - CData. Это можно делать по-разному, в зависимости от задачи и желания: 1) Самое простое, если элементы никогда не удаляются, а их порядок безразличен - в качестве контейнера использовать вектор, а связь команды меню с элементом иметь неявную, т.е. индекс в векторе = CmdID - ID_USER_FIRST. Элементы-то мы добавляем в меню по-порядку, вот пусть так и живет. Однако, если элементы CData могут удаляться, то это уже не прокатит без дополнительных наворотов. 2) И вот один из них: меню заполняем не один раз при загрузке, а на OnUpdate (как я писала в самом первом посте). Хотя можно и по специальному пинку просто перезаполнять меню - при изменени списка CUserData. Т.е. при изменении контейнера CUserData переинициализируем меню. 3) Можно и по-другому извратиться - например, хранить данные не в массиве, а в списке, а при добавлении элементов меню прописывать в них указатели на соотв. элементы списка 4) Или напротив, в меню ничего дополнительно не писать, а в CData добавить поле - ид-р команды, куда заносить номер команды при создании соответствующего пункта меню. И т.д. Но я бы остановилась на первом варианте, как самом простом, с возможным добавлением п. 2, если нужно. -------------------- ... |
||||
|
|||||
| suvolod |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 56 Регистрация: 20.8.2005 Репутация: 1 Всего: 1 |
Большое спасибо за точные и подробные ответы
Это сообщение отредактировал(а) suvolod - 3.11.2010, 06:08 |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |