将事件分配给在运行时动态创建的VCL控件(2) [英] Assigning events to a VCL control created dynamically at runtime (2)
问题描述
我使用了上面列出的/参考文章来解决我的一些代码问题。感谢您提供该示例。我发现它非常有用,并实现了它提供的替代方式,因为我无法使第一种方式起作用。
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 $除非将Clang设置为Microsoft兼容模式,否则c $ c>字段将声明为。
&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_cast
ing 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屋!