Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

А возможна ли такая фишка???

358
18 октября 2002 года
moonmike
423 / / 18.10.2002
Есть идея свернуть меню проги в БД, и оттуда соответственно его выдергивать,
соответственно по минимуму в БД надо сохранять для каждого пункта меню необходимо
сохранить в базе:
Name, Caption и название функции реагирующей на клик. В мануале сказано что
в рнантайме мона добавлять ето так:
MenuItem->OnClick = function;
но все дело в том что в БД сохраняется то название функции, соответственно
при компиляции следющего участка кода:
New->OnClick = WideToAnsi(MTODm->aspReturnMenu->FieldByName("OnClick")->Value);
Выдается ошибка:
[C++ Error] MenuLoad.cpp(38): E2034 Cannot convert 'char *' to 'void (_fastcall
* (_closure )(TObject *))(TObject *)'
Так можно ли ето как - то реализовать???
476
18 октября 2002 года
man2002ua
218 / / 16.10.2002
врядли так получится, ведь OnClick требует NotifyEvent, а это никак не имя процедуры (даже не адрес...хотя могли бы и такое предусмотреть :x )
Придется тебе в БД заносить не имя процедуры, а ее адрес. При инициализации проги - считывай адрес процедуры в список. А при событии меню OnClick - пусть процедура ищет в этом списке адрес той процедуры, к-ю надо выполнить и выполняет ее.

Если нужен пример - говори :)
358
18 октября 2002 года
moonmike
423 / / 18.10.2002
Цитата:
Originally posted by man2002ua
врядли так получится, ведь OnClick требует NotifyEvent, а это никак не имя процедуры (даже не адрес...хотя могли бы и такое предусмотреть :x )
Придется тебе в БД заносить не имя процедуры, а ее адрес. При инициализации проги - считывай адрес процедуры в список. А при событии меню OnClick - пусть процедура ищет в этом списке адрес той процедуры, к-ю надо выполнить и выполняет ее.

Если нужен пример - говори :)


Трабла в том, что при каждой перекомпиляции адрес будет меняться, но адрес по имени я уж как нить достану, постараюсь(хоть и жаль на ето время тратить), а вот примерчик предложенный был бы интересен

476
18 октября 2002 года
man2002ua
218 / / 16.10.2002
Цитата:
Originally posted by moonmike

Трабла в том, что при каждой перекомпиляции адрес будет меняться, но адрес по имени я уж как нить достану, постараюсь(хоть и жаль на ето время тратить), а вот примерчик предложенный был бы интересен



Ладно, я пошутил, что не получиться :D - программеры все могут.
Я тут на Delphi набросал примерный код (Buildera под рукой нету), как ты можешь сделать задуманное. Сам переведешь?

procedure TForm1.Menu1Click...
begin
// нифига
end;

procedure TForm1.MYproc(Sender : TObject);
begin
// новый обработчик меню
// правда, чтобы получить его адрес по имени, он должен быть в Forme или в DLL
end;

// твоя проца инициализации
procedure TForm1.InitMenuItems(Sender: TObject);
var dd : DWORD;
begin
r := Menu1Click; // ты должен определить одну пустую процедуру для пункта меню
// Берем адрес нашей процы
dd := DWORD(Form1.MethodAddress ('MYproc'));
asm
mov eax, dd;
mov dword ptr [r], eax; // заменяем ссылку на реальный обработчик
end;
Menu1Click := r; // пихаем новую стр-ру обратно
end;

442
18 октября 2002 года
HexoGenus
121 / / 20.03.2000
Цитата:
Originally posted by moonmike

Трабла в том, что при каждой перекомпиляции адрес будет меняться, но адрес по имени я уж как нить достану, постараюсь(хоть и жаль на ето время тратить), а вот примерчик предложенный был бы интересен



Зыыы.... оригинальную проблему вы себе выдумали
:-))))
Бессмысленно сохранять меню в БД если в ней же не сохранять вызываемые функции... посудите сами, если в программе включены уже все обработчики пунктов меню то что сложного в том что бы сформировать меню включающее все до единого пункты??? И если нужна возможность формирования различных вариантов меню для пользователей обладающих различными привелегиями и уровнями доступа то проще в БД сохранять не сами пункты меню а только булевую инфу о том какие из них должны быть Visible а какие наоборот...
Правда может потребоваться возможность формировать пунктики каждому пользователю по его мозговитости :-))) т.е. создавать разные названия пунктам меню, различные по сложности коментарии к каждому пункту меню ... что же наверно не стоит в этом случае формировать свитч на адреса... ведь с адресами может возникнуть путаница, так??? К тому же это будет слишком большое количество бессмысленного кода...
Вместо этого всем пунктам меню ставим в свойстве Tag их порядковый номер а обработчик нажатия делаем общим для всех пунктов меню (зашибись будет функция) ... в обработчике пишем
TMenuItem *Punktik=(TMenuItem*)Sender;
int Item=Punktik->Tag;
И делаем не слабый свитчик который будет выполнять действия соответствующие данному пункту...
Вобщем теперь задача сводится не к тому что бы сохранить адреса вызываемых функций а к тому чтобы сохранить число из свойства Tag...

Надеюсь я не слишком путанно свои мысли излагал???:D

476
18 октября 2002 года
man2002ua
218 / / 16.10.2002
Это выход, но он не интересный 8-)
Мы же легких путей не ищем, тем более, если есть необходимость динамически менять процедуру, реагирующую на пункт меню - то мой метод прикольнее. :D

хотя злоупотреблять им не следует...
358
21 октября 2002 года
moonmike
423 / / 18.10.2002
Причем с сохранением именно имени обработчика=)))Спасибо так сказать людям знающим=))Если интересно могу сурцы показать
476
21 октября 2002 года
man2002ua
218 / / 16.10.2002
покажи :D
358
22 октября 2002 года
moonmike
423 / / 18.10.2002
Итак начну сначала.
Главная форма Form1 в которую и надо добавлять пункты меню, при создании(OnCreate) вызывает вторую форму Form2 в которой ето меню и подгружается.
и вот так вот выгдядит код:

TADODataSet *Count = new TADODataSet(this);
Count->Recordset = MTODm->acMenuItemsCount->Execute();
Count->First();
pbMenuLoad->Max = Count->Fields->Fields[0]->Value;
delete Count;
// Смотрим сколько увсего пунктов меню в БД и приравниваем ето Max ProgressBar'a
pbMenuLoad->Step = 1;
TMainMenu *Main = new TMainMenu(this->Owner);
Main = dynamic_cast<TForm*>(this->Owner)->Menu;
// Создаем указатель на Главное меню Form1
MTODm->aspReturnMenu->Open();
MTODm->aspReturnMenu->First();
//ОТкрываем БД с сохраненными пунктами меню
TForm *Form = new TForm(Application);
Form = dynamic_cast<TForm*>(this->Owner);
//Сщздаем указатель на Form1(просто для удобства)
for (int i=0; i< pbMenuLoad->Max; i++)
{
TMenuItem *New = new TMenuItem(0);
//Создаем новый пункт меню
AnsiString a = WideToAnsi(MTODm->aspReturnMenu->FieldByName("Naim")->Value);
New->Name = a.TrimRight();
//Имя пункта
a = WideToAnsi(MTODm->aspReturnMenu->FieldByName("Caption")->Value);
New->Caption = a.TrimRight();
//Caption пункта
a = WideToAnsi(MTODm->aspReturnMenu->FieldByName("OnClick")->Value);
//Название обработчика(обработчик должен быть объявлен в паблишед зоне Form1)
void* AddrProc = Form->MethodAddress(ShortString(a.TrimRight()));
//Получаем адрес обработчика
TMethod Method;
Method.Data = this;
Method.Code = AddrProc;
New->OnClick = *(TNotifyEvent*)&Method;
//Приводим к необходимому типу
Main->Items->Add(New);
//Добавляем пункт к меню
MTODm->aspReturnMenu->Next();
pbMenuLoad->StepIt();
//Продвигаем прогрес-бар на одно деление
}
if (MTODm->aspReturnMenu->Eof)
{
MTODm->aspReturnMenu->Prior();
}
MTODm->aspReturnMenu->Active = false;
ModalResult = mrOk;
//Возвращаемся в Form1
}

Вот и все=)))
476
22 октября 2002 года
man2002ua
218 / / 16.10.2002
Оригинально :)
в том примере (выше), что я написал ассемблером - то же самое. Блин, век живи - век учись. Перед тем как ломать двери, убедись, что они не открываются в другую сторону :)))) я про TMethod узнал только теперь - спасибо, moonmike :D
358
22 октября 2002 года
moonmike
423 / / 18.10.2002
Цитата:
Originally posted by man2002ua
Оригинально :)
в том примере (выше), что я написал ассемблером - то же самое. Блин, век живи - век учись. Перед тем как ломать двери, убедись, что они не открываются в другую сторону :)))) я про TMethod узнал только теперь - спасибо, moonmike :D


Про век живи век учись ето верно!!!Я и сам про TMethod от Вячеслава Ермолаева с Софтфорума узнал...Знающий мужик, и не зануда что приятно.

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог