Можно ли использовать сообщения в процедуре класса?

Я хочу использовать messages в своей программе, и у меня есть вопрос: могу ли я использовать сообщения в class procedure или могу ли я использовать messages в procedure без 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 возвращает следующее сообщение:

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

Большое спасибо.


person pedro.olimpio    schedule 04.02.2016    source источник
comment
Вы, вероятно, можете ответить на это сами. Удалите class перед procedure и скомпилируйте, и все заработает. Добавьте class снова, и это не так. Что непонятно? (Кстати, я не тот, кто проголосовал против. Просто любопытно, какую часть вам нужно было уточнить.)   -  person Ken White    schedule 04.02.2016
comment
Спасибо за вашу помощь @KenWhite. Вы не знаете, могу ли я использовать procedure ловлю message вне класса? procedure из unit? Еще раз спасибо за вашу поддержку.   -  person pedro.olimpio    schedule 04.02.2016
comment
Нет, ты не можешь. Процедура должна быть методом объекта для использования директивы message. (Вы можете снова проверить это самостоятельно.)   -  person Ken White    schedule 04.02.2016
comment
Спасибо. Не могли бы вы опубликовать ответ для меня, проголосовать за вашу помощь?   -  person pedro.olimpio    schedule 04.02.2016
comment
@qasoft написал очень хороший ответ. Вместо этого вы должны проголосовать за этот ответ; это дает больше деталей, чем мои комментарии. Спасибо за предложение. :-)   -  person Ken White    schedule 04.02.2016


Ответы (1)


На эту тему есть очень хорошая статья: Обработка сообщений в Delphi 6. Это необходимо прочитать.

Обработка или обработка сообщения означает, что ваше приложение каким-то образом отвечает на сообщение Windows. В стандартном приложении Windows обработка сообщений выполняется в каждой оконной процедуре.

Однако, интернализируя оконную процедуру, Delphi значительно упрощает обработку отдельных сообщений; вместо одной процедуры, обрабатывающей все сообщения, каждое сообщение имеет свою собственную процедуру. Чтобы процедура была процедурой обработки сообщений, должны быть выполнены три требования:

  • Процедура должна быть методом объекта.

  • Процедура должна принимать один переменный параметр записи TMessage или другого типа записи, относящегося к сообщению.

  • Процедура должна использовать директиву сообщения, за которой следует постоянное значение сообщения, которое вы хотите обработать.

Как вы можете прочитать в статье, процедура должна быть методом объекта, а не класса. Таким образом, вы не можете просто использовать обработчики сообщений в процедуре класса.


Возможный обходной путь для обработки сообщений в экземпляре класса (также в экземпляре объекта или приложениях без окон) — вручную создать дескриптор окна с помощью AllocateHWND и самостоятельно обрабатывать сообщения с помощью процедуры WndProc.

На сайте delphi.about.com есть хороший пример: Отправка сообщений в не оконные приложения (Страница 2):

Следующий образец представляет собой версию приведенного выше примера, измененную для работы с методом класса. (Если использование метода класса на самом деле не требуется, вместо этого используйте оригинальный пример из приведенной выше ссылки):

Во-первых, вам нужно объявить поле дескриптора окна и процедуру 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;

Наконец, в конце файла объявите секцию инициализации и финализации для создания/удаления дескриптора:

initialization
    FHandle := AllocateHWND(WndProc);

finalization
    DeallocateHWnd(FHandle);

Конечно, это не рекомендуемый способ (особенно следите за проблемами с инициализацией/финализацией), это был просто пример, показывающий, что это возможно.

Если у вас нет очень странного требования использовать метод класса, лучше использовать обычный метод класса, а также конструктор и деструктор объекта вместо разделов инициализации и завершения (как показано в Отправка сообщений в не оконные приложения (стр. 2).

person quasoft    schedule 04.02.2016