Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вызов функций из другого модуля 
:(
    Опции темы
Mal Hack
Дата 5.8.2005, 21:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: нет
Всего: 261



В делфи такое делал, но описывая класс во втором модуле.
Задача такова.
Есть модуль с формой.
Хочу сделать отдельный модуль, который программными средствами будет создават кнопочки и т.п. на первой форме.
Все описал. Модуль вот так:
Код
//---------------------------------------------------------------------------
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
#pragma package(smart_init)

TButton  *BBCode[26];
char BBCodeNames[26];

void __fastcall BBCode_Create()
{
 BBCodeNames[ 0 ] = 'B';
 BBCodeNames[ 1 ] = 'I';
 BBCodeNames[ 2 ] = 'U';
 BBCodeNames[ 3 ] = 'URL';
 BBCodeNames[ 4 ] = 'IMG';

 int i;

 for( i = 0 ; i < 4 ; i++ )
  {
   BBCode[ i ] = new TButton( Form1 -> BBCodePanel );

   BBCode[ i ] -> Caption = BBCodeNames[ i ];
   BBCode[ i ] -> Width = 70;
   BBCode[ i ] -> Top = 10;
   BBCode[ i ] -> Left = 10 + ( BBCode[ i ] -> Width * i );
  }
}

//---------------------------------------------------------------------------



модуль с формное начинается так:
Код
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"


#include "Unit2.h"
TForm1 *Form1;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
// *************

}

Вот на месте ************ хочу вызвать BBCode_Create из второго модуля. Можно ли это как-ть сделать не описывая класса и не создавая объекта с нужной функцией?

Задача по русски: хочу вынести генерацию элементов интерфейса в отдельный файл, оставив на файле с формой только рабочий код, основной опять же.
PM ICQ   Вверх
Vitalik
Дата 5.8.2005, 23:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Координатор проекта
Сообщений: 653
Регистрация: 8.11.2004
Где: Ukraine, Kharkov

Репутация: 2
Всего: 12



Может добавить объявление функции в h-файл?..
Или во втором файле написать: "#include "Unit1.cpp"?
А также можно объявление формы в h-файл засунуть smile

P.S. Билдер очень давно не юзал, поэтому могу ошибаться smile Это просто мини мозговой штурм smile
PM MAIL WWW ICQ YIM   Вверх
Vitalik
Дата 5.8.2005, 23:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Координатор проекта
Сообщений: 653
Регистрация: 8.11.2004
Где: Ukraine, Kharkov

Репутация: 2
Всего: 12



Да... Чтобы не было пустых слов - сейчас проверил.
Всё работает smile

1). Файл Unit1.cpp
На форме находится панель с именем BBCodePanel.
Код
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)

  BBCode_Create();
}
//---------------------------------------------------------------------------


2). Файл Unit2.cpp:
Только добавил задание свойства Parent. Но это обязательно !
Код
//---------------------------------------------------------------------------
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

TButton  *BBCode[26];
char BBCodeNames[26];
void __fastcall BBCode_Create()
{
 BBCodeNames[ 0 ] = 'B';
 BBCodeNames[ 1 ] = 'I';
 BBCodeNames[ 2 ] = 'U';
 BBCodeNames[ 3 ] = 'URL';
 BBCodeNames[ 4 ] = 'IMG';
 int i;
 for( i = 0 ; i < 4 ; i++ )
  {
   BBCode[ i ] = new TButton( Form1 -> BBCodePanel );
   BBCode[ i ] -> Parent = Form1 -> BBCodePanel; // Добавил эту строку ;-)
   BBCode[ i ] -> Caption = BBCodeNames[ i ];
   BBCode[ i ] -> Width = 70;
   BBCode[ i ] -> Top = 10;
   BBCode[ i ] -> Left = 10 + ( BBCode[ i ] -> Width * i );
  }
}


3). файл Unit2.h:
Просто добавил объявление нашей функции, чтобы Unit1.cpp её видел smile
Код
//---------------------------------------------------------------------------
#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
void __fastcall BBCode_Create();
#endif


Всё готово --Resize_Images_Alt_Text--
Удачи!
PM MAIL WWW ICQ YIM   Вверх
Mal Hack
Дата 6.8.2005, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: нет
Всего: 261



Vitalik а указание тут:
Код
 BBCode[ i ] = new TButton( Form1 -> BBCodePanel );

родителя не достаточно?
Хотя в Делфи всегда Parent писал smile

Ща буду тестить, но заранее огромное спасибо. Ты меня еще первым постом навел на мою ошибку.
Добавлено @ 00:11
Vitalik огромное спасибо, разобрался.
Вот еще два вопросика из этой темы smile
1. Можно лим обойтись для второго модуля наличием только .cpp файла, или обязательно наличие .h?
2. __fastcall чем отличается от обычной функции.

ЗЫ: Есть книжка Архангельского, но толи я не внимательно смотрел, толи там нет этой информации. Может есть сслки под рукой?


PM ICQ   Вверх
Vitalik
Дата 6.8.2005, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Координатор проекта
Сообщений: 653
Регистрация: 8.11.2004
Где: Ukraine, Kharkov

Репутация: 2
Всего: 12



Цитата(Mal @ 6.8.2005, 00:05)
родителя не достаточно?

При создании vcl-компонента в качестве параметра указывается не родитель, а владелец (Owner).
Чтобы новые кнопочки отобразились на форме нужно обязательно самому задать их родителя (Parent) smile

Цитата(Mal @ 6.8.2005, 00:05)
1. Можно лим обойтись для второго модуля наличием только .cpp файла, или обязательно наличие .h?

Теоретически можно smile В данном случае это действительно будет удобнее smile
Но я попробовал и у меня сразу AV выскочил при обращении к форме... smile

Цитата(Mal @ 6.8.2005, 00:05)
2. __fastcall чем отличается от обычной функции.

Та сильно так ничем и не отличается. Только способом передачи параметром (на "низком" уровне). Для функций-обработчиков событий этот сопособ вроде бы как считается быстрее, но это реально мизер smile
Это в основном нужно при написании своих dll-ек. То есть там действительно нужно одинаково задать способ передачи параметров...
PM MAIL WWW ICQ YIM   Вверх
Mal Hack
Дата 6.8.2005, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: нет
Всего: 261



Цитата(Vitalik @ 6.8.2005, 10:55)
При создании vcl-компонента в качестве параметра указывается не родитель, а владелец (Owner).

Ах вот оно что... А смысл указания Owner'a тогда?

Тут ночью еще два вопроса появилолсь.
1. Есть ли в Си аналог with obj do... как в Делфи? Ман и Архангельский ответа не дали.
2. Как поставить на кнопку свой обработчик OnClick?
пишу:
Код
   BBCode[ i ] = new TButton( BBCodePanel );

   BBCode[ i ] -> Parent = BBCodePanel;
   BBCode[ i ] -> Tag = i;
   BBCode[ i ] -> Caption = BBCodeNames[ i ];
// хотел было написать как в Delphi:
   BBCode[ i ] -> OnClick = MyFnc;

// Объявив: 
void __fastcall BBCode_InputMemo(TObject *Sender)


Получаю сообщение:
Код
[C++ Error] Unit2.cpp(61): E2034 Cannot convert 'void (_fastcall *)(TObject *)' to 'void (_fastcall * (_closure )(TObject *))(TObject *)'


И еще один smile
Создаю PageControl и Tab'ы - все замечательно.
Код
 BBCodePages = new TPageControl( EditorPanel );
 BBCodePages -> Parent = EditorPanel;
 BBCodePages -> Name = "BBCodePages";

 BBCodeTabs[0] = new TTabSheet( BBCodePages );
 BBCodeTabs[0] -> Parent  = BBCodePages;
 BBCodeTabs[0] -> Caption = "WISWIG ðåäàêòèðîâàíèå";

 BBCodeTabs[1] = new TTabSheet( BBCodePages );
 BBCodeTabs[1] -> Parent  = BBCodePages;
 BBCodeTabs[1] -> Caption = "BB-code ðåäàêòèðîâàíèå";

но табы не видны, хотя Parent я указал. Чую, что надо какое-то свойство включить на PageControl'e...

PM ICQ   Вверх
Vitalik
Дата 6.8.2005, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Координатор проекта
Сообщений: 653
Регистрация: 8.11.2004
Где: Ukraine, Kharkov

Репутация: 2
Всего: 12



Цитата(Mal @ 6.8.2005, 12:53)
Ах вот оно что... А смысл указания Owner'a тогда?

Справка пишет: "Owner property indicates the component that is responsible for streaming and freeing this component." smile

Цитата(Mal @ 6.8.2005, 12:53)
1. Есть ли в Си аналог with obj do... как в Делфи? Ман и Архангельский ответа не дали.

Аналога действительно нету smile

Цитата(Mal @ 6.8.2005, 12:53)
2. Как поставить на кнопку свой обработчик OnClick?

Дело в том, что функция-обработчик должна быть методом класса TForm1:
Код
//Файл Unit1.h:
...
class TForm1 : public TForm
{
  ...
  public:
    ...
    void __fastcall MyOnClick(TObject *Sender);
    ...
};
...

//Файл Unit1.cpp:
...
void __fastcall TForm1::MyOnClick(TObject *Sender)
{
  ShowMessage("Hello!");
}
...
{
  ...
  BBCode[ i ] -> OnClick = MyOnClick;
  ...
}
...


Цитата(Mal @ 6.8.2005, 12:53)
Создаю PageControl и Tab'ы - все замечательно.
но табы не видны, хотя Parent я указал. Чую, что надо какое-то свойство включить на PageControl'e...

Всё гораздо проще smile
Нужно просто для вкладок задать свойство PageСontrol:
Код
BBCodeTabs[0] -> PageControl = BBCodePages;


И еще будет одно замечание smile
Так писать нельзя:
Код
 BBCodeNames[ 3 ] = 'URL';    
 BBCodeNames[ 4 ] = 'IMG';
Нужно так:
Код
 BBCodeNames[ 3 ] = "URL";    
 BBCodeNames[ 4 ] = "IMG";
Так как в одинарных кавычках пишется одиночный символ, а в двойных - строка smile

PM MAIL WWW ICQ YIM   Вверх
Mal Hack
Дата 6.8.2005, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: нет
Всего: 261



Цитата(Vitalik @ 6.8.2005, 16:09)
Дело в том, что функция-обработчик должна быть методом класса TForm1:

Даже не смотря на то, что кнопку я сам создаю, как-то не очень удобно получается. Может есть возможность обойти каким-ть образом, т.е. перехватить клик на кнопке?

Цитата(Vitalik @ 6.8.2005, 16:09)
Нужно просто для вкладок задать свойство PageСontrol:

smile


Цитата(Vitalik @ 6.8.2005, 16:09)
Так как в одинарных кавычках пишется одиночный символ, а в двойных - строка

smile

Спасибо еще раз... Моя благодарность не знает границ smile
Добавлено @ 16:44
Цитата(Vitalik @ 6.8.2005, 16:09)
Так как в одинарных кавычках пишется одиночный символ, а в двойных - строка smile

А как тогда правильно объявить?
Пишу char *BBCodeNames[26][6]; - пишет: [C++ Error] Unit2.cpp(50): E2277 Lvalue required
PM ICQ   Вверх
Vitalik
Дата 6.8.2005, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Координатор проекта
Сообщений: 653
Регистрация: 8.11.2004
Где: Ukraine, Kharkov

Репутация: 2
Всего: 12



Цитата(Mal @ 6.8.2005, 16:42)
Даже не смотря на то, что кнопку я сам создаю, как-то не очень удобно получается. Может есть возможность обойти каким-ть образом, т.е. перехватить клик на кнопке?

Как-то должно быть можно, но сейчас уже поздно, так что быстро не соображу...
Утро вечера мудренее smile

Цитата(Mal @ 6.8.2005, 16:42)
А как тогда правильно объявить?
Пишу char *BBCodeNames[26][6]; - пишет: [C++ Error] Unit2.cpp(50): E2277 Lvalue required

Это что еще такое? smile
Если написать просто:
Код
char *BBCodeNames[26][6];
то всё нормально...
Покажи ка весь участок кода smile

PM MAIL WWW ICQ YIM   Вверх
Mal Hack
Дата 6.8.2005, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: нет
Всего: 261



Цитата(Vitalik @ 6.8.2005, 22:57)
то всё нормально...
Покажи ка весь участок кода smile


Цитата(Vitalik @ 6.8.2005, 22:57)
Это что еще такое? smile
Если написать просто:

Вот на этом и выдавал. Я решил проблемы так: AnsiString BBCodeNames[6];

Цитата(Vitalik @ 6.8.2005, 22:57)
Как-то должно быть можно, но сейчас уже поздно, так что быстро не соображу...
Утро вечера мудренее smile

Буду очень благодарен, если подскажешь. Главное не код, направь куда нужно smile
PM ICQ   Вверх
Vitalik
Дата 8.8.2005, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Координатор проекта
Сообщений: 653
Регистрация: 8.11.2004
Где: Ukraine, Kharkov

Репутация: 2
Всего: 12



Цитата(Mal @ 6.8.2005, 22:03)
Вот на этом и выдавал. Я решил проблемы так: AnsiString BBCodeNames[6];

Хороший вариант smile

Цитата(Mal @ 6.8.2005, 22:03)
Буду очень благодарен, если подскажешь. Главное не код, направь куда нужно

Хм... Пытался вчера сделать что-нить по этому поводу, но так и не получилось.
Единственно могу направить: твоя ф-ция должна быть типа TNotifyEvent, а также к ней (или её адресу) возможно нужно как-то прикрутить __closure. В справке по этому __closure написано много всякой всячины, но я так особо и не понял, что там к чему...
Там есть примеры кода, но они хотя и не по теме, но направить могут.

Цитата(__closure)
__closure

Category
C++Builder keyword extensions

Syntax
<type> ( __closure * <id> ) (<param list>);

Description
The keyword __closure was added to support the VCL and is used when declaring event handler functions. For more information, see the keyword extensions.

Цитата(keyword)
...
__closure

The __closure keyword is used to declare a special type of pointer to a member function. In standard C++, the only way to get a pointer to a member function is to use the fully qualified member name, as shown in the following example:

class base
{
  public:
    void func(int x) { };
};
typedef void (base::* pBaseMember)(int);
int main(int argc, char* argv[])
{
  base        baseObject;
  pBaseMember m = &base::func; // Get pointer to member 'func'
  // Call 'func' through the pointer to member
  (baseObject.*m)(17);
  return 0;
}

However, you cannot assign a pointer to a member of a derived class to a pointer to a member of a base class. This rule (called contravariance) is illustrated in the following example:

class derived: public base
{
  public:
    void new_func(int i) { };
};
int main(int argc, char* argv[])
{
  derived        derivedObject;
  pBaseMember m = &derived::new_func; // ILLEGAL
  return 0;
}

The __closure keyword extension allows you to skirt this limitation, and more. Using a closure, you can get a pointer to member function for an object (i.e. a particular instance of a class). The object can be any object, regardless of its inheritance hierarchy. The object’s this pointer is automatically used when calling the member function through the closure. The following example shows how to declare and use a closure. The base and derived classes provided earlier are assumed to be defined.

int main(int argc, char* argv[])
{
  derived        derivedObject;
  void (__closure *derivedClosure)(int);
    derivedClosure = derivedObject.new_func; // Get a pointer to the 'new_func' member.
                                              // Note the closure is associated with the
                                              // particular object, 'derivedObject'.
    derivedClosure(3);  // Call 'new_func' through the closure.
    return 0;
}

Closures also work with pointers to objects, as illustrated in this example:

void func1(base *pObj)
{
  // A closure taking an int argument and returning void.
  void ( __closure *myClosure )(int);

  // Initialize the closure.

  myClosure = pObj->func;

  // Use the closure to call the member function.

  myClosure(1);
  return;
}

int main(int argc, char* argv[])
{
  derived        derivedObject;
  void (__closure *derivedClosure)(int);
    derivedClosure = derivedObject.new_func; // Same as before...
    derivedClosure(3); 
    // We can use pointers to initialize a closure, too.
    // We can also get a pointer to the 'func' member function
    // in the base class.
    func1(&derivedObject);
    return 0;
}

Notice that we are passing a pointer to an instance of the derived class, and we are using it to get a pointer to a member function in the base class - something standard C++ does not allow us to do.
Closures are a key part of the C++ Builder RAD environment. They give us the ability to assign an event handler in the Object Inspector. For example, a TButton object has an event called OnClick. In the TButton class, the OnClick event is a property that uses the __closure keyword extension in its declaration. The __closure keyword allows us to assign a member function of another class (typically a member function in a TForm object) to the property. When you place a TButton object on a form, and then create a handler for the button’s OnClick event, C++ Builder creates a member function in the button’s TForm parent, and assigns that member function to the OnClick event of TButton. This way, the event handler is associated with that particular instance of TButton, and no other.

For more information about events and closures, see Creating events
...

PM MAIL WWW ICQ YIM   Вверх
Mal Hack
Дата 8.8.2005, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Мудрый...
****


Профиль
Группа: Участник Клуба
Сообщений: 9926
Регистрация: 15.2.2004

Репутация: нет
Всего: 261



Че-то ничего не выходит... лан, будем думать... Спасибо в любом случае.
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.1208 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.