Назначение событий элементу управления VCL, созданному динамически во время выполнения (2) - PullRequest
0 голосов
/ 23 января 2019

Это относится к Назначение событий элементу управления VCL, создаваемому динамически во время выполнения .

Я использовал приведенный выше / справочный пост, чтобы решить проблему, возникшую у меня с некоторым кодом.Спасибо за предоставленный пример.Я нашел это очень полезным и реализовал «альтернативный» способ, который он предоставил, так как я не смог заставить работать первый способ.

Я использую C ++ Builder 10.x от Embarcadero.Я только что обновился до C ++ Builder 10.3.Это новое обновление теперь выдает предупреждение:

[bcc32c Warning] LogitToMemo.cpp (196): неявное преобразование между указателем на функцию и указателем на объект является расширением Microsoft

Строка, которую он выбрасывает:

Method.Code = &LogLevelComboBoxOnChange;

Я не уверен, как "исправить" это.

Код поддерживает функцию регистрации вполе памятки, где страница для заметки журнала имеет TComboBox для выбора уровня регистрации / подробности.

TComboBox является внешним по отношению к функции регистрации, как и в форме пользователя.Я хочу, чтобы событие TComboBox::OnChange вызывало мою функцию LogLevelComboBoxOnChange, которая регулирует уровень ведения журнала на основе выбранного элемента / записи TComboBox.

Поддерживающий код включает в себя:

Функцияобъявление - TComboBox::OnChange Событие Функция

void __fastcall LogLevelComboBoxOnChange(void *pThis, TObject *Sender);

Объявление функции - Журнал запускается при наличии поля TMemo для входа в систему и TComboBox

int LogStartWithComboBox(TMemo *LogIt_MemoField, TComboBox *AppLogLevelComboBox, int iThreshold, AnsiString &asFieldTitles);

Этофункция, которая назначает функцию OnChange для объекта TComboBox в форме регистрации пользователя.

int LogStartWithComboBox(TMemo *LogIt_MemoField, TComboBox *AppLogLevelComboBox, int iThreshold, AnsiString &asFieldTitles)
{
  static TMethod Method;

  //
  //  Set-Up CombBox and OnChange Event
  //  - Save ComboBox pointer
  //  - Assign List of Log Levels
  //  - Assign/Set-Up OnChange Function
  //
  LogLevelComboBox = AppLogLevelComboBox;

  AppLogLevelComboBox->Items->Text =
    "Off\n"
    "All Messages\n"
    "Verbose\n"
    "Trace\n"
    "Informational\n"
    "Warning\n"
    "Error\n"
    "Severe\n"
    "Fatal";

  AppLogLevelComboBox->ItemIndex = iThreshold + 1;

  //
  //  Set-Up - On Change Function for "external" Log Level Combo-Box
  //
  Method.Data = NULL; // passed to the pThis parameter, can be whatever you want

  // 
  //  The Following line generates the warning
  //    [bcc32c Warning] LogitToMemo.cpp(196): implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension
  //
  Method.Code = &LogLevelComboBoxOnChange;

  LogLevelComboBox->OnChange = reinterpret_cast<TNotifyEvent&>(Method);

  return 0;
}

1 Ответ

0 голосов
/ 23 января 2019

Вы используете компилятор C ++, основанный на Cang Builder. Предупреждение о «неявном преобразовании», которое вы видите, является проблемой CLang, которая возникла в течение последних нескольких лет в нескольких цепочках инструментов, использующих CLang, а не только в C ++ Builder. Эта проблема не затрагивает «классический» (не CLang) компилятор C ++ Builder.

&LogLevelComboBoxOnChange создает указатель на функцию, которую CLang не любит неявно преобразовывать в void* (то есть, как объявляется поле TMethod::Code), если только Clang не переведен в режим совместимости Microsoft.

Возможные решения:

  • введите указатель в явном виде:

    ( ОБНОВЛЕНИЕ: очевидно CLang не любит static_cast ing указатель на функцию void*, тоже!)
    Method.Code = static_cast (& LogLevelComboBoxOnChange);

    Method.Code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&LogLevelComboBoxOnChange));
    
  • включить флаг -Wmicrosoft-cast в настройках компилятора CLang.

  • отключите предупреждение в своем коде, используя #pragma операторы вокруг присваивания Method.Code:

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wmicrosoft-cast"
    
    Method.Code = &LogLevelComboBoxOnChange;
    
    #pragma clang diagnostic pop
    
  • используйте union (хотя, я уверен, некоторые люди будут утверждать, что это, вероятно, нарушает правила строгого алиасинга, но если это работает ...):

    union {
        void (__fastcall *func)(void*, TObject*);
        void *ptr;
    } u;
    u.func = &LogLevelComboBoxOnChange;
    Method.Code = u.ptr;
    
...