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


#pragma hdrstop

#include "FrmMainCommF.h"
#include "AppGlobalF.h"
#include "FrmMainF.h"
#include "CDSProcessF.h"
#include "CDSCtlrF.h"
#include "CDSFormF.h"
#include "CDSIfscF.h"
#include "CDSImageF.h"
#include "CDSAtmpF.h"
#include "CDSParkF.h"
#include "VmsUtilsF.h"
#include "PacketHandllingF.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)

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

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

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

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

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

#if 1
            switch(AVmsObj->TextAlign)
            {
            case text_align_left:
                //좌측정력인 경우 위치조정 필요 없음.
                break;
            case text_align_right:
                //좌측에서 글자길이를 뺀다음 만약 음수이면 0으로 설정
                AVmsObj->PosX = (AVmsObj->PosX+AVmsObj->Width) - pLabel->Width;
                break;
            case text_align_center:
                //원래 글자의 중앙값을 얻은 다음에 조정된 글자의 1/2 크기를 뺀다음 음수이면 0으로 설정
                AVmsObj->PosX = (AVmsObj->PosX+(AVmsObj->Width/2)) - (pLabel->Width/2);
                break;
            }
            if (AVmsObj->PosX < 0) AVmsObj->PosX = 0;
            AVmsObj->TextWidth = pLabel->Width;
#else
			int 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;
				}
            }
#endif
        }
        catch(Exception &e)
		{
        }
    }
    __finally
    {
        SAFE_DELETE(pLabel);
    }
    return VERR_NONE;
}
//---------------------------------------------------------------------------

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

    VMS_SCHEDULE_INFO *pSch;
    VMS_SCHEDULE_DETL *pSchUnit;

MINFO("MAIN MakeVmsProvideForm: Start");

    nSaveVmsCnt = 0;
    nSaveFormCnt= 0;

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

        if (!pObj->Used) continue;
        if (!pObj->FProvide) continue;

        nSaveVmsCnt++;

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

        pSch = pObj->SCHEDULE;

        pObj->CTRLMODE->MaxDisplayForm = pSch->Count;
        if (pObj->CTRLMODE->MaxDisplayForm > pObj->VMS_MAX_PHSE_NUM)
        {
            MWARN("MAIN VMS Form Max count over1: %s, %d EA", pObj->CTLR_NMBR.c_str(), pObj->CTRLMODE->MaxDisplayForm);
            pObj->CTRLMODE->MaxDisplayForm = pObj->VMS_MAX_PHSE_NUM;
        }
        if (pObj->CTRLMODE->MaxDisplayForm > INT_VMS_MAX_FORM)
        {
            MWARN("MAIN VMS Form Max count over2: %s, %d EA", pObj->CTLR_NMBR.c_str(), pObj->CTRLMODE->MaxDisplayForm);
            pObj->CTRLMODE->MaxDisplayForm = INT_VMS_MAX_FORM;
        }

        pObj->pForms->Lock();
        try
        {
            TCDSAtmp  *pAtmpObj       = NULL;
            AnsiString ATMP_STTN_NMBR = "";

            //최대 제공 메시지 갯수만큼 생성
            for (int ii = 0; ii < pSch->Count && ii < pObj->CTRLMODE->MaxDisplayForm; ii++)
            {
                pSchUnit = &pSch->Unit[ii];
                if (pObj->FExistCngsForm && pSchUnit->DSPL_CNGS_YN == false)
                {
                    //해당 제어기에 정체폼이 존재하는 경우
                    //스케쥴 폼이 정체일때 표출하지 않는 경우
                    //폼을 생성하지 않는다.
                    continue;
                }

                nFormCnt = pObj->pForms->Count();

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

                //소통정보 표출폼 인 경우 표출할 구간의 소통정보가 존재하지 않는 경우
                //폼을 생성하지 않도록 한다.
                switch(pCDSForm->VMS_FORM_TYPE_CD)
                {
                case eFormTp_traf_1://   = 11,  //	소통상황(1단)
                case eFormTp_traf_2://   = 12,  //	소통상황(2단)
                case eFormTp_traf_3://   = 13,  //	소통상황(3단)
                case eFormTp_traf_4://   = 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 = CDSIfscManager->FLists.Find(sVmsIfscId[ss]);
                            if (pTmpIfsc)
                            {
                                if (pTmpIfsc->CMTR_GRAD_CD != "0") bNoData = false;
                            }
                        }
                        if (bNoData)
                        {
                            MWARN("MAIN VMS Schedule Form No Traffic: VmsNmbr(%s), FormId(%s)", pObj->CTLR_NMBR.c_str(), sFormId.c_str());
                            continue;
                        }
                    }
                    break;
#if 0
//폼에 대기환경수집장소가 하나인경우에만 해당
//폼 객체에 대기환경수집장소를 설정하도록 수정하였음.
                 case eFormTp_atmp: //대기환경
                     {
                        //스케줄 정보를 디비에서 읽어서 스케쥴을 작성할때 확인하지만 다시한번 확인
                        //아래 객체를 생성할때 사용할수 있게 미리 메모리를 찾아서 할당한다.
                        ATMP_STTN_NMBR = pSchUnit->FRST_VMS_IFSC_ID;
                        pAtmpObj = NULL;
                        if (CDSAtmpManager) CDSAtmpManager->FLists.Find(ATMP_STTN_NMBR);
                        if (!pAtmpObj) continue;
                        if (pAtmpObj->SUCCESS == false)
                        {
                            pAtmpObj = NULL;
                            continue;
                        }
                     }
                     break;
#endif
                }

                nSaveFormCnt++;

                //폼생성
                pVmsForm = pObj->pForms->AddForm(); // new 를 사용해서 생성하지 않고 기존에 생성한 폼을 이용한다.

                pVmsForm->Success       = false;
                pVmsForm->FtpFileName   = pCDSForm->FtpFileName;    // 정적폼인경우 경로가 지정됨
                pVmsForm->LocalFileName = pCDSForm->LocalFileName;  // 정적폼인경우 경로가 지정됨

                pVmsForm->VMS_SCH_TYPE      = pSchUnit->VMS_SCH_TYPE;
                pVmsForm->VMS_SCH_FORM_TYPE = pSchUnit->VMS_SCH_FORM_TYPE;
                pVmsForm->SYMB_LIB_NMBR     = pSchUnit->SYMB_LIB_NMBR;
                pVmsForm->STRM_ADDR         = pSchUnit->STRM_ADDR;

                pVmsForm->ScenarioSeq           = nFormCnt;                                       /* 폼 표출순서 */
                pVmsForm->VMS_FORM_ID           = pCDSForm->VMS_FORM_ID;                          /* 폼 ID */
                pVmsForm->DSPL_HH               = pSchUnit->DSPL_HH;                              /* 표출시간(초) */
                pVmsForm->VMS_FORM_DSPL_DRCT_CD = AnsiString(pCDSForm->VMS_FORM_DSPL_DRCT_CD);    /* 표출방향 */
                pVmsForm->VMS_FORM_DSPL_MTHD_CD = AnsiString(pCDSForm->VMS_FORM_DSPL_MTHD_CD);    /* 표출기능 */
                pVmsForm->VMS_FORM_TYPE_CD      = pCDSForm->VMS_FORM_TYPE_CD;                     /* 폼 종류 */
                pVmsForm->VMS_FORM_COLR_CD      = pCDSForm->VMS_FORM_COLR_CD;                     /* 배경색상 */
                pVmsForm->Width  = pObj->WIDTH;                                    /* 폼넓이 */
                pVmsForm->Height = pObj->HEIGHT;                                   /* 폼높이 */
                pVmsForm->SvcRes = false;
                pVmsForm->FtpRes = false;

                pVmsForm->Lock();

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

                    //도형식 배경소통정보 폼인 경우 하단에 표출할 정보가 없는 경우
                    //하단 소통정보 객체는 생성하지 않도록 하자.
                    if (pVmsForm->VMS_FORM_TYPE_CD == eFormtp_figure)   //   = 15,  //	소통상황(도형식배경소통정보))
                    {
                        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;
                        }
                    } //pVmsForm->VMS_FORM_TYPE_CD == eFormtp_figure

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

                    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단,소통정보이미지1
                    case  27: //2단,소통정보이미지2
                    case  37: //3단,소통정보이미지3
                    case  47: //4단,소통정보이미지4
                    case 167: //@우회소통정보이미지
                    case 200: //동영상이미지
                    case 300: //스트리밍영상이미지
                    case 406: //@통합대기등급 이미지
                    case 407: //@미세먼지등급 이미지
                    case 408: //@초미세먼지등급 이미지
                    case 413: //@오존등급이미지
                        pVmsObj->ObjectKind = graphicID_object_data;
                        break;
                    default:
                        pVmsObj->ObjectKind = text_object_data;
                        break;
                    } //switch(pCDSObj->VMS_FORM_OBJECT_TYPE_CD)

                    pVmsObj->ObjectType    = pCDSObj->VMS_FORM_OBJECT_TYPE_CD; //NUMBER(3)	N			VMS FORM OBJECT 유형 코드
                    pVmsObj->TextFontName  = pCDSObj->VMS_FONT_NAME_CD;        //NUMBER(3)	N			VMS 글꼴 유형 코드
                    //TODO
                    pVmsObj->StrTextFontName = CodeToFontName(pVmsObj->TextFontName);

                    pVmsObj->TextFontColor = pCDSObj->VMS_FONT_COLR_CD;        //NUMBER(3)	N			VMS 글꼴 색상 코드
                    pVmsObj->TextFontBold  = pCDSObj->VMS_FONT_BOLD;           //NUMBER(3)	Y			VMS 글꼴 방식 코드(0:Normal,1:Bold)
                    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->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->TextWidth     = 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 표출 크기(문자:문자길이,이미지:이미지전체크기)

                    if (pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 201 || //동영상명칭
                        pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 301)   //스트리밍영상주소
                    {
                        pVmsObj->TextData = pSchUnit->STRM_ADDR;             //VARCHAR2(200)	Y		VMS 표출 텍스트
                    }
                    else
                    {
                        pVmsObj->TextData = pCDSObj->VMS_DSPL_TXT;            //VARCHAR2(200)	Y		VMS 표출 텍스트
                    }

                    if (pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 200 || //동영상이미지
                        pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 300)   //스트리밍영상이미지
                    {
                        pVmsObj->ImageId = pSchUnit->SYMB_LIB_NMBR+"0";           //NUMBER(4)	N	0		심벌라이브러리 번호
                        if (pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 200)
                        {
                            pVmsObj->PosX   = 0;                                     //NUMBER(5)	Y			VMS 표출 X좌표
                            pVmsObj->PosY   = 0;                                     //NUMBER(5)	Y			VMS 표출 Y좌표
                            pVmsObj->Width  = pVmsForm->Width;                       //NUMBER(5)	Y	0		VMS 표출 넓이
                            pVmsObj->Height = pVmsForm->Height;                      //NUMBER(5)	Y	0		VMS 표출 높이

                            TCDSImage* pTmpImg = CDSImageManager->FLists.Find(pVmsObj->ImageId);
                            if (pTmpImg)
                            {
                                pVmsForm->DSPL_HH = pTmpImg->PLAY_TM;
                            }
                        }
                    }
                    else
                    {
                        pVmsObj->ImageId = pCDSObj->SYMB_LIB_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
                                {
                                    if (pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 200 || //동영상이미지
                                        pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 300)   //스트리밍영상이미지
                                    {
                                        TCDSImage* pTmpImg = CDSImageManager->FLists.Find(pVmsObj->ImageId);
                                        if (pTmpImg)
                                        {
                                            pVmsObj->pImageData->Picture->Assign(pTmpImg->IMAG_DATA->Picture);
                                        }
                                        else
                                        {
                                            pVmsObj->pImageData->Picture->Assign(pCDSObj->pImage->Picture);
                                        }
                                    }
                                    else
                                    if (CDSAtmpManager &&
                                        (pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 406 || //@통합대기등급 이미지
                                         pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 407 || //@미세먼지등급 이미지
                                         pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 408 || //@초미세먼지등급 이미지
                                         pCDSObj->VMS_FORM_OBJECT_TYPE_CD == 413 )  //@오존등급이미지
                                        )
                                    {
                                        bool isObj = false;
                                        pAtmpObj = CDSAtmpManager->FLists.Find(pCDSObj->VMS_IFSC_ID);
                                        if (pAtmpObj && pAtmpObj->SUCCESS) isObj = true;

                                        if (isObj)
                                        {
                                            //관측장소 정보가 존재하는 경우에만 대기환경이미지를 폼에 적용한다.
                                            int nAtmpGrad = 0;
                                            switch(pCDSObj->VMS_FORM_OBJECT_TYPE_CD)
                                            {
                                            case 406: nAtmpGrad = pAtmpObj->INTG_ATMP_GRAD.ToIntDef(1); break;
                                            case 407: nAtmpGrad = pAtmpObj->PM10_1HH_GRAD.ToIntDef(1);  break;
                                            case 408: nAtmpGrad = pAtmpObj->PM25_1HH_GRAD.ToIntDef(1);  break;
                                            case 413: nAtmpGrad = pAtmpObj->O3_GRAD.ToIntDef(1);        break;
                                            }
                                            if (nAtmpGrad > 0) nAtmpGrad--;

                                            TCDSImage *pTmp1 = CDSImageManager->FLists.Find(pVmsObj->ImageId);
                                            if (pTmp1)
                                            {
                                                AnsiString sGradSymbId = pTmp1->GRAD_SYMB_LIB_NMBR[nAtmpGrad];
                                                TCDSImage *pTmp2 = CDSImageManager->FLists.Find(sGradSymbId);
                                                if (pTmp2) pVmsObj->pImageData->Picture->Assign(pTmp2->IMAG_DATA->Picture);
                                                else       pVmsObj->pImageData->Picture->Assign(pTmp1->IMAG_DATA->Picture);

                                                pVmsObj->ImageId = sGradSymbId;
                                            }
                                            else
                                            {
                                                pVmsObj->pImageData->Picture->Assign(pCDSObj->pImage->Picture);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        pVmsObj->pImageData->Picture->Assign(pCDSObj->pImage->Picture);
                                    }
                                }
                                catch(Exception &e)
                                {
                                    MERROR("SaveMemoryStream1: %s[%s] - %s", pVmsForm->VMS_FORM_ID.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 ||   //고정문자열
                        pVmsObj->ObjectType == 201 ||   //동영상파일명
                        pVmsObj->ObjectType == 301)     //스트리밍영상주소
                    {
#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단,소통정보이미지1
                        pVmsObj->ObjectType == 27 ||    //2단,소통정보이미지2
                        pVmsObj->ObjectType == 37 ||    //3단,소통정보이미지3
                        pVmsObj->ObjectType == 47 ||    //4단,소통정보이미지4
                        pVmsObj->ObjectType == 167 )    //@우회소통정보이미지
                    {
                        if (!pVmsObj->pImageData) continue;

                        TCDSImage *pSymbol = CDSImageManager->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;
                            case 167: pVmsObj->IFSC_ID = pSchUnit->SECD_IMG_IFSC_ID; break;
                            }

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

                                    pVmsObj->ImageId = pCDSObj->SYMB_LIB_NMBR + pTmpIfsc->CMTR_GRAD_CD;

                                    pVmsObj->pImageData->Picture->Bitmap->Canvas->Lock();
                                    try
                                    {
                                        pVmsObj->pImageData->Picture->Bitmap->Canvas->Brush->Style = bsSolid;
                                        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)
                        {
                            MERROR("MAIN SaveMemoryStreamX: %s[%s] - %s", pVmsForm->VMS_FORM_ID.c_str(), pVmsObj->ImageId.c_str(), AnsiString(e.Message).c_str());
                        }
                    }
                    else
                    if (pVmsObj->ObjectType == 3)       //소통정보 배경이미지
                    {
                        if (!pVmsObj->pImageData) continue;

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

                        try
                        {
                            int X, Y;

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

                                    pVmsObj->pImageData->Picture->Bitmap->Canvas->Lock();
                                    try
                                    {
                                        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)
                        {
                            MERROR("MAIN SaveMemoryStream2: %s[%s] - %s", pVmsForm->VMS_FORM_ID.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->ObjectType == 66       //통제유형
                       )
                    {
                        //돌발문안인 경우임
                        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; //@시점명
                            case 63: pVmsObj->TextData = pEvt->END_LCTN_NM;           break; //@종점명
                            case 64: pVmsObj->TextData = pEvt->VMS_INCD_DETL_NM;      break; //@돌발유형
                            case 65: pVmsObj->TextData = pEvt->OCRR_LCTN_NM;          break; //@대응문구(사용안함-발생장소로 일단넣음)
                            case 66: pVmsObj->TextData = pEvt->VMS_INCD_RSTR_TYPE_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 ||    //INCD_TITL
                        pVmsObj->ObjectType == 73 ||    //통제시점명
                        pVmsObj->ObjectType == 74 ||    //통제종점명
                        pVmsObj->ObjectType == 75 ||    //00차로 차단
                        pVmsObj->ObjectType == 76 ||    //00월00일 ~ 00월00일
                        pVmsObj->ObjectType == 77 ||    //대응문구
                        pVmsObj->ObjectType == 78       //@통제유형
                       )
                    {
                        //공사/행사문안 임
                        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->INCD_TITL;       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);
                                    if (nLane == 111111)
                                        pVmsObj->TextData = "차로 차단";
                                    else
                                    if (nLane > 0)
                                        pVmsObj->TextData = "일부 차단";
                                    else
                                        pVmsObj->TextData = " ";
                                }
                                break; //00차로 차단
                            case 76: //00월00일 ~ 00월00일
                                {
                                    String sFrom = pEvt->INCD_STRT_DT.SubString(5,2)     + "월" + pEvt->INCD_STRT_DT.SubString(7,2)     + "일 " + pEvt->INCD_STRT_DT.SubString(9,2)     + "시";
                                    String sTo   = pEvt->INCD_END_PRAR_DT.SubString(5,2) + "월" + pEvt->INCD_END_PRAR_DT.SubString(7,2) + "일 " + pEvt->INCD_END_PRAR_DT.SubString(9,2) + "시";
                                    pVmsObj->TextData = sFrom + " ~ " + sTo;
                                }
                                break;
                            case 77: pVmsObj->TextData = pEvt->OCRR_LCTN_NM;          break; //대응문구(사용안함-발생장소로 일단넣음)
                            case 78: pVmsObj->TextData = pEvt->VMS_INCD_RSTR_TYPE_NM; break; //@통제유형
                            }
                        }
                        if (pVmsObj->TextData == "") pVmsObj->TextData = " ";
                        ChangePosition(pVmsObj);
                    }
                    else
                    if (CDSAtmpManager &&
                        (pVmsObj->ObjectType == 401 || //@관측장소
                         pVmsObj->ObjectType == 402 || //@PM10
                         pVmsObj->ObjectType == 403 || //@PM2.5
                         pVmsObj->ObjectType == 404 || //@PM10등급
                         pVmsObj->ObjectType == 405 || //@PM2.5등급
                         pVmsObj->ObjectType == 409 || //@통합대기등급
                         pVmsObj->ObjectType == 410 || //@통합대기
                         pVmsObj->ObjectType == 411 || //@오존
                         pVmsObj->ObjectType == 412 )  //@오존등급
                        )
                    {
                        bool isObj = false;
                        pAtmpObj = CDSAtmpManager->FLists.Find(pCDSObj->VMS_IFSC_ID);
                        if (pAtmpObj && pAtmpObj->SUCCESS) isObj = true;

                        AnsiString sUnit = "";
                        bool       bUnit = false;
                        if (pVmsObj->TextData.Pos(" -"))
                        {
                            bUnit = true;
                            sUnit = " ";
                        }
                        else
                        if (pVmsObj->TextData.Pos("-"))
                        {
                            bUnit = true;
                        }

                        pVmsObj->TextData = " ";
                        if (pVmsObj->ObjectType == 401)
                        {
                            pVmsObj->TextData = pAtmpObj ? pAtmpObj->VMS_DISP_NM : AnsiString("---");
                        }
                        else
                        if (pVmsObj->ObjectType == 402)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetPM10_VAL(false) : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetPM10_CLR()      : clRed;
                            if (bUnit) pVmsObj->TextData = pVmsObj->TextData + sUnit + "㎍/㎥";
                        }
                        else
                        if (pVmsObj->ObjectType == 403)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetPM25_VAL(false) : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetPM25_CLR()      : clRed;
                            if (bUnit) pVmsObj->TextData = pVmsObj->TextData + sUnit + "㎍/㎥";
                        }
                        else
                        if (pVmsObj->ObjectType == 404)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetPM10_GRAD() : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetPM10_CLR()  : clRed;
                        }
                        else
                        if (pVmsObj->ObjectType == 405)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetPM25_GRAD() : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetPM25_CLR()  : clRed;
                        }
                        else
                        if (pVmsObj->ObjectType == 409)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetATMP_GRAD() : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetATMP_CLR()  : clRed;
                        }
                        else
                        if (pVmsObj->ObjectType == 410)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetATMP_VAL(false) : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetATMP_CLR()      : clRed;
                        }
                        else
                        if (pVmsObj->ObjectType == 411)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetO3_VAL(false) : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetO3_CLR()      : clRed;
                            if (bUnit) pVmsObj->TextData = pVmsObj->TextData + sUnit + "ppm";
                        }
                        else
                        if (pVmsObj->ObjectType == 412)
                        {
                            pVmsObj->TextData      = isObj ? pAtmpObj->GetO3_GRAD() : AnsiString("-");
                            pVmsObj->TextFontColor = isObj ? pAtmpObj->GetO3_CLR()  : clRed;
                        }

                        if (pVmsObj->TextData == "") pVmsObj->TextData = " ";
                        ChangePosition(pVmsObj);
                    }
                    else
                    if (pVmsObj->ObjectType == 501 || //@주차가능대수
                        pVmsObj->ObjectType == 502 )  //@주차혼잡도

                    {
                        TCDSPark *pPark = NULL;
                        if (CDSParkManager) CDSParkManager->FLists.Find(pCDSObj->VMS_IFSC_ID);
                        if (pPark)
                        {
                            AnsiString sFmt = pCDSObj->VMS_DSPL_TXT;

                            sFmt = StringReplace(sFmt, "@", "", TReplaceFlags() << rfReplaceAll);

                            if (pVmsObj->ObjectType == 501)
                            {
                                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(), pPark->TOTAL);
                                }
                                else
                                {
                                    pVmsObj->TextData = AnsiString(pPark->TOTAL);
                                }
                                pVmsObj->TextFontColor = pPark->GetGradeColor();
                            }
                            else
                            if (pVmsObj->ObjectType == 502)
                            {
                                pVmsObj->TextData = pPark->CNGT_DESC;
                                pVmsObj->TextFontColor = pPark->GetGradeColor();
                            }
                        }
                        else
                        {
                            pVmsObj->TextData      = "-";
                            pVmsObj->TextFontColor = clRed;
                        }

                        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->VMS_FORM_TYPE_CD == eFormtp_figure)
                            {
                                VMS_IFSC_ID = pSchUnit->VMS_IFSC_ID;
                            }
                            else
                            if (pVmsForm->VMS_FORM_TYPE_CD == enFormKindCongest)// && pVmsObj->ObjectType == 18)
                            {
                                VMS_IFSC_ID = pSchUnit->VMS_IFSC_ID;
                            }
                            break;
                        case 161: case 162: case 163: case 164: case 165: case 166: case 168:
                            VMS_IFSC_ID = pSchUnit->SECD_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 = CDSIfscManager->FLists.Find(VMS_IFSC_ID);
                        if (pTmpIfsc)
                        {
                            switch(pVmsObj->ObjectType)
                            {
                            case 11: case 21: case 31: case 41: case 161: //구간명
                                pVmsObj->TextData = pTmpIfsc->ROAD_NM;
                                break;
                            case 12: case 22: case 32: case 42: case 93: case 162: //시점명
                                pVmsObj->TextData = pTmpIfsc->DSPL_STRT_NODE_NM;
                                break;
                            case 13: case 23: case 33: case 43: case 94: case 163: //종점명
                                pVmsObj->TextData = pTmpIfsc->DSPL_END_NODE_NM;
                                break;
                            case 14: case 24: case 34: case 44: case 92: case 95: case 164: //소통상황
                                pVmsObj->TextData      = GradeToString(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0), pVmsForm->VMS_FORM_TYPE_CD);
                                pVmsObj->TextFontColor = GradeToColorCode(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0));
                                break;
                            case 19:    //소통상황(가변)
                                {
                                    AnsiString sGradText = GradeToString(pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0), pVmsForm->VMS_FORM_TYPE_CD);
                                    if (pTmpIfsc->CMTR_GRAD_CD.ToIntDef(0) == grade_smoothness)
                                    {
                                        sGradText.printf("소통원활  약 %d 분", pTmpIfsc->TRVL_HH);
                                    }
                                    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: case 165: //통행시간
#if 0
                                pVmsObj->TextData = AnsiString(pTmpIfsc->TRVL_HH);
#else
                                {
                                    AnsiString sFmt = pCDSObj->VMS_DSPL_TXT;

                                    sFmt = StringReplace(sFmt, "@", "", TReplaceFlags() << rfReplaceAll);
                                    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: case 166: //통행속도
                                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: case 168: //지점명
                                pVmsObj->TextData = pTmpIfsc->SPOT_NM;
                                break;
                            }
                            ChangePosition(pVmsObj);
                        }
                    }
                } //FOR_STL(폼객체생성)

                pVmsForm->UnLock();

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

    MINFO("MAIN MakeVmsProvideForm: End. (VMS: %d EA, Forms %d EA)", nSaveVmsCnt, nSaveFormCnt);

    MINFO("MAIN MakeVmsDatabaseForm: Start");

    nSaveVmsCnt = 0;
    nSaveFormCnt= 0;

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

        if (!pObj->Used) continue;
        if (!pObj->FProvide) continue;

        if (g_AppCfg.BottomTrafficCenter)
        {
            //도형식폼의 하단소통정보위치를 가운데로 정렬하는 경우
            MakeVmsFigureFormPos(pObj);
        }
        nSaveFormCnt += MakeVmsDatabaseForm(pObj);
        nSaveVmsCnt++;
    }

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

int __fastcall TFrmMain::MakeVmsFigureFormPos(TCDSCtlr *AObj)
{
int ARRAWGAP =  5;
int TRAFFGAP = 12;

    int nSelCnt = 0;

    if (!AObj) return VERR_MEMORY_ALLOC;

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

    int nObjCnt;
    int nFormT;
    TVmsFormObj *pArw;
    TVmsFormObj *pStr;
    TVmsFormObj *pEnd;
    TVmsFormObj *pTrf;
    int nTotW;
    int nLeft;


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

                if (pForm->VMS_FORM_TYPE_CD != eFormtp_figure)
                {
                    //도형식배경소통정보 폼이 아닌경우 계산하지 않음
                    continue;
                }

                nFormT = pForm->Height - 40;       //하단소통정보 객체의 최대높이를 설정, 이것보다 작으면 위치조정 하지 않음
                pArw = NULL;
                pStr = NULL;
                pEnd = NULL;
                pTrf = NULL;

                //소통상황 시점 -> 종점
                //시점 -> 종점 소통상황
                //위의 2가지 유형에 대하여 가운데 정렬
                nObjCnt = pForm->Count();

                for (int jj = 0; jj < nObjCnt; jj++)
                {
                    TVmsFormObj *pFormObj = pForm->GetItem(jj);
                    if (pFormObj->PosY < nFormT)
                    {
                        continue;
                    }

                    switch(pFormObj->ObjectType)
                    {
                    case  1:    //	심볼	            Y
                    case  2:    //	이미지	            Y
                    case 17:    //	@소통정보이미지	    N
                        if (pFormObj->TRFC_FILL_CD == "T")
                        {
                            pArw = pFormObj;
                        }
                        break;
                    case 12:    //	@시점명	            Y
                    case 93:    //	@축시점명(순환)	    Y
                    case 13:    //	@종점명	            Y
                    case 94:    //	@축종점명(순환)	    Y
                        if (pFormObj->ObjectType == 12 || pFormObj->ObjectType == 93)
                        {
                            pStr = pFormObj;
                        }
                        else
                        {
                            pEnd = pFormObj;
                        }
                        break;
                    case 14:    //	@소통상황	        Y
                    case 15:    //	@통행시간	        Y
                    case 16:    //	@통행속도	        N
                    case 95:    //	@축소통상황(순환)	Y
                    case 96:    //	@축통행시간(순환)	Y
                        pTrf = pFormObj;
                        break;
                    }
                }

                if (pArw && pStr && pEnd && pTrf)
                {
                    if ((pStr->TextWidth +
                         pArw->TextWidth +
                         pEnd->TextWidth +
                         pTrf->TextWidth) > (pForm->Width - ARRAWGAP - ARRAWGAP - TRAFFGAP - 10)
                        )
                    {
                        ARRAWGAP =  3;
                        TRAFFGAP = 10;
                    }

                    nTotW = pStr->TextWidth + ARRAWGAP +
                            pArw->TextWidth + ARRAWGAP +
                            pEnd->TextWidth + TRAFFGAP +
                            pTrf->TextWidth;

                    nLeft = (pForm->Width - nTotW) / 2;

                    if (pStr->PosX < pTrf->PosX)
                    {
                        //시점 -> 종점 소통상황
                        pStr->PosX = nLeft;
                        pArw->PosX = pStr->PosX + pStr->TextWidth + ARRAWGAP;
                        pEnd->PosX = pArw->PosX + pArw->TextWidth + ARRAWGAP;
                        pTrf->PosX = pEnd->PosX + pEnd->TextWidth + TRAFFGAP;
                    }
                    else
                    {
                        //소통상황 시점 -> 종점
                        pTrf->PosX = nLeft;
                        pStr->PosX = pTrf->PosX + pTrf->TextWidth + TRAFFGAP;
                        pArw->PosX = pStr->PosX + pStr->TextWidth + ARRAWGAP;
                        pEnd->PosX = pArw->PosX + pArw->TextWidth + ARRAWGAP;
                    }
                }
            }
		}
		catch(Exception &e)
		{
            MERROR("MAIN MakeVmsFigureFormPos error2: %s, %s", AnsiString(e.ClassName()).c_str(), AnsiString(e.Message).c_str());
		}
	}
	__finally
	{
        AObj->pForms->UnLock();
	}
    return nSelCnt;
}
//---------------------------------------------------------------------------

int __fastcall TFrmMain::MakeVmsDatabaseForm(TCDSCtlr *AObj)
{
    int nSelCnt = 0;

    if (!AObj) return VERR_MEMORY_ALLOC;

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


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

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

                    nObjCnt = pForm->Count();

                    TRect rc;
                    for (int jj = 0; jj < nObjCnt; jj++)
                    {
                        TVmsFormObj *pFormObj = pForm->GetItem(jj);
                        switch(pFormObj->ObjectType)
                        {
                        case   1: //심볼
                        case   2: //이미지
                        case   3: //소통정보배경이미지
                        case  17: //소통정보이미지1
                        case  27: //소통정보이미지2
                        case  37: //소통정보이미지3
                        case  47: //소통정보이미지4
                        case 167: //@우회소통정보이미지
                        case 200: //동영상이미지
                        case 300: //스트리밍영상이미지
                        case 406: //@통합대기등급 이미지
                        case 407: //@미세먼지등급 이미지
                        case 408: //@초미세먼지등급 이미지
                        case 413: //@오존등급이미지
                            if (pFormObj->ObjectType == 17 ||
                                pFormObj->ObjectType == 27 ||
                                pFormObj->ObjectType == 37 ||
                                pFormObj->ObjectType == 47 ||
                                pFormObj->ObjectType == 167
                               )
                            {
                                rc.Top    = pFormObj->PosY;
                                rc.Bottom = pFormObj->PosY + pFormObj->pImageData->Picture->Graphic->Height;
                                rc.Left   = pFormObj->PosX;
                                rc.Right  = pFormObj->PosX + pFormObj->pImageData->Picture->Graphic->Width;
                                pForm->pBitmap->Canvas->StretchDraw(rc, pFormObj->pImageData->Picture->Graphic);
                            }
                            else
                            {
                                pForm->pBitmap->Canvas->Draw(pFormObj->PosX, pFormObj->PosY, pFormObj->pImageData->Picture->Graphic);
                            }
                            break;
                        default://기타 문자열
                            pForm->pBitmap->Canvas->Brush->Color = CodeToBackColor(pFormObj->BkColor);
#if 0
//이력저장할때 폰트색상을 코드로 넣기 때문에 색상값을 직접사용할 수 없다.
                            switch(pFormObj->ObjectType)
                            {
                            //case 401: //@관측장소 ==> 관측장소 폰트 색상은 운영자가 입력한 색상을 그대로 사용한다.
                            case 402: //@PM10
                            case 403: //@PM2.5
                            case 404: //@PM10등급
                            case 405: //@PM2.5등급
                            case 409: //@통합대기등급
                            case 410: //@통합대기
                            case 411: //@오존
                            case 412: //@오존등급
                                pForm->pBitmap->Canvas->Font->Color = (TColor)(pFormObj->TextFontColor);
                                break;
                            default:
                                pForm->pBitmap->Canvas->Font->Color = CodeToFontColor(pFormObj->TextFontColor);
                                break;
                            }
#else
                            pForm->pBitmap->Canvas->Font->Color = CodeToFontColor(pFormObj->TextFontColor);
#endif
                            pForm->pBitmap->Canvas->Font->Name = CodeToFontName(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);
                        //FTP다운로드 하는 경우 폼을 FTP디렉토리에 저장해야함
                        if (pForm->VMS_SCH_FORM_TYPE != eSchTp_hongbo &&    //홍보(제어기별 폼생성시 CDSForm의 파일명으로 설정되어 있음
                            pForm->VMS_SCH_FORM_TYPE != eSchTp_video  &&    //비디오
                            pForm->VMS_SCH_FORM_TYPE != eSchTp_stream )     //스트리밍영상 등은 로컬파일로 저장할 필요가 없음
                        {                                                   //파일이름을 여기서 변경하면 ftp 파일명이 변경된다.
                            if (AObj->FIsFtpDownload)
                            {
                                AnsiString sFormName;
                                sFormName.printf("%s_%02d.bmp", AObj->CTLR_NMBR.c_str(), ii+1);

                                pForm->LocalFileName = AObj->FLocalFormDir + sFormName;
                                pForm->FtpFileName   = AObj->FFtpFormDir + sFormName;

                                pForm->pBitmap->SaveToFile(pForm->LocalFileName);
                            }
                        }
                        pForm->Success = true;

                        switch (pForm->VMS_SCH_FORM_TYPE)
                        {
                        case eSchTp_traffic:    //  = 0,    //0:교통,
                        case eSchTp_incident:   //  = 1,    //1:돌발,
                        case eSchTp_gongsa:     //  = 2,    //2:공사행사,
                        case eSchTp_deture:     //  = 4,    //4:우회,
                        case eSchTp_congest:    //  = 5,    //5:정체,
                            pForm->fileType = P_FILE_TYPE_TRAFFIC;
                            break;
                        case eSchTp_hongbo:     //  = 3,    //3:홍보,
                        case eSchTp_safe:       //  = 6,    //6:안전,
                        case eSchTp_atmp:       //  = 9,    //9:대기환경
                        case eSchTp_park:       //  = 10,   //10:주차정보
                            pForm->fileType = P_FILE_TYPE_TEXT;
                            break;
                        case eSchTp_video:      //  = 7,    //7:동영상,
                            pForm->fileType    = P_FILE_TYPE_VIDEO;
                            pForm->FtpFileName = AnsiString(FTP_VIDEO) + "\\" + pForm->STRM_ADDR;
                            break;
                        case eSchTp_stream:     //  = 8,    //8:스트리밍영상
                            pForm->fileType    = P_FILE_TYPE_STREAM;
                            pForm->FtpFileName = pForm->STRM_ADDR;
                            break;
                        default:
                            pForm->Success = false;
                            break;
                        }

                        MINFO("MAIN CTLR FORM: %s, %d, [%d] [0x%02X], %s", AObj->CTLR_NMBR.c_str(), ii, pForm->VMS_SCH_FORM_TYPE, pForm->fileType, pForm->FtpFileName.c_str());

                        nSelCnt++;
                    }
                    catch(Exception &e)
                    {
                        MERROR("MAIN MakeVmsDatabaseForm error1: %s, %s", AnsiString(e.ClassName()).c_str(), AnsiString(e.Message).c_str());
                        pForm->LocalFileName = "";
                        pForm->FtpFileName   = "";
                    }
                }
                __finally
                {
                    pForm->pBitmap->Canvas->Unlock();
                }
            }
		}
		catch(Exception &e)
		{
            MERROR("MAIN MakeVmsDatabaseForm error2: %s, %s", AnsiString(e.ClassName()).c_str(), AnsiString(e.Message).c_str());
		}
	}
	__finally
	{
        AObj->pForms->UnLock();
	}
    return nSelCnt;
}
//---------------------------------------------------------------------------


