Программное изменение обычно используется при инициализации.
Чаще всего требуется, чтобы "программное изменение" не вызывало onChange и что-либо в этом духе. Это просто не нужно, поскольку вы и так знаете, что вот в этот момент времени значение меняется. Посему - срабатывание события отключают. Например, так:
var
OldOnChange: TNotifyEvent;
begin
OldOnChange:=myContol.OnChange;
try
myControl.OnChange:=nil; // вырубили обработчик события
myControl.чего-то-там; // делаем то, что потенциально может вызвать onChange
finally
myControl.OnChange:=OldOnChange; // восстановили его
end;
end;
Если после подобных манипуляций нужно вызвать "штатный" обработчик - в коде можно это сделать, например, так:
OldOnChange(myControl); // и вот здесь, если все-таки требуется что-то различать, стоит использовать, например, Nil в качестве Sender-а
И в самом обработчике уже проверять Sender-а, и в зависимости от него - выполнять нужные действия.