2010-07-29 17 views
5

Probé un script desde un sitio web Ejecuto http://www.delphi-central.com/runtime.aspx y lo logré.¿Por qué se bloquea mi programa cuando destruyo un botón en su propio controlador OnClick?


private 
    { Private declarations } 
    procedure CustomButtonClick(Sender: TObject); 

procedure TForm1.AddNewButtonClick(Sender: TObject); 
var 
    NewButton : TButton; 
begin 
    NewButton := TButton.create(self); 

    with NewButton do 
    begin 
    Top := 30; 
    Width := 60; 
    Left := Width * (self.ControlCount-2); 
    Parent := self; 
    OnClick := CustomButtonClick; 
    Caption := 'Button '+ inttostr (self.ControlCount-2); 
    end; //With 
end; 

procedure TForm1.DeleteLastButtonClick(Sender: TObject); 
begin 
    if Self.ControlCount>2 then 
    TButton (Controls[ControlCount-1]).destroy; 
end; 

procedure TForm1.CustomButtonClick(Sender: TObject); 
begin  
    ShowMessage(TButton(Sender).caption + ' Pressed'); 
end; 

Pero si cambio el OnClick,

OnClick := CustomButtonClick; ==> OnClick := DeleteLastButtonClick; 

se generará un mensaje de error. ¿Cómo pudo suceder esto ... ???

+5

Si quieres destruir un edificio, ¿lo harás ** dentro ** o ** afuera **? – Alex

+1

Tener su primera pregunta downvoted puede ser muy desalentador. ¿Es esta pregunta realmente "poco clara o no útil"? – mjn

+0

@josef: la respuesta de Mason es correcta; puedes ver TForm (en Forms.pas) cómo hace cosas similares; busque los procedimientos Release y CMRelease, y la constante CM_Release. –

Respuesta

5

Por supuesto que se dispara, eso es lo que sucederá cuando corte la rama en la que está sentado.

No se puede matar un control dentro de un controlador de eventos generado por ese control.

Tenga en cuenta que la muestra de la que está trabajando hizo NO ¡señale el CustomButtonClick en la rutina de eliminación!

+0

Creo que sé lo que quieres decir, ¿puedes dar un pequeño guión, así que lo entiendo mejor? –

+0

¿Un script para qué? El problema es que estás haciendo algo que no se puede hacer, punto. Mira la respuesta de Mason para una forma de hacerlo correctamente. –

+0

Déjeme ponerlo de esta manera Josef: Por favor ingrese a una cabina telefónica, luego, mientras está dentro de la cabina telefónica, por favor dé la orden de que se deje caer un peso de diez toneladas en la cabina telefónica. Ahora entiendes? –

6

Un controlador de eventos es invocado por una función en el objeto del control y podría tener más código para ejecutarse una vez que finalice el controlador de eventos. Si elimina el control, es probable que cualquier código que haga referencia a ese objeto genere una infracción de acceso.

Lo que tienes que hacer es hacer que tu programa elimine el control después de está hecho con todo el código que se está ejecutando actualmente. Para eso, necesitas publicar un mensaje. Si no conoce los mensajes, esta es una buena oportunidad para aprender.

Debe crear una nueva ID de tipo de mensaje. WM_USER + 1 debería funcionar. Uno de los parámetros será la dirección del control que se eliminará. Configure un manejador de mensajes en su formulario que maneje ese tipo de mensaje y libere el control al que se hace referencia en el parámetro de mensaje. Y luego, en el controlador de eventos, póngale a PostMessage ese mensaje en su formulario. Eso debería funcionar sin causar violaciones de acceso.

+0

Gracias Wheeler .. OK, ¿qué quiere decir "nuevo ID de tipo de mensaje"? tal vez me puedas dar un pequeño guión que comprenda más. –

+0

Si solo publico una muestra de código para que la copie y pegue, en realidad no aprenderá nada sobre el uso de mensajes, y entonces no sabrá qué hacer la próxima vez que publique un mensaje que pueda ser útil. Es por eso que StackOverflow realmente no es un sitio de "por favor dame código de trabajo". Es realmente simple si lo buscas y te he dado todo lo que necesitarás una vez que comprendas los principios involucrados. –

+3

Ahora sé lo que quieres decir, me sale un artículo sobre a quién te refieres "http://www.cryer.co.uk/brian/delphi/ howto_send_custom_window_message.htm" He aprendido más muchas gracias ... –

1

Es fácil pensar en el motivo, cuando se considera que el sistema debe de alguna manera volver a dibujar el botón después de soltar el botón/tecla del mouse. Ya que está borrando el objeto del botón ya durante el clic, esto fallará.

Por lo tanto, debe encontrar la forma de eliminar el botón de alguna manera después de que se haya procesado correctamente el evento onClick.

+0

Entonces ... ¿cómo? ¿¿algún consejo?? –

Cuestiones relacionadas