可以在 class 过程中使用消息吗?

Is possible to use messages in a class procedure?

我想在我的程序中使用 messages,我有一个问题:我可以在 class procedure 中使用消息还是可以在 procedure 中使用 messages没有 class?

这是我的代码:

const

  WM_CUSTOM_TCP_CLIENT = WM_USER + 10;

type
    TFeedbackEvent = class
      public
        class procedure feedback(var msg: TMessage); message WM_CUSTOM_TCP_CLIENT;
      end;

Delphi returns 留言如下:

[Error] unit.pas(33): Invalid message parameter list

非常感谢。

关于该主题有一篇非常好的文章:Handling Messages in Delphi 6。这是必读的。

Handling or processing a message means that your application responds in some manner to a Windows message. In a standard Windows application, message handling is performed in each window procedure.

By internalizing the window procedure, however, Delphi makes it much easier to handle individual messages; instead of having one procedure that handles all messages, each message has its own procedure. Three requirements must be met for a procedure to be a message-handling procedure:

  • The procedure must be a method of an object.

  • The procedure must take one var parameter of a TMessage or other message-specific record type.

  • The procedure must use the message directive followed by the constant value of the message you want to process.

正如您在文章中所读到的,过程必须是对象的方法,而不是 class。所以你不能只在 class 过程中使用消息处理程序。


在 class 实例(也在对象实例或 window-less 应用程序中)处理消息的可能解决方法是通过 AllocateHWND 手动创建 window 句柄,然后处理通过 WndProc 过程给自己发送消息。

delphi.about.com 中有一个很好的例子:Sending messages to non-windowed applications (Page 2):

以下示例是上述示例的一个版本,经过修改以使用 class 方法。 (如果确实不需要使用 class 方法,请改用上面 link 中的原始示例):

首先,您需要声明一个window句柄字段和一个WndProc过程:

TFeedbackEvent = class
private
  FHandle: HWND;
protected
  class procedure ClassWndProc(var msg: TMessage); 
end;

procedure WndProc(var msg: TMessage); 

然后,手动处理消息:

procedure WndProc(var msg: TMessage); 
begin
    TFeedbackEvent.ClassWndProc(msg);
end;

procedure TFeedbackEvent.ClassWndProc(var msg: TMessage);
begin
  if msg.Msg = WM_CUSTOM_TCP_CLIENT then
    // TODO: Handle your message
  else
    // Let default handler process other messages
    msg.Result := DefWindowProc(FHandle, msg.Msg, msg.wParam, msg.lParam);
end;

最后,在文件末尾,将初始化和完成部分声明为 create/destroy 句柄:

initialization
    FHandle := AllocateHWND(WndProc);

finalization
    DeallocateHWnd(FHandle);

当然,这不是推荐的方法(尤其要注意 initialization/finalization 的问题),这只是一个例子来说明这是可能的。

除非你有一些非常奇怪的要求使用class方法,否则最好使用常规class方法和对象构造函数和析构函数来代替初始化和结束部分(如[=15=所示) ]).