栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++快速开发例子--lpcdemo之monitor

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++快速开发例子--lpcdemo之monitor

 

// Interprocess Communication Demo
//
//  This program along with the Client.dpr project, demonstrate a number
//  of topics in Win32 programming. Threads, Events, Mutexes, and Shared
//  memory are all used to provide communication between this monitor and
//  it's clients, see IPCThrd.pas.
//
//  To Run, compile this project and the Client.cpp project.  Run one
//  instance of the monitor and then run several instances of the client.
//  You can switch between clients by clicking on the Client's window or
//  by selecting it from the Client menu in the monitor.
//
//  Topics Covered:
//
//    Interprocess Communication
//    Threads
//    Events
//    Mutexes
//    Shared Memory
//    Single instance EXE.
//
//---------------------------------------------------------------------------
#include "Monform.h"
#include "TrcView.h"
#include "About.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"

TMonitorForm *MonitorForm;
__fastcall  TMonitorForm::TMonitorForm(TComponent *Owner):TForm(Owner)
{
}

void __fastcall TMonitorForm::ClearLabels()
{
  int Index;

  for (Index = cfError; Index <= cfAttach; Index++)
  {
    TraceLabels[Index].YLabel->Caption = 0;
    TraceLabels[Index].XLabel->Caption = 0;
  }
}

void __fastcall TMonitorForm::OnConnect(TIPCThread* Sender, Boolean Connecting)
{
  if (Connecting)
  {
    FStatusText = IPCMonitor->ClientName;
    SignalClientStatus();
  }
  else
    FStatusText = "No Client";
  PostMessage(Handle, WM_UPDATeSTATUS, 0, 0);
}

void __fastcall TMonitorForm::OnDirectoryUpdate(TIPCThread *Sender)
{
  PostMessage(Handle, WM_UPDATEMENU, 0, 0);
}

void __fastcall TMonitorForm::OnSignal(TIPCThread *Sender, const TEventData &Data)
{
  FTraceMsg.X = Data.X;
  FTraceMsg.Y = Data.Y;
  FTraceMsg.Flag = Data.Flag;
  PostMessage(Handle,
              WM_SETTRACEDATA,
              FTraceMsg.X,
              FTraceMsg.Y);
}

void __fastcall TMonitorForm::SignalClientStatus()
{
  if (PauseButton->Down == true){
    TClientFlags NoFlags;
    IPCMonitor->SignalClient(NoFlags);
  }
  else
    IPCMonitor->SignalClient(FClientData.Flags);
}

void __fastcall TMonitorForm::UpdateTraceData(TWMTraceData* Msg)
{
   if (FClientData.Flags.Contains(FTraceMsg.Flag))
    {
      TraceLabels[FTraceMsg.Flag].XLabel->Caption = String((int)Msg->X);
      TraceLabels[FTraceMsg.Flag].YLabel->Caption = String((int)Msg->Y);
    }
}

void __fastcall TMonitorForm::UpdateStatusBar(TMessage* Msg)
{
  StatusBar->SimpleText = FStatusText;
  ClearLabels();
}

void __fastcall TMonitorForm::UpdateClientMenu(TMessage* Msg)
{
  int  I;
  int  ID;
  TStringList* List = new TStringList();
  TMenuItem*  mi;

  IPCMonitor->GetClientNames(List);
  while (miClients->Count > 0) {
    miClients->Delete(0);
  }
  if (List->Count == 0)
    miClients->Add(NewItem("(None)", 0, False, False, NULL, 0, ""));
  else
    for(I=0; I < List->Count; I++)
    {
      ID = (int)List->Objects[I];
      mi = NewItem(List->Strings[I], 0, False, True, ClientMenuClick, 0, "");
      mi->Tag = ID;
      mi->RadioItem = True;
      mi->GroupIndex = 1;
      miClients->Add(mi);
    }
  delete List;
}

void __fastcall TMonitorForm::SetupLabelArray()
{
    TraceLabels[cfMouseMove].XLabel = MoveX;
    TraceLabels[cfMouseMove].YLabel = MoveY;
    TraceLabels[cfMouseDown].XLabel = DownX;
    TraceLabels[cfMouseDown].YLabel = DownY;
    TraceLabels[cfResize].XLabel = SizeX;
    TraceLabels[cfResize].YLabel = SizeY;
}

void __fastcall TMonitorForm::FormCreate(TObject* Sender)
{
  IPCMonitor = new TIPCMonitor((int)Application->Handle, "Monitor");
  IPCMonitor->OnSignal = OnSignal;
  IPCMonitor->OnConnect = OnConnect;
  IPCMonitor->OnDirectoryUpdate = OnDirectoryUpdate;
  IPCMonitor->Activate();
  OnDirectoryUpdate(NULL);
  OnConnect(NULL, False);
  FClientData.Flags << cfMouseMove << cfMouseDown << cfResize;
  SetupLabelArray();
}

void __fastcall TMonitorForm::FormDestroy( TObject* Sender)
{
  IPCMonitor->Free();
}

void __fastcall TMonitorForm::ClientMenuClick( TObject* Sender)
{
  int  NewID;

  NewID = (int)((TMenuItem*)Sender)->Tag;
  if (NewID != IPCMonitor->ClientID)
    IPCMonitor->ClientID = NewID;
}

void __fastcall TMonitorForm::miClientsClick(TObject* Sender)
{
 int  I;

  if (IPCMonitor->ClientID != 0)
    for(I=0; I < miClients->Count; I++)
      if (miClients->Items[I]->Tag == IPCMonitor->ClientID)
      {
         miClients->Items[I]->Checked = True;
         break;
      }
}

void __fastcall TMonitorForm::SetTraceFlags( TObject* Sender)
{
 TClientFlag  F;

  F = (TClientFlag)((TCheckBox*)Sender)->Tag;
  if (((TCheckBox*)Sender)->Checked)
        FClientData.Flags << F;
  else
        FClientData.Flags >> F;

  SignalClientStatus();
}

void __fastcall TMonitorForm::AutoClientSwitch1Click( TObject* Sender)
{
    ((TMenuItem*)Sender)->Checked = ! ((TMenuItem*)Sender)->Checked;
    IPCMonitor->AutoSwitch = ((TMenuItem*)Sender)->Checked;
}

void __fastcall TMonitorForm::miFileExitClick( TObject* Sender)
{
  Close();
}

void __fastcall TMonitorForm::ShowTraceButtonClick( TObject* Sender)
{
  IPCMonitor->GetDebugInfo(TraceForm->TraceData->Items);
  TraceForm->ShowModal();
}

void __fastcall TMonitorForm::PauseButtonClick( TObject* Sender)
{
  SignalClientStatus();
}

void __fastcall TMonitorForm::ClearButtonClick( TObject* Sender)
{
  IPCMonitor->ClearDebugInfo();
}

void __fastcall TMonitorForm::ExitButtonClick( TObject* Sender)
{
  Close();
}

void __fastcall TMonitorForm::About1Click( TObject* Sender)
{
  ShowAboutBox();
}

//-----------------------------------------------------------------------------
#include "IPCThrd.h"
#include
//-----------------------------------------------------------------------------

// Utility Routines

void __fastcall Error(const AnsiString Msg)
{
  ShowMessage(Msg);
  throw(Msg);
}

AnsiString __fastcall EventName(TEventKind Event)
{
  switch (Event){
    case evMonitorAttach: return "evMonitorAttach";
    case evMonitorDetach: return "evMonitorDetach";
    case evMonitorSignal: return "evMonitorSignal";
    case evMonitorExit:   return "evMonitorExit";
    case evClientStart:   return "evClientStart";
    case evClientStop:    return "evClientStop";
    case evClientAttach:  return "evClientAttach";
    case evClientDetach:  return "evClientDetach";
    case evClientSwitch:  return "evClientSwitch";
    case evClientSignal:  return "evClientSignal";
    case evClientExit:    return "evClientExit";
    default:              return "";
  }
}

bool __fastcall IsMonitorRunning(THandle& Hndl)
{
   TSharedMem*  SharedMem;
   bool      Result;

   SharedMem = new TSharedMem(CLIENT_DIR_NAME, 4);
   Hndl = *((THandle*)(SharedMem->Buffer));
   Result = (Hndl != 0);
   delete SharedMem;
   return Result;
}

__fastcall  THandledObject::~THandledObject()
{
   if (FHandle != 0)
      CloseHandle(FHandle);
}


__fastcall TEvent::TEvent(const AnsiString Name, bool Manual)
{
   AnsiString buf;

   buf = Name + ".Data";
   FHandle = CreateEvent(NULL, Manual, false, buf.c_str());
   if (FHandle == 0) Abort();
}

void __fastcall TEvent::Reset()
{
   ResetEvent(FHandle);
}

void __fastcall TEvent::Signal()
{
   SetEvent(FHandle);
}

bool __fastcall TEvent::Wait(int TimeOut)
{
   return WaitForSingleObject(FHandle, TimeOut) == WAIT_OBJECT_0;
}

__fastcall TMutex::TMutex(const AnsiString Name)
{
   FHandle = CreateMutex(NULL, false, Name.c_str());
   if (FHandle == 0) Abort();
}

bool __fastcall TMutex::Get(int TimeOut)
{
   return WaitForSingleObject(FHandle, TimeOut) == WAIT_OBJECT_0;
}

bool __fastcall TMutex::Release(void)
{
   return ReleaseMutex(FHandle);
}

__fastcall TSharedMem::TSharedMem(const AnsiString Name, int Size)
{

   try{

    FName = Name;
    FSize = Size;

   
    FHandle = CreateFileMapping((HANDLE)0xFFFFFFFF,
                                NULL,
                                PAGE_READWRITE,
                                0,
                                Size,
                                Name.c_str());
    if (FHandle == 0) Abort();
    FCreated = (GetLastError == 0);
   
    FFileView = MapViewOfFile(FHandle,
                              FILE_MAP_WRITE,
                              0, 0, Size);
    if (FFileView == NULL) Abort();
  }
  catch(...) {
    Error(Format("Error creating shared memory %s (%d)",
                 (TVarRec*)Name.c_str(), GetLastError()));
  }
}

__fastcall TSharedMem::~TSharedMem()
{
   if (FFileView != NULL)
     UnmapViewOfFile(FFileView);
}

#if defined(IPCDEBUG)

 

__fastcall TIPCTracer::TIPCTracer(AnsiString ID)
{
   strcpy(FIDName, ID.c_str());
   FSharedMem = new TSharedMem(TRACE_BUFFER, TRACE_BUF_SIZE);
   FMutex = new TMutex(TRACE_MUTEX);

   //The first four bytes of the buffer contain the number of meaningful
   //bytes in the buffer at any given time.
   if (*((int*)(FSharedMem->Buffer)) == 0)
     *(int*)FSharedMem->Buffer = sizeof(PTraceEntry);
}

__fastcall TIPCTracer::~TIPCTracer()
{
   delete FMutex;
   delete FSharedMem;
}

PTraceEntry __fastcall TIPCTracer::MakePtr(int Ofs)
{
   return PTraceEntry(int(FSharedMem->Buffer) + Ofs);
}

PTraceEntry __fastcall TIPCTracer::FirstEntry()
{
   return MakePtr(sizeof(PTraceEntry));
}

PTraceEntry __fastcall TIPCTracer::NextEntry(void)
{
   return MakePtr(*(int*)(FSharedMem->Buffer));
}

void __fastcall TIPCTracer::Add(PChar AMsg)
{
   PTraceEntry    TraceEntry;
   int            EntrySize;
   TLargeInteger  TempTime;

   FMutex->Get(INFINITE);
   TraceEntry = NextEntry();
   EntrySize = sizeof(AMsg) + sizeof(TTraceEntry) + 16;

 
   if ((EntrySize + *(int*)(FSharedMem->Buffer))  >  FSharedMem->Size)
      TraceEntry = FirstEntry();

   QueryPerformanceCounter(&TempTime);
//  TraceEntry->Time = TempTime.LowPart;
   TraceEntry->Time = (int) TempTime.QuadPart;
   TraceEntry->Size = EntrySize;
   sprintf(TraceEntry->Msg,
          "%s: %s", FIDName, AMsg);
   *(int*)(FSharedMem->Buffer) = *(int*)(FSharedMem->Buffer) + TraceEntry->Size;
   FMutex->Release();
}

void __fastcall TIPCTracer::GetList(TStrings *List)
{
   PTraceEntry  LastEntry;
   PTraceEntry TraceEntry;
   int  Dif;
   int  LastTime;

   List->BeginUpdate();
   try{
    LastEntry = NextEntry();
    TraceEntry = FirstEntry();
    LastTime = TraceEntry->Time;
    List->Clear();
    while (TraceEntry != LastEntry){
      Dif = TraceEntry->Time - LastTime;
      List->Add(Format("%x %10d %s",
                       ARRAYOFCONST((TraceEntry->Time,
                                     Dif,
                                     TraceEntry->Msg))));
      LastTime = TraceEntry->Time;
      (int)TraceEntry = (int)TraceEntry + TraceEntry->Size;
    }
   }
   catch(...){
    List->EndUpdate();
    throw;
   }
   List->EndUpdate();
}

void __fastcall TIPCTracer::Clear()
{
   FMutex->Get(INFINITE);
   *(int*)FSharedMem->Buffer = sizeof(PTraceEntry);
   FMutex->Release();
}

#endif

__fastcall TIPCEvent::TIPCEvent(TIPCThread *AOwner,
                                const AnsiString Name,
                                bool Manual)
                    :TEvent(Name, Manual)
{
   FOwner = AOwner;
   FSharedMem = new TSharedMem(Name, sizeof(TIPCEventInfo));
   FEventInfo = (TIPCEventInfo*) FSharedMem->Buffer;
}

__fastcall TIPCEvent::~TIPCEvent()
{
   delete FSharedMem;
}

int __fastcall TIPCEvent::GetID()
{
   return FEventInfo->FID;
}

void __fastcall TIPCEvent::SetID(int Value)
{
   FEventInfo->FID = Value;
}

TEventKind __fastcall TIPCEvent::GetKind()
{
   return FEventInfo->FKind;
}

void __fastcall TIPCEvent::SetKind(TEventKind Value)
{
   FEventInfo->FKind = Value;
}

TEventData __fastcall TIPCEvent::GetData()
{
   return FEventInfo->FData;
}

void __fastcall TIPCEvent::SetData(const TEventData& Value)
{
   FEventInfo->FData = Value;
}

void __fastcall TIPCEvent::Signal(TEventKind Kind)
{
   SetID(OwnerID);
   FEventInfo->FKind = Kind;
   TEvent::Signal();
}

void __fastcall TIPCEvent::SignalID(TEventKind Kind, int ID)
{
   FEventInfo->FID = ID;
   FEventInfo->FKind = Kind;
   TEvent::Signal();
}

void __fastcall TIPCEvent::SignalData(TEventKind Kind,
                                      int ID,
                                      const TEventData& Data)
{
   FEventInfo->FID = ID;
   FEventInfo->FData = Data;
   FEventInfo->FKind = Kind;
   TEvent::Signal();
}

bool __fastcall TIPCEvent::WaitFor(int TimeOut,
                                      int ID,
                                      TEventKind Kind)
{
   bool returnval = Wait(TimeOut);
   if (returnval)
      returnval = (ID == FEventInfo->FID) && (Kind == FEventInfo->FKind);
   else
      FOwner->DbgStr(Format("Wait Failed %s Kind: %s ID: %x" ,
                            ARRAYOFCONST((FOwner->ClassName(),
                                          EventName(Kind),
                                          ID))));
   return returnval;
}

__fastcall TClientDirectory::TClientDirectory(int MaxClients)
{
   FMaxClients = MaxClients;
   FMutex = new TMutex(CLIENT_DIR_MUTEX);
   FSharedMem = new TSharedMem(CLIENT_DIR_NAME,
                              FMaxClients * sizeof(TClientDirEntry) + 8);
   FMonitorID = (int*) FSharedMem->Buffer;
   (int)FClientCount = (int)FMonitorID + sizeof(FMonitorID);
   (int)FDirBuffer = (int)FClientCount + sizeof(FClientCount);
}

__fastcall TClientDirectory::~TClientDirectory()
{
   delete FSharedMem;
}

int __fastcall TClientDirectory::AddClient(int ClientID, const AnsiString AName)
{
   int Result = -1;
   if (Count == FMaxClients)
      {
      String EString("Maximun of ");
      EString += (int)FMaxClients;
      EString += " clients allowed.";
      Error(EString);
      }
   if (IndexOf(ClientID) > -1)
      Error("Duplicate client ID");
   if (FMutex->Get(TIMEOUT)){
    try{
        FDirBuffer[Count]->ID = ClientID;
        lstrcpy(FDirBuffer[Count]->Name,
                AName.c_str());
        (*FClientCount)++;
        Result = Count-1;
    }
    catch(...){
      FMutex->Release();
      throw;
    } //end catch
   }   //end if (FMutex..
   FMutex->Release();
   return Result;
}

int __fastcall TClientDirectory::GetCount()
{
   return (*FClientCount);
}

TClientDirEntry __fastcall TClientDirectory::GetClientRec(int Index)
{
   if ((Index < 0) || (Index >= Count))
     Error("Invalid client list index");
   return *FDirBuffer[Index];
}

AnsiString __fastcall TClientDirectory::GetClientName(int ClientID)
{
   int  Index;

   Index = IndexOf(ClientID);
   if (Index >= 0)
     return FDirBuffer[Index]->Name;
   else
     return "";
}

int __fastcall TClientDirectory::IndexOf(int ClientID)
{
   int  I;

   for(I=0; I < Count; I++)
   if (FDirBuffer[I]->ID == ClientID){
        return I;
   }
   return -1;
}

int __fastcall TClientDirectory::Last()
{
   if (Count > 0)
     return FDirBuffer[Count-1]->ID;
   else
     return 0;
}

bool __fastcall TClientDirectory::RemoveClient(int ClientID)
{
   int  Index;
   bool  Result;
   Index = IndexOf(ClientID);
   if ((Index > -1) && FMutex->Get(TIMEOUT)){
     try{
       if ((Index > 0) && (Index < Count))
         Move(FDirBuffer[Index+1],
              FDirBuffer[Index],
             (Count - Index) * sizeof(TClientDirEntry));
       (*FClientCount)--;    //Decrement client count
       Result = true;
     }
    catch(...){
       FMutex->Release();
       throw;
     }
     FMutex->Release();
   } //end if
   else
      Result = false;
   return Result;
}

int __fastcall TClientDirectory::GetMonitorID()
{
   return *FMonitorID;
}

void __fastcall TClientDirectory::SetMonitorID(int MonitorID)
{
   *FMonitorID = MonitorID;
}

__fastcall TIPCThread::TIPCThread(int AID, const AnsiString AName)
                      :TThread(true)
{
   FID = AID;
   FName = AName;
#if defined(IPCDEBUG)
   if (dynamic_cast(this) != 0)
      FTracer = new TIPCTracer(FName);
   else
      FTracer = new TIPCTracer(IntToHex(FID, 8));
#endif
   FMonitorEvent = new TIPCEvent(this, MONITOR_EVENT_NAME, false);
   FClientEvent = new TIPCEvent(this, CLIENT_EVENT_NAME, false);
   FConnectEvent = new TIPCEvent(this, CONNECT_EVENT_NAME, false);
   FClientDirectory = new TClientDirectory(MAX_CLIENTS);
}

__fastcall TIPCThread::~TIPCThread()
{
   DeActivate();
   delete FClientDirectory;
   delete FClientEvent;
   delete FMonitorEvent;
   FState = stInActive;
#if defined(IPCDEBUG)
   delete FTracer;
#endif
}

void __fastcall TIPCThread::DbgStr(const AnsiString S)
{
#if defined(IPCDEBUG)
   FTracer->Add(S.c_str());
#endif
}

__fastcall TIPCMonitor::TIPCMonitor(int AID, const AnsiString AName)
                      : TIPCThread(AID, AName),
                        FAutoSwitch(true)

{
}

void __fastcall TIPCMonitor::Activate()
{
   if (FState == stInActive) {
    // Put the monitor handle into the client directory so we can use it to
    //  prevent multiple monitors from running
    if (FClientDirectory->MonitorID == 0)
      FClientDirectory->MonitorID = FID;
    else
        throw EMonitorActive("Monitor is already active.");
    FState = stDisconnected;
    Resume();
   }
}

void __fastcall TIPCMonitor::DeActivate()
{
   if ((State != stInActive) && !(Suspended)){
    FClientDirectory->MonitorID = 0;
    FMonitorEvent->Signal(evMonitorExit);
    if (WaitForSingleObject((void *)Handle, TIMEOUT) != WAIT_OBJECT_0)
        TerminateThread((void *)Handle, 0);
   }
}

void __fastcall TIPCMonitor::Execute()
{
   int WaitResult;
   bool bContinueThread = true;
   DbgStr(FName + " Activated");

   if (FClientDirectory->Count > 0)
     FMonitorEvent->SignalID(evClientStart, FClientDirectory->Last());
   while (bContinueThread == true){
    try {
      WaitResult = WaitForSingleObject(FMonitorEvent->Handle, INFINITE);
      if (WaitResult >= WAIT_ABANDONED)
            DisconnectFromClient(false);
      else{
        if (WaitResult == WAIT_OBJECT_0)
        {
          DbgStr("Event Signaled: " + EventName(FMonitorEvent->Kind));
          switch (FMonitorEvent->Kind){
            case evClientSignal:
              DoOnSignal();
              break;
            case evClientStart:
              if ((AutoSwitch == true) || (FClientID == 0))
                ConnectToClient(FMonitorEvent->ID);
              DoOnDirUpdate();
              break;
            case evClientStop:
              DoOnDirUpdate();
              break;
            case evClientDetach:
              DisconnectFromClient(false);
              Sleep(100);
              if (AutoSwitch != false)
                ConnectToClient(FClientDirectory->Last());
              break;
            case evClientSwitch:
              ConnectToClient(FMonitorEvent->ID);
              break;
            case evMonitorExit:
              DisconnectFromClient(false);
              bContinueThread = false;
              break;
            default:
              break;
          } //end switch
        } //end if
        else {
          DbgStr(Format("Unexpected Wait Return Code: %d",
                        ARRAYOFCONST((WaitResult))));
        } //end else
      } //end else
    } //end try
    catch(Exception& E){
      DbgStr(Format("Exception raised in Thread Handler: %s at %X",
                    ARRAYOFCONST((E.Message, ExceptAddr))));
    } //end catch
   }//end while
   FState = stInActive;
   DbgStr("Thread Handler Exited");
}

void __fastcall TIPCMonitor::ConnectToClient(int ID)
{
   if (ID == FClientID) return;
   if (FState == stConnected)
      DisconnectFromClient(true);
   if (ID == 0) return;
   DbgStr(Format("Sending evMonitorAttach: %X",
                ARRAYOFCONST((ID))));

   
   FConnectEvent->SignalID(evMonitorAttach, ID);

   
   if ((FMonitorEvent->WaitFor(TIMEOUT, ID, evClientAttach) != false) &&
     (FMonitorEvent->Data.Flag == cfAttach)) {
      FClientID = ID;
      FState = stConnected;
      if (FOnConnect != NULL)
        OnConnect(this, true);
      DbgStr("ConnectToClient Successful");
  }
  else
      DbgStr("ConnectToClient Failed: " + EventName(FMonitorEvent->Kind));
}

void __fastcall TIPCMonitor::DisconnectFromClient(bool Wait)
{
   if (FState == stConnected){
    DbgStr(Format("Sending evMonitorDetach: %x",
                  ARRAYOFCONST((FClientID))));

   
    FClientEvent->SignalID(evMonitorDetach, FClientID);

   
    if (Wait)
      if (FMonitorEvent->WaitFor(TIMEOUT, FClientID, evClientDetach) == 0){
        DbgStr(Format("Error waiting for client to detach: %x",
                      ARRAYOFCONST((FClientID))));
        FClientDirectory->RemoveClient(FClientID);
      }
    FClientID = 0;
    FState = stDisconnected;
    if (FOnConnect != 0)
      FOnConnect(this, false);

    if ((! Wait) && (FOnDirUpdate != NULL))
      DoOnDirUpdate();
    }
}

void __fastcall TIPCMonitor::DoOnSignal(void)
{
   if ((FOnSignal != NULL) && (FMonitorEvent->ID == FClientID))
     FOnSignal(this, FMonitorEvent->Data);
}

void __fastcall TIPCMonitor::SignalClient(const TClientFlags Value)
{
   if (FState == stConnected){
      FClientEvent->EventInfo->FData.Flags = Value;
      DbgStr("Signaling Client");
      FClientEvent->SignalData(evMonitorSignal, FClientID, FClientEvent->Data);
   }
}

AnsiString __fastcall TIPCMonitor::GetClientName()
{
   return FClientDirectory->Name[FClientID];
}

void __fastcall TIPCMonitor::GetClientNames(TStringList* List)
{
   int  I;
   AnsiString  S;
   int  DupCnt;

   List->BeginUpdate();
   try{
    List->Clear();
    for(I=0; I < FClientDirectory->Count; I++){
      S = FClientDirectory->ClientRec[I].Name;
      DupCnt = 1;

     
      while(List->IndexOf(S) > -1){
           DupCnt++;
           S = Format("%s (%d)",
                      ARRAYOFCONST((FClientDirectory->ClientRec[I].Name,
                                    DupCnt)));
      }
      List->AddObject(S, (TObject*)FClientDirectory->ClientRec[I].ID);
    }
   }
   catch(...){
    List->EndUpdate();
    throw;
   }
   List->EndUpdate();
}

void __fastcall TIPCMonitor::SetCurrentClient(int ID)
{
   if (ID == 0)
     ID = FClientDirectory->Last();
   if (ID !=0)
     FMonitorEvent->SignalID(evClientSwitch, ID);
}

void __fastcall TIPCMonitor::ClearDebugInfo()
{
#ifdef IPCDEBUG
   FTracer->Clear();
#endif
}

void __fastcall TIPCMonitor::GetDebugInfo(TStrings *List)
{
#ifdef IPCDEBUG
   FTracer->GetList(List);
#else
   List->Add("Debug Tracing Disabled");
#endif
}

void __fastcall TIPCMonitor::SaveDebugInfo(const AnsiString FileName)
{
#if defined(IPCDEBUG)
   TStringList*  List;

   List = new TStringList();
   try{
      GetDebugInfo(List);
      List->SaveToFile(FileName);
   }
   catch(...){
      delete List;
      throw;
   }
   delete List;
#endif
}

void __fastcall TIPCMonitor::DoOnDirUpdate()
{
   if (FOnDirUpdate != NULL)
     FOnDirUpdate(this);
}

void __fastcall TIPCClient::Activate()
{
   if (FState == stInActive){
     FWaitEvent = FConnectEvent;
     FMonitorEvent->OwnerID = FID;
     FConnectEvent->OwnerID = FID;
     FClientEvent->OwnerID = FID;
     FClientDirectory->AddClient(FID, FName);
     FState = stDisconnected;
     Resume();
   }
}

void __fastcall TIPCClient::DeActivate()
{
   if (FClientDirectory != NULL)
     FClientDirectory->RemoveClient(FID);
   if ((FState != stInActive) && !(Suspended)){
      FWaitEvent->Signal(evClientExit);
      if (WaitForSingleObject((void *)Handle, TIMEOUT) != WAIT_OBJECT_0)
        TerminateThread((void *)Handle, 0);
    }
}

void __fastcall TIPCClient::Execute(void)
{
   DbgStr(FName + " Activated");
   bool bContinueThread = true;

   if ((FClientDirectory->MonitorID) != 0)
    {
      FMonitorEvent->SignalID(evClientStart, FID);
    }
   while (bContinueThread == true){
    try{
      if (WaitForSingleObject(FWaitEvent->Handle, INFINITE) != WAIT_OBJECT_0)
        break;
      if (FWaitEvent->ID != FID){
        Sleep(200);
        continue;
      }
      DbgStr("Client Event Signaled: " + EventName(FWaitEvent->Kind));
      switch(FWaitEvent->Kind){
        case evMonitorSignal:
          if (FOnSignal != NULL)
            FOnSignal(this, FWaitEvent->Data);
          break;
        case evMonitorAttach:
          ConnectToMonitor();
          break;
        case evMonitorDetach:
          DisconnectFromMonitor(false);
          Sleep(200);
          break;
        case evClientExit:
          if (FClientDirectory->MonitorID != 0) {
            if (FState == stConnected)
              DisconnectFromMonitor(true);
            else
              FMonitorEvent->Signal(evClientStop);
          }
          bContinueThread = false;
          break;
        default:
          break;
      } //end switch
    } //end try
    catch(Exception& E){
      DbgStr(Format("Exception raised in Thread Handler: %s at %X",
                    ARRAYOFCONST((E.Message, ExceptAddr))));
    }//end try-catch
   } //end while
   FState = stInActive;
   DbgStr("Thread Handler Exited");
}

void __fastcall TIPCClient::ConnectToMonitor()
{
   TEventData Data;
   DbgStr("ConnectToMonitor Begin");
   FConnectEvent->Reset();
   try {
     FState = stConnected;
     FWaitEvent = FClientEvent;
     Data.Flag = cfAttach;
     FMonitorEvent->SignalData(evClientAttach, FID, Data);
     if (FOnConnect != 0)
       FOnConnect(this, true);
   }
   catch(Exception& E){
     DbgStr("Exception in ConnectToMonitor: " + E.Message);
     Data.Flag = cfError;
     FMonitorEvent->SignalData(evClientAttach, FID, Data);
   }
   DbgStr("ConnectToMonitor End");
}

void __fastcall TIPCClient::DisconnectFromMonitor(bool Wait)
{
   DbgStr("DisconnectFromMonitor Begin");
   if (FState == stConnected) {
     if (Wait){
       DbgStr("Sending evClientDetach");
       FMonitorEvent->Signal(evClientDetach);
       if (FClientEvent->WaitFor(TIMEOUT, FID, evMonitorDetach))
         DbgStr("Got evMonitorDetach");
       else
         DbgStr("Error waiting for evMonitorDetach");
     }
     FState = stDisconnected;
     FWaitEvent = FConnectEvent;
     if (! Wait){
       DbgStr("DisconnectFromMonitor sending evClientDetach");
       FMonitorEvent->Signal(evClientDetach);
     }
     if (FOnConnect != NULL)
       FOnConnect((TIPCThread*)this, false);
   }
   DbgStr("DisconnectFromMonitor End");
}

void __fastcall TIPCClient::SignalMonitor(const TEventData& Data)
{
   if (FState == stConnected){
     DbgStr("Signaling Monitor");
     FMonitorEvent->SignalData(evClientSignal, FID, Data);
   }
}

int __fastcall TIPCClient::ClientCount()
{
   return FClientDirectory->Count;
}

void __fastcall TIPCClient::MakeCurrent()
{
   FMonitorEvent->SignalID(evClientStart, FID);
}
 

//---------------------------------------------------------------------------
#include "about.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TAboutBox *AboutBox;

 __fastcall TAboutBox::TAboutBox(TComponent* Owner) : TForm(Owner)
{
}

void __fastcall TAboutBox::FormCreate(TObject *Sender)
{
  Caption = Format("About %s",
                   ARRAYOFCONST((Application->Title)));
  ProgramIcon->Picture->Assign(Application->Icon);
  ProgramName->Caption = Application->Title;
}


void __fastcall ShowAboutBox()
{
  TAboutBox* a = new TAboutBox(Application);
  try{
    a->ShowModal();
  }
  catch(...){
    a->Free();
    throw;
  }
  a->Free();
}
 

//-----------------------------------------------------------------------------
#include "TrcView.h"
//-----------------------------------------------------------------------------
#pragma resource "*.DFM"

TTraceForm*  TraceForm;
__fastcall TTraceForm::TTraceForm(TComponent* Owner) : TForm(Owner)
{
}


void __fastcall TTraceForm::TraceDataKeyPress( TObject* Sender, Char& Key)
{
  if (Key == 0x27) Close();
}
 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/951883.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号