将事件分配给在运行时动态创建的VCL控件(2)

时间:2019-01-23 15:36:08

标签: c++builder vcl

这与Assigning events to a VCL control created dynamically at runtime有关。

我使用上面列出的/参考文章解决了一些代码存在的问题。感谢您提供该示例。我发现它非常有用,并实现了它提供的“替代”方式,因为我无法使第一种方式起作用。

我正在使用Embarcadero的C ++ Builder10.x。我刚刚更新到C ++ Builder 10.3。现在,此新更新引发警告:

  

[bcc32c警告] 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 :(得分:0)

您正在使用C ++ Builder基于CLang的C ++编译器。您看到的“隐式转换”警告是一个CLang问题,该问题在过去几年中出现在使用CLang的多个工具链中,而不仅仅是在C ++ Builder中。此问题不会影响C ++ Builder的“经典”(非CLang)编译器。

&LogLevelComboBoxOnChange创建一个指向函数的指针,除非将Clang放入Clang中,否则CLang不希望将其隐式转换为void*(这是TMethod::Code字段的声明)。 Microsoft兼容模式。

可能的解决方案之一是:

  • 显式类型化指针:

    更新:显然是doesn't like static_casting指向void*的函数指针!)
    Method.Code = static_cast (&LogLevelComboBoxOnChange);

    Method.Code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&LogLevelComboBoxOnChange));
    
  • 在CLang编译器设置中启用-Wmicrosoft-cast标志。

  • 通过在分配给#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;