问题1:在 MainForm 中,我让 Form1  ShowModal,   Form1 中有个按钮,点击按   钮, 则 Form2 ShowModal, 同时 Form1 关闭,如果这个按钮的ModalResult 设为mrOK,则可以实现,如果不设置,我应该怎样实现?问题2:有一个 Form 是 ShowModal 的 上面没有按钮,我想在某个条件下,比如收到一条消息,把这个 Form 关闭,应该怎样实现?

解决方案 »

  1.   

    1.  
      Free;
      Form2.ShowModal;2.
      SendMessage(Form2.Handle, WM_CLOSE, 0, 0);
      

  2.   

    Form2.showmodal;
       form1.close;
      

  3.   

    1. 在按钮的OnClick事件中写Form2.ShowModal
    2. 调用Close()或者使用ModalResult :=mrOK等
      

  4.   

    我早就试过了,Form1 是不会关闭的
      

  5.   

    Form2.showmodal;
       form1.close;
      

  6.   

    Form2.showmodal;
       form1.close;
      

  7.   

    要先写Form1.Close;
    再写Form2.ShowModal;
    因为ShowModal是要被关闭之后才会执行以后的代码.
      

  8.   

    1.不能简单这么写,
    close;
    form2.showmodal;
    showmodal后,form2窗体handlemessage,控制不会去执行close。
    应当:
    hide;
    form2.showmodal;
    free;
    这样可以满足要求。
    2.在“某个条件下”直接写form.modalresult := mrok/mrcancel 就可以关闭
    form了
      

  9.   

    to yx_elee:
       不好意思,我错了,没有经过测试就发表议论.我事后测试是不行.
    但是我按你的设置了ModalResult也不行.看看你的.我已经试了几下都不能.
      

  10.   

    =======================================
    这里找不到答案吗?来这里试试看!
    这里有问必答
    http://systemer.51.net/cgi-bin/leoboard.cgi
    希望你能在这里找到你满意的答案
    =========================================
      

  11.   

    1可以实现,需要走迂回路线。在form1上放置一个timer,在timer1里面将
    form2 showmodal:
      timer1.close;
      form3.showmodal;
    form2的按钮事件这么写:
      form1.timer1.enabled:=true;
      close;
    这样就可以了,不过感觉这种解决方法很土:)
    在form2里实现不太可能吧
      

  12.   

    呵呵,俺来说两句:
    一旦直接或间接执行了ModalResult := mrOK;(这里的mrOK可以是任何非mrNone的值),窗口就关闭(可能是Hide也可能是Free)即ShowModal函数执行完毕。
    如果编写如下语句序列:
    SomeForm.ShowModal;
    SomeProcCall;
    那么直到ShowModal执行完毕即窗口关闭,才有可能执行SomeProcCall。这里之所以说有可能,是因为如果在SomeForm的OnClose等事件处理程序中直接调用某些例程导致应用程序终止,那么SomeProcCall则不会执行。
      

  13.   

    其实hide 和 colse 两个过程有什么区别呢?大家发表一下意见吧
      

  14.   

    有谁可以解决这个问题呢?问题版本更新:点击 Form 1 (始终存在) 上的按钮 button 1, 则Form2  ShowModal, 点击 Form 2 上的按钮 button 2, 则 Form 2 关闭, Form 3  ShowModal, 点击 Form 3 上的按钮 button 3,则 Form 3 关闭, Form 2 ShowModal, 可以如此循环,而且不想用 Free, 那位大虾可以帮忙解答,小弟在此先谢过了
      

  15.   

    为什么要这么引用啊,建议先看一看VCL中对ShowModal是如何做的吧.
    违反规则是要受惩罚的。模态窗口有自己的规则。
    function TCustomForm.ShowModal: Integer;
    var
      WindowList: Pointer;
      SaveFocusCount: Integer;
      SaveCursor: TCursor;
      SaveCount: Integer;
      ActiveWindow: HWnd;
    begin
      CancelDrag; //禁用拖放停靠
      if Visible or not Enabled or (fsModal in FFormState) or
        (FormStyle = fsMDIChild) then //可见的,不可用的,MID等窗口不能用模态窗口
        raise EInvalidOperation.Create(SCannotShowModal);
      if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
      ReleaseCapture;
      Include(FFormState, fsModal);
      ActiveWindow := GetActiveWindow;
      SaveFocusCount := FocusCount;
      Screen.FSaveFocusedList.Insert(0, Screen.FFocusedForm);
      Screen.FFocusedForm := Self;
      SaveCursor := Screen.Cursor;
      Screen.Cursor := crDefault;
      SaveCount := Screen.FCursorCount;
      WindowList := DisableTaskWindows(0);
      try
        Show; //其实showmodal也是一般窗口的Show啊,没有什么差别
        try
          SendMessage(Handle, CM_ACTIVATE, 0, 0);//激活
          ModalResult := 0;
          repeat //等消息循环是否有mrOk等按键
            Application.HandleMessage;
            if Application.FTerminate then ModalResult := mrCancel else
              if ModalResult <> 0 then CloseModal;
          until ModalResult <> 0;
          Result := ModalResult;
          SendMessage(Handle, CM_DEACTIVATE, 0, 0);
          if GetActiveWindow <> Handle then ActiveWindow := 0;
        finally
          Hide; //注意啦,关闭时VCL先将模态窗口隐藏的
        end;
      finally //后面的才是正常清理关闭窗口的代码。
        if Screen.FCursorCount = SaveCount then
          Screen.Cursor := SaveCursor
        else Screen.Cursor := crDefault;
        EnableTaskWindows(WindowList);
        if Screen.FSaveFocusedList.Count > 0 then
        begin
          Screen.FFocusedForm := Screen.FSaveFocusedList.First;
          Screen.FSaveFocusedList.Remove(Screen.FFocusedForm);
        end else Screen.FFocusedForm := nil;
        if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
        FocusCount := SaveFocusCount;
        Exclude(FFormState, fsModal);
      end;
    end;
      

  16.   

    非要搞两个模态窗口切换,有什么意义。
    一次性把两个窗口都创建好,用Hide或Visible来控制就可以了吧。
    很方便。
      

  17.   

    在调用窗体中使用hide,

    在主窗体中按顺序调用:
    form1.ShowModal;
    form1.close;
    form2.ShowModal;
    form2.close;
    form3.ShowModal;
    form3.close;
    form2.ShowModal;
    form2.close;
    form1.ShowModal;
    form1.close;
      

  18.   

    以下代码是ShowModal的核心代码,如果搞研究,你可以把这段代码加到自己的窗口中去。
        Show; //其实showmodal也是一般窗口的Show啊,没有什么差别
        try
          SendMessage(Handle, CM_ACTIVATE, 0, 0);//激活
          ModalResult := 0;
          repeat //等消息循环是否有mrOk等按键
            Application.HandleMessage;
            if Application.FTerminate then ModalResult := mrCancel else
              if ModalResult <> 0 then CloseModal;
          until ModalResult <> 0;
          Result := ModalResult;
          SendMessage(Handle, CM_DEACTIVATE, 0, 0);
          if GetActiveWindow <> Handle then ActiveWindow := 0;
        finally
          Hide; //注意啦,关闭时VCL先将模态窗口隐藏的
        end;
    //这段代码很有意思,VCL内建的管理控制的列表
    Screen.FFocusedForm := Screen.FSaveFocusedList.First;
    Screen.FSaveFocusedList.Remove(Screen.FFocusedForm);举个例子,若在模态窗口A中调用模态窗口B的同时想关闭A是不可能的,除非B关闭掉。这就形成了后进先出的一个堆栈,必须依次Remove掉,最先ShowModal的窗口才能在最后关闭。
    好多废话。自己想想。
      

  19.   

    感谢 maoke000(老茂) 原来他们是以堆栈的形式建立自己的消息循环,也就是只有在栈顶的才有权处理消息(这是我的理解吧)所以要相互 ShowModal 是不可能的
      

  20.   

    对,就是这样子的,ShowModal方法就限制了你这么用。
    因为Screen.FFocusedForm := Screen.FSaveFocusedList.First;这条语句,先取第第一个模态的窗口。
    Screen.FSaveFocusedList.Remove(Screen.FFocusedForm);然后再依次释放。OK,事情就是这样子的。想在多个模态窗口之间用现成的方法肯定不行的。
    包括楼上的所有办法,即便是发消息也是不可能的。
      

  21.   

    楼主可能没有搞清showmodal和show的区别
    show是非模态窗口
    showmodal是模态窗口,
    Form2.show
    Form1.close
      

  22.   

    新的要求依旧可以实现!需要走迂回路线,原理就是将show form的消息放在
    modal form close的消息后面,用timer就可实现。
    在form1上放置timer1、timer2,interval都设为50,enabled初始为false
    timer事件如下
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      timer1.Enabled :=false;
      form3.ShowModal;
    end;procedure TForm1.Timer2Timer(Sender: TObject);
    begin
      timer2.Enabled :=false;
      form2.ShowModal ;
    end;
    form1.button1的click事件如下
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      form2.ShowModal;
    end;form2.button1的的click事件如下:
    procedure TForm2.Button1Click(Sender: TObject);
    begin
      form1.Timer1.Enabled :=true;
      close;
    end;form3.button1的的click事件如下:
    procedure TForm3.Button1Click(Sender: TObject);
    begin
      form1.Timer2.Enabled :=true;
      close;
    end;
    以上的方法仅就实现要求的效果而言。
      

  23.   

    to NightCloud():构思很巧妙啊,其实每次都是把控制权给回 Form1 ,由 Form1 控制另外两个 Form 的 ShowModal
      

  24.   

    nod
    原理就是将show form的消息放在modal form close的消息后面