Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 22-01-2013
cd.rafael cd.rafael is offline
Miembro
 
Registrado: abr 2012
Posts: 59
Poder: 13
cd.rafael Va por buen camino
error en dll con una form

Cordial saludo,

He revisado muchos temas respecto al manejo de forms dentro de una dll y hasta ahora no he podido resolver mi problema, que a continuación expongo:

Tengo un ejecutable normal el cual invoca a una dll que a su vez lanza una form. Si dicha form la muestro con "ShowModal" todo funciona bien, pero si la dejo solo como "Show", el ejecutable deja de responder.

Este es el código que uso en el ejecutable:

Código:

procedure TForm1.Button1Click(Sender: TObject);
type
    TDLLFunc = procedure(pStUsuario: String; pStPassword: String; pStDB: String; pStEsquema: String; pStTabla: String);
const
    DLLFunc: TDLLFunc = nil;
var
    DLLHandle: THandle;
begin
    DLLHandle := LoadLibrary('forma.dll');
    if (DLLHandle < HINSTANCE_ERROR) then
        raise Exception.Create('Librería no encontrada.' + SysErrorMessage(GetLastError));

    try
        @DLLFunc := GetProcAddress(DLLHandle, 'pFormaMaestro');
        if Assigned(DLLFunc) then
            DLLFunc(txtUsuario.Text, txtContra.Text, txtBD.Text, txtEsquema.Text, txtTabla.Text);

    finally
        FreeLibrary(DLLHandle);
    end;
end;
Y el código de la dll es:

Código:
library forma;

uses
    ShareMem,
    SysUtils,
    Dialogs,
    Windows,
    Classes,
    DConexion in 'DConexion.pas' {dtmConexion: TDataModule} ,
    FPrincipal in 'FPrincipal.pas' {frmPrincipal} ,
    FAcerca in 'FAcerca.pas' {frmAcerca} ,
    FBusqueda in 'FBusqueda.pas' {frmBusqueda} ,
    FSplash in 'FSplash.pas' {frmSplash} ,
    FRegistro in 'FRegistro.pas' {frmRegistro};

procedure pFormaMaestro(pStUsuario: String; pStPassword: String; pStDB: String; pStEsquema: String; pStTabla: String);
begin
    //Pantalla Inicial
    frmSplash := TfrmSplash.Create(nil);
    frmSplash.Show;
    frmSplash.Update;

    //Crear el DataModulo
    dtmConexion := TdtmConexion.Create(nil);
    dtmConexion.gStTabla := pStTabla;
    dtmConexion.gStUsuario := pStUsuario;
    dtmConexion.gStPassword := pStPassword;
    dtmConexion.gStDB := pStDB;
    dtmConexion.gStEsquema := pStEsquema;
    dtmConexion.pInicioDatos;
    frmSplash.Hide;
    frmSplash.Free;

    //Crear la Forma
    if (dtmConexion.gBlSelect) then
    begin
        try
            frmPrincipal := TfrmPrincipal.Create(nil);
            frmPrincipal.ShowModal;
            dtmConexion.cdsPrincipal.Close;
            dtmConexion.qryPrincipal.Close;
            frmPrincipal.Hide;
            frmPrincipal.Free;
        except
            on E: Exception do
            begin
                ShowMessage(E.Message);
            end;
        end;
    end;
end;

exports pFormaMaestro;

begin

end.
Como comenté anteriormente, el código que acabé de exponer funciona bien, pero si cambio el "ShowModal" por el "Show" la aplicación falla.

Cabe anotar que estas líneas de código:

Código:
dtmConexion.cdsPrincipal.Close;
dtmConexion.qryPrincipal.Close;
frmPrincipal.Hide;
frmPrincipal.Free;
Las manejo dentro de los eventos de cierre del form cuando lo muestro con "Show".

Agradezco de antemano cualquier colaboración.
Responder Con Cita
  #2  
Antiguo 23-01-2013
Avatar de nlsgarcia
[nlsgarcia] nlsgarcia is offline
Miembro Premium
 
Registrado: feb 2007
Ubicación: Caracas, Venezuela
Posts: 2.206
Poder: 21
nlsgarcia Tiene un aura espectacularnlsgarcia Tiene un aura espectacular
cd.rafael,

Cita:
Empezado por cd.rafael
He revisado muchos temas respecto al manejo de forms dentro de una dll y hasta ahora no he podido resolver mi problema, que a continuación expongo: Tengo un ejecutable normal el cual invoca a una dll que a su vez lanza una form. Si dicha form la muestro con "ShowModal" todo funciona bien, pero si la dejo solo como "Show", el ejecutable deja de responder.
Revisa este código:
Código Delphi [-]
Library DLLForm;

uses
  SysUtils,
  Forms,
  UnitFrmDLL in 'UnitFrmDLL.pas' {FrmDLL};

{$R *.res}

procedure ShowForm; StdCall;
var
   f : TFrmDLL;
begin
   f := TFrmDLL.Create(Application);
   f.Show;
end;

exports
   ShowForm;

begin
end.
El código anterior declara una DLL (DLLForm) que Exporta el Procedure ShowForm el cual muestra un formulario con el método Show declarado en la unidad UnitFrmDLL.pas

Revisa el código de la Unidad UnitFrmDLL del DLL anterior.
Código Delphi [-]
unit UnitFrmDLL;

interface

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

type
  TFrmDLL = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  function mSum(x1, x2 : Double) : Double;
  function mSub(x1, x2 : Double) : Double;
  function mMul(x1, x2 : Double) : Double;
  function mDiv(x1, x2 : Double) : Double;

implementation

{$R *.dfm}

function mSum(x1, x2 : Double) : Double;
begin
   Result := x1 + x2;
end;

function mSub(x1, x2 : Double) : Double;
begin
   Result := x1 - x2;
end;

function mMul(x1, x2 : Double) : Double;
begin
   Result := x1 * x2;
end;

function mDiv(x1, x2 : Double) : Double;
begin
   Result := x1 / x2;
end;

procedure TFrmDLL.Button1Click(Sender: TObject);
var
   x1, x2 : Double;
begin
   x1 :=  StrToFloat(Edit1.Text);
   x2 :=  StrToFloat(Edit2.Text);
   ShowMessage(FloatToStr(mSum(x1,x2)));
end;

procedure TFrmDLL.Button2Click(Sender: TObject);
var
   x1, x2 : Double;
begin
   x1 :=  StrToFloat(Edit1.Text);
   x2 :=  StrToFloat(Edit2.Text);
   ShowMessage(FloatToStr(mSub(x1,x2)));
end;

procedure TFrmDLL.Button3Click(Sender: TObject);
var
   x1, x2 : Double;
begin
   x1 :=  StrToFloat(Edit1.Text);
   x2 :=  StrToFloat(Edit2.Text);
   ShowMessage(FloatToStr(mMul(x1,x2)));
end;

procedure TFrmDLL.Button4Click(Sender: TObject);
var
   x1, x2 : Double;
begin
   x1 :=  StrToFloat(Edit1.Text);
   x2 :=  StrToFloat(Edit2.Text);
   ShowMessage(FloatToStr(mDiv(x1,x2)));
end;

procedure TFrmDLL.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   Action := caFree;
end;

end.
Este formulario es instanciado en el Procedure ShowForm Exportado en el DLL anterior.

Revisa este código:
Código Delphi [-]
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure ShowForm; StdCall; External 'DLLForm';

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
   ShowForm;
end;

end.
El código anterior declara una referencia al procedure ShowForm del DLL anterior e invoca una llamada al mismo.

Revisa estos links:
Cita:
Creating and Using DLLs from Delphi
http://delphi.about.com/od/windowssh...dll_basics.htm

Static vs. Dynamic Dynamic Link Library Loading - A Comparison
http://delphi.about.com/od/windowssh...ic-dynamic.htm

Creating and Using DLLs from Delphi
http://delphi.about.com/od/windowssh...dll_basics.htm

Tutorials - Adding forms to a DLL
http://www.delphi-central.com/formdll.aspx
Todo el código anterior este disponible en el link: http://terawiki.clubdelphi.com/Delph...orm_in_DLL.rar

Espero sea útil

Nelson.

Última edición por nlsgarcia fecha: 23-01-2013 a las 02:40:22.
Responder Con Cita
  #3  
Antiguo 23-01-2013
Avatar de ozsWizzard
ozsWizzard ozsWizzard is offline
Miembro
 
Registrado: may 2004
Ubicación: Murcia
Posts: 190
Poder: 20
ozsWizzard Va por buen camino
Hola, cd.rafael.

A ver, lo primero son consejillo. Cuando crees y liberes objetos, yo me aseguraría de que se liberen siempre, haya habido errores o no en el código intermedio. Lo haría de la siguiente manera:
Código Delphi [-]
   Objeto := TObjeto.Create(param);
   try
      //Codigo...
   finally
      Objeto.Free; //Si la variable es global, incluso usaría FreeAndNil(Objeto);
   end;


Por otra parte, sobre este código:
Código Delphi [-]
procedure pFormaMaestro(pStUsuario: String; pStPassword: String; pStDB: String; pStEsquema: String; pStTabla: String);
begin
    //Pantalla Inicial
    frmSplash := TfrmSplash.Create(nil);
    frmSplash.Show;
    frmSplash.Update;

    //Crear el DataModulo
    dtmConexion := TdtmConexion.Create(nil);
    dtmConexion.gStTabla := pStTabla;
    dtmConexion.gStUsuario := pStUsuario;
    dtmConexion.gStPassword := pStPassword;
    dtmConexion.gStDB := pStDB;
    dtmConexion.gStEsquema := pStEsquema;
    dtmConexion.pInicioDatos;
    frmSplash.Hide;
    frmSplash.Free;

    //Crear la Forma
    if (dtmConexion.gBlSelect) then
    begin
        try
            frmPrincipal := TfrmPrincipal.Create(nil);
            frmPrincipal.ShowModal;
            dtmConexion.cdsPrincipal.Close;
            dtmConexion.qryPrincipal.Close;
            frmPrincipal.Hide;
            frmPrincipal.Free;
        except
            on E: Exception do
            begin
                ShowMessage(E.Message);
            end;
        end;
    end;
end;

Lo primero de lo que me doy cuenta es que el DataModule no lo liberas nunca, a veces las llamadas a dll dan problemas por cosas así.

Por otra parte, yo he tenido problemas usando formularios y componentes de base de datos en dll, pero sólo con dbexpres. Y no he sido capaz de arreglarlo, es dbexpres es así
__________________
La Madurez se llama...
~~~Gaia~~~
Responder Con Cita
  #4  
Antiguo 23-01-2013
cd.rafael cd.rafael is offline
Miembro
 
Registrado: abr 2012
Posts: 59
Poder: 13
cd.rafael Va por buen camino
Cordial Saludo,

De antemano agradezco sus prontas respuestas.

Respecto a la respuesta de nlsGarcia, tu apunte funciona perfecto, pero el tema es que quisiera que fuera de manera dinámica para evitar el crecimiento del tamaño del ejecutable. La idea es usar esa dll con el fin de evitar casi 20 formas que son similares.


Para la otra respuesta de ozsWizzard, te comento que ya había probado el liberar el DataModulo, pero me generaba excepciones que no pude controlarlas. Lo más extraño es que si lo hago de manera estática, como propone nlsGarcia, no me genera error. El problema es cuando es dinámica.

Voy a tratar de hacer una forma sencilla sin datamodulo y sin componentes, para ver qué puede ser.

Voy comentando lo que me vaya pasando...
Responder Con Cita
  #5  
Antiguo 23-01-2013
cd.rafael cd.rafael is offline
Miembro
 
Registrado: abr 2012
Posts: 59
Poder: 13
cd.rafael Va por buen camino
Cordial Saludo,

Pude resolver el problema colocando "SimpleShareMem" en el "uses" de la librería (tiene que estar de primero). El asunto es que cuando llamo al form con Show, la librería sigue su ejecución y no espera a que el formulario interactúe con el usuario. La verdad no sé porqué puede ser.

Lo que necesito es que la librería no termine su ejecución hasta que el formulario se cierre, pero no quiero usar ShowModal, porque me bloquea la aplicación principal.

Agradezco toda la colaboración que me puedan prestar.
Responder Con Cita
  #6  
Antiguo 23-01-2013
cd.rafael cd.rafael is offline
Miembro
 
Registrado: abr 2012
Posts: 59
Poder: 13
cd.rafael Va por buen camino
Cordial Saludo,

Ya logré realizar el cargue de la librería más de una vez. Se debe eliminar la instrucción "FreeLibrary" del mismo procedure donde se llama, hay que buscar otra forma para liberarla, tratando de detectar si la forma ya se cerró.

En fin... la gran decepción que tuve fue lo siguiente:

Cuando se lanza por primera vez la dll, la cual maneja los datos de una tabla X, funciona perfectamente. Cuando se llama la dll por segunda vez para manejar los datos de la tabla Y, sin haber terminado la primera llamada, la primera instancia que estaba manejando la tabla X, adopta los datos de la tabla Y que se maneja en la segunda instancia. Puede que sea por el manejo compartido de direcciones de memoria.

Lo único que me queda es pasar de librería a un ejecutable para no perder el trabajo.

Si de pronto alguien tiene alguna sugerencia, con gusto será escuchada.

Gracias.
Responder Con Cita
  #7  
Antiguo 23-01-2013
Avatar de ozsWizzard
ozsWizzard ozsWizzard is offline
Miembro
 
Registrado: may 2004
Ubicación: Murcia
Posts: 190
Poder: 20
ozsWizzard Va por buen camino
Yo haría funciones distintas para cada tabla. Si no es eso creo que no he entendido bien cual es el problema.
__________________
La Madurez se llama...
~~~Gaia~~~
Responder Con Cita
  #8  
Antiguo 23-01-2013
cd.rafael cd.rafael is offline
Miembro
 
Registrado: abr 2012
Posts: 59
Poder: 13
cd.rafael Va por buen camino
Cordial Saludo,

La idea de la librería es proporcionar una forma que me permita manejar las operaciones básicas en una tabla cualquiera (insertar, modificar, eliminar, imprimir y exportar). De esta manera evito tener una forma para cada tabla (aclarando que son tablas básicas, de referencia), ya que puedo enviarle a la dll cualquier tabla sin necesidad de generar código específico para cada tabla. Lo más importante es que se cargara de forma dinámica y no incrementar el tamaño del ejecutable principal.

Si el requerimiento hubiera permitido mantener la forma en estado modal, no habría problema, pero se necesita poder ver abrir más de una vez dicha librería y es ahí donde todo se complica, porque no independiza los datos. No coloco una función para cada tabla porque no sería algo estándar.

Gracias.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Error al crear un MDI Form jafera OOP 6 19-07-2011 14:10:13
Error con AdoQuery y 2 Form Cecilio Conexión con bases de datos 2 23-10-2008 17:37:04
Error al crear MDI Form Faust Varios 8 23-04-2008 05:12:01
Error en form de login FGarcia Varios 2 05-02-2006 05:00:27
Error Creating Form RolphyReyes Varios 4 02-09-2005 19:56:42


La franja horaria es GMT +2. Ahora son las 08:21:41.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi