2012-06-06 15 views
19

con una classe (TObject) ho:Messaggi personalizzati in classi non-Windowed - bisogno di un gestore predefinito?

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

dove TH_MYMESSAGE = WM_USER + 1

nel costruttore della classe:

FHwnd := AllocateHWND(HandleMyMessage); 

L'unico oggetto che riceve un riferimento a FHwnd è una consuetudine privata TThread (creato all'interno di questa classe) e l'unico messaggio che invia è TH_MYMESSAGE. La mia comprensione è che la direttiva message nella dichiarazione di procedura limita la sua gestione solo a TH_MYMESSAGE.

Questo stava funzionando bene nei test, ma dopo l'integrazione in un'applicazione molto più grande sto ricevendo il feedback che HandleMyMessage si attiva anche per altri messaggi (con evidenti risultati indesiderati).

Questo è stato facilmente corretto aggiungendo if Message.Msg <> TH_MYMESSAGE then Exit; in HandleMyMessage. La mia domanda è: perché sta succedendo questo?

La mia ipotesi migliore è che AllocateHWND abbia reso HandleMyMessage l'equivalente di un DefWndProc nonostante abbia la direttiva message. C'è un modo corretto per implementare questo che mi manca?

+4

la tua ipotesi è corretta 'HandleMyMessage' diventa' WndProc' del creato non visivo finestra. quindi riceve tutti i messaggi; anche la tua soluzione per filtrare 'Message.Msg' è corretta. modificatore del metodo 'message' usato da Delphi per la gestione predefinita delle chiamate' TObject.Dispatch' (in classi non a finestra) – teran

+0

@teran Supponendo, quindi, che volessi un 'WndProc' predefinito per gli altri messaggi il filtro' HandleMyMessage' correttamente con la direttiva 'message' se avessi fatto' AllocateHWND' su qualche altra procedura generale? –

+0

@Ken Nessun problema con WM_USER qui. –

risposta

13

Beh, sì certo. AllocateHWnd accetta un TWndMethod per agire come la procedura della finestra della finestra creata. La confusione, credo, è causata dal fatto che il compilatore accetta la direttiva messsage. Non metterlo:

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; 


edit: (risposta al commento). Per avere il messaggio gestito sulla classe che ha creato la finestra di utilità, è possibile instradare il messaggio dalla finestra AllocateHWnd crea alla classe:

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 finestra che riceve le trasmissioni? Per qualcosa di simile, sarei alla ricerca di una finestra solo messaggio, HWND_MESSAGE. –

+1

Questo ha senso. La seconda parte della domanda: potrebbe essere definita nella stessa classe un'altra procedura che utilizzava la direttiva 'message' per indirizzare messaggi specifici dal gestore principale? –

+1

@David - Certo, ma usare AllocateHWnd è molto più semplice. Il mio sistema è pieno di 'TPUtilWindow in qualsiasi momento. –