tags:

views:

116

answers:

3

I want my procedure WMInput(var Mess: TMessage); message WM_INPUT; to be placed in a separate unit.

Should I declare this the same way in the other unit (I'm asking if the prototype would still be the same procedure WMInput(var Mess: TMessage); message WM_INPUT;)?
How can I call this? Would the following be acceptable?

procedure WMInput(var Msg: TMessage)
begin
FUnit:= Fotherunit.create(self);
FUnit.WMInput(Msg);
end;

Are there any other alternatives?

+1  A: 

EDIT: this answer only kept for history reasons. For the real answer, see Rob Kennedy's answer.

You can do this. You don't strictly need a form though for your other unit - a 'unit' will work as well.

For the other unit: declare the procedure in the interface. And then you will not need a create either. Don't forget to included in 'uses'.

Tobiasopdenbrouw
Doesn't the message handler have to be a procedure "of object"? There is a hidden self parameter stored in such pointers.
mj2008
Tobiasopdenbrouw
+1 on mj2008 and iamjoosy
Tobiasopdenbrouw
+3  A: 

Although it is not quite clear to me what you want to achieve, a message method is, as mj2008 pointed out correctly, a method expecting a hidden self parameter. As such, it is typically declared as a method of a class(TControl or descedants). Back to your question: Since your procedure WMInput(var Mess: TMessage); message WM_INPUT;must be a (dynamic) method of a class (declaring it outside of a class will give you a compiler error), the answer to your question would be: no, you can't declare your message method in another unit.

But maybe you can clarify your question, trying to explain what you want to achieve, so that we can help you better.

iamjoosy
+5  A: 

Message handlers are methods, and they therefore must be declared and implemented within the same unit as the class they belong to.

That doesn't stop you from delegating the real work to some other function in another unit, though. There's nothing special about message handlers in that regard. Declare whatever function you like, and pass it whatever parameters it will need in order to accomplish its duties. If all it needs are the contents of the TMessage record, then so be it. However, it will probably also need to know what form received the message, so pass a reference to that, too. Or maybe it just needs to know the values of some of the form's private fields, so pass those instead.

You could make a unit for handling messages. Its interface section could look like this:

unit MessageHandlers;

interface

uses OtherUnit;

procedure HandleWMInput(Form: FOtherUnit; var Message: TWMInput);

There's nothing to designate that function as handling wm_Input messages; the message directive is only for classes.

Then, the implementation section of your form's unit can use that unit and call its functions:

uses MessageHandlers;

procedure FOtherForm.WMInput(var Message: TWMInput);
begin
  HandleWMInput(Self, Message);
end;

I've used TWMInput instead of TMessage. If Delphi doesn't already declare that type for you (in Messages.pas), then I suggest you declare it yourself. It lets Delphi perform the message-parameter cracking for you. For example, with the declaration below, the raw-input handle has a better type and name than the corresponding field in TMessage.

type
  TWMInput = packed record
    Msg: Cardinal;
    InputCode: Byte;
    Unused: array[0..2] of Byte;
    RawInput: HRawInput;
    Result: LongInt;
  end;
Rob Kennedy
Thanks for the comprehensive answer. It was a huge help. :D
Dian