Ver Mensaje Individual
  #4  
Antiguo 15-02-2010
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Reputación: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Al parecer, a partir de esa versión, Delphi cambió la forma en que maneja la ventana principal y la ventana de la aplicación. No termino todavía de entender cuáles son las diferencias pero parecen estar controladas por la propiedad MainFormOnTaskBar que por defecto está en false aunque todas las aplicaciones creadas con Delphi 2007 o superior ponen dicha propiedad en true en el DPR.

Hace mucho tiempo que lidié con este problema en Windows XP y el resultado fue éste. Aquí, utilizaba IsIconic sobre el handle de la aplicación para saber si estaba minimizada. Con la nueva propiedad en true, la ventana de la aplicación no se minimiza, sólo la del formulario principal. Aunque me extraña lo que comentas acerca de que no detecta el estado de la ventana ya que (al menos en Delphi 2010), cuando se minimiza la aplicación se ejecuta lo siguiente:

Código Delphi [-]
if FMainFormOnTaskBar then
begin
  if FMainForm <> nil then
    FMainForm.WindowState := wsMinimized
  else
    FInitialMainFormState := wsMinimized;
end

Bueno, en todo caso, he estado haciendo pruebas, para ver de qué manera podía yo corregir mi unidad uiapp.pas.

Finalmente, creo que lo he logrado, cambiando el procedimiento AppWndProc por este otro:

Código Delphi [-]
function AppWndProc(Handle: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LongInt; stdcall;
var
  FgThreadId  : DWORD; { Hilo de la app. que tenga el foco }
  AppThreadId : DWORD; { Hilo de nuestra aplicación        }

begin
  if Msg = mActivar then
  begin
    { Restaurar la aplicación }
    Application.Restore;

    { Obtener los hilos }
    FgThreadId  := GetWindowThreadProcessId(GetForegroundWindow, nil);
    AppThreadId := GetWindowThreadProcessId(Handle, nil);

    { Anexar el hilo de nuestra app. al de la  que tenga el foco }
    AttachThreadInput(AppThreadId, FgThreadId, true);

    { Ahora sí, activar la applicación }
    SetForegroundWindow(Handle);

    { Separar el hilo de nuestra app de la otra }
    AttachThreadInput(AppThreadId, FgThreadId, false);

    Result := 0;
    end
    else
        { Dejar que el procedimiento original se encargue de los otros mensajes }
        Result := CallWindowProc(PrevWndProc, Handle, Msg, wParam, lParam);
end;

que es más sencillo pues no hace distinción entre el estado iconizado y el normal, y parece que funciona también con Delphi7 por lo que supongo que también funcionará en XP (ahora mismo estoy probando con Vista).

Cabe notar que yo nunca pude hacer funcionar bien esto usando sólo BringToFront, si la instancia original no estaba minimizada. Lo unico que obtenía era el botón de la barra de tareas parpadeando. Pero posiblemente algo se me escapa. El caso es que por eso está el AttachThreadInput en mi código; para poder pasar al frente la aplicación y no sólo restaurarla.

También conviene observar que él método que uso es bastante distinto del que usa el componente que mencionas. En lugar de archivos mapeados en memoria, yo uso un mutex. Y en lugar de crear un componente, mi técnica consiste simplemente en incluir la unidad uiapp al comienzo del archivo dpr del proyecto.

En fin, por si quieres probar, adjunto aquí la unidad modificada. Recuerda que no es un componente sino simplemente un archivo a incluir en tu proyecto.

// Saludos
Archivos Adjuntos
Tipo de Archivo: zip UiApp.zip (1,1 KB, 41 visitas)
Responder Con Cita