线程运行中能不能显示form出来,有谁做过吗?指点一下吧,比较急?????
什么意思
不明白?

解决方案 »

  1.   

    最好发消息,
    线程中操作Delphi控件,容易出问题。
      

  2.   

    线程?你说的进程还是线程?
    线程一般都没有form的,因为它没有消息循环,处理不了form的消息。
    你想说啥?想好了说。
      

  3.   

    举个简单的例子拉,希望对你有帮助!unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        Edit1: TEdit;
        Image1: TImage;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;TMyThread = class(TThread)
      private
        child : TComponent;
        step : integer;  public
        procedure draw;
        constructor Create(parent : TComponent);
        procedure Execute; override;  end;var
      Form1: TForm1;
    implementation{$R *.dfm}{ TMyThread }constructor TMyThread.Create(parent: TComponent);
    begin
      child := parent;
      inherited Create(false);
    end;procedure TMyThread.draw;
    begin
      if (child is TEdit) then
      begin
        (child as TEdit).Text := inttostr(step);
      end
      else if(child is TImage) then
      begin
        (child as TImage).Canvas.Brush.Color := TColor(step*4);
        (child as TImage).Canvas.FillRect(rect(0,0,100,100));
      end;
    end;procedure TMyThread.Execute;
    var
      i : integer;
    begin
      inherited;
      for i:= 0 to 10000 do
      begin
           step := i;
           synchronize(draw);
      end;
      if Terminated then Exit;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      TMythread.Create(Edit1);
      TMythread.Create(image1);end;end.
      

  4.   

    我是在主form中,有一个线程,线程监视串口的数据,如条件满足,则把创建另一子form实例,并显示出来,等待用户处理
    各位清除了吗?谢谢,或者给我一个其它的解决办法吧
      

  5.   

    你可在主线程(主窗体的程序,它可用循环检测,也可以设一个定时器)里加入判断,如果满足某条件则显示另一子窗体呀,当然这个条件(状态)是你的串口线程中改变的.
    当然在线程的代码中也可以这么写 Form3.showmodal?(你得包含这窗体的单元)
    线程单元中是不能处理消息的.
    我做的工控程序就有很多线程,其中一个为串口单元.
      

  6.   

    showmodal可行,
    刚才我在串口单元的串口线程Execute方法里调用了
      FormInf.ShowModal;
    是可行的.
      

  7.   

    我是显示另一子窗体后,线程继续运行,循环检测。我很想用form3.showodal的方式,但
    当form create时,就出错"canvas can not allow drawing".
      

  8.   

    myyanghua(水手) 说的对,发消息就比较安全,你可以在
    线程满足条件后给主Form发一个消息,然后在主Form中处理
    这个消息就行了。
      

  9.   

    你那个要显示的窗口放到
    Auto-create forms里而不是Available forms内如何?
      

  10.   

    线程中当然可以处理消息的!!!
    procedure TMyThread.Execute;
    var
      i : integer;
    begin
      inherited;
      for i:= 0 to 10000 do
      begin
          step := i;
          if step = 5000 then
          begin
             SendMessage(Form1.Handle,WM_SYSCOMMAND,SC_MINIMIZE,0);
          end;
          synchronize(draw);
      end;end;
    你就用消息来处理吧!
      

  11.   

    感谢leeky及各位,我还有些疑惑:
    1,我用在线程中显示form的,测试代码如下:
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
        passadmit = class(Tthread)
        protected
                 procedure Execute;override;
        end;  TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses Unit2;{$R *.dfm}procedure passadmit.Execute;
    begin
         Form2:=Tform2.create(nil);
         Form2.showmodal;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
         passadmit.create(false);
    end;end.
    调试执行时,出错为canvas does not allow draw
    不知是否是我的delphi或系统有问题,delphi6,win20002、看来发消息是一个好的解决办法,但我要传递一些参数,和一幅图像,谁能给个消息传递的例子吗?我还没怎么用过那一块。
      

  12.   

    关于消息,哪天有空再试试.
    :)
    确实还是可以,
    synchronize(progress);
          if PeekMessage(myMsg,0,0,0,PM_REMOVE) then
            begin
               if (myMsg.message = WM_QUIT) then
                  Terminate;
            end;我还想做进一步……
      

  13.   

    关于消息,哪天有空再试试.
    :)
    确实还是可以,
    synchronize(progress);
          if PeekMessage(myMsg,0,0,0,PM_REMOVE) then
            begin
               if (myMsg.message = WM_QUIT) then
                  Terminate;
            end;我还想做进一步……
      

  14.   

    当然不是你的系统或delphi有问题,
    而是VCL在线程中是危险的,必须使用同步技术,
    实际上当你创建窗体时,canvas 被Lock住了,此时是不允许你画的!
      

  15.   

    这个是根据你的代码改了一下,不太准确
    const CM_FORMSHOW = WM_USER + $0100;
    type
        passadmit = class(Tthread)
               FHandle: THandle;
               FImage : TImage;
        protected
                procedure Execute;override;
        constructor Create(Handle: THandle;image: TImage);
        end;  TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
         procedure CMFORMSHOW(var msg: TMsg);message CM_FORMSHOW;
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses Unit2;{$R *.dfm}
    constructor passadmit.Create(Handle: THandle;image: TImage);
    begin
       FHandle := Handle;
       Fimage  := image;
    end;procedure passadmit.Execute;
    begin
       if ... then begin
          SendMessage(FHandle,CM_FORMSHOW,0,0);
       end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
        passadmit.create(Handle,Image);
    end;procedure TForm1.CMFORMSHOW(var msg: TMsg);
    begin
       //
       Form2.ShowModal;
    end;end.delphi的线程对象真的不爽
      

  16.   

    你还可以这样来做:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls;type
      TForm1 = class(TForm)
        Edit1: TEdit;
        Image1: TImage;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;TMyThread = class(TThread)
      private
        child : TComponent;
        step : integer;
        FormThread : TForm1;  public
        procedure draw;
        constructor Create(parent : TComponent);
        destructor destroy;
        procedure Execute; override;  end;var
      Form1: TForm1;
    implementation{$R *.dfm}{ TMyThread }constructor TMyThread.Create(parent: TComponent);
    begin
      child := parent;
      inherited Create(false);
    end;destructor TMyThread.destroy;
    begin
      if FormThread <> nil then
        FreeAndNil(FormThread);
    end;procedure TMyThread.draw;
    begin
      if (child is TEdit) then
      begin
        (child as TEdit).Text := inttostr(step);
      end
      else if(child is TImage) then
      begin
        (child as TImage).Canvas.Brush.Color := TColor(step*4);
        (child as TImage).Canvas.FillRect(rect(0,0,100,100));
      end;
      if Step = 5000 then
      begin
        FormThread :=TForm1.Create(nil);
        FormThread.Show;
      end;
    end;procedure TMyThread.Execute;
    var
      i : integer;
    begin
      inherited;
      for i:= 0 to 10000 do
      begin
          step := i;
          if step = 5000 then
          begin
            // SendMessage(Form1.Handle,WM_SYSCOMMAND,SC_MINIMIZE,0);
          end;
          synchronize(draw);
      end;end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      TMythread.Create(Edit1);
      TMythread.Create(image1);end;end.
    虽然这里面还有个step的同步问题,但足可以解决你的问题!
      

  17.   

    现在依pathe(睡斛) 用同步技术,能把我的哪个测试程序改一下吗?主form中就开个线程,显示另一form?谢谢另外假如发送消息来处理的话,参数传递怎处理?通过全局变量吗?谢谢各位,问题还没完全解决,我先研究研究各位的方法,请各位还继续关注一下我的问题。到中午了,该开饭了,要不我请客?:)我在深圳
      

  18.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
        passadmit = class(Tthread)
        private
           FrmThread : TForm2;
        protected
                procedure Execute;override;
        public
                procedure draw;
                destructor destroy;
            end;  TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses Unit2;{$R *.dfm}
    destructor passadmit.destroy;
    begin
      if frmThread <> nil then
        FreeAndNil(frmThread);
    end;
    procedure passadmit.draw;
    begin
        if frmThread <> nil then
          FreeAndNil(frmThread);
        frmThread:=Tform2.create(nil);
        frmThread.show;//showmodal 会阻塞线程;
    end;
    procedure passadmit.Execute;
    var
      i : integer;
    begin
      for i:=0 to 10000 do
      begin
        if i = 5000 then
          sychronize(draw);
        do sth;
      end;    
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
        passadmit.create(false);
    end;end.
      

  19.   

    我刚吃完回来,赫赫, 你怎么不早说!
    有什么好吃的,可惜我不在深圳,要不, 你打个package, Eat-Mail过来!
    发消息,用全局变量吧,或者用Mutex, Event等等之类的,不过不知道Delphi封装了没有,
    否则还得用SDK!
      

  20.   

    for i:=0 to 10000 do
      begin
        if i = 5000 then
          sychronize(draw);
        do sth;
      end;    
    循环是不是同步必须的要的?
    pathe(睡斛) 你在哪?
      

  21.   

    当然不是!
    这只是个例子,要不然线程一下子就结束了!
    我只不过让他多消耗点时间!
    我明白你的意思,实际上你是开一个线程来监视串口数据,
    如果满足条件就调用sychronize(draw);
      

  22.   

    主窗体里加入一全局变量myCommEvent:Boolean,设置内部定时器(不是TTimer呵呵)——查查SetTimer()的使用,此步放在主窗体的Create 方法里?,在串口线程中设myCommEvent为True;
    而在SetTimer所设置的处理函数内判断myCommEvent,为真则你的显示窗体。
      

  23.   

    主窗体里加入一全局变量myCommEvent:Boolean,设置内部定时器(不是TTimer呵呵)——查查SetTimer()的使用,此步放在主窗体的Create 方法里?,在串口线程中设myCommEvent为True;
    而在SetTimer所设置的处理函数内判断myCommEvent,为真则你的显示窗体。
      

  24.   

    衷心感谢各位,尤其是pathe和leeky。问题基本解决,还是用pathe的同步方法,只是显示稍慢一
    点,我先加分,再给分。
      

  25.   

    就是sychronize(draw); 其原理在于:将有关draw内的可视化操作串入可视化主线程,从而避免与可视化主线程发生冲突。执行完draw后,再回到自己的子线程。