Delphi: Qué es la aplicación.Manejar?


¿Qué es TApplication.Handle?

  • ¿De dónde viene?
  • por Qué existe?
  • Y lo más importante: ¿por qué todos los formularios lo tienen como su controlador de ventana padre?

La ayuda de Delphi dice:

TApplication.Handle

Proporciona acceso al controlador de ventana de la forma principal (ventana) de la aplicación.

property Handle: HWND;

Descripción

Use Handle cuando llame a la API de Windows funciones que requieren una ventana padre manejar. Por ejemplo, una DLL que muestra su propia ventana emergente de nivel superior windows necesita una ventana padre para mostrar sus ventanas en el aplicación. Uso de la propiedad Handle hace que tales ventanas parte de la aplicación, por lo que son minimizado, restaurado, habilitado y desactivado con la aplicación.

Si me centro en las palabras " el manejador de ventana de la forma principal de la aplicación", y lo tomo como el manejador de ventana de la forma principal de la aplicación , entonces puedo comparar:

  • "el manejador de ventana de la forma principal de la aplicación", con
  • la manija de la ventana del MainForm del Application

Pero no son lo mismo:{[27]]}

Application.MainForm.Handle: 11473728
Application.Handle: 11079574

Entonces, ¿qué es Application.Handle?

  • ¿De dónde viene?
  • ¿Qué manejador de ventana de Windows ® es?
  • Si es el controlador de ventana de Windows® de los Application's MainForm, entonces ¿por qué no partido?
  • Si es no el manejador de ventana de los Application's MainForm, entonces ¿qué es?
  • Más importante: ¿Por qué es el último padre propietario de cada forma?
  • Y lo más importante: ¿Por qué todo se vuelve loco si trato de que una forma sea sin parent sin dueño (para que pueda aparecer en la barra de tareas), o intento usar algo como IProgressDialog?

Realmente lo que estoy preguntando es: ¿Cuál es la justificación del diseño que hace Solicitud.Handle exist? Si puedo entender el por qué, el cómo debería ser obvio.


Update Comprensión a través de un juego de veinte preguntas:

Al hablar de la solución de hacer que una ventana aparezca en la barra de tareas haciendo que su propietario null, Pedro Abajo en 2000 dijo :

Esto puede causar algunos problemas con las formas modales mostradas desde formularios secundarios.

Si el usuario se aleja de la aplicación mientras que un modal forma está arriba, y luego de vuelta a la forma que lo mostró, la forma modal puede escóndete debajo del formulario. Es posible lidiar con esto asegurándose de la forma modal es parented [sic; él significó poseído] a la forma que la mostró (usando params.WndParent como antes)

Pero esto no es posible con el estándar los diálogos de la unidad Dialogs y las excepciones , que necesitan más esfuerzo para hacer que funcionen bien (básicamente manejando Application.OnActivate, buscando formas modales parented to Application via GetLastActivePopup y llevándolos a la parte superior de la orden Z vía SetWindowPos).

  • ¿Por qué una forma modal termina atascada detrás de otras formas?
  • ¿Qué mecanismo normalmente trae una forma modal al frente, y por qué no es funcional aquí?
  • Windows® es responsable de mostrar las ventanas apiladas. ¿Qué ha salido mal que Windows® no muestra las ventanas correctas?

También habló sobre el uso de las nuevas Ventanas extendidas estilo que obliga a una ventana a aparecer en la barra de tareas (cuando las reglas normales de hacerlo no propiedad son insuficientes, poco prácticas o indeseables), agregando el estilo extendido WS_EX_APPWINDOW:

procedure TForm2.CreateParams(var Params: TCreateParams); 
begin 
   inherited CreateParams( params ); 

   Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; 
end; 

Pero luego advierte:

Si hace clic en un botón de la barra de tareas de formularios secundarios mientras que otra aplicación está activa esto todavía traerá todos los formularios de solicitud al frente. Si no quiero que haya opción

Que está llevando todas las formas al frente cuando el propietario del formulario sigue siendo Application.Handle. ¿la aplicación está haciendo esto? ¿Por qué está haciendo esto? En lugar de hacer esto, no debería no estar haciendo esto? ¿Cuál es la desventaja de no hacer esto; veo la desventaja de hacerlo (el menú del sistema no funciona correctamente, las miniaturas de los botones de la barra de tareas son inexactas, Windows® shell no puede minimizar windows.


En otro post que trata de la Application, Mike Edenfield dice que la ventana padre envía otros ventana de su minimizar, maximizar y restaurar mensajes :

Esto agregará el botón de la barra de tareas para su formulario, pero hay algunos otros detalles menores para manejar. Obviamente, su formulario todavía recibe minimizar / maximizar que se envía al padre formulario (el formulario principal de la solicitud). Para evitar esto, puede instalar un mensaje manejador para WM_SYSCOMMAND agregando una línea como:

procedure WMSysCommand(var Msg: TMessage); WM_SYSCOMMAND; 

procedure TParentForm.WMSysCommand(var Msg: TMessage); 
begin 
   if Msg.wParam = SC_MINIMIZE then 
   begin 
      // Send child windows message, don't 
      // send to windows with a taskbar button. 
   end; 
end; 

Tenga en cuenta que este controlador va en el PARENT forma de la que desea comportarse independientemente > del resto de la aplicación, para evitar pasar el mensaje minimizar. Puede agregar código similar > para SC_MAXIMIZE, SC_RESTORE, etc.

¿Cómo es que minimizar/maximizar/restaurar mensajes para mi Windows® windows no van a mi ventana? ¿Es porque los mensajes destinados a una ventana son enviados por Windows® al propietario de la ventana? Y en este caso todos los formularios en una aplicación Delphi son "propiedad" de Application? ¿No significa eso que hacer que el propietario sea nulo:

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
   inherited;
   Params.WndParent := 0; //NULL
end;

Eliminará Application y su controlador de ventana de interferir con mi formulario, y Windows debería enviar una vez más me mis mensajes mimimize/maximize/restore?


Tal vez si comparamos y contrastamos ahora una aplicación de Windows "normal" hace cosas, con la forma en que Borland diseñó inicialmente las aplicaciones de Delphi para hacer cosas, con respecto a este objeto Application y su bucle principal.

  • ¿qué ¿la solución fue la solución de objetos Application?
  • ¿Qué cambio se hizo con las versiones posteriores de Delphi para que estos mismos problemas no existan?
  • ¿El cambio en las versiones posteriores de Delphi no introdujo otros problemas, que el diseño de la aplicación inicial trató tan duro de resolver?
  • ¿Cómo pueden seguir funcionando esas nuevas aplicaciones sin que la Aplicación interfiera con ellas?

Obviamente Borland se dio cuenta de la falla en su diseño inicial. ¿Cuál fue su inicial diseño, ¿qué problema estaba resolviendo, cuál es el defecto, cuál fue el rediseño, y cómo resuelve el problema?

Author: Ian Boyd, 2010-02-05

3 answers

El motivo de la ventana de la aplicación tiene un historial un poco sórdido. Al desarrollar Delphi 1, sabíamos que queríamos usar el modelo de interfaz de usuario "SDI" (windows dispersado por todo el escritorio) para el IDE. También sabíamos que Windows apestaba (y todavía lo hace) a ese modelo. Sin embargo, también notamos que Visual Basic en ese momento empleaba ese modelo y parecía funcionar bien. Tras un examen adicional, encontramos que VB utilizó una ventana de estacionamiento especial "oculta" que se utilizó como el "propietario" (Ventanas borra el noción de padre y propietario a veces, pero la distinción es similar a VCL) para todas las otras ventanas visibles.

Así es como resolvimos el "problema" donde las ventanas que contenían el menú principal rara vez se enfocaban, por lo que procesar Alt-F para el menú Archivo simplemente no funcionaría. Al usar esta ventana central de estacionamiento como intermediario, podríamos realizar un seguimiento y enrutar los mensajes a las ventanas apropiadas.

Este arreglo también resolvió otro problema donde normalmente múltiples ventanas de nivel superior eran totalmente independientes. Al hacer que la aplicación maneje el "propietario" de todas estas ventanas, todas se comportarían en concierto. Por ejemplo, es posible que haya notado que cuando selecciona cualquier de las ventanas de la aplicación, todas las ventanas de la aplicación se mueven al frente y conservan su orden z relativo entre sí. Esto también haría que la aplicación minimice y restaure como una agrupación funcional.

Eso es una consecuencia del uso de este modelo. Nos podría haber hecho manualmente todo este trabajo para mantener las cosas en orden, pero la filosofía de diseño era no reinventar Ventanas, sino aprovecharlas donde pudiéramos. También es por eso que un TButton o un TEdit es realmente un BOTÓN de "Usuario" de Windows y una clase y estilo de ventana de edición, respectivamente.

A medida que Windows evolucionó, ese modelo "SDI" comenzó a caer en desgracia. De hecho, Windows mismo comenzó a ser "hostil" a ese estilo de aplicación. Comenzando con Windows Vista y continuando con 7, el shell de usuario no parece funcionar bien con una aplicación que usa una ventana de estacionamiento. Por lo tanto, nos propusimos barajar las cosas en VCL para eliminar la ventana de estacionamiento y mover su función a la forma principal. Esto presentó varios problemas de" gallina y huevo "por lo que necesitamos tener la ventana de estacionamiento disponible lo suficientemente temprano en la inicialización de la aplicación para que otras ventanas puedan" adjuntarse " a ella, pero la forma principal en sí puede no ser construida lo suficientemente pronto. TApplication tiene que saltar a través de unos pocos aros para conseguir que esto funcione, y ha habido algunos casos sutiles de borde que han causado problema, pero la mayoría de los problemas se han resuelto. Sin embargo, para cualquier aplicación que avance, seguirá utilizando el modelo de ventana de estacionamiento anterior.

 48
Author: Allen Bauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-05 17:55:37

Todas las aplicaciones VCL tienen una ventana de nivel superior "oculta" llamada Aplicación. Esto se crea automáticamente al iniciar la aplicación. Entre otras cosas, es el principal manejador de mensajes de Windows para la aplicación VCL-hence.ProcessMessages.

Tener la ventana de nivel superior de aplicaciones oculta causa algunas cosas extrañas, notablemente el menú del sistema incompleto que se muestra en la barra de tareas, y las ventanas de clavos de pulgar incorrectas en Vista. Versiones posteriores de Delphi corrigen esto.

Sin embargo, no todas las ventanas debe tenerlo como padre, Windows solo tiende a funcionar mejor si lo es. Sin embargo, cualquier formulario creado con la Aplicación.CreateForm lo tendrá como padre, y también será propiedad del objeto de la aplicación. Como son propiedad, se liberarán una vez que se libere la Aplicación. Esto sucede detrás de las escenas en Formas.DoneApplication

 11
Author: Gerry Coll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-05 04:01:57

De mirar la fuente en los formularios.pas (Delphi 2009), parece que crean una ventana "master" en aplicaciones gui win32 para permitir llamadas a

  • TApplication.Minimizar
  • TApplication.Restaurar
  • etc

Parece que los mensajes pasados a Application.Handle se reenvían según corresponda a MainForm, si existe. Esto permitiría que la aplicación responda a minimizar, etc. si la ventana principal no se ha creado. Modificando el origen del proyecto puede crear un delphi app sin una ventana principal.

En este caso, los métodos TApplication seguirán funcionando, incluso si no ha creado una ventana principal. No estoy seguro de si estoy entendiendo todos los propósitos, pero no tengo tiempo para revisar todo el código de TApplication.

Según sus preguntas:

  • ¿de Dónde provienen? Es el identificador de una ventana creada en TApplication.Create

  • ¿Qué manija de las ventanas es? una ventana falsa que cada aplicación gui delphi requiere como parte de la abstracción de TApplication

  • ¿Es el manejador de windows de la forma principal de la aplicación No

  • Si no es el manejador de la forma principal de la aplicación, ¿qué es? Véase más arriba

  • Más importante aún: ¿por qué es el padre último de cada forma? asumiendo que tienes razón en que es el padre final, asumo que es así porque hace que sea fácil encontrar todos los formularios en su solicitud (enumerando la hijos de esta forma "maestra").

  • Y lo más importante: ¿por qué todo se vuelve loco si trato de que una forma no esté paralizada creo que debido a que la forma "maestra" oculta está recibiendo mensajes del sistema que debería pasar a sus hijos y/o a la forma principal, pero no puede encontrar la forma no paralizada.

De todos modos, esa es mi opinión. Probablemente puede obtener más información mirando la declaración y el código de TApplication en forms.pas. La línea de fondo de lo que veo que es una abstracción conveniente.

Saludos cordiales,

Don

 8
Author: Don Dickinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-05 14:28:13