Обратные вызовы в MIDAS через TSocketConnection
if Assigned(ClientIntf) then
ClientIntf.OnCall(MsgStr);
finally
Owner.unlock;
end;
end;
except
end;
if wParam <> 0 then // сообщение отработано - уничтожаем
TMsgClass(wParam).Free;
end
else
Result := DefWindowProc(Window, Message, wParam, lParam);
end;
Номер сообщению CM_CallbackMessage присваивается вызовом
RegisterWindowMessage('bkServer Callback SyncMessage'); |
также в секции инициализации.
Вот, собственно, и все - обратный вызов осуществляется из нужного потока. Теперь можно приступать к реализации клиентской части.
Клиентская часть
Состоит из одной формы, просто чтобы попробовать механизм передачи сообщений. На этапе разработки форма выглядит следующим образом (Рисунок 2):
Рисунок 2
Здесь присутствует TSocketConnection (scMain), которая соединяется с сервером BkServer. Кнопка "Соединиться" (btnConnect) предназначена для установки соединения, кнопка "Послать" (btnSend) – для отправки сообщения, записанного в окне редактирования (eMessage) остальным клиентским частям.
Код клиентской части довольно короток:
procedure TfrmClient.btnConnectClick(Sender: TObject); begin with scMain do Connected := not Connected; end; procedure TfrmClient.btnSendClick(Sender: TObject); var AServer: IrdmMainDisp; begin if not scMain.Connected then raise Exception.Create('Нет соединения'); AServer := IrdmMainDisp(scMain.GetServer); AServer.Broadcast(eMessage.Text); end; procedure TfrmClient.scMainAfterConnect(Sender: TObject); var AServer: IrdmMainDisp; begin FCallBack := TBackCall.Create; AServer := IrdmMainDisp(scMain.GetServer); AServer.RegisterCallBack(FCallBack); lConnect.Caption := 'Соединение установлено'; btnConnect.Caption := 'Отключиться'; end; procedure TfrmClient.scMainAfterDisconnect(Sender: TObject); begin FCallBack := nil; lConnect.Caption := 'Нет соединения'; btnConnect.Caption := 'Соединиться'; end; |
Фактически все управляется scMain, обработчиками OnAfterConnect (регистрирующим callback-интерфейс) и OnAfterDisconnect (производящим обратное действие). Разумеется, библиотека типов сервера подключена к проекту, но не через Import Type Library. Дело в том, что в проекте присутствует ActiveX Object TBackCall, который реализует интерфейс IBackCall, описанный в библиотеке типов сервера. Сделать такой объект очень просто: надо просто выбрать New -> Automation Object и в диалоге ввести имя BackCall (можно и другое, это не принципиально), выбрать ckSingle, и нажать ОК. В получившейся библиотеке типов сразу удалить интерфейс IBackCall, и на вкладке uses библиотеки типов подключить библиотеку типов сервера (есть локальное меню). После этого на вкладке Implements кокласса выбрать из списка интерфейс IBackCall. После обновления в модуле будет создан заглушка для метода OnCall, а в каталоге проекта клиента организуется файл импорта библиотеки типов сервера BkServer_TLB.pas, который остается только подключить к проекту и прописать в секциях uses модулей главной формы и СОМ-объекта. Метод OnCall я реализовал простейшим образом:
procedure TBackCall.OnCall(const MsgStr: WideString); begin ShowMessage(MsgStr); end; |
После компиляции приложение можно запустить в двух-трех экземплярах и проверить его работоспособность. Необходимо учитывать, что сообщения получают все клиенты, кроме пославшего его.
Таким образом, получилось хоть и минимальное, но работоспособное приложение с обратными вызовами и передачей сообщений между клиентскими частями. Хотя практически все реализовано вручную, без использования готовых методик COM, мне этот способ кажется наиболее предпочтительным, я просто реализовал обратные вызовы и маршалинг так, как мне хотелось. В результате вся реализация достаточно понятна и позволяет программировать вызовы так, как хочется.
Хотя мои друзья обозвали этот способ маршалинга вызовов "хакерским", мне все равно хотелось бы выразить им глубокую признательность за советы и терпение, с каким они отвечали на мои вопросы ;-)).
ПРИМЕЧАНИЕ Исполняемые модули были созданы в Delphi5 SP1. Для работы приложения, естественно, необходимо запустить Borland Socket Server, который входит в поставку Delphi. |