Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 更改VCL组件内容的正确方法_C++_C++builder_Vcl - Fatal编程技术网

C++ 更改VCL组件内容的正确方法

C++ 更改VCL组件内容的正确方法,c++,c++builder,vcl,C++,C++builder,Vcl,当我制作VCL程序时,经常会遇到这样的情况: 我在表单上有许多组件,用户可以随意处理。最常见的是一堆编辑框 当用户手动输入stuff时,这些编辑框的内容需要通过OnChange事件进行验证 在表单的其他地方,有一些组件,用户可以单击这些组件,将一些默认值加载到编辑框中(在TEdit::Text中) 现在我想要的是,每当用户在TEdit::Text中键入内容时,OnChange事件必须处理用户输入。但是当我的程序将TEdit::Text设置为默认值时,这是不必要的,因为这样我就知道该值是正确的

当我制作VCL程序时,经常会遇到这样的情况:

  • 我在表单上有许多组件,用户可以随意处理。最常见的是一堆编辑框
  • 当用户手动输入stuff时,这些编辑框的内容需要通过OnChange事件进行验证
  • 在表单的其他地方,有一些组件,用户可以单击这些组件,将一些默认值加载到编辑框中(在TEdit::Text中)
现在我想要的是,每当用户在TEdit::Text中键入内容时,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";