Спасибо за советы. Пока сделал так:
Код:
MODULE TmpOpenForm;
   IMPORT Files, Views, FormViews, FormModels, Containers, Controls, StdDialog, Dialog, Windows, Properties, StdLog;
   (*
      1.2[3]4 -> 1.2[fix]4
      1.2(3)4 -> 1.2(fix)4
   *)
   PROCEDURE Fix (VAR s: Dialog.String; IN fix: ARRAY OF CHAR);
      VAR new: Dialog.String;
         i (* s reader *), j (* new writer *), k (* fix reader *): INTEGER;
            c: CHAR;
   BEGIN
      i := 0;
      WHILE (i < LEN(s)) & (s[i] # 0X) & (s[i] # '.') DO new[i] := s[i]; INC(i) END;
      IF (i < LEN(s)) & (s[i] = '.') THEN
         new[i] := '.'; INC(i);
         
         WHILE (i < LEN(s)) & (s[i] # 0X) & ~((s[i] = '[') OR (s[i] = '(')) DO new[i] := s[i]; INC(i) END;
         IF (i < LEN(s)) & ((s[i] = '[') OR (s[i] = '(')) THEN
            new[i] := s[i]; j := i + 1;
            IF s[i] = '[' THEN
               c := ']'
            ELSE (* '(' *)
               c := ')'
            END;
            WHILE (i < LEN(s)) & (s[i] # 0X) & (s[i] # c) DO INC(i) END;
            IF (i < LEN(s)) & (s[i] = c) THEN
               INC(i);
               
               k := 0;
               WHILE (k < LEN(fix)) & (fix[k] # 0X) DO
                  new[j] := fix[k]; (* TRAP on new[j] bound overflow OK *)
                  INC(j);
                  INC(k)
               END;
               
               new[j] := c; INC(j); (* TRAP on new[j] bound overflow OK *)
               
               WHILE (i < LEN(s)) & (s[i] # 0X) DO
                  new[j] := s[i]; (* TRAP on new[j] bound overflow OK *)
                  INC(j);
                  INC(i)
               END;
         
               new[j] := 0X; (* TRAP on new[j] bound overflow OK *)
         
               StdLog.String(s); StdLog.String(" -> ");
         
               s := new;
               
               StdLog.String(s); StdLog.Ln
            END
         END
      END
   END Fix;
   (* сделано как в UnicodeConv.ControlsControl *)
   PROCEDURE ControlsControl (src: Controls.Control; IN fix: ARRAY OF CHAR): Controls.Control;
      VAR
         res: Controls.Control;
         plist : Properties.Property;
         p : Controls.Prop;
         poll : Properties.PollMsg;
         set : Properties.SetMsg;
   BEGIN
      res := Views.CopyOf(src, Views.deep)(Controls.Control);
      Views.HandlePropMsg(src, poll);
      plist := poll.prop;
      WHILE (plist # NIL) & ~(plist IS Controls.Prop) DO
         plist := plist.next
      END;
      IF plist # NIL THEN
         p := plist(Controls.Prop);
         p.known := {Controls.link,Controls.guard,Controls.notifier};
         p.valid := {Controls.link,Controls.guard,Controls.notifier};
         Fix(p.link, fix);
         Fix(p.guard, fix);
         Fix(p.notifier, fix);
         set.old := NIL; set.prop := p;
         Views.HandlePropMsg(res, set)
      END;
      RETURN res
   END ControlsControl;
   (* сделано как в UnicodeConv.ConvertThisView *)
   PROCEDURE ConvertThisView (src: Views.View; IN fix: ARRAY OF CHAR): Views.View;
      VAR dst: Views.View;
   BEGIN
      WITH src: Controls.Control DO
         dst := ControlsControl(src, fix)
      ELSE
         dst := NIL
      END;
      RETURN dst
   END ConvertThisView;
   (* сделано как в UnicodeConv.FormViewsView *)
   PROCEDURE FormViewsView (src: FormViews.View; IN fix: ARRAY OF CHAR): FormViews.View;
      VAR
         res: FormViews.View; m: FormModels.Model; c: Containers.Controller;
         v, v1, cv: Views.View;
   BEGIN
      res := Views.CopyOf(src, Views.deep)(FormViews.View);
      m := res.ThisModel(); c := res.ThisController();
      c.GetFirstView(Containers.any, v);
      WHILE v # NIL DO
         v1 := v; c.GetNextView(Containers.any, v1);   (* след-й надо брать до замены *)
         cv := ConvertThisView(v, fix); IF cv # NIL THEN m.ReplaceView(v, cv) END;
         v := v1
      END;
      RETURN res
   END FormViewsView;
   PROCEDURE GetForm (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR): FormViews.View;
      VAR v: FormViews.View;
   BEGIN
      v := Views.OldView(Files.dir.This(masterDir), masterName$)(FormViews.View);
      ASSERT(v # NIL);
      RETURN FormViewsView(v, fix)
   END GetForm;
   (* сделано как в StdApi.ThisMask *)
   PROCEDURE Mask (v: Views.View);
      VAR c: Containers.Controller;
   BEGIN
      IF v # NIL THEN
         WITH v: Containers.View DO
            c := v.ThisController();
            IF c # NIL THEN
               c.SetOpts(c.opts - {Containers.noFocus} + {Containers.noCaret, Containers.noSelection})
            ELSE Dialog.ShowMsg("#System:NotEditable")
            END
         ELSE Dialog.ShowMsg("#System:ContainerExpected")
         END
      END
   END Mask;
   (* сделано как в StdApi.OpenAuxDialog *)
   PROCEDURE OpenAuxDialog* (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR; IN title: ARRAY OF CHAR);
      VAR t0: Views.Title; done: BOOLEAN;
         v: Views.View;
   BEGIN
      Dialog.MapString(title, t0);
      Windows.SelectByTitle(NIL, {Windows.isAux}, t0, done);
      IF ~done THEN
         v := GetForm(masterDir, masterName, fix);
         Mask(v);
         StdDialog.Open(v, title, NIL, "", NIL, FALSE, TRUE, TRUE, FALSE, TRUE)
      END
   END OpenAuxDialog;
   (* сделано как в StdApi.OpenToolDialog *)
   PROCEDURE OpenToolDialog* (IN masterDir, masterName: ARRAY OF CHAR; IN fix: ARRAY OF CHAR; IN title: ARRAY OF CHAR);
      VAR t0: Views.Title; done: BOOLEAN;
         v: Views.View;
   BEGIN
      Dialog.MapString(title, t0);
      Windows.SelectByTitle(NIL, {Windows.isTool}, t0, done);
      IF ~done THEN
         v := GetForm(masterDir, masterName, fix);
         Mask(v);
         IF v # NIL THEN
            StdDialog.Open(v, title, NIL, "", NIL, TRUE, FALSE, TRUE, FALSE, TRUE)
         END
      END
   END OpenToolDialog;
   PROCEDURE Test*;
   BEGIN
      OpenAuxDialog("Tmp/Rsrc", "X1", "0", "Form X1 1 aux");
      OpenAuxDialog("Tmp/Rsrc", "X1", "1", "Form X1 2 aux");
      OpenToolDialog("Tmp/Rsrc", "X1", "1", "Form X1 2 tool")
   END Test;
END TmpOpenForm.
(!)TmpOpenForm.Test
Все отображения (Views), размещаемые на форме, должны быть Control-ами, потому что иначе к ним будет неудобно привязываться. Если какой-нибудь график надо выводить, то его тоже надо оборачивать в Control.