C++ 更改VCL组件内容的正确方法
当我制作VCL程序时,经常会遇到这样的情况:C++ 更改VCL组件内容的正确方法,c++,c++builder,vcl,C++,C++builder,Vcl,当我制作VCL程序时,经常会遇到这样的情况: 我在表单上有许多组件,用户可以随意处理。最常见的是一堆编辑框 当用户手动输入stuff时,这些编辑框的内容需要通过OnChange事件进行验证 在表单的其他地方,有一些组件,用户可以单击这些组件,将一些默认值加载到编辑框中(在TEdit::Text中) 现在我想要的是,每当用户在TEdit::Text中键入内容时,OnChange事件必须处理用户输入。但是当我的程序将TEdit::Text设置为默认值时,这是不必要的,因为这样我就知道该值是正确的
- 我在表单上有许多组件,用户可以随意处理。最常见的是一堆编辑框
- 当用户手动输入stuff时,这些编辑框的内容需要通过OnChange事件进行验证
- 在表单的其他地方,有一些组件,用户可以单击这些组件,将一些默认值加载到编辑框中(在TEdit::Text中)
myedit->Text=“Default”这样编写代码代码>触发OnChange事件
我倾向于用一种我认为相当难看的方法来解决这个问题:通过创建bool变量is\u user\u input
,该变量TEdit::OnChange
检查。如果为true,则TEdit::文本将得到验证,否则将被忽略。但当然,这并不妨碍程序在不必要时启动TEdit::OnChange
有没有更好或更干净的方法来实现这一点
有没有办法让OnChange检查是谁打电话的?或者我想,暂时禁用OnChange事件的方法会更好TEdit::Enabled
似乎不会影响是否触发OnChange
。您只需暂时取消分配OnChange
事件处理程序:
template <typename T>
void SetControlTextNoChange(T *Control, const String &S)
{
TNotifyEvent event = Control->OnChange;
Control->OnChange = NULL;
try {
Control->Text = S;
}
__finally {
Control->OnChange = event;
}
}
或者,RAII对这类事情有好处:
template <typename T>
class DisableChangeEvent
{
private:
T *m_control;
TNotifyEvent m_event;
public:
DisableChangeEvent(T *control);
{
m_control = control;
m_event = control->OnChange;
control->OnChange = NULL;
}
~DisableChangeEvent();
{
m_control->OnChange = m_event;
}
T* operator->() { return m_control; }
};
有没有办法让OnChange检查是谁打电话的
通常,事件有一个参数Sender,您可以在事件函数中检查(Sender==ButtonSetDefaults)。不确定如果按钮触发OnChange事件并且现在无法测试它,会发生什么
另外,除了定时问题之外,我还没有看到全局变量的问题,但是您也可以遇到禁用事件的情况。
您是否认为验证也适用于您的默认值?如果您决定在某一点更改默认值,并且错误地将其设置在合法范围之外,该怎么办?@barakmanos通常是这样。但通常情况下,多个组件与同一组私有变量相关。因此,我让所有组件从各自的OnChange调用相同的“change”setter函数。现在假设我也想在内部更改这个变量,那么我必须更新所有组件以反映更改。如果我这样做了,他们会自动触发OnChange并一次又一次地启动“change”功能。因此,有了这样的设计,我最终会遇到奇怪的循环依赖。再加上毫无意义的执行延迟。谢谢,这是好东西。我假设RAII版本将被称为disasblechangevent(myedit)->Text=“Default”代码>?也是,代码>最后,<代码>一个C++ Builder扩展名,还是C++ 11?还是什么?我省略了<代码> <代码>部分,因为编译器应该能够根据所传递的参数来推断它的值,但是,也可以显式指定它。最后,
是一个C++Builder编译器扩展。是的,但是当我键入myedit->Text=“hello”时,谁将是发送者代码>在我的程序和OnChange触发器中的某个地方?那么,发送者将始终是它的父表单吗?我怎么能用它来知道是用户还是程序触发了这个功能?这就是我不确定的意思,因为我这里没有运行的Borland,但也许你可以试试。禁用事件时,当control->OnChange=NULL时触发另一个事件时,您可能会遇到问题;使用互斥锁可能会有所帮助。我做了一个实验,它确实似乎总是编辑框。此外,我不相信您会遇到您描述的那种问题,因为GUI中的所有事件通常都是从单个线程执行的。IIrc,您可能会遇到类似的问题,但它们与Windows消息队列相关。类似于。。。如果您执行了导致SendMessage而不是PostMessage的操作,则可能会在另一个事件仍在运行时触发一个事件。我不记得构建器内部如何工作的细节了。好吧,除非有一个函数SetText(Sender,undestring),否则我看不到一种方法来解决这个问题。谢谢你的努力,也很抱歉浪费了你的时间!
template <typename T>
class DisableChangeEvent
{
private:
T *m_control;
TNotifyEvent m_event;
public:
DisableChangeEvent(T *control);
{
m_control = control;
m_event = control->OnChange;
control->OnChange = NULL;
}
~DisableChangeEvent();
{
m_control->OnChange = m_event;
}
T* operator->() { return m_control; }
};
DisableChangeEvent(myedit)->Text = "Default";