打开的窗体均为MDI窗体
procedure TfrmMain.MyCreateForm(InstanceClass: TComponentClass;frm: TForm);
begin
  if not formExists(InstanceClass,frm.Caption,true) then
  begin
    Application.CreateForm(InstanceClass, frm);
    frm.Show;
  end;
end;function TfrmMain.FormExists(OBJFormType: TClass; OBJFormCaption: string = ''; bShow: Boolean=True): Boolean;
var
  i : integer;
begin
  Result := False;
  for i := Application.MainForm.MdiChildCount - 1 downto 0 do     //防止产生多个窗口实例
    if Application.MainForm.MDIChildren[i] is OBJFormType then
      if (OBJFormCaption = '') or ((OBJFormCaption <> '')
         and (OBJFormCaption = Application.MainForm.MDIChildren[i].Caption)) then //若窗口标题存在
      begin
         if bShow then
           Application.MainForm.MDIChildren[i].Show; //若窗口存在,激活此窗口
         Result := True;
         Break;
      end;
end;=================================================================使用这种方法,窗体内线程代码出现访问无效内存区域错误估计是使用窗体名+控件访问的问题请问如何解决?谢谢啦!

解决方案 »

  1.   

    if not Assigned(frmPrdtErpAnti) then
      begin
      Application.CreateForm(TfrmPrdtErpAnti, frmPrdtErpAnti);
      frmPrdtErpAnti.Show;
      end
      else
      begin
      frmPrdtErpAnti.Show;
      frmPrdtErpAnti.BringToFront;
      end;现在只能用这种办法,觉得太累了,不方便呵呵
      

  2.   

    以前也出现过这种错误,后来改用了一个通用的调用方法
    procedure ShowForm(aFormName: string; aFormClass: TFormClass; aShowModal: Integer = 1);
    var
      aForm: TForm;
    begin
      aForm := CreateClientForm(Screen, aFormName, aFormClass);  case aShowModal of
        0: begin
            aForm.BorderIcons := [];
            aForm.WindowState := wsMaximized;
            aForm.Show;
          end;
        1: begin
            try
              aForm.BorderIcons := [biSystemMenu, biMinimize, biMaximize];
              aForm.WindowState := wsNormal;
              aForm.ShowModal;
            finally
              FreeAndNil(aForm);
            end;
          end;
      end;
    end;// 判断窗体是否被创建function FormIsExist(Scr: TScreen; FormName: string): Boolean;
    var
      i: Integer;
    begin
      Result := false;
      for i := 0 to Scr.CustomFormCount - 1 do
      begin
        if (CompareStr(UpperCase(FormName), UpperCase(Scr.CustomForms[i].Name)) = 0) then
          Result := true;
      end;
    end;// 返回已经被创建的窗体的指针function GetRegisteredForm(Scr: TScreen; FormName: string): TForm;
    var
      i: Integer;
    begin
      Result := nil;
      for i := 0 to Scr.CustomFormCount - 1 do
      begin
        if (CompareStr(UpperCase(FormName), UpperCase(Scr.Forms[i].Name)) = 0) then
        begin
          Result := Scr.Forms[i];
          Exit;
        end;
      end;
    end;// 得到窗体的指针function CreateClientForm(Scr: TScreen; FormName: string; FormClass: TFormClass): TForm;
    var
      Form: TForm;
    begin
      if (FormIsExist(Scr, FormName)) then
      begin
        Form := GetRegisteredForm(Scr, FormName);
      end
      else
      begin
        Form := FormClass.Create(Application);
        //App.CreateForm(FormClass,Form);
        Form.Name := FormName
      end;  Result := Form;
    end;
      

  3.   

    to:ZyxIp(绝望中...) 
    线程是在被打开的窗体中建立的,但是线程中一些需要访问该窗体控件时出现错误。我使用的是窗体名+对象的方式访问,提示内存错误。
      

  4.   

    to:pongjun64(迪安)使用你的代码也是提示错误,线程中代码还是不可执行。procedure TThreadGetInfo.Execute;
    var
      strZTInfo:string;
      i:integer;
    begin
      strZTInfo:='';  for I := 0 to 50 - 1 do
        begin
          strZTInfo:=strZTInfo+inttostr(i);
        end;  frmprdterpanti.txtGetinfo.Text:='s';
      //重新建立与ERP帐套的连接
      frmPrdtErpAnti.adoconn.Connected:=false;===========================================
    以上代码,执行到窗体调用时,出错误
      

  5.   

    搞不明白你为什么使用线程打开MDI子窗体
    搞一个主界面设置为formstyle为MDIPARENT
    然后所有字界面设置formstyle为MDIPCHILD然后当点击按钮的时候用SHOWFORM方法调用就可以了。始终不明白你用线程的原因,这里打开所有窗体并不是并发来处理,是有先后顺序的
      

  6.   

    procedure TfrmMain.MyCreateForm(InstanceClass: TComponentClass;frm: TForm);
    begin
      if not formExists(InstanceClass,frm.Caption,true) then
      begin
        Application.CreateForm(InstanceClass, frm);
        frm.Show;
      end;
    end;这个函数我觉得有问题,如果frm不存在,你怎么能访问frm.Caption?
    你要保证线程中访问的frm是否存在,是否已创建
      

  7.   

    另外线程中访问主线程的VCL控件需要以Synchronize()来保证安全procedure TThreadGetInfo.Connect;
    begin
      frmprdterpanti.txtGetinfo.Text:='s';
      //重新建立与ERP帐套的连接
      frmPrdtErpAnti.adoconn.Connected:=false;
    end;
    procedure TThreadGetInfo.Execute;
    var
      strZTInfo:string;
      i:integer;
    begin
      strZTInfo:='';  for I := 0 to 50 - 1 do
        begin
          strZTInfo:=strZTInfo+inttostr(i);
        end;   Synchronize(Connect);  ......
      

  8.   

    线程内不要直接去访问窗体控件.
    要是向窗体送数据用POSTMESSAGE的方式.
      

  9.   

    可能是这个问题:
    线程中访问Ado等com对象时需要这样:CoInitialize(nil);
    try
       ...
      frmPrdtErpAnti.adoconn.Connected:=false;  ...
    fianlly
      CoUnInitialize;
    end;
      

  10.   

    要是向窗体送数据用POSTMESSAGE的方式===========================读数据呢?基本上好多都是读取变量进行一些设置