liberar um form mdi shield da memória e chamá-lo novamente.
tenho um botão no form mdi shield e utilizo o comando "self.relesead" para remover o form da memória. Mas não consigo chamar a tela novamente. Simplesmente não aparece nada e não nenhuma mensagem de erro.
Alterei para o modelo abaixo, já que o Delphi 2007 não aceitou o comando "action = caFree;" para ser executado no onclik do botão.
private
{ private declarations }
vPodeFechar : Boolean;
procedure TForm940.FormCreate(Sender: TObject);
begin
vPodeFechar := False;
end;
procedure TForm940.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if vPodeFechar then
Action := caFree;
end;
procedure TForm940.BotaoFecharClick(Sender: TObject);
begin
vPodeFechar := True;
Close;
end;
Desse modo funcionou perfeitamente, mas não achei nada elegante.
Teria alguma outra solução ?
Alterei para o modelo abaixo, já que o Delphi 2007 não aceitou o comando "action = caFree;" para ser executado no onclik do botão.
private
{ private declarations }
vPodeFechar : Boolean;
procedure TForm940.FormCreate(Sender: TObject);
begin
vPodeFechar := False;
end;
procedure TForm940.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if vPodeFechar then
Action := caFree;
end;
procedure TForm940.BotaoFecharClick(Sender: TObject);
begin
vPodeFechar := True;
Close;
end;
Desse modo funcionou perfeitamente, mas não achei nada elegante.
Teria alguma outra solução ?
Nirlan Fundao
Curtidas 0
Respostas
Guinther Pauli
18/11/2008
Olá Nirlan,
Self é um ponteiro que aponta para outro o ponteiro real. Junta isso ao novo gerenciador de memoria FAST MMI que entrou no delphi 2006 e temos um comportamento diferente agora.
Bem, usando MDI isso fica mais claro ainda por isso que vc esta usando self.released e não funciona.
Assim, para liberar um objeto efetivamente da memória a partir do Delphi 2006 use freeandnil().
Bem no seu caso no onclose do formulário onde esta Action := caFree;
Faça:
FreeAnNil(SeuForm). Não use self pelo motivo exposto acima use sempre a variavel do formulário mesmo.
Aguardamos seu retorno,
abs
GOSTEI 0
Guinther Pauli
18/11/2008
Nirlan,
Bom dia !
Mais alguma dúvida sobre este chamado ou podemos encerrá-lo?
abs
GOSTEI 0
Nirlan Fundao
18/11/2008
usando o FreeAndNil eu consigo reabrir o form.
Mas ao fecha-lo recebo a mensagem de erro:
control "" has no parent window
alguma sugestão do motivo dessa mensagem ?
abraços
Nirlan
Mas ao fecha-lo recebo a mensagem de erro:
control "" has no parent window
alguma sugestão do motivo dessa mensagem ?
abraços
Nirlan
GOSTEI 0
Guinther Pauli
18/11/2008
Nirlan,
Existe mais algum codigo sendo executado no onClose ou no OnClose Query. Pois no exemplo que fiz e montei não deu este problema. Esta mensagem geralmente e dada quando tentamos por exemplo mover um foco a um controle não criado mas não ainda exibido, netre outras coisas.
Teria como mandar o exemplo que vc fez para que eu possa analisar ???
Aguardo retorno,
abs
GOSTEI 0
Nirlan Fundao
18/11/2008
Form Padrão:
var
Form940: TForm940;
implementation
uses DataModu;
{$R *.DFM}
procedure TForm940.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = Vk_Escape then Close;
end;
procedure TForm940.FormResize(Sender: TObject);
begin
GroupBox1.Left := (Panel3.ClientWidth div 2) - (GroupBox1.Width div 2);
GroupBox1.Top := (Panel3.ClientHeight div 2) - (GroupBox1.Height div 2);
PanelBotao.Left := (Panel1.ClientWidth div 2) - (PanelBotao.Width div 2);
end;
procedure TForm940.BotaoFecharClick(Sender: TObject);
begin
Close;
end;
procedure TForm940.Query1AfterOpen(DataSet: TDataSet);
var
k: Integer;
begin
for k := 0 to Query1.Fields.Count - 1 do
Query1.Fields.Fields[k].ProviderFlags := [pfInUpdate];
Query1.FieldByName( DM.vCampoChave ).ProviderFlags := [pfInUpdate,pfInKey];
end;
==================
O Form de inclusao do registro aonde ocorre a mensagem de erro, quando se clica no botão "fechar":
type
TForm100 = class(TForm940)
procedure BotaoCancelaClick(Sender: TObject);
procedure BotaoOKClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure BotaoAlteracaoClick(Sender: TObject);
procedure BotaoExclusaoClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure ConfiguraNovoRegistro;
public
{ Public declarations }
end;
var
Form100: TForm100;
implementation
uses DataModu, Prog102, Prog104;
{$R *.dfm}
procedure TForm100.BotaoAlteracaoClick(Sender: TObject);
begin
DM.OpenForm(TForm102, TForm(Form102));
end;
procedure TForm100.BotaoExclusaoClick(Sender: TObject);
begin
DM.OpenForm(TForm104, TForm(Form104));
end;
procedure TForm100.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeAndNil(Form100);
end;
procedure TForm100.FormActivate(Sender: TObject);
var
vSQL : String;
begin
if not ClientDS1.Active then
begin
vSQL := Select * From T06_GRUP +
Where +
T06_Exclusao is Null and +
T06_NumGrupo = -1 ;
if not DM.AbreTabela( ClientDS1, vSQL , T06_NumGrupo , True ) then
begin
Application.MessageBox(Ocorreu um erro na leitura dos dados. Tente novamente.,
Atenção, mb_ok + mb_IconError );
PostMessage(Handle, wm_Close, 0, 0);
end;
ConfiguraNovoRegistro;
end;
end;
procedure TForm100.ConfiguraNovoRegistro;
begin
ClientDS1.Append;
frNome.SetFocus;
end;
procedure TForm100.BotaoCancelaClick(Sender: TObject);
begin
if Application.MessageBox( Confirma o cancelamento da inclusão ?,
Atenção, mb_YesNo + mb_IconQuestion ) = idYes then
begin
ClientDS1.Cancel;
ConfiguraNovoRegistro;
end
else
frNome.SetFocus;
end;
procedure TForm100.BotaoOKClick(Sender: TObject);
begin
// Verifica a validade do nome do grupo
// ====================================
if StrAlltrim(frNome.Text) = then
begin
Application.MessageBox(O nome do grupo precisa ser informado.,
Atenção, mb_ok + mb_IconError );
frNome.SetFocus;
Exit;
end;
// Verifica existencia do nome
// ===========================
Query0.Close;
Query0.SQL.Clear;
Query0.SQL.Add( Select * From T06_GRUP );
Query0.SQL.Add( Where );
Query0.SQL.Add( T06_Exclusao is Null and );
Query0.SQL.Add( T06_NomeGrupo = :P0 );
Query0.Params[00].AsString := frNome.Text;
Query0.Open;
if not Query0.EOF then
begin
Application.MessageBox( Este grupo já foi cadastrada anteriormente. + #10#13 +
A gravação dos dados não pode ser efetuada.,
Atenção, mb_ok + mb_IconError );
frNome.SetFocus;
Exit;
end;
// Efetua a gravacao dos dados
// ===========================
try
ClientDS1.Post;
except
end;
if ClientDS1.ApplyUpdates(0) > 0 then
Application.MessageBox(Ocorreu um erro na gravação dos dados. Tente novamente.,
Atenção, mb_ok + mb_IconError )
else
begin
ClientDS1.Refresh;
ConfiguraNovoRegistro;
end;
end;
var
Form940: TForm940;
implementation
uses DataModu;
{$R *.DFM}
procedure TForm940.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key = Vk_Escape then Close;
end;
procedure TForm940.FormResize(Sender: TObject);
begin
GroupBox1.Left := (Panel3.ClientWidth div 2) - (GroupBox1.Width div 2);
GroupBox1.Top := (Panel3.ClientHeight div 2) - (GroupBox1.Height div 2);
PanelBotao.Left := (Panel1.ClientWidth div 2) - (PanelBotao.Width div 2);
end;
procedure TForm940.BotaoFecharClick(Sender: TObject);
begin
Close;
end;
procedure TForm940.Query1AfterOpen(DataSet: TDataSet);
var
k: Integer;
begin
for k := 0 to Query1.Fields.Count - 1 do
Query1.Fields.Fields[k].ProviderFlags := [pfInUpdate];
Query1.FieldByName( DM.vCampoChave ).ProviderFlags := [pfInUpdate,pfInKey];
end;
==================
O Form de inclusao do registro aonde ocorre a mensagem de erro, quando se clica no botão "fechar":
type
TForm100 = class(TForm940)
procedure BotaoCancelaClick(Sender: TObject);
procedure BotaoOKClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure BotaoAlteracaoClick(Sender: TObject);
procedure BotaoExclusaoClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
procedure ConfiguraNovoRegistro;
public
{ Public declarations }
end;
var
Form100: TForm100;
implementation
uses DataModu, Prog102, Prog104;
{$R *.dfm}
procedure TForm100.BotaoAlteracaoClick(Sender: TObject);
begin
DM.OpenForm(TForm102, TForm(Form102));
end;
procedure TForm100.BotaoExclusaoClick(Sender: TObject);
begin
DM.OpenForm(TForm104, TForm(Form104));
end;
procedure TForm100.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FreeAndNil(Form100);
end;
procedure TForm100.FormActivate(Sender: TObject);
var
vSQL : String;
begin
if not ClientDS1.Active then
begin
vSQL := Select * From T06_GRUP +
Where +
T06_Exclusao is Null and +
T06_NumGrupo = -1 ;
if not DM.AbreTabela( ClientDS1, vSQL , T06_NumGrupo , True ) then
begin
Application.MessageBox(Ocorreu um erro na leitura dos dados. Tente novamente.,
Atenção, mb_ok + mb_IconError );
PostMessage(Handle, wm_Close, 0, 0);
end;
ConfiguraNovoRegistro;
end;
end;
procedure TForm100.ConfiguraNovoRegistro;
begin
ClientDS1.Append;
frNome.SetFocus;
end;
procedure TForm100.BotaoCancelaClick(Sender: TObject);
begin
if Application.MessageBox( Confirma o cancelamento da inclusão ?,
Atenção, mb_YesNo + mb_IconQuestion ) = idYes then
begin
ClientDS1.Cancel;
ConfiguraNovoRegistro;
end
else
frNome.SetFocus;
end;
procedure TForm100.BotaoOKClick(Sender: TObject);
begin
// Verifica a validade do nome do grupo
// ====================================
if StrAlltrim(frNome.Text) = then
begin
Application.MessageBox(O nome do grupo precisa ser informado.,
Atenção, mb_ok + mb_IconError );
frNome.SetFocus;
Exit;
end;
// Verifica existencia do nome
// ===========================
Query0.Close;
Query0.SQL.Clear;
Query0.SQL.Add( Select * From T06_GRUP );
Query0.SQL.Add( Where );
Query0.SQL.Add( T06_Exclusao is Null and );
Query0.SQL.Add( T06_NomeGrupo = :P0 );
Query0.Params[00].AsString := frNome.Text;
Query0.Open;
if not Query0.EOF then
begin
Application.MessageBox( Este grupo já foi cadastrada anteriormente. + #10#13 +
A gravação dos dados não pode ser efetuada.,
Atenção, mb_ok + mb_IconError );
frNome.SetFocus;
Exit;
end;
// Efetua a gravacao dos dados
// ===========================
try
ClientDS1.Post;
except
end;
if ClientDS1.ApplyUpdates(0) > 0 then
Application.MessageBox(Ocorreu um erro na gravação dos dados. Tente novamente.,
Atenção, mb_ok + mb_IconError )
else
begin
ClientDS1.Refresh;
ConfiguraNovoRegistro;
end;
end;
GOSTEI 0
Guinther Pauli
18/11/2008
Nirlan,
Retire o codigo FreeAndNil(Form100); do OnCLose e coloque no evento OnDestroy do formulario isso irá resolver o seu problema.
Aguardo seu retorno,
abs
GOSTEI 0
Nirlan Fundao
18/11/2008
Fazendo isso o form é somente minimizado, pois ao clicar no botão Fechar, existe o comando Close, que apenas minimiza o form mdishield. Neste caso o evento onDestroy nunca é executado.
abraços
Nirlan
GOSTEI 0
Guinther Pauli
18/11/2008
Nirlan,
Segue link com vídeo e fonte do projeto que foi feito para você.
http://video.devmedia.com.br/naoexclusivos/RodrigoMourao/Consultoria/Chamado596.zip
Aguardamos seu retorno,
abs
GOSTEI 0
Nirlan Fundao
18/11/2008
muito obrigado. Problema resolvido.
GOSTEI 0