A: One solution would be to do nothing in the OnChange event handler unless ActiveControl is equal to the control that is calling the event handler.
procedure TForm1.Edit2Change(Sender: TObject);
begin
if ActiveControl = Edit2 then
Edit1.Text := IntToHex(StrToInt(Edit2.Text),0);
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
if ActiveControl = Edit1 then
Edit2.Text := IntToStr(StrToInt('$'+Edit1.Text));
end;
Options: Instead of OnChange. Use OnKeyDown. This way 1 Keydown
equates to 1 loop as you intend.