Devolver TApplication para DLL ao fecha Form MDI

Delphi

28/11/2006

Salve pessoal,
Lendo alguns topicos aqui no Forum eu estou abrindo um Form do tipo MDI que esta dentro de uma DLL, de acordo com as informações que encontrei aqui no Forum quando fazemos isso temos que passar o TApplication do EXE para a DLL e depois quando finalizamos nosso EXE temos que devolver o TApplication antigo da DLL para a mesma. Pois bem eu fiz tudo isso e esta tudo funcionando sem problemas, o que eu gostaria é de deixar o codigo da minha DLL para que possa ser analizado e ver se existe alguma falha mesmo estando funcionando. Segue o codigo:

Código da DLL

library FormMDI;

uses
  SysUtils, Classes, Windows, Forms,
  uMDIChild in ´uMDIChild.pas´ ;

{$R *.res}

var
  OldApplication : TApplication;
  OldScrean : TScreen;

procedure AbreForm( Ap : TApplication; Sc : TScreen ); stdcall; 
var
  Form : TMDIChild;
begin

  if (OldApplication = nil) and (OldScrean = nil) then begin
    OldApplication := Application;
    OldScrean := Screen;

    Application := Ap;
    Screen := Sc;
  end;

  Form := TMDIChild.Create(Application);
  Form.Show;

end;

procedure RetornaTudo; stdcall;
begin
  Application := OldApplication;
  Screen := OldScrean;
end;


Exports
  AbreForm,
  RetornaTudo;

begin
end.



Código do aplicativo que chama a mesma:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Menu1: TMenuItem;
    Abre1: TMenuItem;
    procedure Abre1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

procedure AbreForm( Ap : TApplication; Sc : TScreen ); stdcall; external ´FormMDI.dll´;
procedure RetornaTudo; stdcall; External ´FormMDI.dll´;

implementation

{$R *.dfm}

procedure TForm1.Abre1Click(Sender: TObject);
begin
  AbreForm(Application, Screen);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  RetornaTudo;
end;

end.



Para falar a verdade eu estou com uma pulga atraz da orelha referente estra procedure que eu exportei e coloquei no Destroy do form que chama a DLL.

Bom se alguem puder opinar ...

Valew


Mmoreira

Mmoreira

Curtidas 0

Respostas

Mmoreira

Mmoreira

28/11/2006

Depois que eu adicionei um DBGrid no meu Form ... quando eu finalizo meu sistema é gerado o seguinte erro:

A instrção no ´0x00f4536´ fez referencia a memoria no ´0x018f1f90´. A memoria nao pode ser ´read´. Clique em ´OK´ para encerrar o programa Dai clico em OK e vem outro erro: Runtime error 216 at 00F43536


Detalhe se eu volto na DLL retiro o DBGrid ai o sistema fecha normal sem erro algum ... coloco o DBGrid ... o erro volta. E a mesma coisa acontece quando eu coloco um TSpeedButton ... coloco da erro na hora de fechar .. tiro ele ... nada de erro ... Alguem sabe como resolver isso?

Valeww


GOSTEI 0
Mmoreira

Mmoreira

28/11/2006

Bom ainda estou garimpando aqui para ver se consigo solucionar o problema ...

Referente ao erro que mencionei acima este ai eu ja resolvi da seguinte maneira ... Eu tinha no sistema que chamava a DLL declarado no USES a unit:

XPMan


Foi só remover que parou de dar a mensagem de erro ao fechar o sistema ... mas gostaria de contornar este problema ... pois gosto da aparencia que ela da para a aplicação.


Agora estou com outro problema ...
Adicionei um DataModulo na minha DLL, entao agora minha DLL esta assim:

library IntegraSistema;

uses
  SysUtils,
  Classes,
  Forms,
  ufrmPrincipal in ´ufrmPrincipal.pas´ ,
  udmCadastro in ´udmCadastro.pas´ {dmCadastro: TDataModule},
  XPMan;

{$R *.res}

var
  OldApplication : TApplication;
  OldScreen : TScreen;

procedure IntegraSistemaPadrao; stdcall;
begin
  Application := OldApplication;
  Screen := OldScreen;


  // Destruir o DataModule dmCadastro caso o mesmo tenha sido criado em algum momento
  if dmCadastro <> nil then dmCadastro.Destroy;
end;

procedure AbreIntegraSistema( aApplication : TApplication; sScreen : TScreen ); stdcall;
begin

  if (OldApplication = nil) and (OldScreen = nil) then begin
    OldApplication := Application;
    OldScreen := Screen;

    Application := aApplication;
    Screen := sScreen;
  end;

  if dmCadastro = nil then begin
    dmCadastro := TdmCadastro.Create(Application);
  end;
     
  if frmPrincipal = nil then begin
    frmPrincipal := TfrmPrincipal.Create(Application);
    frmPrincipal.Show;
  end;

end;


Exports
  IntegraSistemaPadrao,
  AbreIntegraSistema;

begin
end.



No meu DataModulo eu tenho:

Um SoapConnection e um ClientDataSet ... tudo configurado como deve ser. Adicionei o DataModule no USES do meu Form .. tudo tranquilo.
Tenho um botao no meu Form com este codigo:

  with dmCadastro.cdsEvento do begin
    Close;
    Params[0].AsInteger := 1;
    try
      Open;
    except
      on e : Exception do ShowMessage( ´erro ´ + e.Message);
    end;
  end;


O registro de codigo numero 1 existe no meu banco de dados .. mas quando executo este botao simplesmente nao acontece nada ... o ClientDataSet nao abre o registro ... mas eu sei que a conexao esta funcionando porque no meu DataModule eu tenho um outro ClientDataSet onde eu posso passar comandos SQL atravez dele ... entao eu faço assim em outro botao:

procedure TfrmPrincipal.Button2Click(Sender: TObject);
begin
  with dmCadastro.cdsExecSql do begin
    Close;
    CommandText := ´insert into EVENTO (IDEVENTO) values (:idevento)´;
    Params.ParamByName( ´idevento´ ).AsInteger := 2;
    try
      Execute;
    except
      on e : Exception do ShowMessage( ´´ + e.Message);
    end;
    Close;
  end;
end;


Ai o registro é inserido normalmente no banco de dados ... ou seja o ClientDataSet nao da um Open mas executa o SQL. Um detalhe como descrevi aqui tudo isso dentro da DLL mas uma coisa muito importante é que fiz todo este procedimento em um aplicação normal .. sem usar a DLL .. fui la criei uma nova aplicacao ... adicionei um SoapConnection ... o ClientDataSet ... Configurei tudo e mandei abrir o registro de codigo 1 ... Funcionou perfeitamente ... ou seja ... o problema esta na DLL.

Estou usando o Delphi 7 + DBExpress + ClientDataSet ... Fiz isso tudo usando um Servidor SOAP e meu banco de dados é Firebird.


GOSTEI 0
Mmoreira

Mmoreira

28/11/2006

Quando eu coloco o SoapConnection direto no meu Form ... ai o sistema funciona perfeitamente ... mas quando volto com o SoapConnection para o DataModule ... para de funcionar.

Nossa isso ja esta me deixando maluco.


GOSTEI 0
POSTAR