将事件分配给在运行时动态创建的VCL控件(2) [英] Assigning events to a VCL control created dynamically at runtime (2)

查看:77
本文介绍了将事件分配给在运行时动态创建的VCL控件(2)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这与将事件分配给在运行时动态创建的VCL控件

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

I used the above listed/reference post to solve a problem that I had with some code. Thank you for providing that example. I found it very useful, and implemented the "alternative" way that it provided as I was unable to make the first way work.

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

I am using C++Builder 10.x from Embarcadero. I just updated to C++Builder 10.3. This new update is now throwing a warning:


[bcc32c警告] LogitToMemo.cpp(196):指针到函数之间的隐式转换并且指向对象的指针是Microsoft扩展

[bcc32c Warning] LogitToMemo.cpp(196): implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension

它所抛出的行是:

Method.Code = &LogLevelComboBoxOnChange;

我不确定如何修复此问题。

I am not sure how to "fix" this.

该代码支持备忘录字段的日志记录功能,其中日志记录备忘录的页面具有 TComboBox 以选择日志记录级别/详细程度。

The code is in support of a logging function to a memo field, where the page for the logging memo has a TComboBox to select the logging level/verbosity.

TComboBox 在记录功能的外部,就像在用户窗体上一样。我希望 TComboBox :: OnChange 事件调用我的 LogLevelComboBoxOnChange 函数,该函数根据<$调整日志记录级别c $ c> TComboBox 项目/条目。

The TComboBox is external to the logging function, as it is on the user's form. I want the TComboBox::OnChange event to call my LogLevelComboBoxOnChange function, which adjusts the logging level based on the TComboBox item/entry selected.

与此相关的支持代码。

函数声明- TComboBox :: OnChange 事件函数

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

功能声明-在 TMemo 字段以登录到&提供了 TComboBox

Function Declaration - Logging start up where the TMemo field to log to & the TComboBox are provided

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

这是分配 OnChange 的函数函数到用户日志表单上的 TComboBox 对象。

This is the function that assigns the OnChange function to the TComboBox object on the user's logging form.

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;
}


推荐答案

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

You are using C++Builder's CLang-based C++ compiler. The "implicit conversion" warning you are seeing is a CLang issue that has cropped up during the past few years in multiple toolchains that use CLang, not just in C++Builder. This issue does not affect C++Builder's "classic" (non-CLang) compiler.

& LogLevelComboBoxOnChange 创建一个函数指针,CLang不希望将其隐式转换为 void * (这是 TMethod :: Code 字段将声明为。

&LogLevelComboBoxOnChange creates a pointer-to-function, which CLang does not like to implicitly convert to void* (which is what the TMethod::Code field is declared as) unless Clang is put into a Microsoft compatibility mode.

可能的解决方案是:


  • 明确地类型化指针:

  • type-cast the pointer explicitly:

更新:显然是CLang <一个href = https://clang.llvm.org/docs/DiagnosticsReference.html#wmicrosoft-cast rel = nofollow noreferrer>不喜欢 static_cast ing 指向 void * 的函数指针!)

Method.Code = static_cast< void *>( & LogLevelComboBoxOnChange);

(UPDATE: apparently CLang doesn't like static_casting a pointer-to-function to void*, either!)
Method.Code = static_cast<void*>(&LogLevelComboBoxOnChange);

Method.Code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(&LogLevelComboBoxOnChange));


  • 启用 -Microsoft-cast 在CLang编译器设置中标记。

  • enable the -Wmicrosoft-cast flag in the CLang compiler settings.

    通过使用 #pragma 语句在代码中禁用警告围绕对 Method.Code 的赋值:

    disable the warning in your code by using #pragma statements around the assignment to Method.Code:

    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wmicrosoft-cast"
    
    Method.Code = &LogLevelComboBoxOnChange;
    
    #pragma clang diagnostic pop
    


  • 使用 union (不过,我敢肯定有些人会说这可能违反了严格的别名规则,但如果可行的话...):

  • use a union (though, I'm sure some people will argue that this probably violates Strict Aliasing rules, but if it works...):

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


  • 这篇关于将事件分配给在运行时动态创建的VCL控件(2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆