//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
#include <psapi.h>
#include <windows.h>
#include <stdio.h>
#include <time.h>
//---------------------------------------------------------------------------

#include "AppGlobalF.h"
#include "VmsDataTypeF.h"
#include "FrmMainF.h"
#include "VMSProtocolF.h"
#include "DMCOMMF.h"
#include "CommThread.h"
#include "FrmOptionF.h"
#include "FrmSysLogF.h"
#include "FrmVmsInfoF.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFrmMain *FrmMain;
//---------------------------------------------------------------------------

__fastcall TFrmMain::TFrmMain(TComponent* Owner)
    : TForm(Owner)
{
    ::CoInitialize(NULL);

    FServerRun = false;
    FTickState = 0;
    g_AppCfg.bAppLoad  = false;
    g_AppCfg.bAppClose = false;

    Caption = " " + g_AppCfg.sTitle + " - " + Now().DateTimeString();;

    VmsManager   = new TVmsCtlrManager();
    ImageManager = new TCDSImageManager();
    FormManager  = new TCDSFormManager();
    FontManager  = new TCDSFontManager();
    IfscManager  = new TCDSIfscManager();

    FCur5Min = StrToInt(Now().FormatString("nn"));;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::FormCreate(TObject *Sender)
{
    Application->ShowMainForm = false;

    try {
        Application->Icon->LoadFromResourceName(((unsigned int)HInstance), "MAINICON");
    } catch(...) { ShowMessage("LoadFromResourceName failed"); }

    SYS_WritePidFile((long)Handle);
    g_AppCfg.lMainWinHandle = (long)Handle;

    FrmSysLog = new TFrmSysLog(pnlLog);
    FrmSysLog->Parent = pnlLog;
    FrmSysLog->Show();

    FrmVmsInfo = new TFrmVmsInfo(pnlVms);
    FrmVmsInfo->Parent = pnlVms;
    FrmVmsInfo->Show();

    Application->ShowMainForm = true;
}
//---------------------------------------------------------------------------

bool __fastcall TFrmMain::StartJobThread()
{
    TCommThread *pCommThread = new TCommThread();
    m_CommThreadID = pCommThread->ThreadID;
    m_CommHandle   = pCommThread->Handle;
    if (m_CommThreadID == NULL)
    {
        LERROR("CommThread initialization fail");
        return false;
    }
    LINFO("Job thread started.");

    return true;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::FormShow(TObject *Sender)
{
    StartJobThread();
    CheckResource((g_AppCfg.MaxMemory * 1024), g_AppCfg.MaxHandle, g_AppCfg.MaxThread, g_AppCfg.MaxGdi);
    //CheckManagerApp();
    tmrAppState->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::FormCloseQuery(TObject *Sender, bool &CanClose)
{
    if (!g_AppCfg.bAppClose)
    {
        String strMsg;
        strMsg = Caption + "\r\n\r\nAre you sure you want to exit the program?\r\nIf the Process Manager is running the program will be restarted automatically!!!";

        //if (Application->MessageBox(strMsg.c_str(), L"Confirm program exit", MB_YESNO|MB_ICONQUESTION) == IDYES)
        {
            FServerRun = false;
            g_AppCfg.bThrExit  = true;
            g_AppCfg.bAppClose = true;
        }
        CanClose = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::FormClose(TObject *Sender, TCloseAction &Action)
{
    CommClose();

    ::CoUninitialize();

    Action = caFree;
    FrmMain = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::CommClose()
{
    try
    {
        SYS_WriteConfigInfo("LOG", "LOGDAY", Now().FormatString("dd"), g_AppCfg.sConfigFile);

        if (VmsManager)
        {
            VmsManager->FLists.Lock();
            FOR_STL(TVmsCtlr*, pObj, VmsManager->FLists)
            {
                //SAFE_DELETE(pObj->FLogFile);
            }
            VmsManager->FLists.UnLock();
        }
        //SAFE_DELETE(VmsManager);

        if (ImageManager)
        {
        }
        //SAFE_DELETE(ImageManager);
    }
    catch(Exception &e)
    {
    }
}
//---------------------------------------------------------------------------

bool __fastcall TFrmMain::InitApplication(void)
{
    String sTitle, sMsg;
    int nResult;

    LINFO("Program initialize start...");

    m_bAction = state_normal;
    m_bComm   = state_error;
    m_bDB     = state_normal;

    FTickState = 0;
    FServerRun = true;

    CommUtil_MakeBasisTime(m_oTimer, VMS_CHECK_TIME, 0);
    CommUtil_MakeBasisTime(m_tTimer, g_AppCfg.nTrafficCycleTime, g_AppCfg.nTrafficBasisTime);
    m_rTimer = Now();

    LINFO("VMS Information initialize...");

    g_SysInfo->State.CommThreadID = m_CommThreadID;

    LINFO("Center communication initialize...");
    //통신초기화를 최초 수행한 후 디비읽어서 처리
    nResult = VComm_Initialize((long)Handle, g_AppCfg.sSystemId, "VMS", g_AppCfg.comm.nCenterPort, g_AppCfg.sLogDay);
    if (VERR_NONE != nResult)
    {
        sMsg.printf(L"Center communication initialize failed: error %d", nResult);
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }

    if (!DMCOMM->DbConnect(g_AppCfg.db.sConnectStr))
    {
        sTitle = "Process initialize failed...";
        sMsg   = "Database connect failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }

    if (DMCOMM->GetVmsInfo() != VERR_NONE)
    {
        DMCOMM->DbClose();

        sTitle = "Process initialize failed...";
        sMsg   = "VMS information initialize failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }
    if (DMCOMM->GetVmsIfscInfo() != VERR_NONE)
    {
        DMCOMM->DbClose();

        sTitle = "Process initialize failed...";
        sMsg   = "VMS IFSC information initialize failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }
    if (DMCOMM->GetProcessInfo() != SYS_ERR_NONE)
    {
        DMCOMM->DbClose();

        sTitle = "Process initialize failed...";
        sMsg   = "Center communication process load failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }
    if (DMCOMM->GetVmsImage() != VERR_NONE)
    {
        DMCOMM->DbClose();

        sTitle = "Process initialize failed...";
        sMsg   = "VMS image information initialize failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }
    if (DMCOMM->LoadVmsForm() != VERR_NONE)
    {
        DMCOMM->DbClose();

        sTitle = "Process initialize failed...";
        sMsg   = "VMS form information initialize failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }

    if (DMCOMM->GetFontInfo() != VERR_NONE)
    {
        DMCOMM->DbClose();

        sTitle = "Process initialize failed...";
        sMsg   = "VMS Font initialize failed.\r\nProgram exit.\r\n";
        //sMsg  += DMComm->ErrorString;
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }

    DMCOMM->DbClose();

    //LoadOldVmsInfo();
    //LoadFtpVmsInfo();
    //LoadFontVmsInfo();
    //LoadBitmapVmsInfo();

    //이미지로 저장하는 경우에 대한 Ftp다운로드 처리여부 확인
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->FBmpDownload)
        {
            if (pObj->FIsOldProtocol)
            {
                //이전 버전중 레도것이 아닌경우는 모두 ftp를 사용함
                pObj->FIsFtpDownload = true;
            }
        }
        else
        {
            //FtpVMS.inf에 등록된 VMS만 FTP로 다운로드하면 된다
        }
    }

    FrmVmsInfo->InitVmsList();

    if (VERR_NONE != VComm_Open())//g_AppCfg.comm.nCenterPort))
    {
        sMsg.printf(L"Center communication open failed: error %d", nResult);
        LERROR(AnsiString(sMsg).c_str());
        return false;
    }

    SendInitial();
    ProvideEvent(provide_event, NULL, NULL);

    //통신서버 시작
    tbConnectClick(this);

    LINFO("Program initialize success...[Completed]");

    return true;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::tmrAppStateTimer(TObject *Sender)
{
    tmrAppState->Enabled = false;
    plTime->Caption = Now().DateTimeString();

    if (!g_AppCfg.bAppLoad)
    {
        if (!InitApplication())
        {
            g_AppCfg.bAppClose = true;
            TerminateApplication();
            Sleep(500);
            Close();
            return;
        }
        // 초기화작업완료

        CheckResource((g_AppCfg.MaxMemory * 1024), g_AppCfg.MaxHandle, g_AppCfg.MaxThread, g_AppCfg.MaxGdi);

        g_AppCfg.bAppLoad     = true;   // 프로그램이 로딩되었음을 확인
        tmrAppState->Interval = 1000;   // 프로그램 상태점검주기=1초
        tmrAppState->Enabled  = true;

        DMCOMM->MonitoringVms(FServerRun);
        DMCOMM->MonitoringVmsClient(FServerRun);
        CheckCommState();   //통신상태정보 체크

        return;
    }

    if (g_AppCfg.bAppClose)
    {
        // 응용프로그램 종료
        g_AppCfg.bThrExit = true;
        Sleep(500);
        TerminateApplication();
        Close();
        return;
    }

    g_AppCfg.lMainWinHandle = (long)Handle;

    UpdateProcessStatePanel();

    if (!(++FTickState % 5))
    {
        DMCOMM->MonitoringVms(FServerRun);
        DMCOMM->MonitoringVmsClient(FServerRun);
        CheckCommState();   //통신상태정보 체크
    }


#if 0
    FCurMin = StrToInt(Now().FormatString("nn"));
    if (!(FCurMin % 5))
    {
        if (FCur5Min != FCurMin)
        {
            FCur5Min = FCurMin;

            SendProcessState();
            SendDbThreadMessage(WM_EQUIP_STATE_ALL, NULL, NULL);
        }
    }
#endif
    if (!(FTickState % 60))
    {
        FSendMsg = SEND_MSG_NONE;
        //1분주기 상태정보를 업데이트 한다.
        //if (!(FSendMsg & SEND_MSG_PROCESS))
        {
            SendProcessState();
        }
        //if (!(FSendMsg & SEND_MSG_EQUIP))
        {
            SendDbThreadMessage(WM_EQUIP_STATE_ALL, NULL, NULL);
            LINFO(">>>>>>>>>>>>>>> SendEquipStateAll");
        }

#if 0
        if (m_bDB != state_normal)
        {
            SendDbThreadMessage(WM_DATABASE_REFLASH, NULL, NULL);
        }
#endif

        if (CheckResource((g_AppCfg.MaxMemory * 1024), g_AppCfg.MaxHandle, g_AppCfg.MaxThread, g_AppCfg.MaxGdi))
        {
            LERROR("Resource error");
#if 0
            AutoClose();
#endif
        }
        FTickState++;
    }

#if 0
    //PASIG에서는 사용하지 않음
    if (CheckBasisTime(m_oTimer, VMS_CHECK_TIME, 0))
    {
        SendDbThreadMessage(WM_GET_ONOFF,     NULL, NULL);
        SendDbThreadMessage(WM_DOWNLOAD_PROC, NULL, NULL);
    }
#endif

    if (CheckBasisTime(m_tTimer, g_AppCfg.nTrafficCycleTime, g_AppCfg.nTrafficBasisTime))
    {
        if (CommUtil_TimeDiff(m_rTimer) > g_AppCfg.nTrafficCycleTime)
        {
            LINFO("*** VMS Traffic Timer Acitve");
            ProvideEvent(provide_event, NULL, NULL);
            FTickState++;
        }
    }

    CheckProvideSave();

    tmrAppState->Enabled  = true;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::AutoClose()
{
    g_AppCfg.bAppClose = true;
    //Close();
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::tbConnectClick(TObject *Sender)
{
    FServerRun = true;
    g_AppCfg.bThrExit = false;

    tbConnect->Enabled = false;
    tbDisconnect->Enabled = true;

    //m_bAction = state_normal;
    SendProcessState();
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::tbDisconnectClick(TObject *Sender)
{
    FServerRun = false;
    g_AppCfg.bThrExit = true;

    tbDisconnect->Enabled = false;

    DMCOMM->TerminateVms();
    Sleep(500);
    DMCOMM->TerminateVms();
    DMCOMM->TerminateVmsClient();

    //m_bAction = state_error;
    SendProcessState();

    tbConnect->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::tbOptionsClick(TObject *Sender)
{
    FrmOption = new TFrmOption(this);
    FrmOption->Left = FrmMain->Left + 80;
    FrmOption->Top = FrmMain->Top + 80;
    FrmOption->ShowModal();
    if (FrmOption->FUpdate)
    {
        try
        {
            ITSLog->FLogCfg = g_LogCfg;
            FDbLog->FLogCfg = g_LogCfg;

            VmsIterator it;
            for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
            {
                TVmsCtlr *pObj = (TVmsCtlr*)it->second;
                if (!pObj->FDispLog)
                {
                    pObj->FCLog->FLogCfg = g_LogCfg;
                    pObj->FSLog->FLogCfg = g_LogCfg;
                }
            }
        }
        catch(Exception &e)
        {
        }
    }
    delete FrmOption;
    FrmOption = NULL;
}
//---------------------------------------------------------------------------

int __fastcall TFrmMain::ChangePosition(TVmsFormObj *AVmsObj)
{
	TLabel *pLabel = NULL;
	int     nWidth;

    if (AVmsObj->TextData == "") return VERR_NONE;

	try
    {
        pLabel = new TLabel(NULL);
        if (pLabel == NULL) return VERR_OTHER;

        try
		{
			pLabel->AutoSize   = true;
            pLabel->Font->Name = CodeToFont(AVmsObj->TextFontName);
			pLabel->Font->Size = AVmsObj->TextFontSize;
			pLabel->Caption    = AVmsObj->TextData;

			if (AVmsObj->TextFontBold)
                pLabel->Font->Style = TFontStyles() << fsBold;
            else
                pLabel->Font->Style = TFontStyles();

			nWidth = AVmsObj->Width - pLabel->Width;

			if (nWidth > 0)
			{
				switch(AVmsObj->TextAlign)
				{
				case text_align_right:  AVmsObj->PosX += nWidth;       break;
				case text_align_center: AVmsObj->PosX += (nWidth / 2); break;
				}
            }
        }
        catch(Exception &e)
		{
        }
    }
    __finally
    {
        SAFE_DELETE(pLabel);
    }
    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TFrmMain::MakeVmsDownloadForm()
{
    int          nFormCnt;
    int          nSaveVmsCnt, nSaveFormCnt;
    TCDSForm    *pCDSForm;
	TVmsForm    *pVmsForm;
	TVmsFormObj *pVmsObj;

    VMS_SCHEDULE_INFO *pSch;
    VMS_SCHEDULE_DETL *pSchUnit;

LINFO("MakeVmsDownloadForm: Start");
//CheckResource((g_AppCfg.MaxMemory * 1024), g_AppCfg.MaxHandle, g_AppCfg.MaxThread, g_AppCfg.MaxGdi);
//LINFO("MakeVmsDownloadForm: Memory_S(%u)", FMemSize);

    nSaveVmsCnt = 0;
    nSaveFormCnt= 0;

    //VMS스케줄에 대하여 다운로드 폼을 생성한다.
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;

        if (!pObj->FProvide) continue;

        nSaveVmsCnt++;

        //운영모드 변경
        pObj->RSTATE.OprMode = pObj->CTLMODE->Control;

        pSch = pObj->SCHEDULE;

        pObj->CTLMODE->MaxDisplayForm = pSch->Count;
        if (pObj->CTLMODE->MaxDisplayForm > pObj->VMS_MAX_PHSE_NUM)
        {
            LWARN("VMS Form Max count over1: %s, %d EA", pObj->VmsNo.c_str(), pObj->CTLMODE->MaxDisplayForm);
            pObj->CTLMODE->MaxDisplayForm = pObj->VMS_MAX_PHSE_NUM;
        }
        if (pObj->CTLMODE->MaxDisplayForm > INT_MAX_VMS_FORM)
        {
            LWARN("VMS Form Max count over2: %s, %d EA", pObj->VmsNo.c_str(), pObj->CTLMODE->MaxDisplayForm);
            pObj->CTLMODE->MaxDisplayForm = INT_MAX_VMS_FORM;
        }

        try
        {
            pObj->pForms->Lock();

            //최대 제공 메시지 갯수만큼 생성
            for (int ii = 0; ii < pSch->Count && ii < pObj->CTLMODE->MaxDisplayForm; ii++)
            {
                nFormCnt = pObj->pForms->Count();
                pSchUnit = &pSch->Unit[ii];

                AnsiString sFormId = pSchUnit->VMS_FORM_ID;
                pCDSForm = FormManager->FLists.Find(sFormId);
                if (!pCDSForm)
                {
                    LERROR("VMS Schedule Form Not found: VmsNmbr(%s), FormId(%s) %d", pObj->VmsNo.c_str(), sFormId.c_str(), ii);
                    continue;
                }

                //소통정보 표출폼 인 경우 표출할 구간의 소통정보가 존재하지 않는 경우
                //폼을 생성하지 않도록 한다.
                switch(pCDSForm->VMS_FORM_TYPE_CD)
                {
                case enFormKindTrfRow1:// = 11,     // 소통상황(1단)
                case enFormKindTrfRow2:// = 12,     // 소통상황(2단)
                case enFormKindTrfRow3:// = 13,     // 소통상황(3단)
                case enFormKindTrfRow4:// = 14,     // 소통상황(4단)
                    {
                        int  ss;
                        bool bNoData = true;
                        AnsiString sVmsIfscId[4];

                        for (ss = 0; ss < 4; ss++)
                            sVmsIfscId[ss] = "";

                        sVmsIfscId[0] = pSchUnit->FRST_VMS_IFSC_ID;
                        sVmsIfscId[1] = pSchUnit->SECD_VMS_IFSC_ID;
                        sVmsIfscId[2] = pSchUnit->THIR_VMS_IFSC_ID;
                        sVmsIfscId[3] = pSchUnit->FOUR_VMS_IFSC_ID;

                        for (ss = 0; ss < 4; ss++)
                        {
                            if (sVmsIfscId[ss] == "") continue;
                            TCDSIfsc *pTmpIfsc = IfscManager->FLists.Find(sVmsIfscId[ss]);
                            if (pTmpIfsc)
                            {
                                if (pTmpIfsc->CMTR_GRAD_CD != "0") bNoData = false;
                            }
                        }
                        if (bNoData)
                        {
                            LWARN("VMS Schedule Form No Traffic: VmsNmbr(%s), FormId(%s)", pObj->VmsNo.c_str(), sFormId.c_str());
                            continue;
                        }
                    }
                    break;
                }

                nSaveFormCnt++;

                //폼생성
                //pVmsForm = new TVmsForm();
                pVmsForm = pObj->pForms->AddForm();

                pVmsForm->ScenarioSeq = nFormCnt;                                       /* 폼 표출순서 */
                pVmsForm->FormId      = pCDSForm->VMS_FORM_ID;                          /* 폼 ID */
                pVmsForm->DisplayTime = pSchUnit->DSPL_HH;                              /* 표출시간(초) */
                pVmsForm->DisplayMode = AnsiString(pCDSForm->VMS_MSG_DSPL_MTHD_CD);     /* 표출기능 */
                pVmsForm->DisplayDir  = AnsiString(pCDSForm->VMS_MSG_DSPL_DRCT_CD);     /* 표출방향 */
                pVmsForm->FormKind    = pCDSForm->VMS_FORM_TYPE_CD;                     /* 폼 종류 */
                pVmsForm->BkColor     = pCDSForm->VMS_FORM_BCKG_HUE_CD;                 /* 배경색상 */
                pVmsForm->Width       = pObj->WIDTH;                                    /* 폼넓이 */
                pVmsForm->Height      = pObj->HEIGHT;                                   /* 폼높이 */
                pVmsForm->SvcRes      = false;
                pVmsForm->FtpRes      = false;

                //pObj->pForms->AddFormA(pVmsForm);

                pVmsForm->Lock();

                //폼객체생성
                FOR_STL(TCDSFormObj*, pCDSObj, pCDSForm->FLists)
                {
                    if (pVmsForm->Count() >= MAX_VMS_OBJ_LIST)
                    {
                        continue;
                    }

                    //도형식 배경소통정보 폼인 경우 하단에 표출할 정보가 없는 경우
                    //하단 소통정보 객체는 생성하지 않도록 하자.
                    if (pVmsForm->FormKind == enFormKindTrfImg)
                    {
                        switch(pCDSObj->VMS_FORM_OBJECT_TYPE_CD)
                        {
                        case 0: //문자열
                        case 1: //심볼
                        case 2: //이미지
                            //N:일반(모두표출하는것)
                            //T:소통정보(소통정보가 있는 경우에만 표출하는것)
                            //F:하단고정(소통정보가 없는 경우에만 표출하는것)
                            if (pSchUnit->VMS_IFSC_ID == "")
                            {
                                //표출할 소통정보가 없는 경우
                                if (pCDSObj->TRFC_FILL_CD == "T") continue; //
                            }
                            else
                            {
                                //표출할 소통정보가 있는 경우
                                if (pCDSObj->TRFC_FILL_CD == "F") continue; //
                            }

                            break;
                        case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19:
                            if (pSchUnit->VMS_IFSC_ID == "") continue; //하단에 표출할 정보제공구간이 없는 경우임
                            break;
#if 0
                        case  1://심볼(소통정보 시점 종점 사이 화살표)
#if 1
                            if (pCDSObj->VMS_DSPL_TXT.Trim() == "->")
                                if (pSchUnit->VMS_IFSC_ID == "") continue; //하단에 표출할 정보제공구간이 없는 경우임
#else
                            if (pSchUnit->VMS_IFSC_ID == "") continue; //하단에 표출할 정보제공구간이 없는 경우임
#endif
                            break;
#endif
                        default: break;
                        }
                    }

                    pVmsObj = pVmsForm->AddFormObject();
                    pVmsObj->IFSC_ID = "";

                    switch(pCDSObj->VMS_FORM_OBJECT_TYPE_CD)
                    {
                    case  1: //이미지 심볼
                        pVmsObj->ObjectKind = graphicID_object_data;  //요건 다운로드되어 있는 경우인데 다운로드상관없이 표출되도록하기위함
                        //pVmsObj->ObjectKind = graphic_object_data;
                        break;
                    case  2: //파일이미지
                        pVmsObj->ObjectKind = graphicID_object_data;
                        break;
                    case  3: //소통정보배경이미지
                        pVmsObj->ObjectKind = graphic_object_data;
                        break;
                    case 17: //소통정보이미지1
                    case 27: //소통정보이미지2
                    case 37: //소통정보이미지3
                    case 47: //소통정보이미지4
                        pVmsObj->ObjectKind = graphicID_object_data;
                        break;
                    default:
                        pVmsObj->ObjectKind = text_object_data;
                        break;
                    }
                    pVmsObj->ObjectType    = pCDSObj->VMS_FORM_OBJECT_TYPE_CD; //NUMBER(3)	N			VMS FORM OBJECT 유형 코드
                    pVmsObj->TextFontName  = pCDSObj->VMS_FONT_TYPE_CD;        //NUMBER(3)	N			VMS 글꼴 유형 코드
                    //TODO
                    pVmsObj->StrTextFontName = CodeToFont(pVmsObj->TextFontName);

                    pVmsObj->TextFontColor = pCDSObj->VMS_FONT_HUE_CD;         //NUMBER(9)	N			VMS 글꼴 색상 코드
                    pVmsObj->TextFontBold  = pCDSObj->VMS_FONT_STYL_CD;        //NUMBER(3)	Y			VMS 글꼴 방식 코드
                    pVmsObj->TextFontSize  = pCDSObj->VMS_FONT_SIZE;           //NUMBER(3)	Y	0		VMS 글꼴 크기
                    pVmsObj->TextAlign     = pCDSObj->VMS_FONT_ALIGN;          //NUMBER(1)	Y	0		VMS 표출 문자열정열방식(0:LEFT,1:RIGHT,2:CENTER)
                    pVmsObj->TextData      = pCDSObj->VMS_DSPL_TXT;            //VARCHAR2(200)	Y		VMS 표출 텍스트
                    pVmsObj->PosX          = pCDSObj->VMS_DSPL_XCRDN;          //NUMBER(5)	Y			VMS 표출 X좌표
                    pVmsObj->PosY          = pCDSObj->VMS_DSPL_YCRDN;          //NUMBER(5)	Y			VMS 표출 Y좌표
                    pVmsObj->Width         = pCDSObj->VMS_DSPL_WIDTH;          //NUMBER(5)	Y	0		VMS 표출 넓이
                    pVmsObj->Height        = pCDSObj->VMS_DSPL_HEIGHT;         //NUMBER(5)	Y	0		VMS 표출 높이
                    pVmsObj->IsBlinking    = pCDSObj->VMS_DSPL_BLINKING;       //NUMBER(1)	Y	0		VMS 표출 점멸 여부(0:지속, 1:점멸)
                    pVmsObj->BkColor       = pCDSObj->VMS_DSPL_BKCOLOR;        //NUMBER(1)	Y	0		VMS 표출 배경색상코드
                    pVmsObj->ObjectSize    = pCDSObj->VMS_DSPL_SIZE;           //NUMBER(7)	Y	0		VMS 표출 크기(문자:문자길이,이미지:이미지전체크기)
                    pVmsObj->ImageId       = pCDSObj->SYMBLIB_NMBR+"0";            //NUMBER(4)	N	0		심벌라이브러리 번호
                    pVmsObj->ImageType     = "0";   //Bitmap

                    if (pVmsObj->ObjectKind != text_object_data)
                    {
                        if (pVmsObj->NewImage() != NULL)
                        {
                            try
                            {
                                pVmsObj->pImageData->Picture->Bitmap->Canvas->Lock();
                                try
                                {
                                    pVmsObj->pImageData->Picture->Assign(pCDSObj->pImage->Picture);
                                }
                                catch(Exception &e)
                                {
                                    LERROR("SaveMemoryStream1: %s[%s] - %s", pVmsForm->FormId.c_str(), pVmsObj->ImageId.c_str(), AnsiString(e.Message).c_str());
                                }
                            }
                            __finally
                            {
                                pVmsObj->pImageData->Picture->Bitmap->Canvas->Unlock();

                                pVmsObj->pImageStream->Clear();
                                pVmsObj->pImageStream->Position = 0;
                                pVmsObj->pImageData->Picture->Graphic->SaveToStream((Classes::TStream*)pVmsObj->pImageStream);
                            }
                        }
                    }

                    //폼객체 유형별 Fill In
                    if (pVmsObj->ObjectType == 0)       //고정문자열
                    {
#if 0
                        if (pObj->FBmpDownload == false && pObj->FIsOldProtocol == false)
                        {
                            //신규VMS인 경우 첫자리가 0 인경우 해당 문자를 표출하지 못함
                            if (pVmsObj->TextData != "")
                            {
                                if (pVmsObj->TextData.SubString(1,1) == "0")
                                {
                                    pVmsObj->TextData = " " + pVmsObj->TextData;
                                    pVmsObj->PosX = pVmsObj->PosX - 5;
                                }
                            }
                        }
#endif
                        ChangePosition(pVmsObj);
                    }
                    else
                    if (pVmsObj->ObjectType == 1 ||     //심볼
                        pVmsObj->ObjectType == 2 )      //파일이미지
                    {
                        ;   //처리없음
                    }
                    else
                    if (pVmsObj->ObjectType == 17 ||    //소통정보이미지1
                        pVmsObj->ObjectType == 27 ||    //소통정보이미지2
                        pVmsObj->ObjectType == 37 ||    //소통정보이미지3
                        pVmsObj->ObjectType == 47 )     //소통정보이미지4
                    {
                        if (!pVmsObj->pImageData) continue;

                        TCDSImage *pSymbol = ImageManager->FLists.Find(pVmsObj->ImageId);
                        if (!pSymbol) continue;

                        try
                        {
                            int X, Y;

                            switch(pVmsObj->ObjectType)
                            {
                            case 17: pVmsObj->IFSC_ID = pSchUnit->FRST_IMG_IFSC_ID; break;
                            case 27: pVmsObj->IFSC_ID = pSchUnit->SECD_IMG_IFSC_ID; break;
                            case 37: pVmsObj->IFSC_ID = pSchUnit->THIR_IMG_IFSC_ID; break;
                            case 47: pVmsObj->IFSC_ID = pSchUnit->FOUR_IMG_IFSC_ID; break;
                            }

                            FOR_STL(TCDSImageCell*, pCell, pSymbol->FLists)
                            {
                                TCDSIfsc *pTmpIfsc = IfscManager->FLists.Find(pVmsObj->IFSC_ID);
                                if (pTmpIfsc)
                                {
                                    X = pCell->POSX;
                                    Y = pCell->POSY;

                                    pVmsObj->ImageId = pCDSObj->SYMBLIB_NMBR + pTmpIfsc->CMTR_GRAD_CD;
                                    try
                                    {
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Lock();
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Brush->Color = GradeToFillColor(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                        TColor clColor = pVmsObj->pImageData->Picture->Bitmap->Canvas->Pixels[X][Y];
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->FloodFill(X, Y, clColor, fsSurface);
                                    }
                                    __finally
                                    {
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Unlock();
                                    }
                                }
                            }
                            pVmsObj->pImageStream->Clear();
                            pVmsObj->pImageStream->Position = 0;
                            pVmsObj->pImageData->Picture->Graphic->SaveToStream((Classes::TStream*)pVmsObj->pImageStream);
                        }
                        catch(Exception &e)
                        {
                            LERROR("SaveMemoryStreamX: %s[%s] - %s", pVmsForm->FormId.c_str(), pVmsObj->ImageId.c_str(), AnsiString(e.Message).c_str());
                        }
                    }
                    else
                    if (pVmsObj->ObjectType == 3)       //소통정보 배경이미지
                    {
                        if (!pVmsObj->pImageData) continue;

                        TCDSImage *pSymbol = ImageManager->FLists.Find(pVmsObj->ImageId);
                        if (!pSymbol) continue;

                        try
                        {
                            int X, Y;

                            FOR_STL(TCDSImageCell*, pCell, pSymbol->FLists)
                            {
                                TCDSIfsc *pTmpIfsc = IfscManager->FLists.Find(pCell->VMS_IFSC_ID);
                                if (pTmpIfsc)
                                {
                                    X = pCell->POSX;
                                    Y = pCell->POSY;

                                    try
                                    {
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Lock();
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Brush->Color = GradeToFillColor(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                        TColor clColor = pVmsObj->pImageData->Picture->Bitmap->Canvas->Pixels[X][Y];
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->FloodFill(X, Y, clColor, fsSurface);
                                    }
                                    __finally
                                    {
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Unlock();
                                    }
                                }
                            }
                            pVmsObj->pImageStream->Clear();
                            pVmsObj->pImageStream->Position = 0;
                            pVmsObj->pImageData->Picture->Graphic->SaveToStream((Classes::TStream*)pVmsObj->pImageStream);
                        }
                        catch(Exception &e)
                        {
                            LERROR("SaveMemoryStream2: %s[%s] - %s", pVmsForm->FormId.c_str(), pVmsObj->ImageId.c_str(), AnsiString(e.Message).c_str());
                        }
                    }
                    else
                    if (pVmsObj->ObjectType == 61 ||    //구간명
                        pVmsObj->ObjectType == 62 ||    //시점명
                        pVmsObj->ObjectType == 63 ||    //종점명
                        pVmsObj->ObjectType == 64 ||    //돌발종류
                        pVmsObj->ObjectType == 65 )     //대응문구
                    {
                        //돌발문안인 경우임
                        pVmsObj->TextData = " ";
                        VMS_EVENT_DETL *pEvt = pSchUnit->EVENT;
                        if (pEvt)
                        {
                            switch(pVmsObj->ObjectType)
                            {
                            case 61: pVmsObj->TextData = pEvt->VMS_IFSC_NM;      break; //구간명(사용안함)
                            case 62: pVmsObj->TextData = pEvt->STRT_LCTN_NM;     break; //VMS돌발시점명
                            case 63: pVmsObj->TextData = pEvt->END_LCTN_NM;      break; //VMS돌발종점명
                            case 64: pVmsObj->TextData = pEvt->VMS_INCD_DETL_NM; break; //VMS돌발세부유형명
                            case 65: pVmsObj->TextData = pEvt->OCRR_LCTN_NM;     break; //대응문구(사용안함-발생장소로 일단넣음)
                            }
                        }
                        if (pVmsObj->TextData == "") pVmsObj->TextData = " ";
                        ChangePosition(pVmsObj);
                        //TB_VMS_FORM_OBJECT_TYPE 테이블에 유형추가하고
                        //돌발화면에서 필요한 항목 추가, TB_INCD_OCRR_VMS 테이블에 컬럼추가해야함
                    }
                    else
                    if (pVmsObj->ObjectType == 71 ||    //발생장소
                        pVmsObj->ObjectType == 72 ||    //해당도로
                        pVmsObj->ObjectType == 73 ||    //통제시점명
                        pVmsObj->ObjectType == 74 ||    //통제종점명
                        pVmsObj->ObjectType == 75 ||    //00차로 차단
                        pVmsObj->ObjectType == 76 ||    //00월00일 ~ 00월00일
                        pVmsObj->ObjectType == 77 )     //대응문구
                    {
                        //공사/행사문안 임
                        pVmsObj->TextData = " ";
                        VMS_EVENT_DETL *pEvt = pSchUnit->EVENT;
                        if (pEvt)
                        {
                            switch(pVmsObj->ObjectType)
                            {
                            case 71: pVmsObj->TextData = pEvt->OCRR_LCTN_NM;    break; //발생장소
                            case 72: pVmsObj->TextData = pEvt->VMS_IFSC_NM;     break; //해당도로
                            case 73: pVmsObj->TextData = pEvt->STRT_LCTN_NM;    break; //통제시점명
                            case 74: pVmsObj->TextData = pEvt->END_LCTN_NM;     break; //통제종점명
                            case 75:
                                {
                                    int nLane = pEvt->INCD_CLSR_LANE.ToIntDef(0);
#ifdef LANG_ENG
                                    if (nLane == 111111)
                                        pVmsObj->TextData = "차로 차단";
                                    else
                                    if (nLane > 0)
                                        pVmsObj->TextData = "일부 차단";
                                    else
                                        pVmsObj->TextData = " ";
#else
                                    if (nLane == 111111)
                                        pVmsObj->TextData = "차로 차단";
                                    else
                                    if (nLane > 0)
                                        pVmsObj->TextData = "일부 차단";
                                    else
                                        pVmsObj->TextData = " ";
#endif
                                }
                                break; //00차로 차단
                            case 76: //00월00일 ~ 00월00일
                                {
#ifdef LANG_ENG
                                    String sFrom = pEvt->INCD_STRT_DT.SubString(5,2)     + "월" + pEvt->INCD_STRT_DT.SubString(7,2)     + "일";
                                    String sTo   = pEvt->INCD_END_PRAR_DT.SubString(5,2) + "월" + pEvt->INCD_END_PRAR_DT.SubString(7,2) + "일";
#else
                                    String sFrom = pEvt->INCD_STRT_DT.SubString(5,2)     + "월" + pEvt->INCD_STRT_DT.SubString(7,2)     + "일";
                                    String sTo   = pEvt->INCD_END_PRAR_DT.SubString(5,2) + "월" + pEvt->INCD_END_PRAR_DT.SubString(7,2) + "일";
#endif
                                    //문자열 맨 앞이 '0'으로 시작하는 경우 VMS에서 표출되지 않음
                                    //if (g_AppCfg.DownloadBitmap == false)
                                    if (pObj->FBmpDownload == false)
                                    {
                                        if (sFrom.SubString(1,1) == "0")
                                        {
                                            sFrom = " " + sFrom;
                                            pVmsObj->PosX = pVmsObj->PosX - 5;
                                        }
                                    }
                                    pVmsObj->TextData = sFrom + " ~ " + sTo;
                                }
                                break;
                            case 77: pVmsObj->TextData = pEvt->OCRR_LCTN_NM;    break; //대응문구(사용안함-발생장소로 일단넣음)
                            }
                        }
                        if (pVmsObj->TextData == "") pVmsObj->TextData = " ";
                        ChangePosition(pVmsObj);
                    }
                    else
                    if (pVmsObj->ObjectType == 81 ||    //돌발종류
                        pVmsObj->ObjectType == 82 ||    //해당도로
                        pVmsObj->ObjectType == 83 ||    //우회도로
                        pVmsObj->ObjectType == 84 )     //발생장소
                    {
                        pVmsObj->TextData = " ";
                        VMS_EVENT_DETL *pEvt = pSchUnit->EVENT;
                        if (pEvt)
                        {
                            switch(pVmsObj->ObjectType)
                            {
                            case 81: pVmsObj->TextData = pEvt->VMS_INCD_DETL_NM;    break; //돌발종류
                            case 82: pVmsObj->TextData = pEvt->VMS_IFSC_NM;         break; //해당도로
                            case 83: pVmsObj->TextData = pEvt->VMS_IFSC_NM;         break; //우회도로
                            case 84: pVmsObj->TextData = pEvt->OCRR_LCTN_NM;        break; //발생장소
                            }
                        }
                        if (pVmsObj->TextData == "") pVmsObj->TextData = " ";
                        ChangePosition(pVmsObj);
                    }
                    else
                    {
                        //객체가 가변(소통정보 표출) 인 경우 가변문자를 설정하자....
                        AnsiString VMS_IFSC_ID = "";
                        switch(pVmsObj->ObjectType)
                        {
                        case 11: case 12: case 13: case 14: case 15: case 16: case 18: case 19:
                            VMS_IFSC_ID = pSchUnit->FRST_VMS_IFSC_ID;
                            if (pVmsForm->FormKind == enFormKindTrfImg)
                            {
                                VMS_IFSC_ID = pSchUnit->VMS_IFSC_ID;
                            }
                            else
                            if (pVmsForm->FormKind == enFormKindCongest && pVmsObj->ObjectType == 18)
                            {
                                VMS_IFSC_ID = pSchUnit->VMS_IFSC_ID;
                            }
                            break;
                        case 21: case 22: case 23: case 24: case 25: case 26: case 28:
                            VMS_IFSC_ID = pSchUnit->SECD_VMS_IFSC_ID;
                            break;
                        case 31: case 32: case 33: case 34: case 35: case 36: case 38:
                            VMS_IFSC_ID = pSchUnit->THIR_VMS_IFSC_ID;
                            break;
                        case 41: case 42: case 43: case 44: case 45: case 46: case 48:
                            VMS_IFSC_ID = pSchUnit->FOUR_VMS_IFSC_ID;
                            break;
                        case 91: case 92:
                            VMS_IFSC_ID = pCDSObj->VMS_IFSC_ID; //축통행시간/축소통상황(고정)
                            break;
                        case 93: case 94: case 95: case 96:
                            VMS_IFSC_ID = pSchUnit->VMS_IFSC_ID;
                            break;
                        default: continue;
                        }
                        pVmsObj->TextData = " ";
                        TCDSIfsc *pTmpIfsc = IfscManager->FLists.Find(VMS_IFSC_ID);
                        if (pTmpIfsc)
                        {
                            switch(pVmsObj->ObjectType)
                            {
                            case 11: case 21: case 31: case 41: //구간명
                                pVmsObj->TextData = pTmpIfsc->VMS_IFSC_NM;
                                break;
                            case 12: case 22: case 32: case 42: case 93://시점명
                                pVmsObj->TextData = pTmpIfsc->DSPL_STRT_NODE_NM;
                                break;
                            case 13: case 23: case 33: case 43: case 94://종점명
                                pVmsObj->TextData = pTmpIfsc->DSPL_END_NODE_NM;
                                break;
                            case 14: case 24: case 34: case 44: case 92: case 95://소통상황
#if 0
                                pVmsObj->TextData = GradeToString(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0), pVmsForm->FormKind);
#else
                                if (pObj->VmsType == "VUTP") //도형식인 경우
                                    pVmsObj->TextData = GradeToString(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0), enFormKindTrfImg);
                                else
                                    pVmsObj->TextData = GradeToString(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0), pVmsForm->FormKind);
#endif
                                pVmsObj->TextFontColor = GradeToColorCode(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                break;
                            case 19:    //소통상황(가변)
                                {
                                    AnsiString sGradText = GradeToString(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0), pVmsForm->FormKind);
                                    if (pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0) == grade_smoothness)
                                    {
#ifdef LANG_ENG
                                        sGradText.printf("소통원활  약 %d 분", pTmpIfsc->TRVL_HH);
#else
                                        sGradText.printf("소통원활  약 %d 분", pTmpIfsc->TRVL_HH);
#endif
                                    }
                                    pVmsObj->TextData = sGradText;
                                    pVmsObj->TextFontColor = GradeToColorCode(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                }
                                break;
                            case 15: case 25: case 35: case 45: case 91: case 96://통행시간
#if 0
                                pVmsObj->TextData = AnsiString(pTmpIfsc->TRVL_HH);
#else
                                {
                                    AnsiString sFmt = pCDSObj->VMS_DSPL_TXT;

                                    if (sFmt.Pos("0"))
                                    {
                                        sFmt = StringReplace(sFmt, "0000", "%4d", TReplaceFlags() << rfReplaceAll);
                                        sFmt = StringReplace(sFmt, "000", "%3d", TReplaceFlags() << rfReplaceAll);
                                        sFmt = StringReplace(sFmt, "00", "%2d", TReplaceFlags() << rfReplaceAll);
                                        sFmt = StringReplace(sFmt, "0", "%d", TReplaceFlags() << rfReplaceAll);

                                        pVmsObj->TextData.printf(sFmt.c_str(), pTmpIfsc->TRVL_HH);
                                    }
                                    else
                                    {
                                        pVmsObj->TextData = AnsiString(pTmpIfsc->TRVL_HH);
                                    }
                                }
#endif
                                pVmsObj->TextFontColor = GradeToColorCode(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                break;
                            case 16: case 26: case 36: case 46://통행속도
                                pVmsObj->TextData = AnsiString(pTmpIfsc->SPED);
                                pVmsObj->TextFontColor = GradeToColorCode(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                break;
                            case 17: case 27: case 37: case 47: //방향이미지...???
                                break;
                            case 18: case 28: case 38: case 48:
                                pVmsObj->TextData = pTmpIfsc->SPOT_NM;
                                break;
                            }
                            ChangePosition(pVmsObj);
                        }
                    }
                } //FOR_STL(폼객체생성)

                pVmsForm->UnLock();

            } //for(최대 제공 메시지 갯수만큼 생성)
        }
        __finally
        {
            pObj->pForms->UnLock();
        }
    } //iterator(VMS전체루프)

    LINFO("MakeVmsDownloadForm: End. (VMS: %d EA, Forms %d EA)", nSaveVmsCnt, nSaveFormCnt);


    LINFO("MakeVmsDatabaseForm: Start");

    nSaveVmsCnt = 0;
    nSaveFormCnt= 0;

    //데이터베이스에 저장할 폼을 생성한다.
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;

        if (pObj->Server.UseFlag != bit_enable) continue;
        if (!pObj->FProvide) continue;

        nSaveFormCnt += MakeVmsDatabaseForm(pObj);
        nSaveVmsCnt++;
    }

    LINFO("MakeVmsDatabaseForm: End. (VMS: %d EA, Forms %d EA)", nSaveVmsCnt, nSaveFormCnt);
    return VERR_NONE;
}
//---------------------------------------------------------------------------

int __fastcall TFrmMain::MakeVmsDatabaseForm(TVmsCtlr *AObj)
{
	int nResult = VERR_OTHER;
    int nSelCnt = 0;


    if (!AObj) return VERR_MEMORY_ALLOC;

    int nFormCnt = AObj->pForms->Count();
    if (nFormCnt == 0) return VERR_NONE;

	try
	{
		try
		{
            AObj->pForms->Lock();

            for (int ii = 0; ii < nFormCnt; ii++)
            {
				TVmsForm *pForm = AObj->pForms->GetItem(ii);

                int nObjCnt;
                try
                {
        			pForm->pBitmap->Canvas->Lock();

                    pForm->FormClear(CodeToColor(pForm->BkColor));

                    nObjCnt = pForm->Count();

                    for (int jj = 0; jj < nObjCnt; jj++)
                    {
                        TVmsFormObj *pFormObj = pForm->GetItem(jj);
                        switch(pFormObj->ObjectType)
                        {
                        case  1: //심볼
                        case  2: //이미지
                        case 17: //소통정보이미지1
                        case 27: //소통정보이미지2
                        case 37: //소통정보이미지3
                        case 47: //소통정보이미지4
                        case  3: //소통정보배경이미지
                            pForm->pBitmap->Canvas->Draw(pFormObj->PosX, pFormObj->PosY, pFormObj->pImageData->Picture->Graphic);
                            break;
                        default://기타 문자열
                            pForm->pBitmap->Canvas->Brush->Color = CodeToColor(pFormObj->BkColor);
                            pForm->pBitmap->Canvas->Font->Color  = CodeToColor(pFormObj->TextFontColor);
                            pForm->pBitmap->Canvas->Font->Name   = CodeToFont(pFormObj->TextFontName);
                            pForm->pBitmap->Canvas->Font->Size   = pFormObj->TextFontSize;
                            if (pFormObj->TextFontBold)
                                pForm->pBitmap->Canvas->Font->Style = TFontStyles() << fsBold;
                            else
                                pForm->pBitmap->Canvas->Font->Style = TFontStyles();

                            pForm->pBitmap->Canvas->TextOutA(pFormObj->PosX, pFormObj->PosY, pFormObj->TextData);
                            break;
                        }
                    }

                    try
                    {
                        pForm->pStream->Clear();
                        pForm->pStream->Position = 0;
                        pForm->pBitmap->SaveToStream(pForm->pStream);
                    }
                    catch(Exception &e)
                    {
                        LERROR("SaveMemoryStream3: %s", AnsiString(e.Message).c_str());
                    }

                    try
                    {
                        if (g_AppCfg.SaveFormImage)
                        {
                            String sFormImage;
                            String sFormDir = g_sFormDir + AObj->VmsId + "\\";
                            //ForceDirectories(sFormDir.c_str());

                            sFormImage.printf(L"%s%s_%02d.bmp", sFormDir.c_str(), String(AObj->VmsId).c_str(), ii);
                            pForm->pBitmap->SaveToFile(sFormImage);
                        }
                    }
                    catch(Exception &e)
                    {
                        LERROR("SaveMemoryStream-SaveToFile: %s", AnsiString(e.Message).c_str());
                    }

#if 0
                    try
                    {
                        //pForm->pBitmap->SaveToFile(g_sFormDir + AObj->VmsId + "\\" + AObj->VmsId + "_" + PHASE);

                        //FTP다운로드 하는 경우 폼을 FTP디렉토리에 저장해야함
                        if (AObj->FIsFtpDownload)
                        {
                            String DefForm, RunForm;
                            DefForm.printf(L"%s9%d.bmp", String(AObj->VmsDownId).c_str(), ii);
                            RunForm.printf(L"%s%02d.bmp",  String(AObj->VmsDownId).c_str(), ii);

                            if (AObj->CTLMODE->Control == 'B')
                            {
                                //pForm->pBitmap->SaveToFile(g_sFtpDir + DefForm);
                            }
                            pForm->pBitmap->SaveToFile(g_sFtpDir + RunForm);
                        }
                    }
                    catch(Exception &e)
                    {
                        LERROR("SaveMemoryStream-SaveToFile: %s", AnsiString(e.Message).c_str());
                    }
#endif

                    nSelCnt++;
                }
                __finally
                {
                    pForm->pBitmap->Canvas->Unlock();
                }
            }

            nResult = VERR_NONE;
		}
		catch(Exception &e)
		{
            LERROR("SaveMemoryStream4: %s", AnsiString(e.Message).c_str());
		}
	}
	__finally
	{
        AObj->pForms->UnLock();
	}
    return nSelCnt;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::OnWMUserMessage(TMessage &Msg)
{
    ReplyMessage(0);

    if ((int)Msg.WParam == WM_MAKE_DOWNLOAD_FORM)
    {
        int nResult = MakeVmsDownloadForm();
        SendDbThreadMessage(WM_SAVE_DOWNLOAD_FORM, NULL, NULL);
        return;
    }

    if ((int)Msg.WParam == WM_WINDOW_RESTORE)
    {
        Application->Restore();
        Application->BringToFront();
    }

    if ((int)Msg.WParam == WM_DATABASE_CLOSE)
    {
        m_bDB = state_error;
    }

    if ((int)Msg.WParam == WM_DATABASE_OPEN)
    {
        m_bDB = state_normal;
    }

    if ((int)Msg.WParam == WM_THREAD_TERMINATE)
    {
        Sleep(500);
        AutoClose();
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::OnVmsThreadMessage(TMessage &Msg)
{
    TVmsCtlr *pObj = (TVmsCtlr*)Msg.LParam;
    switch(Msg.WParam)
    {
    case WM_VMS_SERVER_STTS:
        FrmVmsInfo->UpdateServerState((int)pObj);
        SendDbThreadMessage(WM_EQUIP_STATE, Msg.LParam, 1);
        break;
    case WM_VMS_CLIENT_STTS:
        FrmVmsInfo->UpdateClientState((int)pObj);
        break;
    case WM_VMS_STATE_STTS:
        FrmVmsInfo->UpdateClientState((int)pObj);
        SendDbThreadMessage(WM_EQUIP_STATE, Msg.LParam, 0);
        break;
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::OnUdpDataRecvMessage(TMessage &Msg)
{
    int                  nResult;
    IPCUDPMESSAGESTRUCT *RcvData = (IPCUDPMESSAGESTRUCT*)Msg.LParam;
    INT_SENDER          *Sender  = &RcvData->Sender;
    INT_PACKET          *Pkt     = &RcvData->Pkt;
    INT_HEAD            *head    = &Pkt->head;
    INT_DATA            *data    = &Pkt->data;
    char                *pData   = &data->Data[2];
    BYTE                 OpCode  = (BYTE)data->Data[0];

    LINFO("OPR Client Req: %s.%d, %02X[%02X]", VComm_ulong2ip(Sender->IP), Sender->Port, head->OPCode, OpCode);

    if (head->OPCode == INT_OP_COMM_COMMON)
    {
        switch(OpCode)
        {
        case INT_OP_VMS_POWER_CTL:
            {
                INT_VMS_POWER_CTL_REQ *pReq = (INT_VMS_POWER_CTL_REQ*)pData;
                LINFO("VmsPowerCtlReq: %.*s, %s, %s, %d", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId, pReq->Command);
                if ((nResult = SendVmsThreadMessage(pReq->VmsId, RcvData, OpCode, (char*)pReq)) != VERR_NONE)
                {
                    //ClientResponse(SEND_NACK, &Req, result, NULL);
                }
            }
            break;
        case INT_OP_VMS_LUMINANCE_CTL:
            {
                INT_VMS_LUMINANCE_REQ *pReq = (INT_VMS_LUMINANCE_REQ*)pData;
                LINFO("VmsLuminanceReq: %.*s, %s, %s, %d", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId, pReq->Luminance);
                if ((nResult = SendVmsThreadMessage(pReq->VmsId, RcvData, OpCode, (char*)pReq)) != VERR_NONE)
                {
                    //ClientResponse(SEND_NACK, &Req, result, NULL);
                }
            }
            break;
        case INT_OP_VMS_RESET:
            {
                INT_VMS_RESET_REQ *pReq = (INT_VMS_RESET_REQ*)pData;
                LINFO("VmsResetReq: %.*s, %s, %s", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId);
                if ((nResult = SendVmsThreadMessage(pReq->VmsId, RcvData, OpCode, (char*)pReq)) != VERR_NONE)
                {
                    //ClientResponse(SEND_NACK, &Req, result, NULL);
                }
            }
            break;
        case INT_OP_VMS_PARA_SET:
            {
                INT_VMS_PARA_SET_REQ *pReq = (INT_VMS_PARA_SET_REQ*)pData;
                LINFO("VmsParaSetReq: %.*s, %s, %s", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId);
                LINFO("VmsParaSetReq: %d.%d,%d,%d,%d,%d,%d",
                        pReq->SchMsgTime,
                        pReq->ModuleTemp,
                        pReq->FanTemp,
                        pReq->HeaterTemp,
                        pReq->ModuleFail,
                        pReq->RetryCount,
                        pReq->TimeOut);
                if ((nResult = SendVmsThreadMessage(pReq->VmsId, RcvData, OpCode, (char*)pReq)) != VERR_NONE)
                {
                    //ClientResponse(SEND_NACK, &Req, result, NULL);
                }
            }
            break;
        case INT_OP_VMS_PARA_SET2:
            {
                INT_VMS_PARA_SET_REQ2 *pReq = (INT_VMS_PARA_SET_REQ2*)pData;
                LINFO("VmsParaSetReq: %.*s, %s, %s", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId);
                LINFO("VmsParaSetReq: %d.%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
                        pReq->DefCommErr,                           // 통신장애 기본값, 제어기가 Host로부터 Poll 또는 명령을 받지 않고 경과할 수 있는 최대시간 (default ; 60초)
                        pReq->SlotCommErr,                          // 통신장애 slot번호, 통신 fail 시 표시할 메시지 번호(default 0번)
                        pReq->SlotPowerErr,                         // 전원장애 slot번호, 전원장애 시 표시할 메시지 번호(default 0번)
                        pReq->NightLuminance,                       // 야간 휘도 값, 0x30 ~ 0x3F
                        pReq->DayLuminance,                         // 주간 휘도 값, 0x40 ~ 0x4F
                        pReq->PhaseCycleTime,                       // phase시간주기, 장애시 phase주기 (default : 3초, 범위 : 0 ~ 10초)
                        pReq->ModuleFailRate,                       // 모듈장애율, 한개의 module을 장애로 처리하기 위한 장애 pixel백분율 (default 10%)
                        pReq->ModuleCheckTime,                      // 모듈감시 주기, 0 ~ 255 (단위:초)
                        pReq->BoardOnHour,                          // 전광판 On time(시), 0시 ~ 23시
                        pReq->BoardOnMin,                           // 전광판 On time(분), 0시 ~ 23시
                        pReq->BoardOffHour,                         // 전광판 Off time(시), 0시 ~ 23시
                        pReq->BoardOffMin);                          // 전광판 Off time(분), 0시 ~ 23시
                if ((nResult = SendVmsThreadMessage(pReq->VmsId, RcvData, OpCode, (char*)pReq)) != VERR_NONE)
                {
                    //ClientResponse(SEND_NACK, &Req, result, NULL);
                }
            }
            break;
        case INT_OP_VMS_COMMON:
            {
                INT_VMS_COMMON_REQ *pReq = (INT_VMS_COMMON_REQ*)pData;
                LINFO("VmsCommonReq: %.*s, %s, %s : 0x%02x", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId, pReq->Command);
                if (pReq->Command == 0x01)
                {
                    //메시지 바로 다운로드함
                    ProvideEvent(provide_event, NULL, NULL);
                }
            }
            break;
        case INT_OP_VMS_DIRECT:
            {
                INT_VMS_DIRECT_CTL_REQ *pReq = (INT_VMS_DIRECT_CTL_REQ*)pData;
                LINFO("VmsDirectReq: %.*s, %s, %s : 0x%02x", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId, pReq->Command);
                if ((nResult = SendVmsThreadMessage(pReq->VmsId, RcvData, OpCode, (char*)pReq)) != VERR_NONE)
                {
                    //ClientResponse(SEND_NACK, &Req, result, NULL);
                }
            }
            break;
        case INT_OP_VMS_MODE:
            {
                INT_VMS_MODE_REQ *pReq = (INT_VMS_MODE_REQ*)pData;
#if 0
                LINFO("VmsModeSetReq: %.*s, %s, %s, %c", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->VmsId, pReq->OperId, pReq->Mode);
#else
                LINFO("VmsModeSetReq: %.*s, %s, %s, %d EA", INT_VMS_MAX_DATETIME, pReq->CmdTime, pReq->OperId, pReq->Count);
#endif
    			//ProvideEvent(provide_mode, pReq->VmsId, pReq->Mode);
    			ProvideEvent(provide_mode, (BYTE*)pReq, NULL);
            }
            break;
        case INT_OP_VMS_STATE_REQ:
            LINFO("VmsStateReq");
            DMCOMM->SendEquipStateAllProc();
            break;
        case INT_OP_VMS_IMAGE_SYMBOL:
            LINFO("VmsImageSymbolUpdate");
            SendDbThreadMessage(WM_MASTER_IMAGE_SYMBOL, NULL, NULL);
            break;
        case INT_OP_VMS_IMAGE_TRAFFIC:
            LINFO("VmsImageTrafficUpdate");
            SendDbThreadMessage(WM_MASTER_IMAGE_TRAFFIC, NULL, NULL);
            break;
        case INT_OP_VMS_FORM_UPDATE:
            LINFO("VmsFormUpdate");
            SendDbThreadMessage(WM_MASTER_FORM, NULL, NULL);
            break;
        case INT_OP_VMS_IFSC_UPDATE:
            LINFO("VmsIfscUpdate");
            SendDbThreadMessage(WM_MASTER_VMS_IFSC, NULL, NULL);
            break;
        default:
            LERROR("Unknown Client Request: %02X", OpCode);
            break;
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::TerminateApplication(void)
{
    LERROR("Program terminated start");

    /* 연결 소켓 종료 */
    DMCOMM->TerminateVms();
    Sleep(500);
    DMCOMM->TerminateVms();
    DMCOMM->TerminateVmsClient();

    SendTerminal();

    if (m_CommThreadID != NULL)
    {
        g_SysInfo->State.hFinishEvent = CreateEvent(NULL, FALSE, FALSE, "");
        if (g_SysInfo->State.hFinishEvent == NULL)
        {
            LERROR("Create thread finish event fail");
        }

        if (!PostThreadMessage(m_CommThreadID, WM_QUIT, NULL, NULL))
        {
            LDEBUG("PostThreadMessage fail:%d", GetLastError());
        }
        m_CommThreadID = NULL;

        if (g_SysInfo->State.hFinishEvent != NULL)
        {
            DWORD dwWaitResult;

            dwWaitResult = WaitForSingleObject(g_SysInfo->State.hFinishEvent, 5000);
            if (dwWaitResult != WAIT_OBJECT_0)
            {
                LERROR("Wait finish event fail");
            }
            CloseHandle(g_SysInfo->State.hFinishEvent);
        }
    }

    m_bAction = state_error;
    m_bComm   = state_error;
    m_bDB     = state_error;

    SendProcessState();
    Sleep(500);

    VComm_Close();

    LERROR("Program terminated end");
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::UpdateProcessStatePanel()
{
    TColor clState;

    clState = clGreen;
    if (m_bAction != vms_normal) clState = clRed;
    if (plStateAction->Color != clState) plStateAction->Color = clState;

    if (m_bComm == state_normal)  clState = clGreen;
    else
    if (m_bComm == state_unknown) clState = clGray;
    else                          clState = clRed;
    if (plStateComm->Color != clState) plStateComm->Color = clState;

    if (m_bDB == state_normal)  clState = clGreen;
    else
    if (m_bDB == state_unknown) clState = clGray;
    else                        clState = clRed;
    if (plStateDb->Color != clState) plStateDb->Color = clState;
}
//---------------------------------------------------------------------------

int __fastcall TFrmMain::SendDbThreadMessage(UINT Msg, int wParam, int lParam)
{
    int result = VERR_OTHER;

    if (m_CommThreadID != NULL)
    {
        if (PostThreadMessage(m_CommThreadID, Msg, (WPARAM)wParam, (LPARAM)lParam))
        {
            result = VERR_NONE;
        }
        else
        {
            result = VERR_INTERNAL;
        }
    }
    return result;
}
//---------------------------------------------------------------------------

int __fastcall TFrmMain::SendDbThreadDataMessage(UINT Msg, void *pData, int iLen)
{
    int   result = VERR_OTHER;
    char *p;

    if (m_CommThreadID != NULL)
    {
        p = new char[iLen];
        if (p != NULL)
        {
            try
            {
                memcpy(p, pData, iLen);

                if (PostThreadMessage(m_CommThreadID, Msg, (WPARAM)p, NULL))
                {
                    result = VERR_NONE;
                    Sleep(50);
                }
                else
                {
                    result = VERR_INTERNAL;
                }
            }
            __finally
            {
                if (result != VERR_NONE) delete []p;
            }
        }
        else
        {
            result = VERR_MEMORY_ALLOC;
        }
    }
    return result;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::ClientResponse(int Flag, CLIENT_COMMAND *pReq, int error, void *pData)
{
#ifdef CENTERCOMM
    BYTE ErrCode;
    int sResult;

    switch(error)
    {
    case SYS_ERR_NONE:                 break;
    case SYS_ERR_OTHER:                ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_INTERNAL:             ErrCode = INT_ERROR_SYSTEM; break;
    case SYS_ERR_MEMORY:               ErrCode = INT_ERROR_SYSTEM; break;
    case SYS_ERR_DATABASE:             ErrCode = INT_ERROR_SYSTEM; break;
    case SYS_ERR_RESET:                ErrCode = INT_ERROR_SYSTEM; break;
    case SYS_ERR_START:                ErrCode = INT_ERROR_SYSTEM; break;
    case SYS_ERR_OFFLINE:              ErrCode = INT_ERROR_OFFLINE; break;
    case SYS_ERR_NO_RES:               ErrCode = INT_ERROR_NO_RESPONSE; break;
    case SYS_ERR_ACCESS:               ErrCode = INT_ERROR_PROCESS; break;
    case SYS_ERR_INVALID:              ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_UNKNOWN:              ErrCode = INT_ERROR_UNKNOWN_CODE; break;
    case SYS_ERR_WRITE_LENGTH:         ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_PACKET_SIZE_LARGE:    ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_INVALID_TAG:          ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_CRC:                  ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_LENGTH:               ErrCode = INT_ERROR_LENGTH; break;
    case SYS_ERR_ADDRESS:              ErrCode = INT_ERROR_ADDRESS; break;
    case SYS_ERR_HEADER_OPTIONS:       ErrCode = INT_ERROR_HEADER; break;
    case SYS_ERR_UNKNOWN_COMMAND:      ErrCode = INT_ERROR_UNKNOWN_OPCODE; break;
    case SYS_ERR_RECEIVE_TIMEOUT:      ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_DATA_SIZE:            ErrCode = INT_ERROR_DISCORD; break;
    case SYS_ERR_MISMATCH:             ErrCode = INT_ERROR_OTHER; break;
    case SYS_ERR_INVALID_PARA:         ErrCode = INT_ERROR_INVALID_DATA; break;
    case SYS_ERR_MOVEMENT:             ErrCode = INT_ERROR_MOVEMENT; break;
    case SYS_ERR_UNAUTHORIZED:         ErrCode = INT_ERROR_UNAUTHORIZED; break;
    default:                           ErrCode = INT_ERROR_OTHER; break;
    }

    if (Flag == SEND_ACK)
    {
        INT_ACK_RES Ack;

        memset(&Ack, 0x00, sizeof(Ack));

        Ack.OPCode.Type = INT_TYPE(pReq->OpCode);
        Ack.OPCode.Kind = INT_KIND(pReq->OpCode);
        Ack.MsgSeq = pReq->MsgSeq;

        if ((sResult = AckRes(&Ack, pReq->ProcessID)) != UDP_ERR_NONE)
        {
            LERROR("AckRes fail %d", sResult);
        }
    }
    else
    if (Flag == SEND_NACK)
    {
        INT_NACK_RES Nack;

        memset(&Nack, 0x00, sizeof(Nack));

        Nack.OPCode.Type = INT_TYPE(pReq->OpCode);
        Nack.OPCode.Kind = INT_KIND(pReq->OpCode);
        Nack.MsgSeq = pReq->MsgSeq;
        Nack.ErrCode = ErrCode;

        if ((sResult = NackRes(&Nack, pReq->ProcessID)) != UDP_ERR_NONE)
        {
            LERROR("NackRes fail %d", sResult);
        }
    }
#endif
}
//---------------------------------------------------------------------------

bool __fastcall TFrmMain::CheckBasisTime(char *p, int Cycle, int Basis)
{
    char cTime[15];

    CommUtil_MakeBasisTime(cTime, Cycle, Basis);

    if (memcmp(p, cTime, 14) != 0)
    {
        memcpy(p, cTime, 14);
        return true;
    }

    return false;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::ProvideEvent(int Type, BYTE *pVmsId, BYTE Mode)
{
    int result;
    PROVIDE_STRUCT Pro;

    memset(&Pro, 0x00, sizeof(Pro));

    Pro.Type = Type;
    if (pVmsId)
    {
        INT_VMS_MODE_REQ *pReq = (INT_VMS_MODE_REQ*)pVmsId;
        Pro.Count = pReq->Count;
        memcpy(Pro.Unit, pReq->Unit, sizeof(Pro.Unit));
    }

#if 0
    switch(Type)
    {
    case provide_event:
        Pro.Type = Type;
        break;
    case provide_mode:
        Pro.Type = Type;
        //memcpy(Pro.VmsId, pVmsId, VMS_ID_SIZE);
        //Pro.Mode = Mode;
        INT_VMS_MODE_REQ *pReq
        break;
    default:
        return;
    }
#endif

    if ((result = SendDbThreadDataMessage(WM_PROVIDE_PROC, &Pro, sizeof(Pro))) != SYS_ERR_NONE)
    {
        LERROR("SendDbThreadDataMessage Error %d", result);
    }
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::CheckProvideSave()
{
    SAVE_STRUCT ProvideSave;
    SAVE_STRUCT DownLoadSave;

    memset(&ProvideSave,  0x00, sizeof(ProvideSave));
    memset(&DownLoadSave, 0x00, sizeof(DownLoadSave));

    ProvideSave.Type  = save_provide;
    ProvideSave.Count = 0;

    DownLoadSave.Type  = save_download;
    DownLoadSave.Count = 0;

    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->Server.UseFlag != bit_enable) continue;

        if ((pObj->DOWNLOAD->SaveFlag == false) &&
            (CommUtil_TimeDiff(pObj->DOWNLOAD->dTimer) > VMS_DOWNLOAD_TIMEOUT))
        {
             DownLoadSave.pObj[DownLoadSave.Count++] = (void *)pObj;
             pObj->DOWNLOAD->SaveFlag = true;
        }

		if ((pObj->CTLMODE->SaveFlag == false) &&
			(CommUtil_TimeDiff(pObj->CTLMODE->pTimer) > VMS_PROVIDE_TIMEOUT))
		{
			ProvideSave.pObj[ProvideSave.Count++] = (void *)pObj;
			pObj->CTLMODE->SaveFlag = true;
		}
    }

    if (ProvideSave.Count != 0)
    {
        SendDbThreadDataMessage(WM_PROVIDE_SAVE, &ProvideSave, sizeof(ProvideSave));
    }

    if (DownLoadSave.Count != 0)
    {
        SendDbThreadDataMessage(WM_PROVIDE_SAVE, &DownLoadSave, sizeof(DownLoadSave));
    }
}
//---------------------------------------------------------------------------

bool __fastcall TFrmMain::CheckResource(size_t MaxMemory, DWORD MaxHandle, DWORD MaxThread, DWORD MaxGdi)
{
    bool result;
    HANDLE hProcess;
    PROCESS_MEMORY_COUNTERS pmc;
    size_t uSize;
    DWORD HandleCount, ThreadCount, GdiCount;
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    DWORD ProcessId;

    result = false;
    uSize = 0;
    HandleCount = 0;
    ThreadCount = 0;
    GdiCount = 0;

    hProcess = GetCurrentProcess();

    if (hProcess != NULL)
    {
        if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
        {
            uSize = pmc.WorkingSetSize/1024;

            if ((MaxMemory != 0) && (uSize > MaxMemory))
            {
                LERROR("Memory usage exceeds standards!!!...[%d][%d]", MaxMemory, uSize);
                result = true;
            }
        }

        if ( GetProcessHandleCount( hProcess, &HandleCount) )
        {
            if ((MaxHandle != 0) && (HandleCount > MaxHandle))
            {
                LERROR("Window handle exceed standards!!!...[%d][%d]", MaxHandle, HandleCount);
                result = true;
            }
        }

        ProcessId = GetCurrentProcessId();

        if ((hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 )) != INVALID_HANDLE_VALUE)
        {
            pe32.dwSize = sizeof( PROCESSENTRY32 );

            if ( Process32First( hProcessSnap, &pe32 ) )
            {
                do
                {
                    if (pe32.th32ProcessID == ProcessId)
                    {
                        ThreadCount = pe32.cntThreads;

                        if ((MaxThread != 0) && (ThreadCount > MaxThread))
                        {
                            LERROR("Criteria exceeded thread!!!...[%d][%d]", MaxThread, ThreadCount);
                            result = true;
                        }
                        break;
                    }
                } while( Process32Next( hProcessSnap, &pe32 ) );
            }

            CloseHandle( hProcessSnap );
        }

        GdiCount = GetGuiResources( hProcess, GR_GDIOBJECTS);

        if ((MaxGdi != 0) && (GdiCount > MaxGdi))
        {
            LERROR("GDI Objects exceeding standards!!!...[%d][%d]", MaxGdi, GdiCount);
            result = true;
        }
        CloseHandle( hProcess );
    }

    try
    {
FMemSize = uSize;
        plMemory->Caption = FormatFloat("##,##0", uSize)      ;// + " KB";
        plHandle->Caption = FormatFloat("##,##0", HandleCount);// + " EA";
        plThread->Caption = FormatFloat("##,##0", ThreadCount);// + " EA";
        plGdi->Caption    = FormatFloat("##,##0", GdiCount)   ;// + " EA";
    } catch (Exception &e) {}

    return result;
}
//---------------------------------------------------------------------------

int TFrmMain::LogWrite(int ALogKind, char *AFmt, ...)
{
    va_list     ap;
    int         cnt = 0;
    char        szFmtData[MAX_LOG_BUFFER];
    AnsiString  sLogKind;

    bool bLog = false;
    switch(ALogKind)
    {
    case eLOG_INFO   : bLog = g_LogCfg.Info;    sLogKind = " [INF] "; break;
    case eLOG_DATA   : bLog = g_LogCfg.Data;    sLogKind = " [DAT] "; break;
    case eLOG_ERROR  : bLog = g_LogCfg.Error;   sLogKind = " [ERR] "; break;
    case eLOG_WARNING: bLog = g_LogCfg.Warning; sLogKind = " [WAN] "; break;
    case eLOG_DEBUG  : bLog = g_LogCfg.Debug;   sLogKind = " [DBG] "; break;
    case eLOG_DETAIL : bLog = g_LogCfg.Detail;  sLogKind = " [DET] "; break;
    }
    if (!bLog) return -1;

    try
    {
        va_start(ap, AFmt);
        cnt = vsprintf(szFmtData, AFmt, ap);
        va_end(ap);

        ITSLog->LogWrite(NULL, ALogKind, szFmtData);

        IPC_LOG_MESSAGE *pLog = &FLogMsg;//new IPC_LOG_MESSAGE;
        if (pLog)
        {
            pLog->Kind = ALogKind;
            pLog->Flag = 0;
            pLog->Len  = strlen(szFmtData);
            pLog->Tm   = Now();
            memset(pLog->Msg, 0x00, sizeof(pLog->Msg));
            sprintf(pLog->Msg, "%sMAIN %s", sLogKind.c_str(), szFmtData);

            DWORD   dwResult = 0;
            LRESULT lResult = SEND_LOGMSG(FrmSysLog->Handle, WM_LOG_DISPLAY, pLog, NULL, SMTO_NORMAL, 2000, dwResult);
            if (lResult == 0)
            {
                dwResult = GetLastError();
                if (dwResult == ERROR_TIMEOUT)
                {
                }
                //SAFE_DELETE(pLog);
            }
        }
    }
    catch(Exception &e)
    {
    }

    return cnt;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::Panel16DblClick(TObject *Sender)
{
    CheckResource((g_AppCfg.MaxMemory * 1024), g_AppCfg.MaxHandle, g_AppCfg.MaxThread, g_AppCfg.MaxGdi);
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::plStateDbDblClick(TObject *Sender)
{
SendDbThreadMessage(WM_MASTER_IMAGE_SYMBOL, NULL, NULL);
Sleep(500);
SendDbThreadMessage(WM_MASTER_FORM, NULL, NULL);
Sleep(500);
SendDbThreadMessage(WM_MASTER_VMS_IFSC, NULL, NULL);
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::plStateActionDblClick(TObject *Sender)
{
ProvideEvent(provide_event, NULL, NULL);
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::LoadOldVmsInfo()
{
//LINFO("Old Protocol Version VMS Information Loading...");

    TStringList *slFile = NULL;

    String sCfgFile = g_sCfgDir + "OldVMS.inf";
    try
    {
        slFile = new TStringList;

        slFile->Clear();
        slFile->LoadFromFile(sCfgFile);

        int      ii;
        unsigned int hn, ln;
        BYTE     chn, cln, val;
        char     szData[2048];
        BYTE     RxBuff[VMS_MAX_PACKET_SIZE];
        int      RxLen;

        RxLen = 0;
        memset(RxBuff, 0x00, sizeof(RxBuff));

        for (ii = 0; ii < slFile->Count; ii++)
        {
            AnsiString sVmsId = slFile->Strings[ii].Trim();
            if (sVmsId == "") continue;
            if (sVmsId == "\r\n") continue;

            TVmsCtlr *pObj = FindVms(sVmsId);
            if (pObj)
            {
                pObj->FIsOldProtocol = true;
                //LINFO("%s : 이전 버전 프로토콜 사용", sVmsId.c_str());
            }
            else
            {
                //LINFO("%s : 이전 버전 프로토콜 사용(찾을수 없음)", sVmsId.c_str());
            }
        }
    }
    catch(Exception &e)
    {
        LERROR("LoadOldVmsInfo Exception: %s", AnsiString(e.Message).c_str());
    }
    delete slFile;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::LoadFtpVmsInfo()
{
//LINFO("FTP Download VMS Information Loading...");

    TStringList *slFile = NULL;

    String sCfgFile = g_sCfgDir + "FtpVMS.inf";
    try
    {
        slFile = new TStringList;

        slFile->Clear();
        slFile->LoadFromFile(sCfgFile);

        int      ii;
        unsigned int hn, ln;
        BYTE     chn, cln, val;
        char     szData[2048];
        BYTE     RxBuff[VMS_MAX_PACKET_SIZE];
        int      RxLen;

        RxLen = 0;
        memset(RxBuff, 0x00, sizeof(RxBuff));

        for (ii = 0; ii < slFile->Count; ii++)
        {
            AnsiString sVmsId = slFile->Strings[ii].Trim();
            if (sVmsId == "") continue;
            if (sVmsId == "\r\n") continue;

            TVmsCtlr *pObj = FindVms(sVmsId);
            if (pObj)
            {
                pObj->FIsFtpDownload = true;
                pObj->FBmpDownload   = true;    //FTP로 다운로드 하는 경우 이미지로 전송되어야함
                //LINFO("%s : FTP Downloaod 사용", sVmsId.c_str());
            }
            else
            {
                //LINFO("%s : FTP Downloaod 사용(찾을수 없음)", sVmsId.c_str());
            }
        }
    }
    catch(Exception &e)
    {
        LERROR("LoadFtpVmsInfo Exception: %s", AnsiString(e.Message).c_str());
    }
    delete slFile;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::LoadFontVmsInfo()
{
//LINFO("Protocol Font Name VMS Information Loading...");

    TStringList *slFile = NULL;

    String sCfgFile = g_sCfgDir + "FontNameVMS.inf";
    try
    {
        slFile = new TStringList;

        slFile->Clear();
        slFile->LoadFromFile(sCfgFile);

        int      ii;
        unsigned int hn, ln;
        BYTE     chn, cln, val;
        char     szData[2048];
        BYTE     RxBuff[VMS_MAX_PACKET_SIZE];
        int      RxLen;

        RxLen = 0;
        memset(RxBuff, 0x00, sizeof(RxBuff));

        for (ii = 0; ii < slFile->Count; ii++)
        {
            AnsiString sVmsId = slFile->Strings[ii].Trim();
            if (sVmsId == "") continue;
            if (sVmsId == "\r\n") continue;

            TVmsCtlr *pObj = FindVms(sVmsId);
            if (pObj)
            {
                pObj->FIsProtolFontName = true;
                //LINFO("%s : Font Name Protocol 사용", sVmsId.c_str());
            }
            else
            {
                //LINFO("%s : Font Name Protocol 사용(찾을수 없음)", sVmsId.c_str());
            }
        }
    }
    catch(Exception &e)
    {
        LERROR("LoadFontVmsInfo Exception: %s", AnsiString(e.Message).c_str());
    }
    delete slFile;
}
//---------------------------------------------------------------------------

void __fastcall TFrmMain::LoadBitmapVmsInfo()
{
//LINFO("Bitmap Form VMS Information Loading...");

    TStringList *slFile = NULL;

    String sCfgFile = g_sCfgDir + "BitmapVMS.inf";
    try
    {
        slFile = new TStringList;

        slFile->Clear();
        slFile->LoadFromFile(sCfgFile);

        int      ii;
        unsigned int hn, ln;
        BYTE     chn, cln, val;
        char     szData[2048];
        BYTE     RxBuff[VMS_MAX_PACKET_SIZE];
        int      RxLen;

        RxLen = 0;
        memset(RxBuff, 0x00, sizeof(RxBuff));

        for (ii = 0; ii < slFile->Count; ii++)
        {
            AnsiString sVmsId = slFile->Strings[ii].Trim();
            if (sVmsId == "") continue;
            if (sVmsId == "\r\n") continue;

            TVmsCtlr *pObj = FindVms(sVmsId);
            if (pObj)
            {
                pObj->FBmpDownload = true;
                //LINFO("%s : Bitmap Form 사용", sVmsId.c_str());
            }
            else
            {
                //LINFO("%s : Bitmap Form 사용(찾을수 없음)", sVmsId.c_str());
            }
        }
    }
    catch(Exception &e)
    {
        LERROR("LoadBitmapVmsInfo Exception: %s", AnsiString(e.Message).c_str());
    }
    delete slFile;
}
//---------------------------------------------------------------------------

TVmsCtlr* __fastcall TFrmMain::FindVms(AnsiString AVmsId)
{
    VmsIterator it;
    for(it=VmsManager->FLists.FMapObject.begin(); it != VmsManager->FLists.FMapObject.end(); ++it)
    {
        TVmsCtlr *pObj = (TVmsCtlr*)it->second;
        if (pObj->VmsId.AnsiCompare(AVmsId) == 0)
        {
            return pObj;
        }
    }

    return NULL;
}
//---------------------------------------------------------------------------

