Proper way to change contents of a VCL component
c++, c++builder, vcl
Solution
You could simply unassign the `OnChange` event handler temporarily:
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;
}
}
SetControlTextNoChange(myedit, "Default");
Alternatively, RAII is good for this kind of thing:
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";
Problem
Quite often when I make VCL programs, I run into a scenario like this: - I have a number of components on the form, that the users are allowed to fiddle with. Most commonly a bunch of edit boxes. - The contents of these edit boxes need to be verified by the OnChange event when the user types in stuff manually. - Somewhere else on the form, there's some component that the user can click on to get some default values loaded into the edit boxes (in TEdit::Text). Now what I want is that whenever the user is typing something in the TEdit::Text, the OnChange event must process the user input. But when my program is setting the TEdit::Text to a default value, this isn't necessary, because then I know that the value is correct. Unfortunately, writing code like `myedit->Text = "Default";` triggers the OnChange event. I tend to solve this with what I think is a rather ugly approach: by creating a bool variable `is_user_input`, which `TEdit::OnChange` checks. If it is true, the TEdit::Text will get validated, otherwise it will get ignored. But of course, this doesn't prevent the program from launching `TEdit::OnChange` when it is unnecessary. Is there a better or cleaner way to achieve this? Is there a way for OnChange to check who called it? Or I suppose, a way of disabling the OnChange event temporarily would be even better. `TEdit::Enabled` doesn't seem to affect whether `OnChange` gets triggered or not.