Русские документы
Ежедневные компьютерные новости RSS rusdoc.ru  Найти :
Новости
Последние поступления
Книжный магазин
  Hardware:
Видеоустройства
Системные платы
Процессоры
Мобильные устройства
Аудиосистема
Охлаждение системы
Накопители информации
КПК и ноутбуки
Телефоны и связь
Периферия
Система
Сети
Разные устройства
 
  Programming:
Web-разработка
Языки программирования
Технологии и теория
Разработка игр
Программная инженерия
 
  Software:
Операционные системы
Windows 7
Базы данных
Обзоры программ
Графика и дизайн
   
  Life:
Компьютерная жизнь
Разные материалы
   
Партнеры
Публикация
Правовая информация
Реклама на сайте
Обратная связь
Экспорт в RSS Экспорт в RSS2.0
    Читать в Яндекс.Ленте



Коллекция фрагментов кода из реально работающих программ на C++ Builder

Раздел: Programming / С++ @ 07.11.2007 | Ключевые слова: функции borland c++ версия для печати

Источник: articles.org.ru

#include
#pragma hdrstop
#include "code.h"

#define main_page "bcdev.narod.ru"
#define e_mail yerm@mail.ru
// Это не faq (часто задаваемые вопросы) и caq (обычно
// задаваемые вопросы). Скорее всего это можно
// охарактеризовать как коллекцию фрагментов кода из
// реально работающих программ. Очень часто, разрабатывая
// новый проект, сталкиваешься с ситуацией, когда вдруг
// понимаешь, что подобная задача уже была однажды решена
// тобой. К сожалению, найти предыдущее решение бывает
// не всегда легко. А в случае смены места работы и вовсе
// невозможно. Поэтому я решил создать эту коллекцию и
// обнародовать ее в Инете. Там иногда найти легче, чем
// на своем компьютере :). К тому же, может быть, это
// будет представлять интерес не только для меня.
// Фрагменты снабжены комментариями, поясняющими суть
// решаемой проблемы.
// Здесь надо обратить внимание, каким образом определяется
//символьный эквивалент значения переменной типа enum.
//Основное требование, при котором данный код сработает,
//заключается в том, чтобы этот тип enum был зарегистрирован
//в rtti, т.е. хоть раз был использован в качестве типа для
//опубликованного свойства. В данном случае речь идет о типе
//twindowstate, использовался как тип для published свойства
//windowstate в tform. Надо заметить, что если для получения
//информации о типе использовать tcustomform, функция getpropinfo
//либо выдаст exception (c++builder 5), либо null(c++builder 6),
//т.к. в tcustomform это свойство объявлено лишь как public
//-----------------------------------------------------

void __fastcall tdatawrapper::defineproperties(tfiler* filer)
{

inherited::defineproperties(filer);
//определяем, какие свойства будут сохраняться и функции
//это будут выполнять
filer->defineproperty("formstate",readformstate, writeformstate, true);
}
//-----------------------------------------------------
void __fastcall tdatawrapper::readformstate(treader* reader)
{
tentrypointform* form = (tentrypointform*)owner;
//получение информации о свойстве, имеющего тип twindowstate
typinfo::ptypeinfo ptypeinfo =
*(typinfo::getpropinfo(__typeinfo(tform),"windowstate"))->proptype;
//чтение значения свойства в символьном виде
ansistring strenumvalue = reader->readident();
//перевод символьного вида в значение типа enum
twindowstate state = (twindowstate)getenumvalue(ptypeinfo,strenumvalue);
if(form->settingsclient->fstoredparams.contains(spstate))
form->fwindowstate = state;

}
//------------------------------------------------------
void __fastcall tdatawrapper::writeformstate(twriter* writer)
{

tentrypointform* form = (tentrypointform*)owner;
//получение информации о свойстве, имеющего тип twindowstate
typinfo::ptypeinfo ptypeinfo =
*(typinfo::getpropinfo(__typeinfo(tform),"windowstate"))->proptype;
//запись значения enum в символьном виде
writer->writeident(getenumname(ptypeinfo,form->fwindowstate));
}

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

class tform1 : public tform
{
__published: // ide-managed components
tbutton* button1;
tbutton* button2;
void __fastcall button1click(tobject *sender)
private: // user declarations
public: // user declarations
__fastcall tform1(tcomponent* owner);
};
//-----------------------------------------------------
//через первый параметр будет перадаваться this
void __fastcall globalclick(void* this, tobject *sender)
{
showmessage(ansistring("global:")+
((tcomponent*)this)->name + "->" +
((tcomponent*)sender)->name);
}
//------------------------------------------------------
__fastcall tform1::tform1(tcomponent* owner)
: tform(owner)
{
//присвоить глобальную функцию событию
tmethod method;
method.data = this;
method.code= globalclick;
button2->onclick = *(tnotifyevent*)&method;

//вызвать метод по обычную адресу
tnotifyevent click = &button1click;
tmethod method1 = *(tmethod*)&click;
//через первый скрытый параметр передаем this
typedef void (__fastcall *func)(void*,tobject *);
func func;
func = (func)method1.code;
func(this, button1);

//вызвать опубликованный метод по имени
shortstring procname = "button1click";
tmethod method2;
method2.code = methodaddress(procname);
if (method2.code)
{
method2.data = this;
tnotifyevent click = *(tnotifyevent*)&method2;
click(button1);
}

//получить имя обработчика события
tmethod method3 = *(tmethod*)&(button1->onclick);
shortstring procname1 = methodname(method3.code);
showmessage( procname1);
}
//------------------------------------------------------
void __fastcall tform1::button1click(tobject *sender)
{
showmessage(ansistring("method:") +
this->name + "->" + ((tcomponent*)sender)->name);
}
//------------------------------------------------------


////////////////////////////////////////////////////////
//Пример, как простенькая задача может превратиться в
//головную боль. Требовалось всего на всего подменить
//стандартный caption, который набирается из caption строк,
//входящих в комплексную строку, на свой. Для этого фирма
//devexpress предлагает воспользоваться событием ondrawcaption,
//в котором нужно задать требуемый текст и указать, что
//дальнейшая отработка не требуется

void __fastcall tattrvaluesetframe::inspectordrawcaption(
tdxinspectorrow *sender, tcanvas *acanvas, const trect &arect,
ansistring &atext, tfont *afont, tcolor &acolor, bool &adone)
{
atext = "Мой собственный caption";
adone = true;
}
//Все работает замечательно, пока эта строка не является
//подстрокой. В этом случае справа от caption резервируется
//область под кнопку, отрисовка которой происходит после
//события ondrawcaption. А поскольку установив adone в true,
//мы указали, что дальнейшей отрисовки не требуется, вместо
//кнопки появлялся всякий мусор. Если же установить adone=true,
//кнопка отрисовывалась нормально, но вместо нужного caption
//выводился стандартный. Переписка с devexpress ничего не дала.
//Они предлагали отрисовывать кнопку прямо в этом событии.
//Это приводило довольно к объемному коду, поскольку нужно было
//анализировать нужна кнопка или нет и вид кнопки в зависимости
//от стиля. Мной найден был более простой способ
void __fastcall tattrvaluesetframe::inspectordrawcaption(
tdxinspectorrow *sender, tcanvas *acanvas, const trect &arect,
ansistring &atext, tfont *afont, tcolor &acolor, bool &adone)
{
class tdxinspectoraccess:public dxinspct::tdxinspector
{
public:
__property indent;
};
tdxinspectorcomplexrow* complexrow = dynamic_cast(sender);
if (complexrow)
{
trect textrec = arect;
textrec.left = ((tdxinspectoraccess*)sender->inspector)->indent+1;
acanvas->brush->color = acolor;
acanvas->textrect(textrec, arect.left + 1, textrec.top + 1,
"Мой собственный caption");
//Изюминка здесь. Дальнейшая обработка не прерывается
//Просто стандартный caption будет отрисовываться
//в области с нулевой шириной.
textrec.right = textrec.left;
//А здесь снимаем защиту разработчиков, которые
//запретили изменение arect
const_cast(arect) = textrec;
//и разрешаем дальнейшую отрисовку.
adone = false;
}
//Надо сказать, что компоненты devexpress хороши, когда их
//используешь как есть. Но если требуется что-то неординарное
//возникает куча проблем из-за недостаточной продуманности
//их структуры.

////////////////////////////////////////////////////////
//Решение проблемы, которая возникает как правило
//при использовании пары tform - tdatamodule. Суть проблемы
//состоит в следующем: в приложении динамически создаются
//экземпляр tform1 и tdatamodule1. При этом data contols формы
//ссылаются tdatasource модуля. Если эти ссылки присваивать в
//в дизайне, то при создании вторых экземпляров формы и модуля
//в приложении в рантайме, котролы второго экземпляра формы будут
//ссылаться на tdatasource`s первого экземпляра модуля. Для того,
//что бы перенаправить их на нужный модуль можно использовать
//следующую универсальную функцию, которая должна вызываться или
//после создания формы или непосредственно в конструкторе

void __fastcall tentrypointform::redirect(tcomponent *root, tdatamodule *datamodule)
{

typinfo::ttypekinds supportkinds;
supportkinds << tkclass;
for(int i = 0; i < root->componentcount; ++i)
{
tcomponent* component = root->components[i];
typinfo::tproplist plist;
int npropcount = getproplist((typinfo::ptypeinfo)(component->classinfo()),
supportkinds,((typinfo::pproplist)(&plist)));
for( int j = 0; j < npropcount; j++)
if (__classid(tdatasource) == getobjectpropclass(component, plist[j]->name))
{
tdatasource* source = dynamic_cast
(getobjectprop(component, plist[j], __classid(tdatasource)));
if (source)
{
tdatasource* destination =
dynamic_cast(datamodule->findcomponent(source->name));
if (destination)
setobjectprop(component, plist[j], destination);
}
}
if (component->componentcount)
redirect(component, datamodule);
}
}
//А теперь использование

tdatamodule1* module1 = new tdatamodule(application);
tform1* form1 = new tform1(application);
form1->redirect(form1,module1);


////////////////////////////////////////////////////////
// Ответ на вопрос, заданный на одном из форумов:
//"Как вызвать у компонента tstringgrid защищенный
// виртуальный метод drawcell?". Не вдаваясь в обсуждение
// целесообразности вызова drawcell просто привожу код
// как это можно сделать

void __fastcall tform1::button1click(tobject *sender)
{
class tpublicgrid:public tstringgrid
{
public:
void __fastcall drawcell(int acol, int arow,
const windows::trect &arect, grids::tgriddrawstate astate){}
};
((tpublicgrid*)stringgrid1)->drawcell(1,1, trect(), tgriddrawstate());
}



////////////////////////////////////////////////////////
// Создание компонента по его метаклассу:
// (Из форума rsdn)

tcomponent *createcomponent( tcomponentclass cclass, tcomponent *aowner)
{
typedef tcomponent *( __fastcall *tconstructor)( tcomponentclass, bool, tcomponent *);
tconstructor constructor = ((tconstructor *) cclass)[ vmtcreateobject - 1];
return constructor( cclass, true, aowner);
};

////////////////////////////////////////////////////////
// Динамическое создание action, actionmanager
// и actionmainmenubar и добавление action в actionmanager
// и actionmainmenubar

tactionmanager* actionmanager = new tactionmanager(this);

//создание первого action
taction* action = new taction(this);
action->name = "testaction1";
action->category = "main";
action->onexecute = action1execute;
//добавление в actionmanager
action->actionlist = actionmanager;

//создание второго action
action = new taction(this);
action->name = "testaction2";
action->category = "main";
action->onexecute = action2execute;
//добавление в actionmanager
action->actionlist = actionmanager;


tactionbaritem* baritem = actionmanager->actionbars->add();

//создание actionmainmenubar
tactionmainmenubar* menubar = new tactionmainmenubar(this);
baritem->actionbar = menubar;
menubar->parent = this;

class tproxyactionbar : public tcustomactionbar {
public:
__property items;
using tcustomactionbar::createcontrol;
};

//формируем меню "main" из action, принадлежащих к категории "main"
tactionclientitem* item = ((tproxyactionbar*)menubar)->items->add();
item->caption = "main";
for( int i= 0; i < actionmanager->actioncount; i++)
if ( ((taction*) actionmanager->actions[i])->category == "main" )
item->items->add()->action = actionmanager->actions[i];

((tproxyactionbar*)menubar)->createcontrol(item);

////////////////////////////////////////////////////////
// Исправления, которые необходимо внести в shellctrls.cpp
// для того, чтобы компонент tshelllistview нормально работал
// (см. examplesshellcontrols)
void __fastcall tcustomshelllistview::rootchanged(void)
{
bool stayfresh;
if(fupdating)
return;
fupdating = true;
try
{
stayfresh = fautorefresh;

//autorefresh = false;-ошибка, исправлено на
fautorefresh = false;

synchpaths();
populate();
if(viewstyle == vsreport)
enumcolumns();

//autorefresh = stayfresh;-ошибка, исправлено на
fautorefresh = stayfresh;
}
__finally
{
fupdating = false;
}
}


////////////////////////////////////////////////////////
// Получение интерфейса текущего проекта (tool api)
//

_di_iotaproject __fastcall tpluginmoduleeditor::getproject()
{
_di_iotamoduleservices svc;
borlandideservices->supports(svc);
_di_iotaproject result = 0;
for (int i = 0; i < svc->modulecount; ++i)
{
_di_iotamodule module = svc->modules[i];
_di_iotaprojectgroup group;
if (module->supports(group)) {
result = group->activeproject;
break;
}
return result;
}


////////////////////////////////////////////////////////
// Получение опций текущего проекта (tool api)
//

variant __fastcall tpluginmoduleeditor::getoptions(_di_iotaproject a_project,
const ansistring& a_value)
{
_di_iotaprojectoptions options = a_project->getprojectoptions();
return options->values[a_value];
}

...
//Получение финального пути
ansistring outputdir = getoptions(a_project, "outputdir");
//Получение версии
int majorversion = getoptions(a_project,"majorversion");
int minorversion = getoptions(a_project,"minorversion");
int release = getoptions(a_project,"release");
int build = getoptions(a_project,"build");

Источник:
http://bcdev.narod.ru/

Это интересно:








версия для печатиРаспечатать статью


Вернуться в раздел: Programming / С++


Реклама:
Читать наc на:

Add to Google
Читать в Яндекс.Ленте






Rambler's Top100
© Copyright 1998-2012 Александр Томов. All rights reserved.