我有一个窗体Form1,做主窗体
还有一个窗体form2,做为主窗体的参数窗体,对主窗体上的控件进行配制。
现在我要用form2去控制form1上的edit.text='A',
我觉得在form2中直接使用form1.edit.text='A',这种方式不太好,
请教这种窗体间的控制,怎么做才是最好的?

解决方案 »

  1.   

    我觉得在form2中直接使用form1.edit.text='A',这种方式不太好
    ====================================================
    是指书写形式不太好吗?可以在form1或者form2中设置一个有意义的属性,然后对属性进行操作。
      

  2.   


    您所说的全局变量是在哪里声明呢?楼主的var Form1、Form2,又是在哪里声明的呢?简约、朴素不见得就不好。过份追求理论意义上的缜密,只会使事情变得繁琐。个人之见,说错勿怪。
      

  3.   

    我这样想的,在form2中设置一个edit控件的属性
    然后让fom2.edit:=form1.edit,这种不晓得是不是一种好的方法,
    各位,你们在处理这种窗体间的参数传递是怎么处理的呢,如果不能使用ini等配置文件的情况下,
    大家一起讨论一下!
      

  4.   

    我这样想的,在form2中设置一个edit控件的属性
    然后让fom2.edit:=form1.edit,这种不晓得是不是一种好的方法,
    各位,你们在处理这种窗体间的参数传递是怎么处理的呢,如果不能使用ini等配置文件的情况下,
    大家一起讨论一下!
      

  5.   

    楼上说的对,在一些简单的应用中,太追求形式也不好。
    一个窗体引用另一个窗体在实际应用中很多,但一定要尽量避免两个窗体之间的互相引用。
    我们有时间是在公共单元文件中声明一个全局变量,如Tstringlist等可以传递多个值。
      

  6.   


    请问,单元的
    interface区
    声明了一个
    var
      Form1: TForm1;这是不是全局变量?1、你在公共单元中声明一个全局变量是不是画蛇添足呢?2、难道你的公共单元不需要用uses引用到想用它的单元中去?
      

  7.   

    为TForm1增加一些有代表意义的方法或属性。
      

  8.   

    我一般不会直接操作我有一个窗体Form1,做主窗体 
    还有一个窗体form2,做为主窗体的参数窗体,对主窗体上的控件进行配制。 如果Form2是ShowModal的窗体,那么我会这么干
    Form2加一个public的方法叫Show**(如ShowConfig)
    返回值为Integer(其实就是ModalResult)
    带一个或多个var的参数(参数太多封装为记录体)
    因为是ShowModal的窗体,所以Form2的任务是返回这个var的记录体,并告诉Form1,用户点的是确定还是取消(判断返回值)
    只管自己要做的事,并不应该干涉别人(Form1拿这个记录体要干嘛,Form2管不着)如果Form2是Show的窗体,那我会这么干
    Form2加一个public的方法叫Show**(如ShowConfig)
    返回值不重要了,参数为能够初始化Form2所需要的信息
    Form2增加一个或多个事件(如SelectChanged、TextChanged等)
    Form2改变了什么,就调用相应的事件
    Form1想要那哪个就增加相应的事件处理就行了
    同样,Form2只管自己要做的事,Form1需要事件通知它就订阅,Form2同样管不着
      

  9.   

    TO  lake_cx :你的解答很好,不过对于第一种情况:
    假如我要在Form2中实时控制form1的某个控件的属性,
    好像按你的方法,不太好办哦?
      

  10.   

    要改变你的思维我要在Form2中实时控制form1的某个控件的属性要换成我要在Form2中实时通知form1
      

  11.   

    一般要用Form2不直接控制Form1,不过Form2可以发消息给From1,然后From1通过相关消息做相关操作。
      

  12.   

    如何在在Form2中实时通知form1?
      

  13.   

    你在公共单元中声明一个全局变量是不是画蛇添足呢?
    --------------------------------------
    公用单元的变量不只是给某个FORM用的,应用程序内所有的FORM都可以用到,
    每FORM只记住这个是公用单元,但要是引FORM内值的话,一个窗体还好,若有多个窗体去引用这个FORM值,太多的话思路就不够清晰。
    至少我不喜欢直接去form1.edit.text='A'这样做,呵呵
      

  14.   


    同问。
    那请问您是怎么做的呢?能否写一个例子展示一下您如何在公共单元声明,又如何使用?
    希望不会很繁琐。PS:Form1.Edit.Text := 'A';  ---- 这样做 有什么不可避免的风险呢?
      

  15.   

    风险倒不至于,我的意思是说要是能做到各个窗体之间相互独立一些不是更好吗,省得将来改动时牵一发而动全身。
    很多情况下不需要这样取值,如果它只是个配置信息,我全完可以从配置文件中得到不是更好。
    或者在SHOWMODAL后去全局量中得到相应个值。
    我不想抬杠,只是想表明一点,窗体间相互独立些不是更加合理吗。
      

  16.   

    续上:一、
    消息,需要接收消息一方建立一个消息循环。这样做可以,但要看是否需要这样做。如果根本不需要,那就自寻烦恼了。
    二、如果不用Form1.Edit.Text := 'assss'这样直接赋值,可以在TForm1里增加一个方法,用方法赋值。这样比较符合类封装原则。但是,从单元引用的角度说,这样做与Form1.Edit.Text := 'assss'基本无异。
    这样做的演示如下:
    unit Unit1;interfacetype
      TForm1 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        procedure SetEdit1Text(NewText: string);
      end;var
      Form1: TForm1;implementationuses Unit2;////在这里引用,没有循环引用的问题。{$R *.dfm}procedure TForm1.SetEdit1Text(NewText: string);
    begin
      Edit1.Text := NewText;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      Form2.Show;
    end;end.
    ////===================
    unit Unit2;interface
    //...
    type
      TForm2 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      end;var
      Form2: TForm2;implementationuses Unit1;////在这里引用,没有循环引用的问题。{$R *.dfm}procedure TForm2.Button1Click(Sender: TObject);
    begin
      Form1.SetEdit1Text('abcdefg');///还是要Form1......这样做
    end;end.三、关于在公共单元声明一个全局变量,会更好、更安全、更简洁,----我实在不知如何做但并不是不推荐使用公共单元。还是那句话:要分场合。把一切都放入公共单元,我认为并不可行。
      

  17.   


    说的没错。这个思路在编程过程中是很重要的。我也是这样做的----比如一些普通的全局变量、初始化设置信息、字符串资源等。
    但任何措施都不是万能的,我们总是要做一些取舍,如果为了将来可能或不可能的修改而提前付出巨大的劳动量,就不值得了。----这还是我说的“繁琐”的利弊之处。
    对于Form1.Edit.Text := 'assss'来说,不同的实现方式,无论信息经何处周转,又从何处来,但它总归是要去向Form1的吧!也就是说,代码中总归要出现一个Form1----能理解我要表达的意思吗?千万别误会。我也没有抬杠的意思。讨论问题嘛。如有不礼貌的地方,请您谅解。
    是的,窗体间尽量独立。但只要它们之间要交换信息,就没有也不可能有绝对的独立。
      

  18.   

    不同的实现方式也要分场合!
    我可以这样理解吗?
    呵呵,多谢lihuasoft兄的赐教。
      

  19.   

    续上:我猜测,前面双方讨论的方向可能发生了偏离。如果楼上几位要表达的意思是这样,我完全赞同,并且也推荐楼主这样写:
    unit FormMain;type
      TFormMain...
        Edit1
        Edit2
        Edit3
        ...
       public
       procedure ReadSetupInfo;
      end;procedure TFormMain.ReadSetupInfo;
    begin
      //从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
      Edit1.text := ...;
      Edit2.text := ...;
      Edit3.text := ...;
      ....
    end;
    end.
    unit FormSetup;type
      TFormSetup...
        Button
        ...
       procedure Button1Click...
      end;procedure TFormMain.Button1Click...
    begin
      //把更新后的设置信息写入INI文件或全局设置信息表
      FormMain.ReadSetupInfo;///根据设置信息重置FormMain
      {注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
        这就是我一直“纠缠不清”的问题所在}
    end;end.
      

  20.   

    续上:我猜测,前面双方讨论的方向可能发生了偏离。如果楼上几位要表达的意思是这样,我完全赞同,并且也推荐楼主这样写:
    unit FormMain;type
      TFormMain...
        Edit1
        Edit2
        Edit3
        ...
       public
       procedure ReadSetupInfo;
      end;procedure TFormMain.ReadSetupInfo;
    begin
      //从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
      Edit1.text := ...;
      Edit2.text := ...;
      Edit3.text := ...;
      ....
    end;
    end.
    unit FormSetup;type
      TFormSetup...
        Button
        ...
       procedure Button1Click...
      end;procedure TFormMain.Button1Click...
    begin
      //把更新后的设置信息写入INI文件或全局设置信息表
      FormMain.ReadSetupInfo;///根据设置信息重置FormMain
      {注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
        这就是我一直“纠缠不清”的问题所在}
    end;end.
      

  21.   

    我现在采用的方法就是将edit从form1直接传递到form2去
      

  22.   


    奇怪,刚才连发了两遍不见显示。再发一遍:我猜测,前面“双方”讨论的方向可能发生了偏离。如果楼上几位要表达的意思是这样,我完全赞同,并且也推荐楼主这样写:
    unit FormMain;type
      TFormMain...
        Edit1
        Edit2
        Edit3
        ...
       public
       procedure ReadSetupInfo;
      end;procedure TFormMain.ReadSetupInfo;
    begin
      //从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
      Edit1.text := ...;
      Edit2.text := ...;
      Edit3.text := ...;
      ....
    end;
    end.
    unit FormSetup;type
      TFormSetup...
        Button
        ...
       procedure Button1Click...
      end;procedure TFormMain.Button1Click...
    begin
      //把更新后的设置信息写入INI文件或全局设置信息表
      FormMain.ReadSetupInfo;///根据设置信息重置FormMain
      {注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
        这就是我一直“纠缠不清”的问题所在}
    end;end.
      

  23.   

    Delphi一般用事件通知,又不是线程或者进程间通知,没必要用消息
    多看看控件源代码,停留在使用控件的层面上不是太好,如果能写控件的话,你就很会有感觉了把Form1看成你写的东西,Form2看成是人家的东西,你可能根本就不知道人家Form2中有哪些东西
    但是你工作做得好的话就直接发布一个事件,分工明确对以后的维护有很大的帮助,灵活性更高,能够在一定层度上应付需求变更,通常写代码花的时间比找代码花的时间要少(敲代码也要找对地方敲嘛)。事件使用的例子Form1发布事件OnMyDataChanged
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        ComboBox1: TComboBox;
        procedure ComboBox1CloseUp(Sender: TObject);
      private
        FOnMyDataChanged: TGetStrProc;
        procedure SetOnMyDataChanged(const Value: TGetStrProc);
      public
        property OnMyDataChanged: TGetStrProc read FOnMyDataChanged write SetOnMyDataChanged;
      end;var
      Form1: TForm1;implementation{$R *.dfm}{ TForm1 }procedure TForm1.SetOnMyDataChanged(const Value: TGetStrProc);
    begin
      FOnMyDataChanged := Value;
    end;procedure TForm1.ComboBox1CloseUp(Sender: TObject);
    begin
      if Assigned(FOnMyDataChanged) then
        FOnMyDataChanged(ComboBox1.Text);
    end;end.
    Form2使用事件Form1.OnMyDataChanged
    unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm2 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        procedure Form1DataChanged(const S: string);
      public
        { Public declarations }
      end;var
      Form2: TForm2;implementationuses Unit1;{$R *.dfm}procedure TForm2.Button1Click(Sender: TObject);
    begin
      Form1 := TForm1.Create(Application);
      Form1.OnMyDataChanged := Form1DataChanged;
    end;procedure TForm2.Form1DataChanged(const S: string);
    begin
      Text := S;
    end;end.
      

  24.   

    呵呵,昨天下午回贴不显示。
    再次回贴。
    我“纠缠不清”的观点,在于有人说在Form2里用“Form1.XXX”这样不好,认为要在公共单元加一个全局变量去操作。
    至于说用“方法”(而不是您说的“事件”),仍然会出现“Form1.XXX”这种形式。
    并且,使用“方法”,前面我已经有代码了。下面是昨天下午回贴后没有显示的内容:
    前面双方讨论的方向可能发生了偏离。如果楼上几位要表达的意思是这样,我完全赞同,并且也推荐楼主这样写:unit FormMain;type
      TFormMain...
        Edit1
        Edit2
        Edit3
        ...
       public
       procedure ReadSetupInfo;
      end;procedure TFormMain.ReadSetupInfo;
    begin
      //从INI文件,或全局的设置信息表中读出设置信息并更新FormMain
      Edit1.text := ...;
      Edit2.text := ...;
      Edit3.text := ...;
      ....
    end;
    end.
    unit FormSetup;type
      TFormSetup...
        Button
        ...
       procedure Button1Click...
      end;procedure TFormMain.Button1Click...
    begin
      //把更新后的设置信息写入INI文件或全局设置信息表
      FormMain.ReadSetupInfo;///根据设置信息重置FormMain
      {注意,这里还是要用“FormMain.”,也就是说,这个窗体单元还是要引用unit FormMain
        这就是我一直“纠缠不清”的问题所在}
    end;end.
      

  25.   

    我的问题是在于,是不能使用配置文件的情况,因为使用配置文件,就不能达到在form2中实时控制form1的控件,
    昨天经过实践,将form1的控件做参传到form2就可以达到form2中不引用form1
      

  26.   


    使用配置文件,并不会导致“Form2中不能实时控制Form1”本人退出本贴的讨论。(自己都看花眼了)^_^
      

  27.   

    是有点跑题了,不过真的学到不少东西,呵呵。
    实时控制,lake_cx说的事件传递很不错,学了一招。
    或者用消息传递,把form1的窗体句柄传过去也可以达到目的。