Flash ShowMessage(Pos) o cualquier otra ventana predefinida en la unidad de diálogos en Delphi para SO posterior a WInXP
-
21-09-2019 - |
Pregunta
Este es el enfoque que encontré para Tray...:
http://www.programmersheaven.com/mb/delphikylix/257563/257563/how-can-i-make-a-system-tray-flash/
¿Funciona la misma técnica para los diálogos (ya que, de hecho, son formularios con parámetros de suma)?¿O puedo hacerlo con métodos mucho más rápidos como obtener identificador/dirección/interfaz y sobrecargar o sobrecargar la función con el método FlashWindow(Ex)?
Quiero decir, ¿puedo hacer, por ejemplo ShowMessage(), una ventana/diálogo flash usando el método FlashWindowEx() y, si puedo, puedo hacerlo usando el ejemplo en el enlace que figura arriba?
Por favor, señale la mejor dirección o aclare mis dudas.
Gracias.
Perdón por la mala formulación de la pregunta.
Solución
Hay muchas formas en que se puede mostrar un formulario o diálogo modal (tanto VCL como nativo del sistema) desde un programa Delphi, por lo que necesita conectarse de alguna manera al procesamiento de mensajes y capturar los mensajes que se envían cuando se muestra un formulario o diálogo modal.
Para eso un mensaje gancho se puede configurar usando el SetWindowsHookEx()
Función API.Dado que solo necesita esto mientras la aplicación está inactiva, puede configurarlo en el controlador del OnDeactivate
evento de aplicación y restablecerlo en el controlador para el OnActivate
evento de aplicación:
var
gNextHook: HHOOK;
procedure TForm1.AppActivate(Sender: TObject);
begin
if gNextHook <> 0 then
UnhookWindowsHookEx(gNextHook);
gNextHook := 0;
end;
procedure TForm1.AppDeactivate(Sender: TObject);
begin
gNextHook := SetWindowsHookEx(WH_CALLWNDPROC, @WndProcHook, 0,
GetCurrentThreadId);
end;
La función de enlace vigilaría los mensajes que se envían cuando se muestra un cuadro de diálogo o formulario modal y llamaría FlashWindowEx()
con los parámetros correctos:
function WndProcHook(nCode: integer; AWParam: WPARAM; ALParam: LPARAM): LRESULT; stdcall;
var
DataPtr: PCWPStruct;
Fwi: TFlashWInfo;
begin
DataPtr := PCWPStruct(ALParam);
if (DataPtr^.message = WM_INITDIALOG)
or ((DataPtr^.message = CM_ACTIVATE) and (DataPtr^.lParam = 0) and (DataPtr^.wParam = 0))
then begin
Fwi.cbSize := SizeOf(TFlashWInfo);
// flash caption of new modal window
Fwi.hwnd := DataPtr^.hwnd;
Fwi.dwFlags := FLASHW_ALL or FLASHW_TIMERNOFG;
Fwi.uCount := 0;
Fwi.dwTimeout := 0;
FlashWindowEx(Fwi);
// uncomment this to flash task bar button as well
(*
Fwi.hwnd := Application.MainForm.Handle;
Fwi.dwFlags := FLASHW_TRAY or FLASHW_TIMERNOFG;
FlashWindowEx(Fwi);
*)
end;
Result := CallNextHookEx(gNextHook, nCode, AWParam, ALParam);
end;
Elegí WM_INITDIALOG
que se envía para cuadros de diálogo nativos como los cuadros de diálogo abrir o guardar, y CM_ACTIVATE
que se envía cuando un formulario VCL se muestra modalmente.Es posible que haya más mensajes de este tipo que deban detectarse.El código anterior funciona para el MessageDlg()
función, la Application.MessageBox()
función y TOpenDialog
al menos.
Dado que estos cuadros de diálogo no tienen su propio botón en la barra de tareas, también agregué (comenté) código para mostrar el botón de la barra de tareas del formulario principal.Esto no es óptimo, ya que no están sincronizados.
Probado con Delphi 2009 en Windows XP, se omitió todo el manejo de errores, utilícelo solo como punto de partida.
Otros consejos
La misma técnica se aplica a cualquier ventana de nivel superior, que incluye cuadros de diálogo. Si usted puede conseguir la manija de la ventana, puede pasarlo a FlashWindowEx
.