Показать сообщение отдельно
Старый 03.11.2005, 16:32     # 11
kot_
Junior Member
 
Аватар для kot_
 
Регистрация: 19.11.2004
Адрес: Dnepropetrovsk
Пол: Male
Сообщения: 67

kot_ Путь к славе только начался
Блин. Сервак падает раз, за разом.
Че за байда?
Что бы написать и отправить пост - четыре часа уходит
******************
Можно. Один из вариантов - создаешь сервер уведомлений на основе хотябы тогоже билдеровского РДМ-модуля. Делается это достаточно просто - создаешь новый проект - в него добаваляешь RDM-модуль(не забудь поставить галочку в эвентсах) и модель выбирай о вкусу - апартмент - на каждого юзера запускается отдельное приложение например, я предпочитаю фри - но эта модель достаточно сложна. Сохраняешь и лезешь в Type Library и в интерфейсах своего класса прописываешь необходимые тебе функции. В импл-модуле определяешь их. После определяешь какие события будут ловиться на твоих клиентах. Соответственно объявляешь их. Дальше свой сервер запускаешь с параметром /regserver. В принципе с сервером все. А ну соответственно в классе формы и классе интерфейса надо определить функции - это ниже. Для клиента прийдется написать заголовочный файл интерфейса класса событий и подключить в проект. Выглядит примерно так:
Код:
#if !defined (NOTCREMOUTESINK_H__)
#define NOTCREMOUTESINK_H__

#include <atlvcl.h>
#include <atlbase.h>
#include <atlcom.h>
#include <ComObj.HPP>
#include <utilcls.h>
#include "..\server\srvnotc_TLB.h"// Файл интерфейсов твоего сервера
//генерируется автоматически в проекте сервера.
typedef void __fastcall (__closure *TNewMessageEvents)( long employeeid );
typedef void __fastcall (__closure *TChangeStatusEvents)( BSTR contractid,long pointid );
//Ловим два события: Вызов фукции сервера GetNewMessage()
//получаем в нем идентификатор пользователя !которому! направлено сообщение
//Изменение статуса записи - событие генерируется при вызове функции InsertContract&UpdateContract
//Остальные сделаешь по примеру - а то листинг   
//Твой класс уведомлений
class TnOTCRemouteSink :
 public TEventDispatcher<TnOTCRemouteSink, &DIID_InOTCRemouteModuleEvents>
{
protected:
 TNewMessageEvents                      FOnNewMessage;
 TChangeStatusEvents                    FOnChangeStatus;
...
 HRESULT InvokeEvent(DISPID id, TVariant* params)
  {
      if ((id == 1) && (FOnNewMessage!= NULL))         FOnNewMessage(params[0]);
      else if ((id == 2) && (FOnChangeStatus != NULL)) 
        FOnChangeStatus(params[0],params[1]);
   ...
      return S_OK;
  }

  CComPtr<IUnknown> m_pSender;

public:
  __property  TNewMessageEvents  OnNewMessage  =
    { read = FOnNewMessage, write = FOnNewMessage };

  __property TChangeStatusEvents OnChangeStatus =
    { read = FOnChangeStatus, write = FOnChangeStatus };
...
public:
  TnOTCRemouteSink() :
     m_pSender(NULL),
     FOnNewMessage(NULL),
     FOnChangeStatus(NULL)
     
  {
  }

  virtual ~TnOTCRemouteSink()
  {
     Disconnect();
  }

    void Connect(IUnknown* pSender)
  {
     if (pSender != m_pSender)
        m_pSender = pSender;
     if (NULL != m_pSender)
       ConnectEvents(m_pSender);
  }

  void Disconnect()
  {
    if (NULL != m_pSender)
    {
      DisconnectEvents(m_pSender);
      m_pSender = NULL;
    }
  }
};

#endif
И в своем приложении пишешь примерно следующий код:
Код:
 TCOMInOTCRemouteModule m_remoute;//Твой сервер уведомлений
TnOTCRemouteSink RMSick;//
...
Srvnotc_tlb::ConOTCRemouteModule::CreateRemote(WideString("you_host"),m_remoute);
RMSick.OnNewMessage = TgfmMain::OnNewMessage;
RMSick.OnChangeStatus = TgfmMain::OnChangeStatus;
...
RMSick.Connect(m_remoute);
m_remoute->GetMessageEm(&myid);
//////////////На сервере функция GetMessage определяется примерно так:
....
STDMETHODIMP TnOTCRemouteModuleImpl::GetMessageEm(long id){
 fmMain->GetMessageEmp(id);
 return S_OK;
}
....
///
void __fastcall TfmMain:: GetMessageEmp(long id){
 int Index  = GetRecordIndexById(id);
//employeeV - ето вектор структур TEmployee - которые содержат инфу о подключенных в данный момент юзерах - заполняется в функции Login.
//Соответсвенно GetRecordIndexById(id) - возвращает индекс в векторе по иду пользователя. 
//employeeV[Index].dm - указатель на датамодуль,employeeV[Index].ra - указатель на интерфейс сервера
//все это опять же инициализируется при логине.
// Можно реализовать это все гораздо проще - или сложней :)
 if(employeeV[Index].dm->adoGetMessage->Active)employeeV[Index].dm->adoGetMessage->Active = false;
 employeeV[Index].dm->adoGetMessage->Parameters->ParamByName("@id")->Value = id;
 employeeV[Index].dm->adoGetMessage->Active = true;
if(employeeV[Index].dm->adoGetMessage->RecordCount)
 employeeV[Index].ra->Fire_OnNewMessage(employeeV[Index].id);
//Если есть новые сообчения - генерим событие.

}
Надеюсь как обработать событие на клиенте - писать не надо?
Ну вот в принципе и все. Просто у меня сервер решает более сложные задачи, которые может быть в твоем случае и на.х не нужны - и работа с базой у меня тоже идет через него. По этому я не расписывал функции логирования на сервер - главное - ты должен создать объект пользователя, приципить к нему уникальный ид и привязать ссылки на дм и рдм. И соответственно при дисконнекте - это все освободить. Да - еще это предполагает что ты пользуешься моделью взаимодействия фри - при аппартменте возможно будет гораздо проще - просто на каждого юзера будет стартовать сое приложение.
__________________
kot_ вне форума