La activación de múltiples aplicaciones de Windows no funciona correctamente
Pregunta
Tengo una aplicación Delphi que tiene un navegador de documentos como formulario principal. Cuando el usuario abre un documento, abrimos una ventana de editor. Queremos tener cada editor con un botón en la barra de tareas, así como el formulario principal. He aplicado el código normal para hacer esto (a continuación), pero cuando hago clic en el formulario principal después de usar la ventana del editor, el editor se deja en la parte superior, mientras que el foco está en el formulario principal. No puedo determinar qué está causando este comportamiento.
Configuración de escenario: abro el formulario principal y un formulario de documento.
-
Haga clic en otra aplicación, haga clic en el formulario principal, el formulario principal permanece enfocado. (Comportándose como se esperaba)
-
Haga clic en el formulario del documento, haga clic en el formulario principal, el formulario del documento viene de atrás hacia adelante, pero se muestra inactivo. (La imagen muestra el resultado)
texto alternativo http://www.matthew-jones.com/temp_xfer/titlebarfailure .jpg
Primer paso, este es Delphi 2007, y tengo en el proyecto:
Application.MainFormOnTaskBar := True;
Para el formulario principal, no tengo código adicional.
Para el formulario del documento, tengo
procedure TCommonEditForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := 0; // GetDeskTopWindow; no diff
end;
He intentado averiguar si hay un mensaje que hace que esto suceda, pero no puedo encontrar nada apropiado. He buscado en el código cualquier cosa que tenga que ver con & Quot; activar & Quot ;. ¡Pistas bienvenidas!
Solución
Mi aplicación funciona de la manera que usted describe. Aquí está el enfoque que tomé. Me hubiera gustado encontrar un enfoque más simple pero nunca lo hice.
Comencé leyendo estos artículos. Este primero es un gran artículo escrito por Peter a continuación:
http: // groups -beta.google.com/group/borland.public.delphi.winapi/msg/e9f75ff48ce960eb?hl=es
También se encontró otra información aquí, sin embargo, esto no resultó ser una solución válida: para mi uso: http://blogs.teamb.com/DeepakShenoy/archive/ 2005/04/26 / 4050.aspx
Finalmente, aquí es con lo que terminé.
Mi pantalla de inicio también funciona como el formulario principal de la aplicación. El formulario principal tiene un vínculo especial con el objeto de aplicación. Usar todos los formularios secundarios me da el comportamiento que estaba buscando.
En cada formulario que quiero en la barra de tareas, anulo CreateParams. Hago esto en mis formularios de edición y lo que los usuarios ven como & Quot; formulario principal & Quot;
procedure TUaarSalesMain.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
Params.WndParent := GetDesktopWindow;
end;
Mi " Principal " En lo que respecta a Delphi, la forma carga la verdadera forma principal en su función Activitate. Utilizo una variable miembro para realizar un seguimiento de la primera activación. Luego, al final de la función, oculto el formulario de presentación, pero no lo cierro. Esto fue importante para mí porque si el usuario estaba editando un documento y cerraba el formulario principal, no quería que las pantallas de edición se cerraran al mismo tiempo. De esta forma, todos los formularios visibles se tratan de la misma manera.
if FFirstActivate = false then
exit;
FFristActivate := false;
/*
Main Load code here
Update Splash label, repaint
Application.CreateForm
etc.
*/
// I can't change visible here but I can change the size of the window
Self.Height := 0;
Self.Width := 0;
Self.Enabled := false;
// It is tempting to set Self.Visible := false here but that is not
// possible because you can't change the Visible status inside this
// function. So we need to send a message instead.
ShowWindow(Self.Handle, SW_HIDE);
end;
Pero todavía hay un problema. Necesita cerrar la ventana principal / de bienvenida cuando todos los demás formularios están cerrados. Tengo un control adicional en mis rutinas cercanas para Parent & Lt; & Gt; nulo porque utilizo formularios como complementos (mis propósitos funcionan mejor que los marcos).
Realmente no me gustó usar el evento Idle, pero no noto que esto sea un lastre para la CPU.
{
TApplicationManager.ApplicationEventsIdle
---------------------------------------------------------------------------
}
procedure TApplicationManager.ApplicationEventsIdle(Sender: TObject;
var Done: Boolean);
begin
if Screen.FormCount < 2 then
Close;
end;
{
TApplicationManager.FormCloseQuery
---------------------------------------------------------------------------
}
procedure TApplicationManager.FormCloseQuery(Sender: TObject;
var CanClose: Boolean);
var
i: integer;
begin
for i := 0 to Screen.FormCount - 1 do
begin
if Screen.Forms[i] <> self then
begin
// Forms that have a parent will be cleaned up by that parent so
// ignore them here and only attempt to close the parent forms
if Screen.Forms[i].Parent = nil then
begin
if Screen.Forms[i].CloseQuery = false then
begin
CanClose := false;
break;
end;
end;
end;
end;
end;
{
TApplicationManager.FormClose
---------------------------------------------------------------------------
}
procedure TApplicationManager.FormClose(Sender: TObject;
var Action: TCloseAction);
var
i: integer;
begin
for i := Screen.FormCount - 1 downto 0 do
begin
if Screen.Forms[i] <> self then
begin
// Forms that have a parent will be cleaned up by that parent so
// ignore them here and only attempt to close the parent forms
if Screen.Forms[i].Parent = nil then
begin
Screen.Forms[i].Close;
end;
end;
end;
end;
Esto me ha servido bien hasta ahora. Realicé un pequeño cambio en Vista porque el ícono de mi & Quot; Main / Splash & Quot; la pantalla todavía se mostraba. Sin embargo, no recuerdo qué fue eso. Probablemente no necesite establecer ancho, alto, habilitado y enviar el mensaje oculto en la pantalla de inicio. Solo quería asegurarme de que no apareciera :-).
Era necesario lidiar con los eventos cercanos. Si recuerdo correctamente, eso era necesario para cuando Windows envió un mensaje de apagado. Creo que solo el formulario principal recibe ese mensaje.
Otros consejos
Lo siento si esto es realmente estúpido, pero no tienes el estilo de formulario establecido en fsStayOnTop, ¿verdad? Esto explicaría este comportamiento.
quizás agregue esto en createparams
Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;
o intente esto en cualquier parte del código. Personalmente lo uso en los formularios. Evento OnCreate.
SetWindowLong(Wnd, GWL_EXSTYLE,
GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ;
la desventaja de esto es que si el formulario principal se minimiza, los otros formularios también se esconden, pero se restauran cuando el formulario principal lo hace.