2012-06-06 13 views
19

Con una clase (TObject) Tengo:Mensajes personalizados en clases sin ventana: ¿necesita un controlador predeterminado?

private 
    FHwnd : HWND; 
    procedure HandleMyMessage(var Message : TMessage); message TH_MYMESSAGE; 

donde TH_MYMESSAGE = WM_USER + 1

En el constructor de la clase:

FHwnd := AllocateHWND(HandleMyMessage); 

El único objeto que recibe una referencia a FHwnd es una costumbre privada TThread (creado dentro de esta clase) y el único mensaje que publica es TH_MYMESSAGE. Entiendo que la directiva message en la declaración de procedimiento restringe su manejo a solo TH_MYMESSAGE.

Esto funcionaba bien en las pruebas, pero después de la integración en una aplicación mucho más grande recibo retroalimentación que HandleMyMessage está disparando también para otros mensajes (con resultados obvios no deseados).

Esto se corrigió fácilmente agregando if Message.Msg <> TH_MYMESSAGE then Exit; en HandleMyMessage. Mi pregunta es: ¿por qué está pasando esto?

Mi mejor conjetura es que AllocateHWND ha hecho HandleMyMessage el equivalente de un DefWndProc a pesar de tener la directiva message. ¿Hay una forma correcta de implementar esto que me falta?

+4

su conjetura es correcta '' HandleMyMessage' convierte WndProc' de creado no visual ventana. para que reciba todos los mensajes; su solución para filtrar 'Message.Msg' también es correcta. modificador de método 'message' Usado por Delphi para el manejo predeterminado de llamadas' TObject.Dispatch' (en clases sin ventana) – teran

+0

@teran Asumiendo, entonces, que quería un 'WndProc' predeterminado para otros mensajes sería' HandleMyMessage' filter correctamente con la directiva 'message' si hubiera hecho' AllocateHWND' en algún otro procedimiento general? –

+0

@Ken No hay problema con WM_USER aquí. –

Respuesta

13

Bueno, sí, por supuesto. AllocateHWnd acepta TWndMethod para actuar como el procedimiento de ventana de la ventana creada. La confusión, creo, es causada por que el compilador acepta la directiva messsage. No lo ponga:

private 
    FHwnd : HWND; 
    procedure HandleMyMessage(var Message : TMessage); 

.. 

procedure TMyClass.HandleMyMessage(var Message: TMessage); 
begin 
    case Message.Msg of 
    TH_MYMESSAGE: // 
    end; 
    Message.Result := DefWindowProc(FHWnd, Message.Msg, Message.WParam, Message.LParam); 
end; 


edición: (respuesta al comentario). Para que el mensaje se maneja en la clase que creó la ventana de utilidad, puede dirigir su mensaje desde la ventana AllocateHWnd crea a su clase:

private 
    FHwnd : HWND; 
    procedure HandleMyMessage(var Message : TMessage); 
    procedure THMyMessage(var Message: TMessage); message TH_MYMESSAGE; 

.. 

procedure TMyClass.HandleMyMessage(var Message: TMessage); 
begin 
    case Message.Msg of 
    TH_MYMESSAGE: Dispatch(Message); 
    end; 
    Message.Result := DefWindowProc(FHWnd, Message.Msg, Message.WParam, Message.LParam); 
end; 

procedure TMyClass.THMyMessage(var Message: TMessage); 
begin 
    // 
end; 
+1

¿AllocateHwnd crea una ventana que recibe transmisiones? Para algo como esto estaría buscando una ventana con solo mensaje, HWND_MESSAGE. –

+1

Esto tiene sentido. La segunda parte de la pregunta: ¿podría definirse otro procedimiento en la misma clase que utilizara la directiva 'message' para desviar mensajes específicos del manejador principal? –

+1

@David - Claro, pero usar AllocateHWnd es mucho más fácil. Mi sistema está lleno de 'TPUtilWindow's en cualquier momento dado. –

Cuestiones relacionadas