The sample project below does what you seem to want.
Update The code below replaces the code I originally posted and avoids the use
of a dataset type (TClientDataSet) which supports fkInternalCalc fields.  It will
work with a TAdoQuery.
Although there is no difficulty in principle in parsing a string field into two subfields
and surfacing them in your gui for editing, the problem with straightforward ways of doing this with
a TAdoQuery is that it only supports fkCalculated calculated fields and db-aware gui controls
treat these as not modifiable by the user.
I'm not sure why this restriction exists, but I imagine that it is related to the fact that
Delphi's db-aware controls were originally developed for the BDE (and in aby case before
fkInternalCalc was added to support TClientDataSet).  The code in DB.Pas which enforces
the restriction is in DB.Pas:
function TField.GetCanModify: Boolean;
begin
  if FieldNo > 0 then
    if DataSet.State <> dsSetKey then
      Result := not ReadOnly and DataSet.CanModify else
      Result := IsIndexField
  else
    Result := False;
end;
The code below works by adding an interposer class for TStringField which
removes the restriction for stringfields whose FieldKind is fkCalculated
which are not ReadOnly and belong to a dataset which is modifiable
(though this latter restriction could be removed, I think).  The
interposer TStringField overrides GetCanModify like so:
function TStringField.GetCanModify: Boolean;
begin
  if (FieldKind = fkCalculated) and DataSet.CanModify and not ReadOnly then
    Result := True
  else
  if DataSet.State <> dsSetKey then
    Result := not ReadOnly and DataSet.CanModify else
    Result := IsIndexField
end;
The full code of an example project is below.  Note that I've used regular
TDBEdits because I have a problem with my current Devex set-up but the code should
work fine with TcxDBEdit as well.
Code:
type
  TStringField = class(db.TStringField)
  protected
    function GetCanModify : Boolean; override;
  end;
type
  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    DataSource1: TDataSource;
    DBEdit1: TDBEdit;
    DBEdit2: TDBEdit;
    ADOQuery1: TADOQuery;
    cxDBMaskEdit1: TcxDBMaskEdit;
    DBEdit3: TDBEdit;
    btnDataLinks: TButton;
    ADOConnection1: TADOConnection;
    ADOQuery1ID: TIntegerField;
    ADOQuery1Field1: TWideStringField;
    ADOQuery1Field2: TWideStringField;
    ADOQuery1SubField1: TStringField;
    ADOQuery1SubField2: TStringField;
    procedure FormCreate(Sender: TObject);
    procedure ADOQuery1BeforePost(DataSet: TDataSet);
    procedure ADOQuery1CalcFields(DataSet: TDataSet);
  private
    procedure UpdateSubFields(DataSet : TDataSet);
    procedure UpdateField1(DataSet: TDataSet);
  end;
[...]
const
  scSeparator = '#4';   // could be a literal #4 instead
procedure TForm1.UpdateField1(DataSet : TDataSet);
var
  S : String;
begin
  if DataSet.FieldByName('SubField1').IsNull or DataSet.FieldByName('SubField2').IsNull then exit;
  S := DataSet.FieldByName('SubField1').AsString + scSeparator +
    DataSet.FieldByName('SubField2').AsString;
  S := Trim(S);
  if Length(S) > DataSet.FieldByName('Field1').Size then
    raise exception.Create('tthe combined size of the subfields is too long');
  DataSet.FieldByName('Field1').AsString := S;
end;
procedure TForm1.UpdateSubFields(DataSet : TDataSet);
var
  S,
  SF1,
  SF2 : String;
  P,
  SF2Start : Integer;
begin
  S := DataSet.FieldByName('Field1').AsString;
  P := Pos(scSeparator, S);
  SF1 := Copy(S, 1, P-1);
  SF1 := Trim(SF1);
  SF2Start :=  P + Length(scSeparator);
  SF2 := Copy(S, Sf2Start, Length(S));
  SF2 := Trim(SF2);
  DataSet.FieldByName('SubField1').AsString := SF1;
  DataSet.FieldByName('SubField2').AsString := SF2;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  AdoQuery1.Open;
end;
procedure TForm1.CDS1CalcFields(DataSet: TDataSet);
begin
  UpdateSubFields(DataSet);
end;
function TStringField.GetCanModify: Boolean;
begin
  if (FieldKind = fkCalculated) and DataSet.CanModify and not ReadOnly then
    Result := True
  else
  if DataSet.State <> dsSetKey then
    Result := not ReadOnly and DataSet.CanModify else
    Result := IsIndexField
end;
procedure TForm1.ADOQuery1BeforePost(DataSet: TDataSet);
begin
  UpdateField1(AdoQuery1);
end;
procedure TForm1.ADOQuery1CalcFields(DataSet: TDataSet);
begin
  UpdateSubFields(DataSet);
end;