curtis
14小時前 3af5c004b4f2d2005d22ee85dccc2c80a66b1556
refactor: spec 輸出
修改3個檔案
刪除10個檔案
新增70個檔案
73864 ■■■■■ 已變更過的檔案
.gitignore 3 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
CB_IMGPSScan.res 修補檔 | 檢視 | 原始 | 究查 | 歷程
CB_IMGPSScanImp.pas 15433 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
CB_IMGPSScanImp.pas.bk 16454 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.api.pas 986 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.caseMgr.pas 107 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.convert.pas 480 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.custdoc.pas 332 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.docmod.pas 196 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.docq.pas 553 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.fileOp.pas 347 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.inbound.pas 147 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.lfcycle.pas 771 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.listMgr.pas 38 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.misc.pas 171 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.omr.pas 980 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.prUpload.pas 800 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/CB_IMGPSScanImp.preview.pas 467 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/bloc/caseManager.pas 60 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/bloc/entityMapping.pas 59 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/img/anchor.pas 68 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/img/transformer.pas 165 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/scan/twain.pas 880 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/transp/fileClient.pas 161 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/transp/payloadArchiver.pas 130 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/listView.pas 77 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/misc.pas 6607 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/msger.pas 66 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/popupMenu.pas 2020 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/scrollView.pas 314 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/toolBar.pas 1104 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
reassemble/view/treeView.pas 822 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/batch_dfm_to_web.js 52 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/CB_IMGPSScanImp.pas.bk.image.csv 103 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/CB_IMGPSScanImp.pas.bk.io.csv 359 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/CB_IMGPSScanImp.pas.bk.scan.csv 36 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/CB_IMGPSScanImp.pas.bk.transp.csv 71 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/CB_IMGPSScanImp.remaining.txt 1051 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/ErrList.pas.image.csv 5 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/ErrList.pas.io.csv 12 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/OldCaseInfo.pas.image.csv 2 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/OldCaseInfo.pas.io.csv 18 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/OldCaseInfo.pas.transp.csv 7 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/PatchFom.pas.image.csv 7 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/PatchFom.pas.scan.csv 3 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/deps.all.csv 607 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/readme.md 18 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/dist/scanimpl_annalysis.remainings.txt 1050 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/final_classify_scanImp_pas.js 264 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/final_classify_scanImp_pas.test.js 115 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/list_dependencies.js 110 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/list_dependencies_run.js 99 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/list_image_dependencies.js 82 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/list_io_dependencies.js 61 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/list_scan_dependencies.js 53 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/list_transport_dependencies.js 56 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/readme.md 30 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/scanimpl_annalysis_addon_json.js 125 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/scanimpl_annalysis_addon_json.test.js 183 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/scanimpl_annalysis_classify.js 115 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/scanimpl_annalysis_disaggregate.js 27 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/scanimpl_annalysis_extract_methods.js 40 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
scripts/scanimpl_annalysis_validate.js 65 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Data.pas 5178 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Data.ts 819 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Main.ts 17 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Scan.pas 1050 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Scan.ts 124 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_UI.pas 6592 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_UI.ts 78 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Utils.pas 2545 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
separate/scanImp/CB_IMGPSScanImp_Utils.ts 59 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
split_pascal.js 98 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/CB_IMGPSScanImp/CB_IMGPSScanImp.ts 216 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/CB_IMGPSScanImp/CB_IMGPSScanImp.vue 264 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/ErrList/ErrList.ts 314 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/ErrList/ErrList.vue 200 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/PatchFom/PatchFom.ts 155 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/PatchFom/PatchFom.vue 144 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/assets/CB_ErrList.png 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/assets/CB_IMGPSScanImp.png 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/assets/CB_PatchFom.png 修補檔 | 檢視 | 原始 | 究查 | 歷程
uiOutput/index.html 387 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
.gitignore
@@ -1 +1,4 @@
__history/
.idea
__recovery
CB_IMGPSScan.res
Binary files differ
CB_IMGPSScanImp.pas
檔案太大
CB_IMGPSScanImp.pas.bk
比對新檔案
檔案太大
reassemble/CB_IMGPSScanImp.api.pas
比對新檔案
@@ -0,0 +1,986 @@
{ ==============================================================================
  方法名稱:GetServerDate
  引用相依:ProcessServlet_Get
  方法描述:從伺服器獲取伺服器時間。透過 HTTPS 請求取得時間字串,解析日期與時間,並
            計算 Server 與本機的時間差(Balance)供後續校時使用。
============================================================================== }
Function TCB_IMGPSScanX.GetServerDate : Boolean;
begin
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/servertimeforocx','',FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    ServerDate := memo1.Lines.Strings[1];
    ServerTime := Copy(ServerDate,9,6);
    ServerDate := Copy(ServerDate,1,8);
    Balance := GetBalance(ServerTime); //Server 跟Local的時間差
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSampleInf
  引用相依:ProcessServlet_Get
  方法描述:從伺服器獲取已註冊的範本表單 ID 清單,並存入 SampleFormIDList。
============================================================================== }
Function TCB_IMGPSScanX.GetSampleInf : Boolean;
var
  str:String;
begin
  Result := False;
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/serversampleforocx','work_no='+FWork_no,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    str := memo1.Lines.Strings[1];
    SampleFormIDList.CommaText:=str;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSetInf1
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 DOC_INF 資料表資訊(模式 1)。方法會加密目前伺服器時間戳記
            並發送 HTTP GET 請求。若成功取得資料(狀態碼 '0'),則利用 SetSQLData 將
            結果解析並存入本地快取 Doc_Inf_List;若發生通訊錯誤或 Session 逾時(偵
            測到登入頁面標籤),則會記錄對應的 HttpErrStr 並返回 False。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf1 : Boolean; //取系統設定資訊Mode1 DOC_INF
Var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT %s FROM DOC_INF WHERE WORK_NO = '%s' ORDER BY DOC_TYPE, DOC_NO, DOC_VERSION"
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  ColumeStr := 'WORK_NO,DOC_NO,DOC_U_DESC,DOC_TYPE,DOC_VERSION,FORM_PAGES,START_DATE,STOP_DATE,IS_DOC_DIV,IS_IN_WH';
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=1&col='+Doc_Inf_Colume+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=1&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,Doc_Inf_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSetInf2
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 DM_FORM_INF 表單關聯資訊(模式 2)。流程包含加密請求參數與
            發送 GET 請求。此方法負責取得表單間的主從關係、相依性以及互斥規則,並將
            回傳的資料行解析後存入本地的 DM_FORM_INF_List。若通訊失敗或 Session
            過期,會設定錯誤訊息並中斷流程。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf2 : Boolean; //取系統設定資訊Mode2  DM_FORM_INF
var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT %s FROM DM_FORM_INF
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  ColumeStr := 'WORK_NO,MAIN_FORM_ID,DOC_VERSION,DEPE_FORM_ID,MUTEX_FORM_ID';
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=2&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
   If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=2&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,DM_FORM_INF_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSetInf3
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 FORM_INF 表單詳細資料(模式 3)。方法會取得包含表單名稱、說
            明、分類、定位點類型(ANCHOR/FRAME)、最大頁數及預設高寬等中繼數據。取得的
            資料會被快取至 FORM_INF_List,作為影像處理(如自動縮放與 OMR 檢核)的重
            要依據。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf3 : Boolean; //取系統設定資訊mode3  FORM_INF
var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT distinct %s FROM FORM_INF T1 LEFT JOIN DOC_INF T2 ON T2.DOC_NO = T1.DOC_NO AND T1.DOC_VERSION = T2.DOC_VERSION AND T1.WORK_NO = T2.WORK_NO WHERE T2.IS_USE = 'Y' AND T2.WORK_NO = %s
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  //ColumeStr := 'T1.WORK_NO,T1.FORM_ID,T1.DOC_KIND,T1.DOC_NO,T1.DOC_VERSION,T1.FORM_NAME,T1.FORM_DESC,T1.DIVISION,T1.ANCHOR,T1.MAX_PAGE,T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.MERGE_IMAGE,T1.CC_FORM_ID,T1.CC_MERGE_FORMID,T2.DOC_TYPE'; {T1.CC_FORM_ID,T1.CC_MERGE_FORMID,}
  ColumeStr := 'T1.WORK_NO,T1.FORM_ID,T1.DOC_NO,T1.DOC_VERSION,T1.FORM_NAME,T1.FORM_DESC,T1.DIVISION,T1.ANCHOR,T1.MAX_PAGE,T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.IS_PRINT,T2.DOC_TYPE'; {T1.CC_FORM_ID,T1.CC_MERGE_FORMID,}
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=3&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=3&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,FORM_INF_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSetInf4
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 CHECK_RULE_INF 檢核規則資訊(模式 4)。此方法取得包含檢核
            代號、描述及顯示類型在內的驗證規則,並將其儲存於 CHECK_RULE_INF_List。
            最後會呼叫 CheckRule2OMRErrInfo,將取得的規則同步更新至 OMR 錯誤資訊
            記錄中,以確保前端檢核邏輯與伺服器同步。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf4 : Boolean; //取系統設定資訊mode4  CHECK_RULE_INF
var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT %s FROM CHECK_RULE_INF WHERE CHECK_TYPE = 'S'
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  ColumeStr := 'WORK_NO,CHECK_NO,CHECK_RULE_DESC,MESG_SHOW_TYPE,MESG_DISP_TYPE,CHECK_MESG,SCAN_MODE';
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=4&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=4&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,CHECK_RULE_INF_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
  CheckRule2OMRErrInfo;
end;
{ ==============================================================================
  方法名稱:GetSetInf5
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 MEMO_INF 註記資訊(模式 5)。方法會取得預設的註記內容及其
            對應的類型名稱,並將其快取至 MEMO_INF_List。這些資料通常用於 UI 上的註
            記選擇選單,方便掃瞄人員在影像處理過程中快速標註預設的說明文字。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf5 : Boolean; //取系統設定資訊mode5  MEMO_INF
  var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT %s FROM MEMO_INF T1 LEFT JOIN MEMO_TYPE_INF T2 ON T2.MEMO_TYPE_NO = T1.MEMO_TYPE WHERE T1.MEMO_SOURCE = '01'
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  ColumeStr := 'T1.WORK_NO,T1.MEMO_TYPE,T1.MEMO_CONTENT,T2.MEMO_TYPE_NAME';
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=5&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,MEMO_INF_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSetInf6
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 WORK_INF 工作參數資訊(模式 6)。此方法取得當前工作項目的
            全域參數(如 PARA_NO 與 PARA_CONTENT),並儲存於 WORK_INF_List。這些參數
            控制了掃瞄器的預設行為(如 DPI、雙面掃瞄等),是系統初始化環境設定的關鍵
            步驟。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf6 : Boolean; //取系統設定資訊mode5  WORK_INF
var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT %s FROM WORK_INF
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  ColumeStr := 'WORK_NO,PARA_NO,PARA_CONTENT';
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=6&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,WORK_INF_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetSetInf7
  引用相依:En_DecryptionStr_Base64, ProcessServlet_Get
  方法描述:向伺服器請求 LASTEST_FORM_INF 最新表單版本資訊(模式 7)。方法會獲取各
            文件編號對應的最新表單 ID 與版本號,並儲存於 LASTEST_FORM_INF_List。此
            資訊用於確保使用者掃瞄的是最新版表單,或是用於舊案件轉檔時的版本對照。
============================================================================== }
Function TCB_IMGPSScanX.GetSetInf7 : Boolean; //取系統設定資訊mode5  LASTEST_FORM_INF
var
  ColumeStr : String;
  S : TStringlist;
  EnCodeDateTime : String;
begin
  //SELECT FORM_ID,DOC_NO,DOC_VERSION FROM FORM_INF WHERE (DOC_NO,DOC_VERSION) in (SELECT DOC_NO, MAX(DOC_VERSION) FROM FORM_INF GROUP BY DOC_NO) ORDER BY DOC_NO
  Result := False;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
  ColumeStr := 'FORM_ID,DOC_NO';
  //If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC02 ','checktime='+EnCodeDateTime+'&mode=5&col='+ColumeStr+'&workno='+FWork_No,FReWrite.Text,Memo1) Then
  If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=7&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else IF memo1.Lines.Strings[0] = '0' Then
  begin
    S := TStringlist.Create;
    S.Text := Memo1.Lines.Text;
    SetSQLData(ColumeStr,S,LASTEST_FORM_INF_List);
    S.Free;
    Result := True;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:TransOldCaseFile
  引用相依:FileExists, upFile
  方法描述:處理舊件引用的檔案傳送。遍歷舊件清單,若發現有引用記錄,則透過 HTTPS 將
            引用資訊上傳至伺服器,並處理伺服器回傳狀態。
============================================================================== }
Function TCB_IMGPSScanX.TransOldCaseFile(Path:String):Boolean;
var
  i : Integer;
  OldCaseID,Year,Data,Verify:String;
  SendData : String;
  OldCaseInfoList,Caseinfolist : TStringlist;
  OldCasePath : String;
begin
  Result := True;
  OldCaseInfoList := TStringlist.Create;
  Caseinfolist := TStringlist.Create;
  try
    OldCaseInfoList.StrictDelimiter := True;
    OldCaseInfoList.Delimiter := #9;
    OldCaseInfoList.DelimitedText := FOldCaseInfo;
    for i := 0 to OldCaseInfoList.Count - 1 do
    begin
      Caseinfolist := SplitString('@#,',OldCaseInfoList.Strings[i]);
      //Caseinfolist.Delimiter := '_';
      //Caseinfolist.DelimitedText := OldCaseInfoList.Strings[i];
      OldCaseID := Caseinfolist.Strings[0];
      Year := Caseinfolist.Strings[1];
      Data := Caseinfolist.Strings[4];
      Verify := Caseinfolist.Strings[5];
      OldCasePath := Path+OldCaseID+'\';
      if FileExists(OldCasePath+'UseCase.dat') and FileExists(OldCasePath+'UseCase.ini') then
      begin
        //////壓檔/////
        //ZipMainFile(Path,Path,'Img.zip');
        ////上傳/////
        SendData:='data='+HTTPEncode(UTF8Encode(Data))+'&verify='+Verify+'&other_case_no='+OldCaseID;
        //Showmessage(FUrl+'service/slic/SLIC02/useOther?'+senddata);
        if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/useOther',SendData,'file',OldCasePath+'UseCase.ini',FReWrite,Memo1,False) then
        begin
          Showmessage(Format(_Msg('傳送舊件編號(%s)檔案時,網路發生錯誤!!'),[OldCaseID])+_Msg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason);
          Result := False;
          Exit;
        end;
        if memo1.Lines.Strings[0] = '1' then
        begin
          Showmessage(Format(_Msg('傳送舊件編號(%s)檔案時,網路發生錯誤!!'),[OldCaseID])+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
          Result := False;
          Exit;
        end
        Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
        begin
          Showmessage(Format(_Msg('傳送舊件編號(%s)檔案時,網路發生錯誤!!'),[OldCaseID])+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
          Result := False;
          Exit;
        end;
      end;
  ////上傳////
    end;
  finally
  OldCaseInfoList.Free;
  Caseinfolist.Free;
  end;
end;
{ ==============================================================================
  方法名稱:Writelog
  引用相依:
  方法描述:透過 ProcessServlet 向伺服器發送列印日誌記錄。傳送案件編號與 FData 等
            參數,並檢查伺服器回傳是否成功或 Session 是否失效。
============================================================================== }
Function TCB_IMGPSScanX.Writelog(CaseID : String):Boolean;
var
  SendData : String;
begin
  Result := True;
  SendData:='data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&case_no='+CaseID;
  If not ProcessServlet(HTTPSClient,FURL+'service/imgpsc/IMGPSC06/printlog',SendData,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:DownLanguage
  引用相依:dnFile, dnFile_Get
  方法描述:從伺服器下載多國語言設定檔 Language.Lng。使用 HTTPS 客戶端執行 GET 請
            求,下載至本地語系路徑。下載後會檢查回傳內容,驗證是否發生錯誤、伺服器回
            傳錯誤訊息,或是因為閒置過久導致 Session 過期被導向登入頁面,並設定對
            應的錯誤字串。
============================================================================== }
Function TCB_IMGPSScanX.DownLanguage:Boolean;  //下載多國語言檔
begin
  Result := True;     // http://192.168.0.101:8080/fbnp/servlet/CWC01?act=getservertime
  //dnFile(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite.Text,Memo1,False,DownImgStatus)
  If not dnFile_Get(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite,Memo1,False,DownImgStatus) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF memo1.Lines.Strings[0] = '1' Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
{ ==============================================================================
  方法名稱:GetOMRCheckSet
  引用相依:FileExists, LoadFromFile, SaveToFile, dnFile_Get, dnFile
  方法描述:從伺服器下載並更新 OMR 檢核設定檔(OMRSet.zip)。程序會檢查本地 LastDat
            eTime.dat 取得最後更新時間,並發送請求。若伺服器有新資料,則下載後解壓
            縮並更新本地時間戳記;若無更新則維持現狀,並包含完整的錯誤處理邏輯。
============================================================================== }
Function TCB_IMGPSScanX.GetOMRCheckSet : Boolean; //下載OMR檢核XML檔
var
  SendData : String;
  LastDateTime : String;
  S : TStringlist;
begin
  Result := True;
  S := TStringlist.Create;
  Try
    if FileExists(CheckXmlPath+'OMRSet.zip') then
      DeleteFile(CheckXmlPath+'OMRSet.zip');
    LastDateTime := '00000000000000';
    if FileExists(CheckXmlPath+'LastDateTime.dat') then
    begin
      S.LoadFromFile(CheckXmlPath+'LastDateTime.dat');
      LastDateTime := S.Strings[0];
    end;
    SendData := 'settype=3&lastupdate='+LastDateTime;
    if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,CheckXmlPath+'OMRSet.zip',FReWrite,Memo1,False,DownImgStatus) then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := False;
      Exit;
    end;
    if FileExists(CheckXmlPath+'OMRSet.zip') then   //有更新
    begin
      ExecuteUnZip(CheckXmlPath+'OMRSet.zip',CheckXmlPath,True);
      S.Clear;
      S.Add(ServerDate+GetBalance2Time(Balance));
      S.SaveToFile(CheckXmlPath+'LastDateTime.dat');
    end
    Else
    begin
      if (Memo1.Lines.Strings[0] = 'nodata') Then   //沒更新
      begin
        Result := True;
      end
      Else if (Memo1.Lines.Strings[0] = '1') Then
      begin
        HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
        Result := False;
        Exit;
      end
      Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
      begin
        HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
        Result := False;
        Exit;
      end;
    end;
  Finally
  S.Free;
  End;
end;
{ ==============================================================================
  方法名稱:GetKeyinSet
  引用相依:FileExists, LoadFromFile, SaveToFile, dnFile_Get, dnFile
  方法描述:從伺服器下載並更新登打設定檔(KeyinSet.zip)。運作機制與 GetOMRCheckSet
             相同,透過比對時間戳記決定是否執行下載與解壓縮,確保本地的登打定位資
            訊與伺服器同步。
============================================================================== }
Function TCB_IMGPSScanX.GetKeyinSet : Boolean; //取登打設定
var
  SendData : String;
  LastDateTime : String;
  S : TStringlist;
begin
  Result := True;
  S := TStringlist.Create;
  Try
    if FileExists(SitePath+'KeyinSet.zip') then
      DeleteFile(SitePath+'KeyinSet.zip');
    LastDateTime := '00000000000000';
    if FileExists(SitePath+'LastDateTime.dat') then
    begin
      S.LoadFromFile(SitePath+'LastDateTime.dat');
      LastDateTime := S.Strings[0];
    end;
    SendData := 'settype=2&lastupdate='+LastDateTime;
    if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,SitePath+'KeyinSet.zip',FReWrite,Memo1,False,DownImgStatus) then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := False;
      Exit;
    end;
    if FileExists(SitePath+'KeyinSet.zip') then  //有更新
    begin
      ExecuteUnZip(SitePath+'KeyinSet.zip',SitePath,True);
      S.Clear;
      S.Add(ServerDate+GetBalance2Time(Balance));
      S.SaveToFile(SitePath+'LastDateTime.dat');
    end
    Else
    begin
      if (Memo1.Lines.Strings[0] = 'nodata') Then   //沒更新
      begin
        Result := True;
      end
      Else if (Memo1.Lines.Strings[0] = '1') Then
      begin
        HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
        Result := False;
        Exit;
      end
      Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
      begin
        HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
        Result := False;
        Exit;
      end;
    end;
  Finally
  S.Free;
  End;
end;
{ ==============================================================================
  方法名稱:CaseAsk
  引用相依:ProcessServlet_Get
  方法描述:在上傳案件前,向伺服器詢問該案件是否可進行傳送。針對 NSCAN 或 DSCAN 模
            式,會封裝案件編號與加密驗證資訊發送至 IMGPSC05/isnew 服務。根據伺服器
            回傳結果(0 表示可上傳,1 表示重複),決定後續的上傳流程。
============================================================================== }
Function TCB_IMGPSScanX.CaseAsk(CaseID: string):Integer;
var
  SendData : String;
begin
//Memo1.Clear;
  SendData := 'data='+HTTPEncode(UTF8Encode(FData))+'&verify='+FVerify+'&case_no='+CaseID+'&work_no='+FWork_no;
  if (FMode = 'NSCAN') or (FMode = 'DSCAN') then
  begin
//ShowMessage('JJJJJ');
    If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC05/isnew',SendData,FReWrite,Memo1,False) Then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := -1;
      Exit;
    end;
  end;
//ShowMessage(SendData);
  IF memo1.Lines.Strings[0] <> '0' Then
  begin
    HttpErrStr := _Msg('')+memo1.Lines.Strings[1]+'。';
    Result := -1;
    Exit;
  end
  Else
  begin
    if (memo1.Lines.Count < 2) then
    begin
      HttpErrStr := _Msg('')+'OCX:Index Count error';
      Result := -1;
      Exit;
    end
    Else
    begin
      if memo1.Lines.Strings[1] = '0' then
      begin
        Result := 0;
      end
      Else if memo1.Lines.Strings[1] = '1' then
        Result := 1
      Else
      begin
        HttpErrStr := _Msg('')+'OCX:Value error';
        Result := -1;
        Exit;
      end;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:CaseComplete
  引用相依:FileExists, LoadFromFile, En_DecryptionStr_Base64
  方法描述:通知伺服器案件傳送完成。函式會收集案件的各項元數據,包含總頁數、主表單
            ID、經辦資訊、被保人資料等,並根據不同的業務模式(如 NSCAN, ESCAN)格式化
            發送數據。若包含 OMR 檢核失敗資訊或備註,也會一併封裝傳送,最後根據伺服
            器回傳值判定作業是否成功。
============================================================================== }
Function TCB_IMGPSScanX.CaseComplete(Path,CaseID:String;MainCase:Boolean):Boolean;  //通知傳送完成
var
  OMRValue,Batchnum,Usermemo,Checkmemo,UpformID,ReMoveMemo: String;
  Case_type,Handle_no,Format_id,Cen_Uid,Cen_Cliname,Cen_Platno,Cen_Apolyno,Case_priority : String;
  Pages : Integer;
  EnCodeDateTime : String;
  SendData : String;
  S : TStringlist;
  i,v,v1 : Integer;
  UpSortID : String;
begin
  Result := True;
  S := TStringlist.Create;
  try
    EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
    UpformID := GetCaseFormID(Path);
    Case_type := '0';
    if FileExists(Path+'Context.dat') then    //掃描頁數
    begin
      S.LoadFromFile(Path+'Context.dat');
      Pages := S.Count;
    end;
    if not FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then //如果沒這個檔就重產生預設值
    begin
      ClearCaseIndex;
      WriteCaseIndex(ImageSavePath+CaseID+'\');
    end;
    {if FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then
    begin
      S.LoadFromFile(ImageSavePath+CaseID+'\CaseIndex.dat');
      Handle_No := S.Strings[0];    //經辦代號
      Cen_Uid := S.Strings[1];      //被保人ID
      Cen_Cliname := S.Strings[2];  //被保人姓名
      Cen_Platno := S.Strings[3];   //車號
      Case_Priority := S.Strings[4];//案件等級
      if FMode = 'SSCAN' then  //簽署章件的時候一律傳Format_ID
      begin
        Format_ID := S.Strings[5];    //主鍵值 (報價單號or續保單號or保單號碼or保險證號)
      end
      Else
      begin
        if (Length(UpformID) = 12) and (UpformID[2] = '-') then
          Format_ID := S.Strings[5]    //主鍵值 (報價單號or續保單號or保單號碼or保險證號)
        else
          Cen_Apolyno := S.Strings[5]; //強制證號
      end;
      if (FMode = 'MSCAN') and (length(Format_ID) = 16) and (Copy(Format_ID,1,2) = '05') then
      begin
        Format_ID := Copy(Format_ID,3,14);   //20130606 yuu說監理站件的主鍵值為16碼且開開為05的要去掉
      end;
    end; }
    if FileExists(ImageSavePath+CaseID+'\GetValue.xml') then    //掃描帶值
    begin
      S.LoadFromFile(ImageSavePath+CaseID+'\GetValue.xml');
      OMRValue := Trim(S.Text);
    end;
    if MainCase then    //雙主約的主要案件
    begin
      if FileExists(ImageSavePath+CaseID+'\Batchnum.dat') then
      begin
        S.LoadFromFile(ImageSavePath+CaseID+'\Batchnum.dat');
        Batchnum := Trim(S.Text);
      end;
    end
    Else    //雙主約的第二案件
    begin
      if FileExists(ImageSavePath+CaseID+'\SecBatchnum.dat') then
      begin
        S.LoadFromFile(ImageSavePath+CaseID+'\SecBatchnum.dat');
        Batchnum := Trim(S.Text);
      end;
    end;
    if FileExists(ImageSavePath+CaseID+'\Scan_Memo.dat') then
    begin
      S.LoadFromFile(ImageSavePath+CaseID+'\Scan_Memo.dat');
      Usermemo := Trim(S.Text);
    end;
    if FileExists(ImageSavePath+CaseID+'\CheckMemo.dat') then
    begin
      S.LoadFromFile(ImageSavePath+CaseID+'\CheckMemo.dat');
      Checkmemo := Trim(S.Text);
    end;
    if FileExists(ImageSavePath+CaseID+'\RemoveMemo.dat') then
    begin
      S.LoadFromFile(ImageSavePath+CaseID+'\RemoveMemo.dat');
      ReMoveMemo := Trim(S.Text);
    end;
  finally
  S.Free;
  end;
  case_priority:='0';
  if (FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') then
  begin
    SendData := 'checktime='+EnCodeDateTime
                +'&work_no='+FWork_No                                  //作業別
                +'&case_id='+CaseID                                    //受理編號
                +'&form_id='+UpformID                                  //表單代號
                +'&scan_page='+inttostr(pages)                         //掃描頁數
                +'&scan_get_value='+HTTPEncode(UTF8Encode(OMRValue))   //掃描帶值
                +'&case_priority='+case_priority                       //案件等級
                +'&batch_no='+batchnum                                 //車隊批號
                +'&user_memo='+HTTPEncode(UTF8Encode(usermemo))        //使用者註記
                +'&check_memo='+HTTPEncode(UTF8Encode(checkmemo))      //檢核註記
                +'&remove_memo='+HTTPEncode(UTF8Encode(ReMoveMemo))    //檢核移除註記
                +'&case_type='+Case_type                               //進件種類    進件0 歸檔1
                +'&handle_no='+Handle_no                               //經辦代號
                +'&format_id='+Format_id                               //案件主鍵值
                +'&cen_uid='+Cen_Uid                                   //被保人ID
                +'&cen_cliname='+HTTPEncode(UTF8Encode(Cen_Cliname))   //被保人姓名
                +'&cen_platno='+Cen_Platno                             //車牌
                +'&cen_apolyno='+Cen_Apolyno                           //強制證號
                +'&has_authorize='+Has_Authorize;                      //是否有授權書影像
                Showmessage(SendData);
    if not RejectCase then
    begin
      If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC05',SendData,FReWrite,Memo1,False) Then
      begin
        HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
        Result := False;
        Exit;
      end;
    end
    Else
    begin
      If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC06',SendData,FReWrite,Memo1,False) Then
      begin
        HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
        Result := False;
        Exit;
      end;
    end;
  end
  Else if FMode = 'ISCAN' then
  begin
    SendData := 'checktime='+EnCodeDateTime
                +'&work_no='+FWork_No
                +'&case_id='+CaseID
                +'&form_id='+UpformID
                +'&format_id='+Format_id
                +'&scan_page='+inttostr(pages)
                +'&user_memo='+HTTPEncode(UTF8Encode(usermemo))
                +'&check_memo='+HTTPEncode(UTF8Encode(checkmemo))
                +'&remove_memo='+HTTPEncode(UTF8Encode(ReMoveMemo))
                +'&has_authorize='+Has_Authorize;    //是否有授權書影像
    //Showmessage(SendData);
    If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC08',SendData,FReWrite,Memo1,False) Then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := False;
      Exit;
    end;
  end
  Else if FMode = 'FSCAN' then
  begin
    SendData := 'checktime='+EnCodeDateTime
                +'&work_no='+FWork_No
                +'&case_id='+CaseID
                +'&scan_page='+inttostr(pages)
                +'&user_memo='+HTTPEncode(UTF8Encode(usermemo))
                +'&check_memo='+HTTPEncode(UTF8Encode(checkmemo))
                +'&remove_memo='+HTTPEncode(UTF8Encode(ReMoveMemo))
                +'&has_authorize='+Has_Authorize;     //是否有授權書影像
    If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC09',SendData,FReWrite,Memo1,False) Then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := False;
      Exit;
    end;
  end
  Else if FMode = 'RSCAN' then
  begin
    SendData := 'checktime='+EnCodeDateTime
                +'&act=rescan'
                +'&workno='+FWork_No
                +'&caseid='+CaseID
                +'&formid='+UpformID
                +'&scanpage='+inttostr(pages)
               // +'&areano='+FUserArea
                +'&scangetvalue='+HTTPEncode(UTF8Encode(OMRValue))
                +'&usermemo='+HTTPEncode(UTF8Encode(usermemo))
                +'&checkmemo='+HTTPEncode(UTF8Encode(checkmemo))
                +'&removememo='+HTTPEncode(UTF8Encode(ReMoveMemo))
                +'&has_authorize='+Has_Authorize;        //是否有授權書影像
    If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC01',SendData,FReWrite,Memo1,False) Then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := False;
      Exit;
    end;
  end
  Else if FMode = 'ESCAN' then
  begin
    SendData := 'checktime='+EnCodeDateTime
                    +'&act=escan'
                    +'&workno='+FWork_No
                    +'&caseid='+CaseID
                    +'&formid='+UpformID
                    +'&scanpage='+inttostr(pages)
                    +'&batchnum='+batchnum
                    +'&usermemo='+HTTPEncode(UTF8Encode(usermemo))
                    +'&checkmemo='+HTTPEncode(UTF8Encode(checkmemo))
                    +'&removememo='+HTTPEncode(UTF8Encode(ReMoveMemo))
                    +'&has_authorize='+Has_Authorize;      //是否有授權書影像
    If not ProcessServlet(HTTPSClient,FURL+'servlet/CWC01',SendData,FReWrite,Memo1,False) Then
    begin
      HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
      Result := False;
      Exit;
    end;
  end;
  if Memo1.Lines.Strings[0] <> '0'then
  begin
    HttpErrStr := _Msg('錯誤原因:')+Memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end;
end;
reassemble/CB_IMGPSScanImp.caseMgr.pas
比對新檔案
@@ -0,0 +1,107 @@
{ ==============================================================================
  方法名稱:Node2DocNo
  引用相依:
  方法描述:從樹狀結構節點 2(文件層)的文字中解析並提取文件編號(DocNo)。
============================================================================== }
Function TCB_IMGPSScanX.Node2DocNo(Node2:TTreeNode):String;  //MyTreeNode2取DocNo出來
var
  v,v1,v2 : Integer;
begin
  v := Posend('{',Node2.Text);
  v1 := Posend('}',Node2.Text);
  v2 := Posend('-',Node2.Text);
  Result := Copy(Node2.Text,v+1,v1-v-1);
  IF v1 = 0 Then
  begin
    Result := '';
  end;
end;
{ ==============================================================================
  方法名稱:Node3DocNo
  引用相依:
  方法描述:從樹狀結構節點 3(表單層)的父節點文字中提取文件編號(DocNo)。
============================================================================== }
Function TCB_IMGPSScanX.Node3DocNo(Node3:TTreeNode):String;  //MyTreeNode3取DocNo出來
var
  v,v1,v2 : Integer;
begin
  v := Posend('{',Node3.Parent.Text);
  v1 := Posend('}',Node3.Parent.Text);
  v2 := Posend('-',Node3.Parent.Text);
  Result := Copy(Node3.Parent.Text,v+1,v1-v-1);
  IF v1 = 0 Then
  begin
    Result := '';
  end;
end;
{ ==============================================================================
  方法名稱:CaseDelete_Enable
  引用相依:FileExists, LoadFromFile
  方法描述:判斷案件是否允許刪除。若案件下有任何文件目錄已被其他程序引用,則禁止刪
            除。
============================================================================== }
Function TCB_IMGPSScanX.CaseDelete_Enable(CaseID:String):Boolean;  //案件可否被刪除
var
  i : Integer;
  CaseDocNoList : TStringlist;
begin
  Result := True;
  CaseDocNoList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
      CaseDocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    for i := 0 to CaseDocNoList.Count - 1 do
    begin
      if GetUseCase('T',DisplayPath,CaseDocNoList.Strings[i]) <> '' then   //有被引用走的
        Result := False;
    end;
  finally
  CaseDocNoList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:DocNoExistsinTree
  引用相依:
  方法描述:檢查指定的案件節點下,是否已經存在具備該文件代號(DocNo)的子節點。
============================================================================== }
Function TCB_IMGPSScanX.DocNoExistsinTree(CaseNode:TTreeNode;DocNo:String):Boolean; //是否己存在樹裡
var
  i : Integer;
begin
  Result := False;
  for I := 0 to CaseNode.Count - 1 do
  begin
    if DocNo = DocNode2Info(CaseNode.Item[i],'I') Then
    begin
      Result := True;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:DocnoNeedGroup
  引用相依:
  方法描述:查詢 Doc_Inf_List 判斷傳入的文件代號是否需要進行文件分組(IS_DOC_DIV
            = "Y")。
============================================================================== }
Function TCB_IMGPSScanX.DocnoNeedGroup(DocNo:String):Boolean; //傳入的DocNo是否需分組
begin
  Result := False;
  If FindSQLData(Doc_Inf_List,'IS_DOC_DIV','DOC_NO',DocNo,0,FindResult) Then
  begin
    if GetFindResult('IS_DOC_DIV') = 'Y' Then
      Result := True;
  end;
end;
reassemble/CB_IMGPSScanImp.convert.pas
比對新檔案
@@ -0,0 +1,480 @@
{ ==============================================================================
  方法名稱:Path2DocDir
  引用相依:FileExists, LoadFromFile
  方法描述:將實體路徑轉換為案件內的文件目錄名稱。透過比對路徑字串與 CaseDocNo.da
            t 中的清單來識別對應的目錄。
============================================================================== }
Function TCB_IMGPSScanX.Path2DocDir(Path,CaseID:String):String;
var
  i : Integer;
  DocnoList : TStringlist;
begin
  Result := '';
  DocNoList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
      DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    if Path[length(Path)]<>'\' then
      path := path+'\';
    for i := 0 to DocNoList.Count - 1 do
    begin
      if (path=ImageSavePath+CaseID+'\'+DocNoList.Strings[i]+'\') then
      begin
        Result := DocNoList.Strings[i];
        Break;
      end;
    end;
  finally
  DocNoList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:FormCode2FormName
  引用相依:
  方法描述:將表單代碼轉換為易讀的文件名稱。優先查詢系統定義表,若無則至自定義文件
            清單中搜尋。
============================================================================== }
Function TCB_IMGPSScanX.FormCode2FormName(CaseID,FormCode:String):String; //用FormCode轉成文件名稱
var
  i,v,ln : Integer;
  DelBarCode : String;
  CusDocNo,CusDocName : String;
begin
  Result := '';
  if (FormCode = '') or (FormCode = 'Attach') or (FormCode = 'S_Attach') then
    Result := _Msg('未歸類')
  //showmessage('a');
  //stringtofile(FORM_INF_List.Text,'D:\121.txt');
  Else If FindSQLData(FORM_INF_List,'T1.FORM_ID,T1.FORM_DESC','T1.FORM_ID',FormCode,0,FindResult) then
    Result := GetFindResult('T1.FORM_DESC');
  ////// 到自訂文件找//////
  if Result = '' then
    Result := GetCustomDocName(ImageSavePath+CaseID+'\',FormCode2DocNo(FormCode));
  {for i := 0 to Cust_DocNoList.Count - 1 do
  begin
    v := Pos('_',Cust_DocNoList.Strings[i]);
    ln := Length(Cust_DocNoList.Strings[i]);
    CusDocNo := copy(Cust_DocNoList.Strings[i],1,v-1);
    CusDocName := Copy(Cust_DocNoList.Strings[i],v+1,ln-v);
    if CusDocNo = FormCode2DocNo(FormCode) then
      Result := DocNo2DocName(CusDocNo);
  end;}
  {DelBarCode := '**'+FormCode;
  for I := 0 to FormCodeList.Count - 1 do
  begin
    if FindDel then //要找下架的
    begin
      if (FormCode = FormCodeList.Strings[i]) or (DelBarCode = FormCodeList.Strings[i]) then
      begin
        Result := FormNameList.Strings[i];
        Break;
      end;
    end
    Else
    begin
      if (FormCode = FormCodeList.Strings[i]) or (DelBarCode = FormCodeList.Strings[i]) then
      begin
        Result := FormNameList.Strings[i];
        Break;
      end;
    end;
  end; }
end;
{ ==============================================================================
  方法名稱:FormCode2FileName
  引用相依:
  方法描述:在指定的檔案清單中,根據表單代碼尋找其對應的第一個影像檔名。
============================================================================== }
Function TCB_IMGPSScanX.FormCode2FileName(FormCode:String;List:TStrings):String; //用FormCode找出檔名(第一頁)
var
  i : Integer;
  v,v1 : Integer;
begin
  Result := '';
  for i := 0 to List.Count - 1 do
  begin
    V := pos('_',List.Strings[i]);
    v1 := pos('.',List.Strings[i]);
    if (FormCode = '') and (V = 0)then //FormCode 為空的則找附件出來
    begin
      Result := List.Strings[i];
      Break;
    end;
    IF FormCode = Copy(List.Strings[i],v+1,v1-v-1) then
    begin
      Result := List.Strings[i];
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FileName2FormCode
  引用相依:
  方法描述:從影像檔名中提取表單代碼(底線與點號之間的部分)。若檔名格式不符則視為
            附件並回傳空字串。
============================================================================== }
Function TCB_IMGPSScanX.FileName2FormCode(FileName:String):String; //從檔名取出FormCode
var
  v,v1 : Integer;
begin
  FileName := ExtractFileName(FileName);
  v := Pos('_',FileName);
  v1 := Pos('.',FileName);
  if v > 0 then
  begin
    Result := Copy(FileName,v+1,v1-v-1);
  end
  Else     //附件
  begin
    Result := '';
  end;
end;
{ ==============================================================================
  方法名稱:FileName2FormName
  引用相依:
  方法描述:根據案件編號與檔案名稱,先取得表單代碼,再轉換為對應的表單名稱。
============================================================================== }
Function TCB_IMGPSScanX.FileName2FormName(CaseID,FileName:String):String; //從檔名取出文件名稱
begin
  Result :=  FormCode2FormName(CaseID,FileName2FormCode(FileName));
end;
{ ==============================================================================
  方法名稱:FileName2ScanPage
  引用相依:
  方法描述:從檔案名稱中提取掃描頁碼。透過尋找底線或點號的位置,截取檔名前段並轉換
            為整數。
============================================================================== }
Function TCB_IMGPSScanX.FileName2ScanPage(FileName:String):Integer; //從檔名轉出掃瞄頁數
Var
  v : Integer;
  FName : String;
begin
  FName := ExtractFileName(FileName);
  v := Pos('_',FName);
  if v = 0 then   //附件
    v := pos('.',FName);
  Result := Strtoint(Copy(FName,1,v-1));
end;
{ ==============================================================================
  方法名稱:FileName2NoQuene_Filename
  引用相依:
  方法描述:從檔案名稱中移除序號部分,僅保留從底線或點號開始的剩餘檔名結構。
============================================================================== }
Function TCB_IMGPSScanX.FileName2NoQuene_Filename(FileName:String):String; //取出沒有序號的檔名
var
  v,v1 : Integer;
  FName : String;
begin
  FName := ExtractFileName(FileName);
  v := Pos('_',FName);
  if v = 0 then   //附件
    v := pos('.',FName);
  v1 := length(FName);
  Result := Copy(FName,v,v1-v+1);
end;
{ ==============================================================================
  方法名稱:FileName2Index
  引用相依:
  方法描述:在 ContextList 清單中搜尋指定的檔案名稱,並回傳其所在的索引位置。
============================================================================== }
Function TCB_IMGPSScanX.FileName2Index(FileName:String):Integer; //從檔名取出在ContextList的序號
var
  i : Integer;
begin
  for i := 0 to ContextList.Count - 1 do
  begin
    if FileName = ContextList.Strings[i] then
    begin
      Result := i;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FileName2NowDcoNo
  引用相依:
  方法描述:從檔案名稱對應的 CTList 中尋找索引,並從 DNList 取得其歸屬的文件代號。
============================================================================== }
Function TCB_IMGPSScanX.FileName2NowDcoNo(FileName:String;CtList,DNList:TStrings):String; //從檔名取出歸屬的文件代號
var
  i : Integer;
begin
  for I := 0 to CTList.Count -1 do
  begin
    if FileName = CTList.Strings[i] then
    begin
      Result := DNList.Strings[i];
      break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FormCode2DocNo
  引用相依:
  方法描述:將表單代碼 (FormCode) 轉換為對應的文件編號 (DocNo)。方法遍歷預載的 Fo
            rmID_List,若找到匹配的表單代碼,則返回 DocNo_List 中相同索引位置的數
            值。若表單代碼不在清單中(通常為使用者自訂的文件),則預設截取代碼的前 8
             位字元作為文件編號返回。
============================================================================== }
Function TCB_IMGPSScanX.FormCode2DocNo(FormCode:String):String;   //FormCode轉Docno
Var
  i : Integer;
begin
  Result := '';
  for i := 0 to FormID_List.Count-1 do
  begin
    if FormID_List.Strings[i] = FormCode then
    begin
      Result := DocNo_List.Strings[i];
      Break;
    end;
  end;
  if (FormCode <> '') and (Result = '') then    //是自訂文件
  begin
    Result := Copy(FormCode,1,8); //20170224 DocNo 固定長度8碼
  end;
  {If FindSQLData(FORM_INF_List,'T1.DOC_NO','T1.FORM_ID',FormCode,0,FindResult) Then  //20130403太慢了..換掉
  begin
    Result := GetFindResult('T1.DOC_NO');
  end;}
end;
{ ==============================================================================
  方法名稱:FormCode2Version
  引用相依:
  方法描述:從表單代碼(FormCode)的特定位置(第 11 位開始取 5 位)提取版本資訊。
============================================================================== }
Function TCB_IMGPSScanX.FormCode2Version(FormCode:String):String; //FormCode轉版本
begin
  Result := Copy(FormCode,11,5);
end;
{ ==============================================================================
  方法名稱:FormCode2Page
  引用相依:
  方法描述:從表單代碼(FormCode)的特定位置(第 9 位開始取 2 位)提取頁數資訊。
============================================================================== }
Function TCB_IMGPSScanX.FormCode2Page(FormCode:String):String; //FormCode轉頁數
begin
  Result := Copy(FormCode,9,2)
end;
{ ==============================================================================
  方法名稱:DocNo2DocName
  引用相依:
  方法描述:解析文件編號對應的描述性名稱。優先權邏輯為:
            1. 若編號符合附件名稱 (AttName),返回「未歸類」。
            2. 從系統定義快取 (Doc_Inf_List) 中搜尋對應的描述 (DOC_U_DESC)。
            3. 若系統定義查無結果,則呼叫 GetCustomDocName 從案件本地的自訂文件設
            定中尋找對應名稱。此方法確保 UI 上能顯示人類可讀的文件類別名稱。
============================================================================== }
Function TCB_IMGPSScanX.DocNo2DocName(CaseID,DocNo:String):String; //Docno轉Doc名稱
var
  i,v,ln : Integer;
  CusDocNo,CusDocName : String;
begin
  Result := '';
  if DocNo = AttName then
  begin
    Result := _Msg('未歸類');
  end
  Else
  begin
    If FindSQLData(Doc_Inf_List,'DOC_U_DESC','DOC_NO',DocNo,0,FindResult) Then
    begin
//ShowMessage(FindResult.Text);
      Result := GetFindResult('DOC_U_DESC');
    end;
  end;
  if Result = '' then  //去自訂文件裡找
  begin
    Result := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
    {for i := 0 to Cust_DocNoList.Count - 1 do
    begin
      v := Pos('_',Cust_DocNoList.Strings[i]);
      ln := length(Cust_DocNoList.Strings[i]);
      CusDocNo := Copy(Cust_DocNoList.Strings[i],1,v-1);
      CusDocName := Copy(Cust_DocNoList.Strings[i],v+1,ln-v);
      if DocNo = CusDocNo then
      begin
        Result := CusDocName;
        Break;
      end;
    end;}
  end;
end;
{ ==============================================================================
  方法名稱:DocNo2FileName
  引用相依:
  方法描述:根據文件代號,在指定的檔案清單中搜尋並回傳該文件第一頁的檔案名稱。
============================================================================== }
Function TCB_IMGPSScanX.DocNo2FileName(DocNo:String;List:TStrings):String; //用DocNo找出檔名(第一頁)
var
  i : Integer;
begin
  Result := '';
  for i := 0 to List.Count - 1 do
  begin
    IF DocNo = FormCode2DocNo(FileName2FormCode(List.Strings[i])) then
    begin
      Result := List.Strings[i];
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FormCode2WorkNo
  引用相依:
  方法描述:透過 FORM_INF_List 查詢表單代碼對應的作業別(WORK_NO)。
============================================================================== }
Function TCB_IMGPSScanX.FormCode2WorkNo(FormCode:String):String; //用FormCode取出作業別
begin
  Result := '';
  If FindSQLData(FORM_INF_List,'T1.WORK_NO','T1.FORM_ID',FormCode,0,FindResult) Then
  begin
    Result := GetFindResult('T1.WORK_NO');
  end;
end;
{ ==============================================================================
  方法名稱:DocNo2WorkNo
  引用相依:
  方法描述:透過 Doc_Inf_List 查詢文件代號對應的作業別(WORK_NO)。
============================================================================== }
Function TCB_IMGPSScanX.DocNo2WorkNo(DocNo:String):String; //用DocNo取出作業別
begin
  Result := '';
  If FindSQLData(Doc_Inf_List,'WORK_NO','DOC_NO',DocNo,0,FindResult) Then
  begin
    Result := GetFindResult('WORK_NO');
  end;
end;
{ ==============================================================================
  方法名稱:DocNoNeedDiv
  引用相依:
  方法描述:檢查指定的文件類型是否需要執行頁面拆分(分份數)。方法透過 FindSQLData
            在 Doc_Inf_List 中查詢該編號的 'IS_DOC_DIV' 欄位,若旗標值為 'Y' 則返
            回 True,否則返回 False。此設定決定了掃瞄流程中是否需要根據條碼自動切
            分文件目錄。
============================================================================== }
Function TCB_IMGPSScanX.DocNoNeedDiv(DocNo:String):Boolean; //是否是需分份數的文件代號
var
  NeedDiv : String;
begin
  Result := False;
  If FindSQLData(Doc_Inf_List,'IS_DOC_DIV','DOC_NO',DocNo,0,FindResult) Then
  begin
    NeedDiv := GetFindResult('IS_DOC_DIV');
    if NeedDiv = 'Y' then
      Result := True;
  end;
end;
{ ==============================================================================
  方法名稱:CaseNode2Info
  引用相依:
  方法描述:從樹狀結構的案件節點文字中,根據指定的模式提取案件編號或案件頁數。
============================================================================== }
Function TCB_IMGPSScanX.CaseNode2Info(Node:TTreeNode;Mode:Char):String;   //案件Node取案件編號  Mode: I:Caseno;P:Page
var
  v,ln : Integer;
begin
  //XXXXXX-XX頁
  V := Pos('-',Node.Text);
  ln := Length(Node.Text);
  case Mode of
  'I': Result := Copy(Node.Text,1,v-1);        //CaseID
  'P': Result := Copy(Node.Text,v+1,ln-v-1);   //CasePage
  end;
end;
{ ==============================================================================
  方法名稱:DocNode2Info
  引用相依:
  方法描述:從樹狀結構的文件節點文字中提取詳細資訊。節點文字格式預期為「文件名稱@
            組數{文件代號}-XX頁」。此函式會根據傳入的模式(Mode),利用分隔符號(@, {,
             }, -)定位並截取回傳文件代號(I)、文件名稱(N)、文件頁碼(P)或文件組別(G)
            。
============================================================================== }
Function TCB_IMGPSScanX.DocNode2Info(Node:TTreeNode;Mode:Char):String;   //文件Node取文件代號 Mode: I:Docno;N:Docname;P:Page;G:Group
var
  v,v1,v2,v3,ln :integer;
begin
  //文件名稱@組數{文件代號}-XX頁
  V := PosEnd('@',Node.Text);
  v1 := PosEnd('{',Node.Text);
  v2 := PosEnd('}',Node.Text);
  v3 := PosEnd('-',Node.Text);
  ln := Length(Node.Text);
  case Mode of
  'I': Result := Copy(Node.Text,v1+1,v2-v1-1);  //DocNo
  'N': Result := Copy(Node.Text,1,v-1);         //DocName
  'P': Result := Copy(Node.Text,v3+1,ln-v3-1);  //DocPage
  'G': Result := Copy(Node.Text,v+1,v1-v-1);    //DocGroup
  end;
end;
{ ==============================================================================
  方法名稱:FormNode2Info
  引用相依:
  方法描述:從樹狀結構的表單節點文字中提取資訊。節點文字格式預期為「表單代號{表單
            名稱}-XX頁」。根據模式(Mode)參數,解析並回傳表單代號(I)、表單名稱(N)或頁
            碼(P)。
============================================================================== }
Function TCB_IMGPSScanX.FormNode2Info(Node:TTreeNode;Mode:Char):String;   //表單Node取表單代號  Mode: I:FormID;N:FormName;P:Page
var
  v,v1,v2,ln :integer;
begin
  //表單代號{表單名稱}-XX頁
  v := Pos('{',Node.Text);
  v1 := PosEnd('}',Node.Text);
  v2 := PosEnd('-',Node.Text);
  ln := Length(Node.Text);
  case Mode of
  'I': Result := Copy(Node.Text,1,v-1); //FormID
  'N': Result := Copy(Node.Text,v1+1,v2-v1-1); //FormName
  'P': Result := Copy(Node.Text,v2+1,ln-v2-1); //Page
  end;
end;
reassemble/CB_IMGPSScanImp.custdoc.pas
比對新檔案
@@ -0,0 +1,332 @@
{ ==============================================================================
  方法名稱:GetNewCustomDocNo
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:產生一個全新的自定義文件編號。讀取 CustomDocNo.ini 中的計數器,根據入
            庫/非入庫性質產生 ZZZZZ 或 YYYYY 開頭的編號,並預設其內部的第一個表單
            代碼,最後將新設定寫回 INI 檔。
============================================================================== }
Function TCB_IMGPSScanX.GetNewCustomDocNo(Path,DocName:String):String; //取出未使用的自訂文件代號
var
  ini : Tinifile;
  Ct:Integer;
  DocNo,FormID : String;
  {i,n,v,ln : Integer;
  C_No,C_Name : String;
  CNo : Integer;
  S : TStringlist;
  NewDocNo : String;}
begin
  ini := Tinifile.Create(Path+'CustomDocNo.ini');
  try
    Ct := ini.ReadInteger('CustomCount','Count',0);
    inc(Ct);
    DocNo := 'ZZZZZ'+Add_Zoo(Ct,3);
    if FIs_In_Wh <> 'Y' then //不是入庫文件
      DocNo := 'YYYYY'+Add_Zoo(Ct,3);
    if (FMode='ESCAN') and (FWH_category='N')  then //20170914 補件下改成非入庫的自定文件
    begin
      DocNo := 'YYYYY'+Add_Zoo(Ct,3);
    end;
    FormID := DocNo+'010101A';
    ini.WriteInteger('CustomCount','Count',Ct);
    ini.WriteString(DocNo,'FormID',FormID);
    ini.WriteString(DocNo,'Name',DocName);
    Result := DocNo;
  finally
  ini.Free;
  end;
  {S := TStringlist.Create;
  try
  NewDocNo :='ZZZZZ001';
  if FileExists(Path+'CustomDocNo.dat') then
  begin
    ///   ZZZZZ001_自定文件名稱  001_自定文件名稱
    S.LoadFromFile(Path+'CustomDocNo.dat');
    for i := 0 to S.Count - 1 do
    begin
      v := Pos('_',S.Strings[i]);
      ln := Length(S.Strings[i]);
      C_No := Copy(S.Strings[i],1,v-1);
      C_Name := Copy(S.Strings[i],v+1,ln-v);
      if DocName = C_Name then
      begin
        Showmessage('文件名稱已存在');
        Result := '';
        Exit;
      end;
    end;
    CNo := strtoint(Copy(C_No,6,3))+1;
    NewDocNo := 'ZZZZZ'+Add_Zoo(CNo,3);
  end;
  S.Add(NewDocNo+'_'+DocName);
  S.SaveToFile(Path+'CustomDocNo.dat');
  Result := NewDocNo;
  finally
  S.Free;
  end; }
end;
{ ==============================================================================
  方法名稱:GetCustomDocName
  引用相依:
  方法描述:從 CustomDocNo.ini 中讀取指定自定義文件編號對應的顯示名稱。
============================================================================== }
Function TCB_IMGPSScanX.GetCustomDocName(Path,DocNo:String):String; //取出自定文件名稱
var
  ini : Tinifile;
begin
  ini := Tinifile.Create(Path+'CustomDocNo.ini');
  try
    Result := ini.ReadString(DocNo,'Name','');
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetCustomFormID
  引用相依:
  方法描述:從 CustomDocNo.ini 中讀取指定自定義文件編號對應的表單代碼(FormID)。
============================================================================== }
Function TCB_IMGPSScanX.GetCustomFormID(Path,DocNo:String):String; //取出自定文件FormID
var
  ini : Tinifile;
begin
  ini := Tinifile.Create(Path+'CustomDocNo.ini');
  try
    Result := ini.ReadString(DocNo,'FormID','');
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetCustomDocDir
  引用相依:
  方法描述:根據自定義文件名稱尋找對應的目錄代號(如 ZZZZZ001)。遍歷 CustomDocNo.i
            ni 中的所有區段,讀取 Name 欄位進行比對,成功則回傳該編號。
============================================================================== }
Function TCB_IMGPSScanX.GetCustomDocDir(Path,DocName:String):String; //取出自定文件DocDir
var
  i,ct:integer;
  ini : Tinifile;
begin
  Result := '';
  ini := Tinifile.Create(Path+'CustomDocNo.ini');
  try
    ct := ini.ReadInteger('CustomCount','Count',0);
    for i := 1 to ct do
    begin
      if ini.ReadString('ZZZZZ'+Add_Zoo(i,3),'Name','') = DocName then
      begin
        Result := 'ZZZZZ'+Add_Zoo(i,3);
        Break;
      end;
      if ini.ReadString('YYYYY'+Add_Zoo(i,3),'Name','') = DocName then
      begin
        Result := 'YYYYY'+Add_Zoo(i,3);
        Break;
      end;
    end;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:FindCustomDocName
  引用相依:
  方法描述:檢查指定的自定義文件名稱是否已存在於 CustomDocNo.ini 設定檔中。
============================================================================== }
Function TCB_IMGPSScanX.FindCustomDocName(Path,DocName:String):Boolean; //尋找自定文件名稱是否存在
var
  ini : Tinifile;
  Ct,i:Integer;
  DocNo,FormID : String;
begin
  Result := False;
  ini := Tinifile.Create(Path+'CustomDocNo.ini');
  try
    Ct := ini.ReadInteger('CustomCount','Count',0);
    for I := 1 to Ct do
    begin
      DocNo := 'ZZZZZ'+Add_Zoo(i,3);
      if DocName = ini.ReadString(DocNo,'Name','') then
      begin
        Result := True;
        Break;
      end;
    end;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:Create_Cust_DocDir
  引用相依:DirectoryExists
  方法描述:根據外部傳入的清單(FC_DocNoList 或 FC_DocNameList)預先產生案件所需的
            文件目錄。會自動處理分份文件的命名、檢查是否已存在,並在 CustomDocNo.in
            i 中註冊新名稱。
============================================================================== }
Procedure TCB_IMGPSScanX.Create_Cust_DocDir(CaseID:String); //產生外面傳入的文件代號及自定文件
var
  i,n : Integer;
  C_DocNoList,C_DocNameList : TStringlist;
  DocNo,DocName,DocDir : String;
  DocNo_Ct,NowDocNo_Ct :integer;
  DocName_Ct : Integer;
  inx : Integer;
begin
  C_DocNoList := TStringlist.Create;
  C_DocNameList := TStringlist.Create;
  try
    if FC_DocNoList <> '' then
    begin
      C_DocNoList.StrictDelimiter := True;
      C_DocNoList.Delimiter := #9;
      C_DocNoList.DelimitedText := FC_DocNoList;
      //Showmessage(C_DocNoList.Text);
      for i := 0 to C_DocNoList.Count - 1 do
      begin
        DocNo := C_DocNoList.Strings[i];
        //舊件不長出錯誤的文件出來
        if (FIs_OldCase = 'Y') and (FWork_no='HLN') and (DocNo = FormCode2DocNo('10000001011112A')) then
          Continue;
        NowDocNo_Ct := GetDocNoCount(CaseID,DocNo);
        if DocNoNeedDiv(DocNo) then
        begin
          DocNo_Ct := 0;
          for n := 0 to i do
          begin
            if C_DocNoList.Strings[n] = DocNo then
              inc(DocNo_Ct);
          end;
          if DocNo_CT <= NowDocNo_Ct then
            Continue;
          if DirectoryExists(ImageSavePath+CaseID+'\'+DocNo+'('+inttostr(DocNo_Ct)+')') then  //存在了
            Continue;
          if (DocNo_Ct = 1) and DirectoryExists(ImageSavePath+CaseID+'\'+DocNo) then  //存在了  20140327加
            Continue;
          DocDir := DocNo2DocNoDir(ImageSavePath+CaseID+'\',DocNo)
        end
        else
        begin
          DocDir := DocNo;
        end;
        if not DirectoryExists(ImageSavePath+CaseID+'\'+DocDir) then
        begin
          MkDir(ImageSavePath+CaseID+'\'+DocDir);
          SetDocNoList('A',-1,CaseID,DocDir,'1');
        end;
        if not DocNoNeedDiv(DocNo) then   //不分份的秀數
          SetDocDirCopies(CaseID,DocNo,GetCustomDocNoCount(DocNo));
      end;
    end;
    if FC_DocNameList <> '' then
    begin
      C_DocNameList.StrictDelimiter := True;
      C_DocNameList.Delimiter := #9;
      C_DocNameList.DelimitedText := FC_DocNameList;
      //Showmessage(C_DocNameList.Text);
      for i := 0 to C_DocNameList.Count - 1 do
      begin
        DocName := C_DocNameList.Strings[i];
        DocName_Ct := GetCustomNameCount(DocName);
        if not FindCustomDocName(ImageSavePath+CaseID+'\',DocName) then
        begin
          DocDir := GetNewCustomDocNo(ImageSavePath+CaseID+'\',DocName);
          if not DirectoryExists(ImageSavePath+CaseID+'\'+DocDir) then
          begin
            MkDir(ImageSavePath+CaseID+'\'+DocDir);
            SetDocNoList('A',-1,CaseID,DocDir,inttostr(DocName_Ct));
          end;
        end
        Else
        begin
          DocDir := GetCustomDocDir(ImageSavePath+CaseID+'\',DocName);
          //inx := DocNoDir2Index(ImageSavePath+CaseID+'\',DocDir);
          SetDocDirCopies(CaseID,DocDir,DocName_Ct);
        end;
      end;
    end;
  finally
  C_DocNoList.Free;
  C_DocNameList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetCustomNameCount
  引用相依:
  方法描述:統計外部傳入清單中,特定自定義文件名稱出現的次數。
============================================================================== }
Function TCB_IMGPSScanX.GetCustomNameCount(CustomName:String):Integer;   //取外傳的名稱數量
var
  i,ct : Integer;
  C_DocNameList : TStringlist;
begin
  C_DocNameList := TStringlist.Create;
  try
    C_DocNameList.StrictDelimiter := True;
    C_DocNameList.Delimiter := #9;
    C_DocNameList.DelimitedText := FC_DocNameList;
    ct := 0;
    for i := 0 to C_DocNameList.Count - 1 do
    begin
      if C_DocNameList.Strings[i] = CustomName then
      begin
        inc(ct);
      end;
    end;
    Result := ct;
  finally
  C_DocNameList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetCustomDocNoCount
  引用相依:
  方法描述:統計外部傳入清單中,特定文件編號(DocNo)出現的次數。
============================================================================== }
Function TCB_IMGPSScanX.GetCustomDocNoCount(Docno:String):Integer;   //取外傳的DocNo數量
var
  i,ct : Integer;
  C_DocNoList : TStringlist;
begin
  C_DocNoList := TStringlist.Create;
  try
    C_DocNoList.StrictDelimiter := True;
    C_DocNoList.Delimiter := #9;
    C_DocNoList.DelimitedText := FC_DocNoList;
    ct := 0;
    for i := 0 to C_DocNoList.Count - 1 do
    begin
      if C_DocNoList.Strings[i] = Docno then
      begin
        inc(ct);
      end;
    end;
    Result := ct;
  finally
  C_DocNoList.Free;
  end;
end;
reassemble/CB_IMGPSScanImp.docmod.pas
比對新檔案
@@ -0,0 +1,196 @@
{ ==============================================================================
  方法名稱:OldCasetoNewCase
  引用相依:LoadFromFile, SaveToFile
  方法描述:將舊系統格式的案件文件份數轉換為新系統規則。方法會載入案件的文件目錄
            清單 (CaseDocNo.dat),並解析由全域變數傳入的舊案文件編號與名稱清單(以
             Tab 字串傳遞)。流程中會針對每個目錄編號統計其在舊資料中的出現次數,並
            將統計後的份數結果更新至 CaseDocNo_Copies.dat 檔案中,以完成歷史資料
            的規格對接。
============================================================================== }
Procedure TCB_IMGPSScanX.OldCasetoNewCase(CaseID:String); //將舊案份數轉成新規則
var
  i,n : Integer;
  C_DocNoList,C_DocNameList : TStringlist;
  DocNoList,DocNo_CopiesList : TStringlist;
  DocNo,DocName,DocDir : String;
  DocNo_Ct :integer;
begin
  C_DocNoList := TStringlist.Create;
  C_DocNameList := TStringlist.Create;
  DocNoList := TStringlist.Create;
  DocNo_CopiesList := TStringlist.Create;
  try
    DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    for i := 0 to DocNoList.Count - 1 do
    begin
      DocNo_CopiesList.Add('0');
    end;
    //Showmessage(FC_DocNoList);
    if FC_DocNoList <> '' then
    begin
      C_DocNoList.StrictDelimiter := True;
      C_DocNoList.Delimiter := #9;
      C_DocNoList.DelimitedText := FC_DocNoList;
      //showmessage(C_DocNoList.Text+#13+#13+DocNoList.Text);
      for i := 0 to DocNoList.Count - 1 do
      begin
        //DocNo := DocNoList.Strings[i];
        DocNo := DocNoDir2DocNo(DocNoList.Strings[i]);  //20140812 因轉舊案錯誤件會出現DocnoDir
        DocNo_Ct := 0;
        for n := 0 to C_DocNoList.Count - 1 do
        begin
          if DocNo = C_DocNoList.Strings[n] then
            inc(DocNo_Ct);
        end;
        if DocNo_CT > 0 Then
          DocNo_CopiesList.Strings[i] := inttostr(DocNo_CT);
      end;
      DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
    end;
    if FC_DocNameList <> '' then
    begin
      C_DocNameList.StrictDelimiter := True;
      C_DocNameList.Delimiter := #9;
      C_DocNameList.DelimitedText := FC_DocNameList;
      for i := 0 to DocNoList.Count - 1 do
      begin
        DocNo := DocNoList.Strings[i];
        DocNo_Ct := 0;
        for n := 0 to C_DocNameList.Count - 1 do
        begin
          if GetCustomDocName(ImageSavePath+CaseID+'\',DocNo) = C_DocNameList.Strings[n] then
            inc(DocNo_Ct);
        end;
        if DocNo_CT > 0 Then
          DocNo_CopiesList.Strings[i] :=inttostr(DocNo_CT);
      end;
    end;
    DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
  finally
  C_DocNoList.Free;
  C_DocNameList.Free;
  DocNoList.Free;
  DocNo_CopiesList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:ErrFormtoCurrentForm
  引用相依:LoadFromFile, FileExists, RenameFile, SaveToFile, MoveFile
  方法描述:修正案件中歸類錯誤的表單代碼及其關聯檔案。邏輯如下:
            1. 取得錯誤與正確表單對應的文件編號。
            2. 遍歷案件下的所有文件目錄,載入各目錄的影像索引檔 (Context.dat)。
            3. 識別檔名中包含 EFormID 的影像,執行實體重新命名並更新索引。
            4. 若該目錄編號與錯誤文件編號一致,則會執行 MoveFile 搬移整個目錄至新
            路徑,並同步更新總文件清單 (CaseDocNo.dat),確保影像與分類資訊的一致性
            。
============================================================================== }
Procedure TCB_IMGPSScanX.ErrFormtoCurrentForm(CaseID,EFormID,CFormID:String);//將舊案的錯誤FormID改正確的FormID
var
  DocNoList,FileList :TStringlist;
  EDocNo,CDocNo,iDocNo,iFormID :String;
  EDocDir,CDocDir:String;
  OldFile,NewFile :String;
  iPath,iiPath : String;
  i,n : Integer;
begin
  EDocNo := FormCode2DocNo(EFormID);
  CDocNo := FormCode2DocNo(CFormID);
  DocNoList :=TStringlist.Create;
  FileList := TStringlist.Create;
  try
    DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    for i := 0 to DocNoList.Count - 1 do
    begin
      EDocDir := DocNoList.Strings[i];
      iDocNo := DocNoDir2DocNo(DocNoList.Strings[i]);
      iPath := ImageSavePath+CaseID+'\'+EDocDir+'\';
      if FileExists(iPath+'Context.dat') then  //20140909漏加這個判斷造成自訂文件但沒影像會出錯誤訊息
        FileList.LoadFromFile(iPath+'Context.dat');
      for n := 0 to FileList.Count - 1 do
      begin
        iFormID := FileName2FormCode(FileList.Strings[n]);
        if iFormID = EFormID then
        begin
          OldFile := FileList.Strings[n];
          NewFile := StringReplace(FileList.Strings[n],iFormID,CFormID,[rfReplaceAll]);
          FileList.Strings[n] := NewFile;
          RenameFile(iPath+OldFile,iPath+NewFile);
          FileList.SaveToFile(iPath+'Context.dat');
        end;
      end;
      if iDocNo = EDocNo then
      begin
        CDocDir := StringReplace(EDocDir,EDocNo,CDocNo,[rfReplaceAll]);
        iiPath := ImageSavePath+CaseID+'\'+CDocDir+'\';
        MoveFile(PWideChar(iPath),PWideChar(iiPath));
        DocNoList.Strings[i] := StringReplace(DocNoList.Strings[i],iDocNo,CDocNo,[rfReplaceAll]);
        DocNoList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
        //SetRecordEditedDocDir('A',CaseID,CDocNo);  //20140918 yuu說改成不紀錄
      end;
    end;
  finally
  DocNoList.Free;
  FileList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:SetRecordEditedDocDir
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:記錄案件中曾被異動(新增或刪除)的文件目錄。將目錄名稱存入 EditedDocDir
            .dat,以便後續判斷哪些內容需要同步上傳或重新計算。
============================================================================== }
Procedure TCB_IMGPSScanX.SetRecordEditedDocDir(Mode:Char;CaseID,DocDir:String);  //記錄被異動的文件目錄  'A:加入D:刪掉'
var
  i : Integer;
  Exists : Boolean;
  EditedDocDirList : TStringlist;
begin
  EditedDocDirList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then
      EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
    case Mode of
      'A':begin
            Exists := False;
            for i := 0 to EditedDocDirList.Count - 1 do
            begin
              if EditedDocDirList.Strings[i]=DocDir then
              begin
                Exists := True;
                Break;
              end;
            end;
            if not Exists then
            begin
              EditedDocDirList.Add(DocDir);
              EditedDocDirList.SaveToFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
            end;
          end;
      'D':begin
            for i := 0 to EditedDocDirList.Count - 1 do
            begin
              if EditedDocDirList.Strings[i] = DocDir then
              begin
                EditedDocDirList.Delete(i);
                if EditedDocDirList.Count > 0 then
                  EditedDocDirList.SaveToFile(ImageSavePath+CaseID+'\EditedDocDir.dat')
                else
                  DeleteFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
                Break;
              end;
            end;
          end;
    end;
  finally
  EditedDocDirList.Free;
  end;
end;
reassemble/CB_IMGPSScanImp.docq.pas
比對新檔案
@@ -0,0 +1,553 @@
{ ==============================================================================
  方法名稱:GetDataDocNoPage
  引用相依:
  方法描述:從 DOC_INF_List 資料中查詢特定文件與版本的預設頁數設定。
============================================================================== }
Function TCB_IMGPSScanX.GetDataDocNoPage(MainDocNo,MainVersion:String):Integer;  //取記錄的文件_版本頁數
var
  P : String;
begin
  Result := 0;
  If FindSQLData(Doc_Inf_List,'FORM_PAGES','DOC_NO,DOC_VERSION',MainDocNo+','+MainVersion,0,FindResult) Then
  begin
    P := GetFindResult('FORM_PAGES');
    if P <> '' then
      Result := strtoint(P)
    else
      Result := 0;
  end;
end;
{ ==============================================================================
  方法名稱:CheckCaseDocNoPage
  引用相依:LoadFromFile
  方法描述:計算案件中特定文件與版本的實際頁數。透過讀取 upload 目錄下的 Context.
            dat 與 DocDir.dat,精確比對 FormID、DocNo、版本與頁碼索引,並排除入庫狀
            態影像,回傳符合條件的影像總數。
============================================================================== }
Function TCB_IMGPSScanX.CheckCaseDocNoPage(CaseID,DocNo,Version:String;Pages:Integer):Integer; //取案件裡的文件_版本頁數
var
  i,n,Count : integer;
  S, S2 : TStringlist;
  FormCode,iPage : String;
  docInt,tempInt:integer;
  v,v2:integer;
begin
  Count := 0;
  docInt:=0;
  tempInt:=0;
  S := TStringlist.Create;
  S2 := TStringlist.Create;
//ShowMessage('page='+IntToStr(Pages));
  try
    S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
    S2.LoadFromFile(ImageSavePath+CaseID+'\upload\DocDir.dat'); //2017 1220 改成只承認第一份的
    for I := 1 to pages do //從0到pages-1  改成 1到pages 20170316 這樣可以修改檢核的頁數問題
    begin
      iPage := Add_Zoo(i,2);
      for n := 0 to S.Count - 1 do
      begin
        if (FWH_category='N') and (FIs_In_Wh='Y') then
        begin
          if ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[n]) then
          begin
            Continue;
          end;
        end;
        if (Length(S2.Strings[n])>8) and (Pos(DocNo,S2.Strings[n])<>0) then //2017 1220 改成只承認第一份的
        begin
//LogFile1.LogToFile(logTimeString+'有進'+docno+','+S2.Strings[n]+IntToStr(Pos(DocNo,S2.Strings[n])));
          v:=Pos('(',S2.Strings[n]);
          v2:=Pos(')',S2.Strings[n]);
          tempInt:=StrToInt(Copy(S2.Strings[n],v+1,v2-v-1));
          if docInt=0 then
          begin
            docInt:=tempInt;
          end;
          if docInt<>tempInt then
          begin
//LogFile1.LogToFile(logTimeString+'docInt='+IntToStr(docInt)+',tempInt='+IntToStr(tempInt));
            Result := Count;
            Break;
          end;
        end;
        FormCode := FileName2FormCode(S.Strings[n]);
//LogFile1.LogToFile(logTimeString+'S.Strings[n]='+S.Strings[n]);
//Showmessage('1:'+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
//LogFile1.LogToFile(logTimeString+'FormCode='+FormCode);
LogFile1.LogToFile(logTimeString+'CheckCaseDocNoPage caseno='+CaseID+','+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
//ShowMessage(DocNo+','+IntToStr(docInt)+','+IntToStr(tempInt));
//LogFile1.LogToFile(logTimeString+'FormCode='+FormCode);
        if (version = FormCode2Version(FormCode)) and (DocNo = FormCode2DocNo(FormCode)) and (ipage = FormCode2Page(FormCode)) then
        begin
LogFile1.LogToFile(logTimeString+'CheckCaseDocNoPage caseno='+CaseID+','+version+','+FormCode2Version(FormCode)+','+DocNo+','+FormCode2DocNo(FormCode)+','+iPage+','+FormCode2Page(FormCode));
//Showmessage(version+','+DocNo+',iPage='+iPage);
//Showmessage(inttostr(Count+1));
          Inc(Count);
          Break;   //找到了...離開
        end;
      end;
    end;
  finally
  S.Free;
  S2.free;
  end;
  Result := Count;
end;
{ ==============================================================================
  方法名稱:FindFormCodePages
  引用相依:LoadFromFile
  方法描述:計算案件中特定 FormID 的實際影像總數,可用於檢核。
============================================================================== }
Function TCB_IMGPSScanX.FindFormCodePages(CaseID,FormCode:String):Integer;  //計算案件裡FormID的頁數
var
  i,Count : integer;
  S : TStringlist;
  iFormCode : String;
begin
  Count := 0;
  S := TStringlist.Create;
  try
    S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
    for i := 0 to S.Count - 1 do
    begin
      if FWH_category='N' then
      begin
        if ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[i]) then
        begin
          Continue;
        end;
      end;
      iFormCode := FileName2FormCode(S.Strings[i]);
      if FormCode = iFormCode then
      begin
        Inc(Count);
      end;
    end;
  finally
  S.Free;
  end;
  Result := Count;
end;
{ ==============================================================================
  方法名稱:GetDataFormCodePages
  引用相依:
  方法描述:查詢特定表單 ID 的最大頁數限制,若未設定則回傳 9999。
============================================================================== }
Function TCB_IMGPSScanX.GetDataFormCodePages(FormCode:String):Integer;   //取記錄的FormcID的頁數
begin
  If FindSQLData(FORM_INF_List,'T1.MAX_PAGE','T1.FORM_ID',FormCode,0,FindResult) Then
  begin
    IF GetFindResult('T1.MAX_PAGE') = '' Then
      Result := 9999
    Else
      Result := Strtoint(GetFindResult('T1.MAX_PAGE'));
  end;
end;
{ ==============================================================================
  方法名稱:GetDocDir_Page
  引用相依:FileExists, LoadFromFile
  方法描述:取得特定文件目錄下的影像總頁數。
============================================================================== }
Function TCB_IMGPSScanX.GetDocDir_Page(CaseID,DocDir:String):Integer;
var
  FileList : TStringlist;
begin
  Result := 0;
  FileList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
    begin
      FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
      Result := FileList.Count;
    end;
  finally
  FileList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDocNoCount
  引用相依:FileExists, LoadFromFile
  方法描述:統計指定案件中某文件編號(DocNo)的總份數。讀取 CaseDocNo.dat 與 CaseDo
            cNo_Copies.dat 並累加匹配項目的份數值。
============================================================================== }
Function TCB_IMGPSScanX.GetDocNoCount(CaseID,DocNo:String):Integer; //取DocNo數量
var
  i : Integer;
  Doc_Ct:Integer;
  iDocNo : String;
  DocNoList,DocNo_CopiesList : TStringlist;
begin
  DocNoList := TStringlist.Create;
  DocNo_CopiesList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
    begin
      DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
      DocNo_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
    end;
    Doc_Ct := 0;
    for i := 0 to DocNoList.Count - 1 do
    begin
      iDocNo := DocNoDir2DocNo(DocNoList.Strings[i]);
      if iDocNo = DocNo then
        Doc_Ct := Doc_Ct + strtoint(DocNo_CopiesList.Strings[i]);
    end;
    Result := Doc_Ct;
   // Showmessage(DocNo+#13+inttostr(Doc_Ct));
  finally
  DocNoList.Free;
  DocNo_CopiesList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDocDirCopies
  引用相依:FileExists, LoadFromFile
  方法描述:取得特定文件目錄(DocDir)目前的份數設定。
============================================================================== }
Function TCB_IMGPSScanX.GetDocDirCopies(CaseID,DocDir:String):Integer; //取DocDir數量
var
  i : Integer;
  DocNoList,DocNo_CopiesList : TStringlist;
begin
  Result := 1;  //預設回傳1  //20140521 由0改成1
  DocNoList := TStringlist.Create;
  DocNo_CopiesList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
      DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat') then
    begin
      DocNo_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
      for i := 0 to DocNoList.Count - 1 do
      begin
        if (DocDir = DocNoList.Strings[i]) and (i <= DocNo_CopiesList.Count-1) then
        begin
          Result := strtoint(DocNo_CopiesList.Strings[i]);
          Break;
        end;
      end;
    end;
  finally
  DocNoList.Free;
  DocNo_CopiesList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:SetDocDirCopies
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:修改並儲存特定文件目錄的份數設定至 CaseDocNo_Copies.dat。
============================================================================== }
Procedure TCB_IMGPSScanX.SetDocDirCopies(CaseID,DocDir:String;NewCopies:Integer); //修改DocDir份數
var
  i : Integer;
  DocNoList,DocNo_CopiesList : TStringlist;
begin
  DocNoList := TStringlist.Create;
  DocNo_CopiesList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
    begin
      DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
      DocNo_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
    end;
    for i := 0 to DocNoList.Count - 1 do
    begin
      if DocDir = DocNoList.Strings[i] then
      begin
        DocNo_CopiesList.Strings[i] := inttostr(NewCopies);
        DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
        Break;
      end;
    end;
  finally
  DocNoList.Free;
  DocNo_CopiesList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDocDirCopies_Rec
  引用相依:
  方法描述:從 FOldCaseInfo 記錄字串中解析並取得特定文件目錄在舊案中的份數。支援
            自定義文件名稱與一般文件編號的匹配。
============================================================================== }
Function TCB_IMGPSScanX.GetDocDirCopies_Rec(Path,CaseID,DocDir:String):Integer; //取記錄裡的DocDir份數
var
  i,n,v,v1 : Integer;
  OldCaseInfoList,Caseinfolist : TStringlist;
  iCaseID,Year,iBS_No,iIS_Old,iDocNo,iCopies:String;
begin
  Result := 1;
  OldCaseInfoList := TStringlist.Create;
  Caseinfolist := TStringlist.Create;
  try
    //OldCaseInfoList 案件編號@#,年度@#,業務別@#,是否舊件@#,Data@#,Verify@#,文件編號[份數]@#,文件編號[份數] tab 案件編號@#,年度@#,業務別@#,是否舊件@#,Data@#,Verify@#,文件編號[份數]@#,文件編號[份數]
    OldCaseInfoList.StrictDelimiter := true;
    OldCaseInfoList.Delimiter := #9;
    OldCaseInfoList.DelimitedText := FOldCaseInfo;
    for i := 0 to OldCaseInfoList.Count - 1 do
    begin
      Caseinfolist:=SplitString('@#,',OldCaseInfoList.Strings[i]);
      //Caseinfolist.Delimiter := '_';
      //Caseinfolist.DelimitedText := OldCaseInfoList.Strings[i];
      iCaseID := Caseinfolist.Strings[0];
      Year := Caseinfolist.Strings[1];
      iBS_No := Caseinfolist.Strings[2];
      iIS_Old := Caseinfolist.Strings[3];
      if CaseID = iCaseID then
      begin
        for n := 6 to Caseinfolist.Count - 1 do
        begin
          v := Pos('[',Caseinfolist.Strings[n]);
          v1 := Pos(']',Caseinfolist.Strings[n]);
          iDocNo := Copy(Caseinfolist.Strings[n],1,v-1);
          iCopies := Copy(Caseinfolist.Strings[n],v+1,v1-v-1);
          if Copy(DocDir,1,5) = 'ZZZZZ' then
          begin
            if iDocNo = GetCustomDocName(Path,DocDir) then
              Result := strtoint(iCopies);
          end
          else
          begin
            if iDocNo = DocNoDir2DocNo(DocDir) then
              Result := strtoint(iCopies);
          end;
        end;
      end;
    end;
  finally
  OldCaseInfoList.Free;
  Caseinfolist.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDocNoEdit
  引用相依:FileExists, LoadFromFile
  方法描述:檢查指定文件是否被異動。程序會載入已編輯目錄清單,並與原始的文件代號/
            名稱清單(FC_DocNoList)進行比對。若文件代號或名稱不在原始清單中,或存在
            於已編輯清單內,則判定該文件已被異動並回傳 "Y"。
============================================================================== }
Function TCB_IMGPSScanX.GetDocNoEdit(CaseID,DocNo,DocName:String):String; //取出DocNo是否被異動 (Y/N)
var
  i : Integer;
  EditedDocDirList : TStringlist;
  C_DocNoList,C_DocNameList : TStringlist;
begin
  Result := 'N';
  EditedDocDirList := TStringlist.Create;
  C_DocNoList := TStringlist.Create;
  C_DocNameList := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then
      EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
    C_DocNoList.StrictDelimiter := True;
    C_DocNoList.Delimiter := #9;
    C_DocNoList.DelimitedText := FC_DocNoList;
    C_DocNameList.StrictDelimiter := True;
    C_DocNameList.Delimiter := #9;
    C_DocNameList.DelimitedText := FC_DocNameList;
    //Showmessage(C_DocNoList.Text);
    if (DocName = '') and (C_DocNoList.IndexOf(DocNo)=-1 ) then
      Result := 'Y';
    if (DocName <> '') and (C_DocNameList.IndexOf(DocName)=-1) then
      Result := 'Y';
    for i := 0 to EditedDocDirList.Count - 1 do
    begin
      if (DocNo = DocNoDir2DocNo(EditedDocDirList.Strings[i]))   then
      begin
        Result := 'Y';
        Break;
      end;
    end;
  finally
  EditedDocDirList.Free;
  C_DocNoList.Free;
  C_DocNameList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDocNo_Count
  引用相依:LoadFromFile
  方法描述:計算指定文件代號在案件中的份數。若文件不需分組則直接回傳 1。否則,遍歷
            影像清單(Context.dat),根據檔案名稱解析出的頁碼是否為第一頁("01")來累
            計該文件的份數。
============================================================================== }
Function TCB_IMGPSScanX.GetDocNo_Count(Path,DocNo:String):Integer;  //取出文件份數
var
  i : Integer;
  iCopys : integer;
  S,S1 : TStringlist;
  iFormID : String;
  DocFirst : Boolean;
begin
  Result := 0;
  if not DocnoNeedGroup(DocNo) then
  begin
    Result := 1;
    Exit;
  end;
  S := TStringlist.Create;
  S1 := TStringlist.Create;
  try
    S.LoadFromFile(Path+'Context.dat');
    S1.LoadFromFile(Path+'Context_DocNo.dat');
    iCopys := 0;
    for i := 0 to S.Count - 1 do
    begin
      iFormID := FileName2FormCode(S.Strings[i]);
      DocFirst := False;
      if FormCode2Page(iFormID) = '01' then
        DocFirst := True;
      if ((iCopys = 0) or DocFirst) and (Docno = S1.Strings[i])  then
      begin
        inc(iCopys);
      end;
    end;
    Result := iCopys;
  finally
  S.Free;
  S1.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDocNo_Page
  引用相依:LoadFromFile
  方法描述:計算指定文件代號在案件中擁有的總影像頁數。遍歷影像對應的文件清單(Cont
            ext_DocNo.dat),統計與傳入代號相符的項目數量。
============================================================================== }
Function TCB_IMGPSScanX.GetDocNo_Page(Path,DocNo:String):Integer;  //取出文件總頁數
var
  i : Integer;
  ipages : integer;
  S,S1 : TStringlist;
begin
  Result := 0;
  S := TStringlist.Create;
  S1 := TStringlist.Create;
  try
    S.LoadFromFile(Path+'Context.dat');
    S1.LoadFromFile(Path+'Context_DocNo.dat');
    iPages := 0;
    for i := 0 to S.Count - 1 do
    begin
      if Docno = S1.Strings[i] then
      begin
        inc(iPages);
      end;
    end;
    Result := ipages;
  finally
  S.Free;
  S1.Free;
  end;
end;
{ ==============================================================================
  方法名稱:FormIDExists
  引用相依:
  方法描述:檢查指定的表單代碼(FormID)是否存在於系統資料庫中。支援日期檢核模式:若
            啟用,則會進一步查詢該表單所屬文件的起迄效期(START_DATE, STOP_DATE),
            並與伺服器當前日期比對,確保表單仍在有效期限內。
============================================================================== }
Function TCB_IMGPSScanX.FormIDExists(FormCode:String;CheckDate:Boolean;index:Integer):Boolean;  //檢查FormID是否存在
var
  STDate,SPDate : String;
  Docno,Version : String;
begin
  Result := False;
  If FormCode = '' then  //附件不檢查
  begin
    Result := True;
    Exit;
  end;
  if CheckDate then  //要檢查日期
  begin
    STDate := '00000000'; //沒設定
    SPDate := '99999999'; //沒設定
    IF FindSQLData(FORM_INF_List,'T1.FORM_ID,T1.DOC_NO','T1.FORM_ID',FormCode,index,FindResult) then
    begin
      DocNo := GetFindResult('T1.DOC_NO');
      Version := FormCode2Version(FormCode);
      if FindSQLData(Doc_Inf_List,'START_DATE,STOP_DATE','DOC_NO,DOC_VERSION',DocNo+','+Version,0,FindResult) then
      begin
        Result := True;
        STDate := GetFindResult('START_DATE');
        SPDate := GetFindResult('STOP_DATE');
        if STDate = '' then STDate := '00000000'; //沒設定
        if SPDate = '' then SPDate := '99999999'; //沒設定
        if (ServerDate < STDate) or (ServerDate > SPDate) then
          Result := False;
      end;
    end;
  end
  Else
  begin
    Result := FindSQLData(FORM_INF_List,'T1.FORM_ID','T1.FORM_ID',FormCode,index,FindResult);
  end;
end;
{ ==============================================================================
  方法名稱:Case_DocNoExists
  引用相依:LoadFromFile
  方法描述:檢查指定的文件代號是否存在於特定案件的 Context.dat 影像清單中。
============================================================================== }
Function TCB_IMGPSScanX.Case_DocNoExists(CaseID,Docno:String):Boolean; //Docno是否存在案件裡
var
  i : Integer;
  S : TStringlist;
  iDocNo : String;
begin
  Result := False;
  S := TStringlist.Create;
  try
    S.LoadFromFile(ImageSavePath + CaseID+'\Context.dat');
    for i := 0 to S.Count - 1 do
    begin
      iDocNo := FormCode2DocNo(FileName2FormCode(S.Strings[i]));
      if Docno = iDocNo then
      begin
        Result := True;
        Break;
      end;
    end;
  finally
  S.Free;
  end;
end;
reassemble/CB_IMGPSScanImp.fileOp.pas
比對新檔案
@@ -0,0 +1,347 @@
{ ==============================================================================
  方法名稱:ReNameContext
  引用相依:SaveToFile
  方法描述:在指定路徑下執行影像清單的更名同步。遍歷 ContextList,比對舊檔名後更新
            為新檔名,同步更新 Context.dat 及對應的文件編號清單(Context_DocNo.dat
            )。
============================================================================== }
Procedure TCB_IMGPSScanX.ReNameContext(Path,OldName,NewName:String);
var
  i : Integer;
begin
  for i := 0 to ContextList.Count - 1 do
  begin
    if OldName = ContextList.Strings[i] then
    begin
      ContextList.Strings[i] := NewName;
      ContextList.SaveToFile(Path+'Context.dat');
      Context_DocnoList.Strings[i] := FormCode2DocNo(FileName2FormCode(NewName));
      Context_DocnoList.SaveToFile(Path+'Context_DocNo.dat');
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:DeleteImageFile
  引用相依:DeleteImageFile, FileExists, LoadFromFile, SaveToFile
  方法描述:刪除指定的影像檔案。執行實體刪除後,自動計算文件目錄,並呼叫 SetContext
            List 從 Context 清單中移除對應的影像記錄。
============================================================================== }
Procedure TCB_IMGPSScanX.DeleteImageFile(Path,FileName,CaseID:String); // 刪除檔案  (無法得到DocDir用)
var
  i : Integer;
  FileList:TStringlist;
  DocDir : String;
begin
  DeleteFile(Path+FileName);
  DocDir := Path2DocDir(Path,CaseID);
//ShowMessage('DocDir='+DocDir);
  SetContextList('D',-1,CaseID,DocDir,FileName);
  {FileList:=TStringlist.Create;
  try
    if FileExists(Path+'Context.dat') then
      FileList.LoadFromFile(Path+'Context.dat');
    for i := 0 to FileList.Count - 1 do
    begin
      if FileName = FileList.Strings[i] then
      begin
        FileList.Delete(i);
        FileList.SaveToFile(Path+'Context.dat');
        Break;
      end;
    end;
    if FileList.Count = 0 then
      DeleteFile(Path+'Context.dat');
  finally
  FileList.Free;
  end;}
end;
{ ==============================================================================
  方法名稱:DeleteFormCodeFile
  引用相依:FileExists, LoadFromFile, DeleteImageFile, ReSortFileName, SaveToFil
            e
  方法描述:刪除案件中指定 FormID 的所有文件。讀取 Context.dat 並遍歷,若 FormID
            匹配則執行刪除(在 ESCAN 模式下會檢查是否非當次掃瞄以保護舊圖)。刪除後
            執行檔案序號重新排序。
============================================================================== }
Procedure TCB_IMGPSScanX.DeleteFormCodeFile(CaseID,DocDir,FormID:String);  //刪除指定FormID文件
var
  i: Integer;
  FileList : TStringlist;
begin
  FileList := TStringlist.Create;
  try
    FileList.Clear;
    if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
      FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
    for i := FileList.Count - 1 downto 0 do
    begin
      if FileName2FormCode(FileList.Strings[i]) = FormID then
      begin
        if (FMode = 'ESCAN') and (FModeName<>_Msg('異動件')) then
        begin
          if ISExistImg(ImageSavePath+CaseID+'\'+DocDir+'\'+FileList.Strings[i]) then
          begin
            //ShowMessage('有圖為非當次掃瞄,不可刪除');
            Break;
          end;
        end;
//ShowMessage(FileList.Strings[i]);
        DeleteImageFile(ImageSavePath+CaseID+'\'+DocDir+'\',FileList.Strings[i],CaseID);
      end;
    end;
  finally
  FileList.Free;
  end;
  ReSortFileName(ImageSavePath+CaseID+'\'+DocDir+'\');
  {for i := ContextList.Count - 1 downto 0 do
  begin
    FName := ContextList.Strings[i];
    if FormID = 'Err' then  //刪未註冊文件
    begin
      If not FormIDExists(FileName2FormCode(FName),False,0) Then
      begin
        DeleteFile(Path+FName);
        ContextList.Delete(i);
      end;
    end
    Else
    begin
      If FormID = FileName2FormCode(FName) then
      begin
        DeleteFile(Path+FName);
        ContextList.Delete(i);
      end;
    end;
  end;
  ContextList.SaveToFile(Path+'Context.dat');
  ReSortFileName(Path); }
end;
{ ==============================================================================
  方法名稱:DeleteDocNoFile
  引用相依:DeleteDocNoFile, SaveToFile, ReSortFileName, LoadFromFile, FileExist
            s
  方法描述:刪除指定的文件編號(DocNo)影像。遍歷 ContextList,比對文件編號後執行實
            體刪除與清單移除(含 Context 與 Context_DocNo)。處理完成後執行檔案重新
            排序並重新載入清單。
============================================================================== }
Function TCB_IMGPSScanX.DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
var
  i: Integer;
  FName : String;
begin
  Result := False;
  for i := ContextList.Count - 1 downto 0 do
  begin
    FName := ContextList.Strings[i];
    If DocNo = FormCode2DocNo(FileName2FormCode(FName)) then
    begin
      DeleteFile(Path+FName);
      ContextList.Delete(i);
      Context_DocnoList.Delete(i);
      Result := True; //有刪到指定文件
    end;
  end;
  ContextList.SaveToFile(Path+'Context.dat');
  Context_DocnoList.SaveToFile(Path+'Context_DocNo.dat');
  ReSortFileName(Path);
  ContextList.LoadFromFile(Path+'Context.dat');
  Context_DocnoList.LoadFromFile(Path+'Context_DocNo.dat');
  if FileExists(Path+'CustomDocNo.dat') then
    Cust_DocNoList.LoadFromFile(Path+'CustomDocNo.dat');
end;
{ ==============================================================================
  方法名稱:DeleteDocNoFileForESCAN
  引用相依:DeleteDocNoFile, SaveToFile, LoadFromFile, _DelTree
  方法描述:在補件模式 (ESCAN) 下刪除屬於特定文件類型 (DocNo) 的影像。方法會從索
            引清單 (ContextList) 的末尾開始向前遍歷,識別符合目標文件編號或附件名
            稱的圖檔。若該檔案並非預先存在的(ISExistImg 返回 False),則執行實體刪
            除並從索引清單中移除。若整個文件目錄因此清空,則會進一步移除該目錄並從
            文件清單中刪除紀錄。
============================================================================== }
Function TCB_IMGPSScanX.DeleteDocNoFileForESCAN(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
var
  i,j,k: Integer;
  FName : String;
  ST1,ST2,ST3:TStringList;
begin
  Result := False;
//ShowMessage(DocNo);
  for i := ContextList.Count - 1 downto 0 do
  begin
    FName := ContextList.Strings[i];
    If (DocNo = FormCode2DocNo(FileName2FormCode(FName))) or (DocNo=AttName) then
    begin
      if not ISExistImg(Path+'\'+FName) then
      begin
        DeleteFile(Path+'\'+FName);
        ContextList.Delete(i);
      end;
      Result := True; //有刪到指定文件
    end;
  end;
  ContextList.SaveToFile(Path+'\Context.dat');
  ContextList.LoadFromFile(Path+'\Context.dat');
  if ContextList.Count=0 then
  begin
    _DelTree(Path);
    SetDocNoList('D',-1,NowCaseNo,NowDocDir,'');
  end;
end;
{ ==============================================================================
  方法名稱:DeleteShowFile
  引用相依:DeleteShowFile
  方法描述:刪除當前顯示清單(NowShowFileList)中的影像檔案並更新索引。
============================================================================== }
Procedure TCB_IMGPSScanX.DeleteShowFile(Path:String); //刪除顯示中的影像
var
  i : Integer;
  DelFile : String;
begin
  for i := 0 to NowShowFileList.Count - 1 do
  begin
    DelFile := NowShowFileList.Strings[i];
    DeleteFile(Path+DelFile);
    SetContextList('D',-1,NowCaseno,NowDocNo,DelFile);
  end;
end;
{ ==============================================================================
  方法名稱:DeleteCustomDocDir
  引用相依:
  方法描述:從 CustomDocNo.ini 中刪除指定的自定義文件區段。
============================================================================== }
Procedure TCB_IMGPSScanX.DeleteCustomDocDir(Path,DocNo:String); //刪除自定文件DocNo
var
  ini : Tinifile;
begin
  ini := Tinifile.Create(Path+'CustomDocNo.ini');
  try
    ini.EraseSection(DocNo);
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:ReSortFileName
  引用相依:ReSortFileName, FileExists, LoadFromFile, RenameFile, SaveToFile
  方法描述:執行影像檔案名稱的重新排序與更名。讀取目錄下的 Context.dat,根據目前的
            排列順序為每個檔案產生新的三位數序號前綴,並呼叫 ReNameFile 執行磁碟
            更名,最後同步更新清單內容並儲存。
============================================================================== }
Procedure TCB_IMGPSScanX.ReSortFileName(Path:String); //檔名重新排序
var
  i : Integer;
  OldName,NewName : String;
  Filelist : TStringlist;
begin
  Filelist := TStringlist.Create;
  try
    if FileExists(Path+'Context.dat') then
    begin
      Filelist.LoadFromFile(Path+'Context.dat');
      for i := 0 to Filelist.Count - 1 do
      begin
        OldName := Filelist.Strings[i];
        //NewName := Add_Zoo(i+1,3)+Copy(OldName,4,length(OldName)-3);
        NewName := Add_Zoo(i+1,3)+FileName2NoQuene_Filename(OldName);
//ShowMessage(OldName+#10#13+NewName);
        ReNameFile(Path+OldName,Path+NewName);
        Filelist.Strings[i] := NewName;
      end;
      Filelist.SaveToFile(Path+'Context.dat');
      ContextList.LoadFromFile(Path+'Context.dat');
    end;
  finally
  Filelist.Free;
  end;
end;
{ ==============================================================================
  方法名稱:ReSortFileName_New
  引用相依:ReSortFileName, FileExists, LoadFromFile, RenameFile, SaveToFile
  方法描述:與 ReSortFileName 類似,執行影像檔案名稱的重新排序,但採用從清單末尾向
            前遍歷的方式執行更名與儲存。
============================================================================== }
Procedure TCB_IMGPSScanX.ReSortFileName_New(Path:String); //檔名重新排序
var
  i : Integer;
  OldName,NewName : String;
  Filelist : TStringlist;
begin
  Filelist := TStringlist.Create;
  try
    if FileExists(Path+'Context.dat') then
    begin
      Filelist.LoadFromFile(Path+'Context.dat');
      for i := Filelist.Count - 1 downto 0 do
      begin
        OldName := Filelist.Strings[i];
        //NewName := Add_Zoo(i+1,3)+Copy(OldName,4,length(OldName)-3);
        NewName := Add_Zoo(i+1,3)+FileName2NoQuene_Filename(OldName);
        ReNameFile(Path+OldName,Path+NewName);
        Filelist.Strings[i] := NewName;
      end;
      Filelist.SaveToFile(Path+'Context.dat');
      ContextList.LoadFromFile(Path+'Context.dat');
    end;
  finally
  Filelist.Free;
  end;
end;
{ ==============================================================================
  方法名稱:ReSortFileName2Scanlist
  引用相依:ReSortFileName, FileExists, LoadFromFile, RenameFile, SaveToFile
  方法描述:針對 scanlist.dat 檔案內的影像路徑進行序號重排。讀取清單後,依序為檔案
            名稱加上新的序號前綴並存回。
============================================================================== }
Procedure TCB_IMGPSScanX.ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
var
  i : Integer;
  OldName,NewName : String;
  S : TStringlist;
begin
  S := TStringlist.Create;
  try
    if FileExists(Path+'scanlist.dat') then
      S.LoadFromFile(Path+'scanlist.dat');
    for i := 0 to S.Count - 1 do
    begin
      OldName := S.Strings[i];
      //NewName := Add_Zoo(i+1,3)+Copy(OldName,4,length(OldName)-3);
      NewName := Add_Zoo(i+1,3)+FileName2NoQuene_Filename(OldName);
      //ReNameFile(Path+OldName,Path+NewName);
      S.Strings[i] := NewName;
    end;
    S.SaveToFile(Path+'scanlist.dat');
  finally
  S.Free;
  end;
end;
reassemble/CB_IMGPSScanImp.inbound.pas
比對新檔案
@@ -0,0 +1,147 @@
{ ==============================================================================
  方法名稱:GetDocNo_IS_WH
  引用相依:
  方法描述:判斷指定文件編號是否屬於「入庫文件」類別。
============================================================================== }
Function TCB_IMGPSScanX.GetDocNo_IS_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
var
  i :Integer;
begin
  Result := False;
  for i := 0 to IN_WH_DocNoList.Count - 1 do
  begin
    if DocNo = IN_WH_DocNoList.Strings[i] then
    begin
      Result := True;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:DocNoIs_In_WH
  引用相依:
  方法描述:判斷指定文件編號(包含自定義 ZZZZZ 系列)是否為入庫文件。
============================================================================== }
Function TCB_IMGPSScanX.DocNoIs_In_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
var
  i : Integer;
begin
  Result := False;
  if (Copy(DocNo,1,5)='ZZZZZ') then //20140728 yuu 說自訂文件也是入庫文件
  begin
    Result := True;
    Exit;
  end;
  for i := 0 to IN_WH_DocNoList.Count -1 do
  begin
    if DocNo = IN_WH_DocNoList.Strings[i] then
    begin
      Result := True;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FormIDAppear
  引用相依:
  方法描述:判斷特定的表單代碼(FormID)是否符合目前入庫/非入庫作業模式的顯示規則。
            主要過濾掉不屬於當前作業範疇的文件。
============================================================================== }
Function TCB_IMGPSScanX.FormIDAppear(FormID:String):Boolean; //FormID是否可出現
var
  iDocNo : String;
begin
  Result := True;
  iDocNo := FormCode2DocNo(FormID);
  if (((FIs_In_Wh  = 'Y') and (not DocNoIs_In_WH(iDocNo))) or   //入庫掃描不看非入庫文件
     ((FIs_In_Wh  = 'N') and (DocNoIs_In_WH(iDocNo)))) and      //非入庫掃描不看入庫文件
     ((iDocNo <> 'Attach') and (iDocNo <> 'S_Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then
       Result := False;
  if (FIs_In_Wh='Y') and (FWH_category='Y') then //20170816 新加
  begin
    if (((FIs_In_Wh  = 'Y') and (not DocNoIs_In_WH(iDocNo))) or   //入庫掃描不看非入庫文件
     ((FIs_In_Wh  = 'N') and (DocNoIs_In_WH(iDocNo)))) and      //非入庫掃描不看入庫文件
     ((iDocNo <> 'Attach') and (iDocNo <> 'S_Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then
       Result := False;
  end;
  if (FIs_In_Wh='Y') and (FWH_category='N') then //20170816 新加
  begin
    Result:=True;
  end;
end;
{ ==============================================================================
  方法名稱:DocNoAppear
  引用相依:
  方法描述:判斷文件編號(DocNo)是否應在介面上顯示。包含針對附件與入庫屬性的互斥過
            濾。
============================================================================== }
Function TCB_IMGPSScanX.DocNoAppear(DocNo:String):Boolean;   //DocNo是否可出現
begin
  Result := True;
  {if (((FIs_In_Wh  = 'Y') and (not DocNoIs_In_WH(DocNo)) or (DocNo ='S_Attach')) or   //入庫掃描不看非入庫文件
     ((FIs_In_Wh  = 'N') and (DocNoIs_In_WH(DocNo)) or (DocNo ='Attach') )) {and      //非入庫掃描不看入庫文件
     (Copy(DocNo,1,5)<>'ZZZZZ')} {then
       {Result := False;}
  //20181031 應該要換成下面的判斷比較對,FIs_In_Wh傳空的話才會出全部
  if (((FIs_In_Wh  = 'Y') and ((not DocNoIs_In_WH(DocNo)) or (DocNo ='S_Attach'))) or   //入庫掃描不看非入庫文件
     ((FIs_In_Wh  = 'N') and ((DocNoIs_In_WH(DocNo)) or (DocNo ='Attach') ))) {and      //非入庫掃描不看入庫文件
     (Copy(DocNo,1,5)<>'ZZZZZ')} then
       Result := False;
end;
{ ==============================================================================
  方法名稱:ISGuideFormID
  引用相依:
  方法描述:檢查指定的表單代碼是否屬於「引導頁(Guide Page)」清單。
============================================================================== }
Function TCB_IMGPSScanX.ISGuideFormID(FormID:String):Boolean;
var
  i : Integer;
begin
  Result := False;
  for i := 0 to GuideFormIDList.Count - 1 do
  begin
    if FormID = GuideFormIDList.Strings[i] then
    begin
      Result := True;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:ISDivPageFormID
  引用相依:
  方法描述:檢查指定的表單代碼是否屬於「分案頁(Division Page)」清單。
============================================================================== }
Function TCB_IMGPSScanX.ISDivPageFormID(FormID:String):Boolean;
var
  i : Integer;
begin
  Result := False;
  for i := 0 to DivPageFormIDList.Count - 1 do
  begin
    if FormID = DivPageFormIDList.Strings[i] then
    begin
      Result := True;
      Break;
    end;
  end;
end;
reassemble/CB_IMGPSScanImp.lfcycle.pas
比對新檔案
@@ -0,0 +1,771 @@
{ ==============================================================================
  方法名稱:DefinePropertyPages
  引用相依:
  方法描述:Delphi ActiveForm 用於定義屬性頁面的存根方法,目前未實作具體內容。
============================================================================== }
procedure TCB_IMGPSScanX.DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage);
begin
  { Define property pages here.  Property pages are defined by calling
    DefinePropertyPage with the class id of the page.  For example,
      DefinePropertyPage(Class_CBS_IMScanXPage); }
end;
{ ==============================================================================
  方法名稱:EventSinkChanged
  引用相依:
  方法描述:當事件接收器改變時觸發。將傳入的 EventSink 轉換為 ICB_IMGPSScanXEvent
            s 並賦值給 FEvents,同時呼叫繼承的 EventSinkChanged 方法。
============================================================================== }
procedure TCB_IMGPSScanX.EventSinkChanged(const EventSink: IUnknown);
begin
  FEvents := EventSink as ICB_IMGPSScanXEvents;
  inherited EventSinkChanged(EventSink);
end;
{ ==============================================================================
  方法名稱:ActivateEvent
  引用相依:
  方法描述:觸發 COM 介面的 OnActivate 事件。
============================================================================== }
procedure TCB_IMGPSScanX.ActivateEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnActivate;
end;
{ ==============================================================================
  方法名稱:ClickEvent
  引用相依:
  方法描述:觸發 COM 介面的 OnClick 事件。
============================================================================== }
procedure TCB_IMGPSScanX.ClickEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnClick;
end;
{ ==============================================================================
  方法名稱:CreateEvent
  引用相依:
  方法描述:觸發 COM 介面的 OnCreate 事件。
============================================================================== }
procedure TCB_IMGPSScanX.CreateEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnCreate;
end;
{ ==============================================================================
  方法名稱:DblClickEvent
  引用相依:
  方法描述:觸發 COM 介面的 OnDblClick 事件。
============================================================================== }
procedure TCB_IMGPSScanX.DblClickEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnDblClick;
end;
{ ==============================================================================
  方法名稱:DeactivateEvent
  引用相依:
  方法描述:觸發 COM 介面的 OnDeactivate 事件。
============================================================================== }
procedure TCB_IMGPSScanX.DeactivateEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnDeactivate;
end;
{ ==============================================================================
  方法名稱:DestroyEvent
  引用相依:_DelTree
  方法描述:銷毀元件時的清理工作。負責釋放大量的 TStringList 物件,包含各類資訊清
            單(表單、規則、註記、工作、影像路徑、條碼等)。針對特定模式(DSCAN/ESCAN),若
             ImagePath 不為空則刪除該目錄及其子目錄。最後觸發 COM 介面的 OnDestro
            y 事件。
============================================================================== }
procedure TCB_IMGPSScanX.DestroyEvent(Sender: TObject);
begin
  //********清單區********
  Doc_Inf_List.Free;  //Doc_Inf 清單   Docno + 版本為key
  DM_FORM_INF_List.Free;  //DM_FORM_INF 清單   Docno + 版本為key
  FORM_INF_List.Free; //FORM_INF的清單
  CHECK_RULE_INF_List.Free;  //CHECK_RULE_INF  清單
  MEMO_INF_List.Free;  //MEMO_INF 清單
  WORK_INF_List.Free;  //WORK_INF 清單
  LASTEST_FORM_INF_List.Free; // LASTEST_FORM_INF 清單
  FindResult.Free ;  //找SQLData的結果
  OMRFileList.Free;  //要OMR檢核的文件(只檢查每種Form的第一頁)
  FormCode_PageSize.Free; //文件的預設大小  FormCode_Height_Width
  DocNo_NeedDoc.Free; //有Docno時要相依的文件   DocNo_相依文件_相依文件
  DocNo_NoDoc.Free; //有Docno時互斥的文件   DocNo_互斥文件_互斥文件
  DocNo_VerinCase.Free; //案件裡的DocNo+版本的清單
  CaseDocNoList.Free;  //案件裡的DocNo清單
  CaseDocNo_CopiesList.Free; //案件裡的DocNo份數清單
  CaseList.Free;    //記錄掃瞄案件的順序
  NoSaveBarCodeList.Free; //不儲存的條碼清單
  FormID_List.Free;  //FormID清單
  DocNo_List.Free; //DocNo清單
  Context_DocnoList.Free; //案件裡的檔案Docno清單
  ContextList.Free; //案件裡的檔案清單
  AttContextList.Free; //案件裡的附加檔案清單
  NowShowFileList.Free;  //目前顯示的影像清單
  NowSelectFileList.Free; //目前被點選的影像清單
  Cust_DocNoList.Free; //自行定義文件名稱
  IN_WH_DocNoList.Free; //入庫的文件清單
  GuideFormIDList.Free; //要當導引頁表單清單
  DivPageFormIDList.Free; //要當分案頁表單清單
  LastInitFormidList.Free;
  LastAddFormidList.Free;
  SampleFormIDList.Free;
  ExistImgList.Free;
  reSizeExistImgList.Free;
  //********清單區********
  if (FMode = 'DSCAN') or (FMode = 'ESCAN')  then //重掃件及異動件要只能掃指定編號的件
  begin
    if ImagePath<>'' then
      _Deltree(ImagePath);
  end;
  if FEvents <> nil then FEvents.OnDestroy;
end;
{ ==============================================================================
  方法名稱:KeyPressEvent
  引用相依:
  方法描述:處理鍵盤按鈕事件,並將按鍵資訊傳遞至 COM 介面的 OnKeyPress 事件。
============================================================================== }
procedure TCB_IMGPSScanX.KeyPressEvent(Sender: TObject; var Key: Char);
var
  TempKey: Smallint;
begin
  TempKey := Smallint(Key);
  if FEvents <> nil then FEvents.OnKeyPress(TempKey);
  Key := Char(TempKey);
end;
{ ==============================================================================
  方法名稱:MouseEnterEvent
  引用相依:
  方法描述:當滑鼠進入元件時,觸發 COM 介面的 OnMouseEnter 事件。
============================================================================== }
procedure TCB_IMGPSScanX.MouseEnterEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnMouseEnter;
end;
{ ==============================================================================
  方法名稱:MouseLeaveEvent
  引用相依:
  方法描述:當滑鼠離開元件時,觸發 COM 介面的 OnMouseLeave 事件。
============================================================================== }
procedure TCB_IMGPSScanX.MouseLeaveEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnMouseLeave;
end;
{ ==============================================================================
  方法名稱:PaintEvent
  引用相依:
  方法描述:當元件需要重繪時,觸發 COM 介面的 OnPaint 事件。
============================================================================== }
procedure TCB_IMGPSScanX.PaintEvent(Sender: TObject);
begin
  if FEvents <> nil then FEvents.OnPaint;
end;
{ ==============================================================================
  方法名稱:ActiveFormCreate
  引用相依:
  方法描述:ActiveForm 建立時的初始化處理。發送啟動訊息、設定預設檢視模式並初始化
            影像顯示區域。遍歷所有影像捲軸盒(ISB),設定預設滑鼠模式為 mmUser 並將
            縮放模式設為全頁顯示,最後延遲啟動 Timer。
============================================================================== }
procedure TCB_IMGPSScanX.ActiveFormCreate(Sender: TObject);
var IScrollBox : TImageScrollBox;
    i          :integer;
begin
  {HotKeyId1 := GlobalAddAtom('MyHotKey1')-$C000;
  HotKeyId2 := GlobalAddAtom('MyHotKey2')-$C000;
  HotKeyId3 := GlobalAddAtom('MyHotKey3')-$C000;
  HotKeyId4 := GlobalAddAtom('MyHotKey4')-$C000;
  RegisterHotKey(handle,HotKeyId1,0,VK_UP);      //printscreen
  RegisterHotKey(handle,HotKeyId1,0,VK_Down);      //printscreen }
  PostMessage(Handle,WM_ACTIVATE,WA_CLICKACTIVE,0);
  vmode := 1;
  DesableImage;
  For i:= 1 to 8 do begin
    IScrollBox := TImageScrollBox( FindComponent('ISB'+IntToStr(i)));
    IScrollBox.MouseMode := mmUser;
    iScrollBox.ZoomMode := zmFullPage;
  end;
  Sleep(500);
  Timer1.Enabled := True;
end;
{ ==============================================================================
  方法名稱:HotKeyDown
  引用相依:
  方法描述:熱鍵按下處理程序,目前為空實作。
============================================================================== }
procedure TCB_IMGPSScanX.HotKeyDown (var Msg : TMessage);
begin
end;
{ ==============================================================================
  方法名稱:InitialLanguage
  引用相依:
  方法描述:元件多國語言初始化核心函式。讀取 Language.Lng 設定檔,根據指定的語系遞
            迴設定畫面上所有控制項(按鈕、選單、標籤、清單、群組框等)的 Caption 或 Hi
            nt 文字,實現介面語系動態切換。
============================================================================== }
procedure TCB_IMGPSScanX.InitialLanguage(Sender: TObject);
var
  ini : Tmeminifile;
  i,n : Integer;
  FormName : String;
  NowForm : TComponent;
begin
  if Sender is TActiveForm then
    NowForm := TActiveForm(Sender);
  if Sender is TForm then
    NowForm := TForm(Sender);
  FormName := NowForm.Name;
  IISUnit.IIS_LngfileName := LngPath+'Language.Lng';  //給IISUnit 轉多國語言字串用
  if FLanguage = '' then
    FLanguage := 'zh_tw';
  IISUnit.IIS_NowLng := FLanguage;
  ini := TMeminifile.Create(LngPath+'Language.Lng');
  try
    IF NowForm is TForm Then
      TForm(NowForm).Caption := ini.ReadString(FLanguage,FormName+'.FormTitle','');
    for i := 0 to NowForm.ComponentCount - 1 do
    begin
//ShowMessage(NowForm.Components[i].Name);
      if NowForm.Components[i] is TButton then
      begin
        TButton(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TButton(NowForm.Components[i]).Name,'');
        //TBitBtn(NowForm.Components[i]).Caption := ini.ReadString(FormName,TBitBtn(NowForm.Components[i]).Name,'');
        //TButton(NowForm.Components[i]).OnMouseEnter := BtnMouseEnter;
      end
      Else if NowForm.Components[i] is TBitBtn then
      begin
        TBitBtn(NowForm.Components[i]).Hint := ini.ReadString(FLanguage,FormName+'.'+TBitBtn(NowForm.Components[i]).Name,'');
        //TBitBtn(NowForm.Components[i]).Caption := ini.ReadString(FormName,TBitBtn(NowForm.Components[i]).Name,'');
        TBitBtn(NowForm.Components[i]).OnMouseEnter := BtnMouseEnter;
      end
      Else if NowForm.Components[i] is TMenuItem then
      begin
        if ini.ValueExists(FLanguage,FormName+'.'+TMenuItem(NowForm.Components[i]).Name) then
          TMenuItem(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TMenuItem(NowForm.Components[i]).Name,'');
      end
      Else if NowForm.Components[i] is TCheckBox then
      begin
        TCheckBox(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TCheckBox(NowForm.Components[i]).Name,'');
      end
      Else if NowForm.Components[i] is TPJMenuSpeedButton then
      begin
        TPJMenuSpeedButton(NowForm.Components[i]).Hint := ini.ReadString(FLanguage,FormName+'.'+TPJMenuSpeedButton(NowForm.Components[i]).Name,'');
      end
      Else if NowForm.Components[i] is TLabel then
      begin
        TLabel(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TLabel(NowForm.Components[i]).Name,'');
      end
      Else if NowForm.Components[i] is TGroupBox then
      begin
        TGroupBox(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TGroupBox(NowForm.Components[i]).Name,'');
      end
      Else if NowForm.Components[i] is TListView then
      begin
        for n := 0 to TListView(NowForm.Components[i]).Columns.Count - 1 do
        begin
          TListView(NowForm.Components[i]).Columns.Items[n].Caption := ini.ReadString(FLanguage,FormName+'.'+TListView(NowForm.Components[i]).Name+'_'+inttostr(n),'');
        end;
      end
      Else if NowForm.Components[i] is TRadioGroup then
      begin
        TRadioGroup(NowForm.Components[i]).Caption := ini.ReadString(FLanguage,FormName+'.'+TRadioGroup(NowForm.Components[i]).Name,'');
        for n := 0 to TRadioGroup(NowForm.Components[i]).Items.Count - 1 do
        begin
          TRadioGroup(NowForm.Components[i]).Items.Strings[n] := ini.ReadString(FLanguage,FormName+'.'+TRadioGroup(NowForm.Components[i]).Name+'_'+inttostr(n),'');
        end;
      end;
    end;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:Timer1Timer
  引用相依:FJpgCompression, GetLocalAppDir, Str2Dir, _DelTree, FileExists, init
            kscan
  方法描述:OCX 元件初始化的核心程序。負責從伺服器下載各類基礎資訊(業務、表單、文件
            、檢核規則、常用片語、系統參數等),並設定本地暫存路徑(ScanTemp)。針對異動
            或重掃模式,會自動建立空案件並下載既有影像。最後執行各類屬性與語系設定
            ,確保掃描環境就緒。
============================================================================== }
procedure TCB_IMGPSScanX.Timer1Timer(Sender: TObject);
var
  StampDate,StampTime : String;
  i: Integer;
begin
  Timer1.Enabled := False;
  //FIs_In_Wh:='Y'; /// test 記得關掉
  //FWH_category :='N';  // test 記得關掉
//  FImgDelete := 'Y'; //test 記得關掉
  //Showmessage('a');
  //self.FIs_OldCase := 'Y';
  PageLVclear := True;
  InitialOk := False;
  FMaxUploadSize:='10';
  FJpgCompression:=50;
  FFtpRootPath := '';  //影像平台沒有給FtpRoot目錄,會直接用FFtpExtraPath切換至指定目錄
  //FMode := 'DSCAN' ;
  //FIs_In_Wh := 'Y';
  if FIs_In_Wh = 'Y' then
    AttName := 'Attach'  //入庫附件
  else
    AttName := 'S_Attach'; //Smartlending 附件
//ShowMessage('1111111');
  if FMode = 'SAMPLESCAN' then
  begin
    NewScanBtn.Visible := False;
    PJLinkedMenuSpeedButton2.Visible := False;
    AddScanBtn.Visible := False;
    CheckCaseBtn.Visible := False;
    Panel18.Visible := False;
    TransBtn.Visible := False;
    FC6.Visible := False;
    SampleScanBtn.Visible := True;
    Panel1.Visible := True;
    Panel6.Visible := True;
    ScanDuplexCB.Visible := False; //雙面掃描
  end
  Else if (FMode = 'NSCAN') then
  begin
    Panel18.Visible := True;
    Panel1.Visible := True;
    Panel6.Visible := True;
    Panel21.Visible := True;
    Panel23.Visible := True;
    AttFileGB.Visible := True;
    Splitter2.Visible := True;
    ScanDuplexCB.Visible := True; //雙面掃描
  end
  Else if FMode = 'FSCAN' then
  begin
    Panel1.Visible := True;
    //Panel6.Visible := True;
  end
  Else
  begin
    Panel18.Visible := True;
    Panel1.Visible := True;
    Panel6.Visible := True;
    Panel21.Visible := True;
    Panel23.Visible := True;
    AttFileGB.Visible := True;
    Splitter2.Visible := True;
  end;
  DisplayMode(1,1,1,Panel9);
  Application.ProcessMessages;
  StatusBar1.Panels[0].Text := 'Ver'+GetCurrentVersionNo;
  StatusBar1.Panels[1].Text := 'Login User:'+FUserName;
  {$IFDEF Test}
    StatusBar1.Panels[0].Text := StatusBar1.Panels[0].Text+'(test)';
  {$ENDIF}
    StatusBar1.Panels[0].Text := StatusBar1.Panels[0].Text;
  if FPrintyn = 'Y' then
    PrtLB.Visible := True;
  initParameter;  //20170222 針對新加的parameter 作初始化參數
  InitScrollRec;
  If FUrl = '' then
  begin
    Showmessage(_Msg('URL cannot be empty,please contact system administrator'));
    Exit;
  end;
  if FUrl[length(FUrl)]<>'/' then
    FUrl := FUrl + '/';
  //20221028 把語言檔改放至 Local目錄裡,才不會有些文字來不及使用
  LngPath := GetLocalAppDir(Handle)+'MPS\CB_IMGPS\';
  Str2Dir(LngPath);
  ////下載語言檔/////  20170218 先拿調以便測試
  If not DownLanguage Then
  begin
    Showmessage('Language File error!!'+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
  InitialLanguage(Self);  //載入多國語言
  if FWork_no='' then
  begin
    Showmessage(_Msg('業務別不能為空白,請洽詢程式人員'));
    Exit;
  end;
  if CaseIDLength = 0 then
  begin
    Showmessage(_Msg('案件編號長度限制不能為空白,請洽詢程式人員'));
    //Exit;  //測試時不退出
  end;
  //********清單區********
  Doc_Inf_List := TStringList.Create;  //Doc_Inf 清單   Docno + 版本為key
  DM_FORM_INF_List := TStringList.Create;  //DM_FORM_INF 清單   Docno + 版本為key
  FORM_INF_List := TStringList.Create; //FORM_INF的清單
  CHECK_RULE_INF_List := TStringList.Create;  //CHECK_RULE_INF  清單
  MEMO_INF_List := TStringList.Create;  //MEMO_INF 清單
  WORK_INF_List := TStringList.Create;  //WORK_INF 清單
  LASTEST_FORM_INF_List := TStringList.Create;  // LASTEST_FORM_INF 清單
  FindResult := TStringlist.Create;  //找SQLData的結果
  OMRFileList := TStringList.Create; //要OMR檢核的文件(只檢查每種Form的第一頁)
  FormCode_PageSize := TStringList.Create; //文件的預設大小  FormCode_Height_Width
  DocNo_NeedDoc := TStringList.Create; //有Docno時要相依的文件   DocNo_相依文件_相依文件
  DocNo_NoDoc := TStringList.Create; //有Docno時互斥的文件   DocNo_互斥文件_互斥文件
  DocNo_VerinCase := TStringList.Create; //案件裡的DocNo+版本的清單
  CaseDocNoList := TStringlist.Create;  //案件裡的DocNo清單
  CaseDocNo_CopiesList := TStringlist.Create; //案件裡的DocNo份數清單
  CaseList := TStringList.Create;    //記錄掃瞄案件的順序
  Context_DocnoList := TStringlist.Create; //案件裡的檔案Docno清單
  ContextList := TStringlist.Create; //案件裡的檔案清單
  AttContextList := TStringlist.Create; //案件裡的附加檔案清單
  NoSaveBarCodeList := TStringlist.Create; //不儲存的條碼清單
  FormID_List := TStringlist.Create;  //FormID清單
  DocNo_List := TStringlist.Create; //DocNo清單
  NowShowFileList := TStringlist.Create;  //目前顯示的影像清單
  NowSelectFileList := TStringlist.Create; //目前被點選的影像清單
  Cust_DocNoList := TStringlist.Create; //自行定義的文件名稱
  IN_WH_DocNoList := TStringlist.Create; //入庫的文件清單
  GuideFormIDList := TStringlist.Create; //要當導引頁表單清單
  DivPageFormIDList := TStringList.Create; //要當分案頁表單清單
  LastInitFormidList :=TStringList.Create;
  LastAddFormidList := TStringList.Create;
  SampleFormIDList := TStringList.Create;//20170627 加入
  ExistImgList := TStringList.Create;  //20170724 新增
  reSizeExistImgList :=TStringList.Create; //20171012 新增
  //********清單區********
  ShowText := _Msg('資料載入中,請稍候');
  DataLoading(True,True);
  IF not GetServerDate Then
  begin
    Showmessage(_Msg('取主機時間時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
  if FMode='SAMPLESCAN' then
  begin
    IF not GetSampleInf Then  //取已存在sample
    begin
      Showmessage(_Msg('取存在範本資訊時,網路發生錯誤!!')+HttpErrStr);
      DataLoading(False,False);
      Exit;
    end;
  end;
//ShowMessage('GetServerDate  '+ServerDate+' , '+ServerTime);
  ////下載系統資訊////
  IF not GetSetInf1 Then  //取DOC_INF  文件資訊
  begin
    Showmessage(_Msg('取文件資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
//ShowMessage('GetSetInf1');
  //showmessage(self.Doc_Inf_List.Text);
  IF not GetSetInf2 Then  //取DM_FORM_INF     相依互斥資訊
  begin
    Showmessage(_Msg('取相依互斥資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
//ShowMessage('GetSetInf2');
  //Showmessage(self.Doc_Inf_List.Text);
  IF not GetSetInf3 Then   //取FORM_INF  表單資訊
  begin
    Showmessage(_Msg('取表單資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
//ShowMessage('GetSetInf3');
  IF not GetSetInf4 Then   //取CHECK_RULE_INF   檢核規則資訊
  begin
    Showmessage(_Msg('取檢核規則資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
  //showmessage(self.CHECK_RULE_INF_List.Text);
//ShowMessage('GetSetInf4');
  IF not GetSetInf5 Then   //取MEMO_INF   常用片語資訊
  begin
    Showmessage(_Msg('取常用片語資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
//ShowMessage('GetSetInf5');
  //showmessage(self.MEMO_INF_List.Text);
  IF not GetSetInf6 Then   //取WORK_INF   系統參數資訊
  begin
    Showmessage(_Msg('取系統參數資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
//ShowMessage('GetSetInf6');
  //showmessage(FORM_INF_List.Text);
  IF not GetSetInf7 Then   //取LASTES_FORM_INF   系統參數資訊
  begin
    Showmessage(_Msg('取最新版FORMID參數資訊時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
//ShowMessage('GetSetInf7');
  //Showmessage(LASTEST_FORM_INF_List.Text);
  SetFormID_DocNo;  //將FormID及Docno抽出塞入List裡  20130403增加
  SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
  GetDefScanIni; //取得掃描預設值及相關設定
  ////下載系統資訊/////
  if ImagePath = '' then
  begin
    Showmessage(_Msg('本機暫存路徑不得為空白'));
    DataLoading(False,False);
    Panel1.Enabled := False;
    Panel2.Enabled := False;
    Exit;
  end;
  initkscan;
  if ImagePath[Length(ImagePath)] <> '\' then
    ImagePath := ImagePath + '\';
//ShowMessage('ImagePath='+ImagePath);
  //CheckXmlPath := ImagePath+'OMRSITE\'+FWork_No;
  CheckXmlPath := ImagePath+'OMRSITE\';  // 20200612 發現影像平台是取回所有業務的設定,所以不能有業務別目錄
//ShowMessage('CheckXmlPath='+CheckXmlPath);
  //SitePath := ImagePath+'Site\'+FWork_No+'\';
  SitePath := ImagePath+'Site\';  // 20200612 發現影像平台是取回所有業務的設定,所以不能有業務別目錄
  //LngPath := ImagePath; //改放至上面取Local目錄
  SamplePath := ImagePath+'Sample\'+FWork_No+'\';
  ImagePath := ImagePath + 'Scantemp\';
//ShowMessage('AA  ImagePath='+ImagePath);
  ScaniniPath :=ImagePath+FWork_No+'\'+FUserUnit +'\';
//ShowMessage('ScaniniPath='+ScaniniPath);
  ImagePath := ImagePath + FWork_No+'\'+FUserUnit+'\'+FMode+'\';
  ImagePath := StringReplace(ImagePath, '\\', '\',[rfReplaceAll, rfIgnoreCase]);
//ShowMessage('BB  ImagePath='+ImagePath);
  ImageSavePath := ImagePath;
  str2dir(CheckXmlPath);
  str2dir(SitePath);
  str2dir(ImagePath);
  str2dir(SamplePath);
  Del_Sub_NothingPath(ImagePath);  //清掉案件目錄是空的
  LogFile1.LogFile:=LngPath+'IMGPSCheck.log';
  ReduceLogFile;
  LogFile1.LogToFile(logTimeString+'OCX取表data結束');
  ShowText := _Msg('資料載入中,請稍候');
  DataLoading(True,True);
//  if not CheckAvailable Then   //檢查授權  20170218 說不用了
//  begin
//    DataLoading(False,False);
//    Panel1.Enabled := False;
//    Panel2.Enabled := False;
//    Exit;
//  end;
//Button3Click(Self);
//ShowMessage('CheckAvailable');
  ShowText := _Msg('資料載入中,請稍候');
  DataLoading(True,True);
  StatusBar1.Panels[1].Text := _Msg('登入人員:')+FUserName;
  //FCaseID:='20150302180133';//測試用
  ////下載語言檔/////
//ShowMessage('OOOO');
  if (FMode = 'RSCAN')  or (FMode = 'DSCAN') or (FMode = 'ESCAN') or (FMode = 'FSCAN') then //重掃件及異動件要只能掃指定編號的件
  begin
    _Deltree(ImagePath);
    str2dir(ImagePath);
    ImageSavePath := ImagePath;
    str2dir(ImageSavePath);
    MkDir(ImageSavePath+FCaseID);
    CreateEmptyCase(ImageSavePath,FCaseID);
    MkDir(ImageSavePath+FCaseID+'\Download');
    IF (FMode = 'ESCAN') or (FMode = 'DSCAN') then  //異動件先下載影像
    begin
      ShowText := _Msg('案件下載中,請稍候');
      DataLoading(True,True);
      If not DownLoadImage(ImageSavePath+FCaseID+'\Download\',FCaseID) Then
      begin
        Showmessage(FCaseID+_msg('載入異動影像時,網路發生錯誤')+DownFileErrStr);
        DataLoading(False,False);
        Exit;
      end;
      {If not Down_Img(ImageSavePath+FCaseID+'\Download\',FCaseID) then
      begin
        Showmessage(FCaseID+_msg('載入異動影像時,網路發生錯誤')+HttpErrStr);
        DataLoading(False,False);
        Exit;
      end;}
//Showmessage(ImageSavePath+FCaseID+'\Download\'+#10#13+ImageSavePath+FCaseID+'\');
      Download2Case(ImageSavePath+FCaseID+'\Download\',ImageSavePath+FCaseID+'\');
//Showmessage('aaa');
      //Download2Case('C:\Users\Hong\Downloads\沒有括號\',ImageSavePath+FCaseID+'\');
      if (FIs_OldCase = 'Y') then
      begin
        if (FWork_no='HLN') then
          ErrFormtoCurrentForm(FCaseID,'10000001011112A','11000001011112A');  //換掉錯的FormID
        //if not FileExists(ImageSavePath+FCaseID+'\CaseDocNo_Copies.dat') then   //這個會在Download2Case時一律產生所以不能有這行 20141013
        OldCasetoNewCase(FCaseID);
        //ErrFormtoCurrentForm(FCaseID,'11B00005011312A','11000001011112A');  //換掉錯的FormID
        //LoadImgFile;
      end;
//      if (FIs_OldCase = 'Y') and (FWork_no='HLN') then   //77版的
//      begin
//        ErrFormtoCurrentForm(FCaseID,'10000001011112A','11000001011112A');  //換掉錯的FormID
//        if not FileExists(ImageSavePath+FCaseID+'\CaseDocNo_Copies.dat') then
//          OldCasetoNewCase(FCaseID);
//        //ErrFormtoCurrentForm(FCaseID,'11B00005011312A','11000001011112A');  //換掉錯的FormID
//        //LoadImgFile;
//      end;
      Create_Cust_DocDir(FCaseID); //產生外面傳入的文件
      if FMode='ESCAN' then
        LastInitFormidListCreate(ImageSavePath+FCaseID+'\Download\');
    end;
  end;
//ShowMessage('GetOMRCheckSet前');
  ////下載檢核XML//////
  IF not GetOMRCheckSet Then
  begin
    Showmessage(_Msg('下載檢核定位檔案時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
  ////下載檢核XML/////
//ShowMessage('GetOMRCheckSet後來');
  ////下載登打設定/////
  IF not GetKeyinSet Then
  begin
    Showmessage(_Msg('下載登打定位檔案時,網路發生錯誤!!')+HttpErrStr);
    DataLoading(False,False);
    Exit;
  end;
  ////下載登打設定/////
//ShowMessage('GetKeyinSet');
  if ScanDenialHint <> '' then   //有設定提示字串就秀在右上角
  begin
    DenialTimeLb.Visible := True;
    DenialTimeLb.Caption := Format(ScanDenialHint,[ScanDenialTime]);
  end;
//ShowMessage(IntToStr(ScanDpi));
  R_W_Scanini('R'); //掃瞄設定的ini
//ShowMessage(IntToStr(ScanDpi));
//ShowMessage('停掉DataLoading');
//DataLoading(False,False);
  ScanDuplexCB.Checked := ScanDuplex;
  if FMode <> 'SAMPLESCAN' then
    LoadImgFile;
  if (FMode = 'RSCAN') or (FMode = 'ESCAN') or (FMode = 'FSCAN') then
  begin
    if TreeView1.Items.Count > 0 then
    begin
      TreeView1.Selected := NewTreeNode.Item[0];
      TreeView1click(self);
    end;
  end;
  InitialOk := True;
  {AttFileGB.Visible := True; //附加電子檔窗  //20120207楊玉說不在這加電子檔先拿掉
  Splitter2.Visible := True;
  AttFileGB.Visible := False; //附加電子檔窗
  Splitter2.Visible := False; }
//ShowMessage('ImageSavePath='+ImageSavePath);
  DataLoading(False,False);
  LogFile1.LogToFile(logTimeString+'OCX初始化結束');
  LogFile1.LogToFile(logTimeString+'FUrl='+FUrl+
    ',FCaseID='+FCaseID+
    ',FMode='+FMode+
    ',FModeName='+FModeName+
    ',FWork_no='+FWork_no+
    ',FUserID='+FUserID+
    ',FUserName='+FUserName+
    ',FUserUnit='+FUserUnit+
    ',FData='+FData+
    ',FVerify='+FVerify+
    ',FReWrite='+FReWrite+
    ',FLanguage='+FLanguage+
    ',FLoanDoc_Value='+FLoanDoc_Value+
    ',FLoanDoc_Enable='+FLoanDoc_Enable+
    ',FUseProxy='+FUseProxy+
    ',FC_DocNoList='+FC_DocNoList+
    ',FC_DocNameList='+FC_DocNameList+
    ',FFixFileList='+FFixFileList+
    ',FIs_In_Wh='+FIs_In_Wh+
    ',FOldCaseInfo='+FOldCaseInfo+
    ',FPrintyn='+FPrintyn+
    ',FIs_OldCase='+FIs_OldCase+
    ',FCustDocYN='+FCustDocYN);
  LogFile1.LogToFile(logTimeString+'FImgDPI='+IntToStr(FImgDPI)+
    ',FScanColor='+    IntToStr(FScanColor)+
    ',FFileSizeLimit='+  IntToStr(FFileSizeLimit)+
    ',FCaseNoLength='+ IntToStr(FCaseNoLength)+
    ',FImgDelete='+FImgDelete+
    ',FIsExternal='+FIsExternal+
    ',FWH_category='+FWH_category+
    ',FCheck_main_form='+FCheck_main_form+
    ',FMaxUploadSize='+FMaxUploadSize);
end;
{ ==============================================================================
  方法名稱:Timer2Timer
  引用相依:
  方法描述:處理進度條或提示文字的動態點點動畫。每觸發一次就會在 ShowText 後方增
            加一個點,模擬載入中的視覺效果。
============================================================================== }
procedure TCB_IMGPSScanX.Timer2Timer(Sender: TObject);
begin
  IF Panel22.Caption = ShowText+'......' Then
    Panel22.Caption := ShowText
  Else
    Panel22.Caption := Panel22.Caption + '.';
  Application.ProcessMessages;
end;
reassemble/CB_IMGPSScanImp.listMgr.pas
比對新檔案
@@ -0,0 +1,38 @@
{ ==============================================================================
  方法名稱:SetFormID_DocNo
  引用相依:
  方法描述:提取 FORM_INF_List 中的 FormID 與 DocNo 欄位至獨立清單。
============================================================================== }
Procedure TCB_IMGPSScanX.SetFormID_DocNo; //將FormID及Docno抽出來另存入list裡    20130403增加
var
  i : Integer;
begin
  for i := 1 to FORM_INF_List.Count-1 do
  begin
    FormID_List.Add(GetSQLData(FORM_INF_List,'T1.FORM_ID',i));
    DocNo_List.Add(GetSQLData(FORM_INF_List,'T1.DOC_NO',i));
  end;
end;
{ ==============================================================================
  方法名稱:SetIn_WH_DocNo
  引用相依:
  方法描述:提取所有入庫屬性(IS_IN_WH)為 'Y' 的文件編號至清單。
============================================================================== }
Procedure TCB_IMGPSScanX.SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
var
  i : Integer;
begin
  for i := 1 to Doc_Inf_List.Count - 1 do
  begin
    if GetSQLData(Doc_Inf_List,'IS_IN_WH',i) = 'Y' then
      IN_WH_DocNoList.Add(GetSQLData(Doc_Inf_List,'DOC_NO',i));
  end;
  {Showmessage(IN_WH_DocNoList.Text);
  StringtoFile(IN_WH_DocNoList.Text,'D:\121.txt');}
end;
reassemble/CB_IMGPSScanImp.misc.pas
比對新檔案
@@ -0,0 +1,171 @@
{ ==============================================================================
  方法名稱:GetCurrentVersionNo
  引用相依:
  方法描述:獲取當前模組的版本號。透過 GetModuleFileName 獲取檔案路徑,再利用 GetF
            ileVersionInfoSize 和 GetFileVersionInfo 讀取版本資訊。接著從 VarFile
            Info\Translation 取得語系資訊,最後從 StringFileInfo 中提取 FileVersi
            on 並回傳為字串。
============================================================================== }
function TCB_IMGPSScanX.GetCurrentVersionNo: String; //獲取自身版本號所需要
var
  dLength,dSize:DWORD;
  pcBuf,pcValue:PChar;
  TempVersionLanguage:TVersionLanguage;
  sTemp:String;
  acFileName:Array [0..255] of Char;
begin
  Result:='';
  GetModuleFileName(HInstance,acFileName,SizeOf(acFileName)-1);
  dSize:=GetFileVersionInfoSize(acFileName,dSize);
  if dSize=0 then Exit;
  pcBuf:=AllocMem(dSize);
  GetFileVersionInfo(acFileName,0,dSize,pcBuf);
  if VerQueryValue(pcBuf, PChar('\VarFileInfo\Translation'),Pointer(pcValue),dLength) then
  begin
    for TempVersionLanguage := vlArabic to vlUnknown do
      if LoWord(Longint(Pointer(pcValue)^)) = LanguageValues[TempVersionLanguage] then Break;
    sTemp:=IntToHex(MakeLong(HiWord(Longint(Pointer(pcValue)^)),LoWord(Longint(Pointer(pcValue)^))), 8);
    if VerQueryValue(pcBuf,PChar('StringFileInfo\'+sTemp+'\FileVersion'),Pointer(pcValue),dLength) then
      Result:=StrPas(pcValue);
  end;
  FreeMem(pcBuf,dSize);
end;
{ ==============================================================================
  方法名稱:WMMOUSEWHEEL
  引用相依:
  方法描述:處理滑鼠滾輪事件。根據滾輪捲動方向(WHEEL_DELTA)對 ScrollBox1 或當前顯
            示的影像捲軸盒(DisplayISB)進行垂直捲動(SB_Lineup 或 SB_LINEDOWN)。若
            同時按下特定鍵(message.Keys=50),則會調整影像的縮放百分比(ZoomPercent
            )。此外也會遍歷所有影像捲軸盒元件並對取得焦點的元件執行捲動操作。
============================================================================== }
procedure TCB_IMGPSScanX.WMMOUSEWHEEL(var message: TWMMouseWheel);
var
  I: Integer;
  iISB : TImageScrollBox;
begin
    inherited;
    //lb1.Caption:=IntToStr(message.Keys);
    if (message.WheelDelta = WHEEL_DELTA) Then
    begin
      if ScrollBox1.Focused then
      begin
        ScrollBox1.VertScrollBar.Increment := 50;
        ScrollBox1.Perform(WM_VSCROLL,SB_Lineup,0);
      end;
      if DisplayISB <> nil then
      begin
        if (DisplayISB.Focused) and (message.Keys=0) then
        begin
           DisplayISB.VertScrollBar.Increment := 50;
           DisplayISB.Perform(WM_VSCROLL,SB_Lineup,0);
        end;
        if (DisplayISB.Focused) and (message.Keys=50) then
        begin
          DisplayISB.ZoomMode := zmPercent;
          if DisplayISB.ZoomPercent < 90 then
            DisplayISB.ZoomPercent := DisplayISB.ZoomPercent+10;
        end;
      end;
      i:=0;
      while FindComponent(ISBName+inttostr(i)) <> nil do
      begin
        iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
        if iISB.Focused then
        begin
          ScrollBox1.VertScrollBar.Increment := 50;
          ScrollBox1.Perform(WM_VSCROLL,SB_Lineup,0);
        end;
        inc(i);
      end;
    end
    else if (message.WheelDelta = -WHEEL_DELTA) then
    begin
      if ScrollBox1.Focused then
      begin
        ScrollBox1.VertScrollBar.Increment := 50;
        ScrollBox1.Perform(WM_VSCROLL, SB_LINEDOWN, 0);
      end;
      if DisplayISB <> nil then
      begin
        if (DisplayISB.Focused) and (message.Keys=0) then
        begin
           DisplayISB.VertScrollBar.Increment := 50;
           DisplayISB.Perform(WM_VSCROLL,SB_LINEDOWN,0);
        end;
        if (DisplayISB.Focused) and (message.Keys=50) then
        begin
          DisplayISB.ZoomMode := zmPercent;
          if DisplayISB.ZoomPercent > 10 then
            DisplayISB.ZoomPercent := DisplayISB.ZoomPercent-10;
        end;
      end;
      i:=0;
      while FindComponent(ISBName+inttostr(i)) <> nil do
      begin
        iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
        if iISB.Focused then
        begin
          ScrollBox1.VertScrollBar.Increment := 50;
          ScrollBox1.Perform(WM_VSCROLL,SB_Lineup,0);
        end;
        inc(i);
      end;
    end;
end;
{ ==============================================================================
  方法名稱:InitExistImgList
  引用相依:LoadFromFile, LoadFileGetMD5
  方法描述:初始化已存在的影像清單。讀取案件路徑下 Download\Context.dat 的檔案內
            容,計算每個檔案的 MD5 雜湊值並存入 ExistImgList,同時將處理過程記錄至
            日誌檔。
============================================================================== }
procedure TCB_IMGPSScanX.InitExistImgList(casepath: String);
var
  ST1,ST2,ST3,ST4:TStringList;
  i,j,k:Integer;
begin
  ST1:=TStringList.Create;
  ST2:=TStringList.Create;
  ST3:=TStringList.Create;
  ExistImgList.Clear;
  ST1.LoadFromFile(casepath+'Download\Context.dat');
  for I := 0 to ST1.Count - 1 do
  begin
LogFile1.LogToFile(logTimeString+casepath+'Download\'+ST1.Strings[i]+',MD5='+LoadFileGetMD5(casepath+'Download\'+ST1.Strings[i]));
    ExistImgList.Add(LoadFileGetMD5(casepath+'Download\'+ST1.Strings[i])) ;
  end;
LogFile1.LogToFile(logTimeString+'ExistImgList.text'+ExistImgList.CommaText);
  ST1.Free;
  ST2.Free;
  ST3.Free;
end;
reassemble/CB_IMGPSScanImp.omr.pas
比對新檔案
@@ -0,0 +1,980 @@
{ ==============================================================================
  方法名稱:CheckRule2OMRErrInfo
  引用相依:
  方法描述:將檢核規則清單(CHECK_RULE_INF_List)中的資料轉換為內部的 OMRErrInfo R
            ecord 陣列,設定各項規則的顯示類型(Display)、是否可忽略(Ignore)及提示
            訊息與掃瞄模式。
============================================================================== }
Procedure TCB_IMGPSScanX.CheckRule2OMRErrInfo;   //檢核規則填入OMRErrINFo Record
var i : Integer;
    CheckNo : String;
begin
  for I := 1 to 11 do
  begin
    CheckNo := Add_Zoo(i,3);
    if FindSQLData(CHECK_RULE_INF_List,'MESG_SHOW_TYPE,MESG_DISP_TYPE,CHECK_MESG,SCAN_MODE','CHECK_NO',CheckNo,0,FindResult) then
    begin
      if GetFindResult('MESG_SHOW_TYPE') = '1' then
        OMRErrInfo[i].Display := True  //顯示
      Else if GetFindResult('MESG_SHOW_TYPE') = '2' then
        OMRErrInfo[i].Display := False; //不顯示
      if GetFindResult('MESG_DISP_TYPE') = '1' then
        OMRErrInfo[i].Ignore := True    //可忽略
      Else if GetFindResult('MESG_DISP_TYPE') = '2' then
        OMRErrInfo[i].Ignore := False;  //不可忽略
      OMRErrInfo[i].Info := GetFindResult('CHECK_MESG');
      OMRErrInfo[i].Mode := GetFindResult('SCAN_MODE');
    end;
  end;
end;
{ ==============================================================================
  方法名稱:DistinctFormCode
  引用相依:LoadFromFile, LoadFileGetMD5
  方法描述:從案件的 Context.dat 檔案中提取不重複的表單代碼(FormCode)並存入 OMRF
            ileList。程序會遍歷上傳目錄下的所有檔案,檢查檔案是否存在且未被處理過。
            接著比對 OMRFileList 中已有的表單代碼,若為新出現的表單代碼且檔案有效
            ,則將其加入清單中,用於後續 OMR 處理。
============================================================================== }
Procedure TCB_IMGPSScanX.DistinctFormCode(CaseID:String); //從案件裡的FormCode取出第一頁
var
  i,n : Integer;
  LForm,OForm : String;
  Addok : Boolean;
  S : TStringlist;
begin
  S := TStringlist.Create;
  try
    S.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');
    for i := 0 to S.Count - 1 do
    begin
LogFile1.LogToFile(logTimeString+S.Strings[i]+' ISExistImg='+BoolToStr(ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[i]),true));
LogFile1.LogToFile(logTimeString+S.Strings[i]+' reSizeExistImgList='+BoolToStr(reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))<>-1,true));
      if FWH_category='N' then
      begin
        if (ISExistImg(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))
        or  (reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))<>-1)  then
        begin
          Continue;
        end;
      end;
      LForm := FileName2FormCode(S.Strings[i]);
      AddOk := True;
      for n := 0 to OMRFileList.Count - 1 do
      begin
        OForm := FileName2FormCode(OMRFileList.Strings[n]);
        if (LForm <> '') and (LForm = OForm) then
        begin
          AddOk := False;
          Break;
        end;
      end;
      if AddOk then
      begin
        OMRFileList.Add(S.Strings[i]);
      end;
    end;
  finally
  S.Free;
  end;
end;
{ ==============================================================================
  方法名稱:OMRCheckCase
  引用相依:ImageReSize_FormID, GetSiteOMR, FindPoint, LoadFromFile, FileExists,
             SaveToFile
  方法描述:執行案件的自動化 OMR 規則檢核,這是確保掃瞄案件合規性的核心邏輯。程序
            流程:
            1. 初始化檢核日誌。
            2. 識別主文件並驗證必要文件是否缺漏、相依與互斥文件是否衝突、以及表單
            是否已停用。
            3. 檢查各文件類型是否超過預設的最大頁數。
            4. 針對案件內每張影像,執行十字定位點縮放 (ImageReSize_FormID) 後,載
            入對應表單的 XML 規則檔。
            5. 執行欄位級檢核,包含必填項 (settype1)、跨文件欄位關聯 (settype3/set
            type8)、相依文件需求 (settype4) 及備註填寫要求 (settype6) 等。
            6. 將所有檢核失敗原因紀錄至 Checkerr.ini。最終返回案件是否通過所有檢
            核規則。
============================================================================== }
Function TCB_IMGPSScanX.OMRCheckCase(CaseID:String):Boolean; //OMR檢核
var
  i,n,m,v,v1 : Integer;
  XT,RelaXT,ValueXT : TXmltool;
  OMRFormCode,OMRFile,OMRFormName,ColEName,ColCName,Site : String;
  Pixel : Integer;
  RelaFormCode,RelaFile,RelaFormName,RelaColEName,RelaColCName,RelaSite : String;
  RelaDocNo,RelaDocName : string;
  RelaPixel : Integer;
  s : String;
  nodename : String;
  OMROK : Boolean;
  CaseOk : Boolean;
  ErrStr : String;
  SiteRec,RelaSiteRec : String;  //多組位置記錄
  OMRValue : String;
  MainFormID,MainDocNo,MainVersion : String; //主FormID
  MainFormPage,CaseFormPage : Integer;  //主要文件需要的頁數
  NeedDocNoStr,NoDocNoStr : String; //相依 互斥文件字串
  List : TStringlist;
  FormCode : String;
  FormDataPages : Integer;
  NoSite : Boolean; //未定位
  Anchor,Anchor1 : String;
  OMROkCount : Integer;
  //Casecheck : Boolean;  //是否要做檢核
  //AllCheck : Boolean;  //是否要做完整檢核
  ISB8W,ISB8H:integer;
begin
  ///OMRErrInfo  1: 必要文件  2:相依文件 3:互斥文件  4:必填 5:欄位有值附文件  6:欄位有值不附文件
  ///            7: 欄位有值相關欄位也要有值  8:欄位有值要寫備註 9:停用日期 10:最大頁數
  //Casecheck := True;
  //Allcheck := True;
  //if (FMode = 'ISCAN') then
    //Allcheck := False;
  CaseOk := True;
  //if Casecheck then
  //begin
    DeleteFile(ImageSavePath+CaseID+'\upload\Checkerr.ini');
    DeleteFile(ImageSavePath+CaseID+'\upload\CheckMemo.dat');
    //DeleteFile(ImageSavePath+CaseID+'\upload\ReSize.dat');
    DeleteFile(ImageSavePath+CaseID+'\upload\RemoveMemo.dat');
    DeleteFile(ImageSavePath+CaseID+'\upload\OMRCheckOk.dat');
    Memo1.Lines.Clear;
    OMRFileList.Clear;
    MainFormID := GetCaseFormID(ImageSavePath+CaseID+'\upload\');
    List := TStringlist.Create;
    try
      //if AllCheck then
      //begin
        if GetCasePage(ImageSavePath,CaseID) =0 then
        begin
        end;
//ShowMessage('MainFormID='+MainFormID);
LogFile1.LogToFile(logTimeString+' '+FModeName+' '+CaseID+' '+'MainFormID='+MainFormID);
        if MainFormID = ''then
        begin
          //20131203 yuu說不檢查這個,先拿掉   20170315 楷琳說未歸類要擋  20170726 因此有檢查必要FormID  所以 可以拿掉
          {if FCheck_main_form='Y' then
          begin
            if (FMode <> 'SSCAN') AND (FMode<>'ESCAN') then  //簽署章件會換主FormID,先跳過 20170629 ESCAN 也不檢查
            begin
              ErrStr:=_Msg('找不到分案文件');   //找不到主文件
              OMRErr2ini(CaseID,ErrStr,'','','','','','',False,False,True);
              CaseOk := false;
//ShowMessage('AAAAA');
            end;
          end;
          }
        end
        Else
        begin
          //////主要非主要文件//////
          DistinctDocinCase(ImageSavePath+CaseID+'\upload\');
//ShowMessage(DocNo_VerinCase.Text);
//DocNo_VerinCase.Add('31A00101_1706A');
LogFile1.LogToFile(logTimeString+' '+CaseID+' '+'DocNo_VerinCase.Text='+DocNo_VerinCase.Text);
          if ModeNeedCheck(OMRErrInfo[1].Mode,FMode) then //是否要檢核
          begin
            for i := 0 to DocNo_VerinCase.Count - 1 do
            begin
              v := Pos('_', DocNo_VerinCase.Strings[i]);
              v1 := length(DocNo_VerinCase.Strings[i]);
              MainDocNo := Copy(DocNo_VerinCase.Strings[i],1,v-1); //FormCode2DocNo(MainFormID);
              MainVersion :=Copy(DocNo_VerinCase.Strings[i],v+1,v1-v); //FormCode2Version(MainFormID);
              MainFormPage := GetDataDocNoPage(MainDocNo,MainVersion); //資料庫記錄主文件頁數
              CaseFormPage := CheckCaseDocNoPage(CaseID,MainDocNo,MainVersion,MainFormPage); //案件主文件的頁數
LogFile1.LogToFile(logTimeString+CaseID+',MainDocNo='+MainDocNo+',MainVersion='+MainVersion+',MainFormPage='+IntToStr(MainFormPage)+',CaseFormPage='+IntToStr(CaseFormPage));
              //CheckFirstDocNoPage
              IF (MainFormPage > 0) and (MainFormPage <> CaseFormPage) then
              begin
                ErrStr:=MainDocNo+Format(OMRErrInfo[1].Info,[Inttostr(MainFormPage),Inttostr(CaseFormPage)]); //主要文件需有XX頁僅附XX頁
                OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[1].Ignore,OMRErrInfo[1].Display);
                if OMRErrInfo[1].Display then
                  CaseOk := false;
              end;
            end;
          end;
          //////主要非主要文件/////
//showmessage(MainFormID);
          MainDocNo := FormCode2DocNo(MainFormID);
          MainVersion := FormCode2Version(MainFormID);
          if FindSQLData(DM_FORM_INF_List,'DEPE_FORM_ID,MUTEX_FORM_ID','MAIN_FORM_ID,DOC_VERSION',MainDocNo+','+MainVersion,0,FindResult) then
          begin
            NeedDocNoStr := GetFindResult('DEPE_FORM_ID');
            NoDocNoStr := GetFindResult('MUTEX_FORM_ID');
          end
          Else if FindSQLData(DM_FORM_INF_List,'DEPE_FORM_ID,MUTEX_FORM_ID','MAIN_FORM_ID,DOC_VERSION',MainDocNo+','+MainVersion,0,FindResult) then
          begin
            NeedDocNoStr := GetFindResult('DEPE_FORM_ID');
            NoDocNoStr := GetFindResult('MUTEX_FORM_ID');
          end;
          //////相依文件/////
          if ModeNeedCheck(OMRErrInfo[2].Mode,FMode) then //是否要檢核
          begin
            List.CommaText := NeedDocNoStr;
            for I := 0 to List.Count - 1 do
            begin
              if not Case_DocNoExists(CaseID,List.Strings[i]) then  //沒附相依文件
              begin
                if FWH_category='N' then
                begin
                  if ISExistImg(ImageSavePath+CaseID+'\upload\'+List.Strings[i]) then
                  begin
                    Continue;
                  end;
                end;
                ErrStr:=Format(OMRErrInfo[2].Info,[DocNo2DocName(CaseID,List.Strings[i])]);   //沒附相依文件
                OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[2].Ignore,OMRErrInfo[2].Display);
                if OMRErrInfo[2].Display then
                  CaseOk := false;
              end;
            end;
          end;
          //////相依文件/////
          //////互斥文件/////
          if ModeNeedCheck(OMRErrInfo[3].Mode,FMode) then //是否要檢核
          begin
            List.CommaText := NoDocNoStr;
            for I := 0 to List.Count - 1 do
            begin
              if Case_DocNoExists(CaseID,List.Strings[i]) then  //附了互斥文件
              begin
                if FWH_category='N' then
                begin
                  if ISExistImg(ImageSavePath+CaseID+'\upload\'+List.Strings[i]) then
                  begin
                    Continue;
                  end;
                end;
                ErrStr:=Format(OMRErrInfo[3].Info,[DocNo2DocName(CaseID,List.Strings[i])]);   //有附互斥文件
                OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[3].Ignore,OMRErrInfo[3].Display);
                if OMRErrInfo[3].Display then
                  CaseOk := false;
              end;
            end;
          end;
          //////互斥文件/////
        end; //MainFormID結束
      //end;
      List.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');
      for i := 0 to List.Count - 1 do
      begin
        FormCode := FileName2FormCode(List.Strings[i]);
        /////未歸類///
        {IF FormCode = 'Attach' Then   //20140211 yuu說不檢查了
        begin
          ErrStr:=_Msg('尚有文件未歸類');
          OMRErr2ini(CaseID,ErrStr,'','','','','','',False,False,True);
          CaseOk := false;
        end; }
        /////未歸類//////
        /////未註冊文件/////
        {IF not FormIDExists(FormCode,False) then  //未註冊文件
        begin
          ErrStr:=FormCode+_Msg('不為此業務的表單代碼');
          OMRErr2ini(CaseID,ErrStr,'','','','',False,False,True);
          CaseOk := false;
        end }
        /////未註冊文件/////
        //////停用文件//
        {Else} IF ModeNeedCheck(OMRErrInfo[9].Mode,FMode) and (not FormIDExists(FormCode,True,0)) and (not checkFormCodeIsCustom(ImageSavePath + CaseID+'\upload\',FormCode)) then  //有停用的文件
        begin
//ShowMessage('AAAA');
          ErrStr:=Format(OMRErrInfo[9].Info,[FormCode2FormName(CaseID,FormCode)]);   //有停用文件
          OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[9].Ignore,OMRErrInfo[9].Display);
//ShowMessage('ErrStr='+ErrStr);
          if OMRErrInfo[9].Display then
            CaseOk := false;
        end;
        //////停用文件////
      end;
    finally
      List.Free;
    end;
    //if AllCheck then
    //begin
      //////最大頁數///
LogFile1.LogToFile(logTimeString+'最大頁數A段 '+CaseID+' '+'OMRFileList.Text='+OMRFileList.Text);
      DistinctFormCode(CaseID);
      if ModeNeedCheck(OMRErrInfo[10].Mode,FMode) then //是否要檢核
      begin
//ShowMessage('AAA'+OMRFileList.Text);
LogFile1.LogToFile(logTimeString+'最大頁數B段 '+CaseID+' '+'OMRFileList.Text='+OMRFileList.Text);
        For i := 0 to OMRFileList.Count - 1 do
        begin
          if FModeName=_Msg('異動件') then Continue;
          if FWH_category='N' then
          begin
            if ISExistImg(ImageSavePath+CaseID+'\upload\'+OMRFileList.Strings[i]) then
            begin
              Continue;
            end;
          end;
          FormCode := FileName2FormCode(OMRFileList.Strings[i]);
          FormDataPages := GetDataFormCodePages(FormCode);
          IF (FormCode <> '') and (FormDataPages > 0) and (FindFormCodePages(CaseID,FormCode) > FormDataPages) then  //有超過最大頁數的文件
          begin
            ErrStr:=Format(OMRErrInfo[10].Info,[FormCode2FormName(CaseID,FormCode),inttostr(FormDataPages)]);   //有超過最大頁數文件
            OMRErr2ini(CaseID,ErrStr,'','','','','','',False,OMRErrInfo[10].Ignore,OMRErrInfo[10].Display);
            if OMRErrInfo[10].Display then
              CaseOk := false;
          end;
        end;
      end;
      /////最大頁數/////
    //end;
    ImageScrollBox1.FileName := '';
    //if FWork_No = 'CW' then   //理賠就不做下面的檢核了
    //begin
      //////OMR檢核///////
      ContextList.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
      DistinctFormCode(CaseID);
      ValueXT := TXmltool.Create;
      Try
//ShowMessage('必填'+OMRFileList.Text);
LogFile1.LogToFile(logTimeString+'必填 '+CaseID+' '+'OMRFileList.Text='+OMRFileList.Text);
        For i := 0 to OMRFileList.Count - 1 do
        begin
//ShowMessage('OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
          if CheckRequiredColumnValues(FWork_NO,CaseID) then Continue;
          OMRFile := OMRFileList.Strings[i];
          OMRFormCode := FileName2FormCode(OMRFileList.Strings[i]);
          OMRFormName := FormCode2FormName(CaseID,OMRFormCode);
          Anchor := FormID2Anchor(OMRFormCode);
          ///依十字定位點縮放////
          ImageReSize_FormID(CaseID,OMRFile);
          ////依十字定位點縮放///
//Display1.Lines.Add('OMRFile='+OMRFile+',OMRFormCode='+OMRFormCode+',OMRFormName='+OMRFormName);
LogFile1.LogToFile(logTimeString+'OMRFile='+OMRFile+',OMRFormCode='+OMRFormCode+',OMRFormName='+OMRFormName);
//ShowMessage('KKKKK');
          if not FileExists(CheckXmlPath+FWork_no+'\'+OMRFormCode+'.xml') then  //沒有Xml就不用檢核
            Continue;
//ShowMessage('11638 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
          XT := TXmltool.Create(CheckXmlPath+FWork_no+'\'+OMRFormCode+'.xml');
          RelaXT := TXmltool.Create;
//ShowMessage('ModeNeedCheck='+BoolToStr(ModeNeedCheck(OMRErrInfo[4].Mode,FMode),true));
          try
            //*******必填********
            if ModeNeedCheck(OMRErrInfo[4].Mode,FMode) then //是否要檢核
            begin
              if XT.SubNodes['/form/settype1/'].First then
              Repeat
                OMROK := False;
                SiteRec := ''; //清掉
                ColEName := XT.SubNodes['/form/settype1/'].NodeName;
                ColCName := XT.Node['/form/settype1/'+ColEName+'/'].Attributes['coldesc'];
                ColCName := Copy(ColCName,1,length(ColCName)-6);
                if XT.SubNodes['/form/settype1/'+ColEName+'/'].First then
                Repeat
                  nodename := XT.SubNodes['/form/settype1/'+ColEName+'/'].NodeName;
                  If nodename <> '@coldesc' then
                  begin
                    Pixel := Strtoint(XT.Node['/form/settype1/'+ColEName+'/'+nodename+'/'].Attributes['pixel']);
                    Site := XT.Node['/form/settype1/'+ColEName+'/'+nodename+'/'].Attributes['colxy'];
                    if SiteRec= '' then   //記錄位置
                      SiteRec := Site
                    else
                      SiteRec := SiteRec+'@'+Site;
                    //有填就ok
                    //Showmessage(ColCName +','+ inttostr(OMRMpsV1.GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site))+','+inttostr(Pixel + SafePixel));
//SafePixel:=90000;
Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
//FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,ANCHOR);
                    if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel)  then
                    begin
                      //Showmessage('oh');
                      OMROK := True;
                      Break;
                    end;
                  end
                  Else
                  begin
                    //ColCName := XT['/form/settype1/'+ColEName+'/'+nodename+'/'];
                  end;
                Until not XT.SubNodes['/form/settype1/'+ColEName+'/'].Next;
                if not OMROk then
                begin
                  ErrStr:=Format(OMRErrInfo[4].Info,[ColCName]);   //XX欄位未填寫
                  OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[4].Ignore,OMRErrInfo[4].Display);
                  if OMRErrInfo[4].Display then
                    CaseOk := false;
                end;
              Until not XT.SubNodes['/form/settype1/'].Next ;
            end;
            //*******必填********
//ShowMessage('11692 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
            //if AllCheck then
            //begin
            //*******有值相關文件的欄位也要有值*******
            if ModeNeedCheck(OMRErrInfo[7].Mode,FMode) then //是否要檢核
            begin
              if XT.SubNodes['/form/settype3/'].First then
              Repeat
                SiteRec := '';
                RelaSiteRec := '';
                ColEName := XT.SubNodes['/form/settype3/'].NodeName;
                ColCName := XT.Node['/form/settype3/'+ColEName+'/'].Attributes['coldesc'];
                ColCName := Copy(ColCName,1,length(ColCName)-6);
                Site := XT.Node['/form/settype3/'+ColEName+'/'].Attributes['colxy'];
                if SiteRec= '' then   //記錄位置
                  SiteRec := Site
                else
                  SiteRec := SiteRec+'@'+Site;
                Pixel := XT.Node['/form/settype3/'+ColEName+'/'].Attributes['pixel'];
Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
                begin
                  ////有填寫////
                  if XT.SubNodes['/form/settype3/'+ColEName+'/'].First then
                  Repeat
                    RelaSiteRec := '';
                    nodename := XT.SubNodes['/form/settype3/'+ColEName+'/'].NodeName;
                    If (nodename <> '@coldesc') and (not XT.SubNodes['/form/settype3/'+ColEName+'/'].NodeIsAttr) then
                    begin
                      RelaFormCode := XT.node['/form/settype3/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
                      RelaColEName := XT.node['/form/settype3/'+ColEName+'/'+nodename+'/'].Attributes['rela_col_name'];
                      RelaColCName := XT.node['/form/settype3/'+ColEName+'/'+nodename+'/'].Attributes['relacoldesc'];
                      RelaColCName := Copy(RelaColCName,1,length(RelaColCName)-6);
                      RelaFile := FormCode2FileName(RelaFormCode,ContextList);
                      RelaFormName := FormCode2FormName(CaseID,RelaFormCode);
                      Anchor1 := FormID2Anchor(RelaFormCode);
                      RelaXT.LoadFromFile(CheckXmlPath+FWork_no+'\'+RelaFormCode+'.xml');
Display1.Lines.Add(RelaFile+','+RelaFormName);
//ShowMessage(RelaFile);
//ShowMessage(ImageSavePath+CaseID+'\upload\'+RelaFile);
                      if RelaFile<>'' then
                      begin
                        ISB8.LoadFromFile(ImageSavePath+CaseID+'\upload\'+RelaFile,1); //20170815
                        ISB8W:= ISB8.Graphic.Width;
                        ISB8H:= ISB8.Graphic.Height;
                        FindPoint(ISB8.Graphic,UpLPoint,UpRPoint,DownLPoint,ISB8W,ISB8H,ANCHOR);  //20170815  抓相關然欄位所在圖檔的定位
                      end;
                      OMROK := False;
                      //OMROK := False;
                      //if RelaXT.SubNodes['/form/settype2/'].First then
                      //Repeat
                        NoSite := True;
                        if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Count >0 then
                          NoSite := False;
                        if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].First then
                        Repeat
                          nodename := RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].NodeName;
                          If nodename <> '@coldesc' then
                          begin
                            RelaPixel := Strtoint(RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['pixel']);
                            RelaSite := RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['colxy'];
                            if RelaSiteRec= '' then   //記錄位置
                              RelaSiteRec := RelaSite
                            else
                              RelaSiteRec := RelaSiteRec+'@'+RelaSite;
                            if  FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
                            begin
Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                              if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSite,Bt) > (RelaPixel + SafePixel)  then
                              begin
                                OMROK := True;
                                Break;
                              end;
                              ///依十字定位點縮放////
                              ImageReSize_FormID(CaseID,OMRFile); //20170815 重新抓定位
                              ////依十字定位點縮放////
                            end;
                          end;
                        Until not RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Next;
                        if not OMROk then
                        begin
                          if not FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
                            ErrStr:=Format(OMRErrInfo[7].Info,[ColCName,RelaColCName])+'('+_msg('未附')+RelaFormName+')'   //XX欄位填寫時,XX欄位未填寫
                          Else if NoSite then
                            ErrStr:=Format(OMRErrInfo[7].Info,[ColCName,RelaColCName])+'('+_msg('未定位')+')'
                          Else
                            ErrStr:=Format(OMRErrInfo[7].Info,[ColCName,RelaColCName]);   //XX欄位填寫時,XX欄位未填寫
                          OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSiteRec,Anchor,Anchor1,False,OMRErrInfo[7].Ignore,OMRErrInfo[7].Display);
                          if OMRErrInfo[7].Display then
                            CaseOk := false;
                        end;
                      //Until not RelaXT.SubNodes['/form/settype2/'].Next ;
                    end;
                  Until not XT.SubNodes['/form/settype3/'+ColEName+'/'].Next;
                end;
              Until not XT.SubNodes['/form/settype3/'].Next ;
            end;
            //*******有值相關文件的欄位也要有值*******
//ShowMessage('11788 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
            //*******有值相關文件的欄位不能有值*******
            if ModeNeedCheck(OMRErrInfo[11].Mode,FMode) then //是否要檢核
            begin
              if XT.SubNodes['/form/settype8/'].First then
              Repeat
                SiteRec := '';
                RelaSiteRec := '';
                OMROkCount := 0;
                ColEName := XT.SubNodes['/form/settype8/'].NodeName;
                ColCName := XT.Node['/form/settype8/'+ColEName+'/'].Attributes['coldesc'];
                ColCName := Copy(ColCName,1,length(ColCName)-6);
                Site := XT.Node['/form/settype8/'+ColEName+'/'].Attributes['colxy'];
                if SiteRec= '' then   //記錄位置
                  SiteRec := Site
                else
                  SiteRec := SiteRec+'@'+Site;
                Pixel := XT.Node['/form/settype8/'+ColEName+'/'].Attributes['pixel'];
Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
                begin
                  ////有填寫// //
                  inc(OMROkCount);
                end;
                if XT.SubNodes['/form/settype8/'+ColEName+'/'].First then
                Repeat
                  RelaSiteRec := '';
                  nodename := XT.SubNodes['/form/settype8/'+ColEName+'/'].NodeName;
                  If (nodename <> '@coldesc') and (not XT.SubNodes['/form/settype8/'+ColEName+'/'].NodeIsAttr) then
                  begin
                    RelaFormCode := XT.node['/form/settype8/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
                    RelaColEName := XT.node['/form/settype8/'+ColEName+'/'+nodename+'/'].Attributes['rela_col_name'];
                    RelaColCName := XT.node['/form/settype8/'+ColEName+'/'+nodename+'/'].Attributes['relacoldesc'];
                    RelaColCName := Copy(RelaColCName,1,length(RelaColCName)-6);
                    RelaFile := FormCode2FileName(RelaFormCode,ContextList);
                    RelaFormName := FormCode2FormName(CaseID,RelaFormCode);
                    Anchor1 := FormID2Anchor(RelaFormCode);
                    RelaXT.LoadFromFile(CheckXmlPath+FWork_no+'\'+RelaFormCode+'.xml');
                    if RelaFile<>'' then
                    begin
                      ISB8.LoadFromFile(ImageSavePath+CaseID+'\upload\'+RelaFile,1); //20170815
                      ISB8W:= ISB8.Graphic.Width;
                      ISB8H:= ISB8.Graphic.Height;
                      FindPoint(ISB8.Graphic,UpLPoint,UpRPoint,DownLPoint,ISB8W,ISB8H,ANCHOR);  //20170815  抓相關然欄位所在圖檔的定位
                    end;
                    OMROK := False;
                    //OMROK := False;
                    //if RelaXT.SubNodes['/form/settype2/'].First then
                    //Repeat
                      NoSite := True;
                      if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Count >0 then
                        NoSite := False;
                      if RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].First then
                      Repeat
                        nodename := RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].NodeName;
                        If nodename <> '@coldesc' then
                        begin
                          RelaPixel := Strtoint(RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['pixel']);
                          RelaSite := RelaXT.Node['/form/settype2/'+RelaColEName+'/'+nodename+'/'].Attributes['colxy'];
                          if RelaSiteRec= '' then   //記錄位置
                            RelaSiteRec := RelaSite
                          else
                            RelaSiteRec := RelaSiteRec+'@'+RelaSite;
                          if  FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
                          begin
Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                            if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSite,Bt) > (RelaPixel + SafePixel)  then
                            begin
                              inc(OMROkCount);
                              //OMROK := True;
                              //Break;
                            end;
                            ///依十字定位點縮放////
                            ImageReSize_FormID(CaseID,OMRFile);
                            ////依十字定位點縮放////
                          end;
                        end;
                        //Else
                        //begin
                          //ColCName := XT['/form/settype1/'+ColEName+'/'+nodename+'/'];
                        //end;
                      Until not RelaXT.SubNodes['/form/settype2/'+RelaColEName+'/'].Next;
                      if OMROkCount > 1  then
                      begin
                        if not FileExists(ImageSavePath+CaseID+'\upload\'+RelaFile) then
                          ErrStr:=Format(OMRErrInfo[11].Info,[ColCName,RelaColCName])+'('+_msg('未附')+RelaFormName+')'   //XX欄位填寫時,XX欄位也填寫
                        Else if NoSite then
                          ErrStr:=Format(OMRErrInfo[11].Info,[ColCName,RelaColCName])+'('+_msg('未定位')+')'
                        Else
                          ErrStr:=Format(OMRErrInfo[11].Info,[ColCName,RelaColCName]);   //XX欄位填寫時,XX欄位也填寫
                        OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,ImageSavePath+CaseID+'\upload\'+RelaFile,RelaSiteRec,Anchor,Anchor1,False,OMRErrInfo[7].Ignore,OMRErrInfo[7].Display);
                        if OMRErrInfo[11].Display then
                          CaseOk := false;
                      end;
                    //Until not RelaXT.SubNodes['/form/settype2/'].Next ;
                  end;
                Until not XT.SubNodes['/form/settype8/'+ColEName+'/'].Next;
              Until not XT.SubNodes['/form/settype8/'].Next ;
            end;
            //*******有值相關文件的欄位不能有值*******
//ShowMessage('11889 OMRFileList.Strings['+IntToStr(i)+']'+OMRFileList.Strings[i]);
              //*******有值相依文件*******
            if ModeNeedCheck(OMRErrInfo[5].Mode,FMode) then //是否要檢核
            begin
              if XT.SubNodes['/form/settype4/'].First then
              Repeat
                SiteRec := '';
                RelaSiteRec := '';
                ColEName := XT.SubNodes['/form/settype4/'].NodeName;
                ColCName := XT.Node['/form/settype4/'+ColEName+'/'].Attributes['coldesc'];
                ColCName := Copy(ColCName,1,length(ColCName)-6);
                Site := XT.Node['/form/settype4/'+ColEName+'/'].Attributes['colxy'];
                if SiteRec= '' then   //記錄位置
                  SiteRec := Site
                else
                  SiteRec := SiteRec+'@'+Site;
                Pixel := XT.Node['/form/settype4/'+ColEName+'/'].Attributes['pixel'];
 Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
                begin
                  ////有填寫////
                  if XT.SubNodes['/form/settype4/'+ColEName+'/'].First then
                  Repeat
                    nodename := XT.SubNodes['/form/settype4/'+ColEName+'/'].NodeName;
                    If (nodename <> 'coldesc') and (not XT.SubNodes['/form/settype4/'+ColEName+'/'].NodeIsAttr) then
                    begin
                      {RelaFormCode := XT.Node['/form/settype4/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
                      RelaFile := FormCode2FileName(RelaFormCode);
                      RelaFormName := FormCode2FormName(RelaFormCode); }
                      RelaDocNo := XT.Node['/form/settype4/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
                      RelaFile := DocNo2FileName(RelaDocNo,ContextList);
                      RelaDocName := XT.Node['/form/settype4/'+ColEName+'/'+nodename+'/'].Attributes['relaformname'];
                      if RelaFile='' then
                      begin
                        ErrStr:=Format(OMRErrInfo[5].Info,[ColCName,RelaDocName]);   //XX文件XX欄位填寫時,需附XX文件
                        OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[5].Ignore,OMRErrInfo[5].Display);
                        if OMRErrInfo[5].Display then
                          CaseOk := false;
                      end;
                    end;
                  Until not XT.SubNodes['/form/settype4/'+ColEName+'/'].Next;
                end;
              Until not XT.SubNodes['/form/settype4/'].Next ;
            end;
              //*******有值相依文件*******
              //*******有值互斥文件*******
            if ModeNeedCheck(OMRErrInfo[6].Mode,FMode) then //是否要檢核
            begin
              if XT.SubNodes['/form/settype5/'].First then
              Repeat
                SiteRec := '';
                RelaSiteRec := '';
                ColEName := XT.SubNodes['/form/settype5/'].NodeName;
                ColCName := XT.Node['/form/settype5/'+ColEName+'/'].Attributes['coldesc'];
                ColCName := Copy(ColCName,1,length(ColCName)-6);
                Site := XT.Node['/form/settype5/'+ColEName+'/'].Attributes['colxy'];
                if SiteRec= '' then   //記錄位置
                  SiteRec := Site
                else
                  SiteRec := SiteRec+'@'+Site;
                Pixel := XT.Node['/form/settype5/'+ColEName+'/'].Attributes['pixel'];
 Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
                begin
                  ////有填寫////
                  if XT.SubNodes['/form/settype5/'+ColEName+'/'].First then
                  Repeat
                    nodename := XT.SubNodes['/form/settype5/'+ColEName+'/'].NodeName;
                    If (nodename <> 'coldesc') and (not XT.SubNodes['/form/settype5/'+ColEName+'/'].NodeIsAttr) then
                    begin
                      {RelaFormCode := XT.Node['/form/settype5/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
                      RelaFile := FormCode2FileName(RelaFormCode);
                      RelaFormName := FormCode2FormName(RelaFormCode);}
                      RelaDocNo := XT.Node['/form/settype5/'+ColEName+'/'+nodename+'/'].Attributes['relaformid'];
                      RelaFile := DocNo2FileName(RelaDocNo,ContextList);
                      RelaDocName := XT.Node['/form/settype5/'+ColEName+'/'+nodename+'/'].Attributes['relaformname'];
                      if RelaFile<>'' then //有附   20130604看到(='')改的(未測)
                      begin
                        ErrStr:=Format(OMRErrInfo[6].Info,[ColCName,RelaDocName]);   //XX文件XX欄位填寫時,不能附XX文件
                        OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[6].Ignore,OMRErrInfo[6].Display);
                        if OMRErrInfo[6].Display then
                          CaseOk := false;
                      end;
                    end;
                  Until not XT.SubNodes['/form/settype5/'+ColEName+'/'].Next;
                end;
              Until not XT.SubNodes['/form/settype5/'].Next ;
            end;
              //*******有值互斥文件*******
              //*******有值寫備註*******
            if ModeNeedCheck(OMRErrInfo[8].Mode,FMode) then //是否要檢核
            begin
              if XT.SubNodes['/form/settype6/'].First then
              Repeat
                SiteRec := '';
                ColEName := XT.SubNodes['/form/settype6/'].NodeName;
                ColCName := XT.Node['/form/settype6/'+ColEName+'/'].Attributes['coldesc'];
                ColCName := Copy(ColCName,1,length(ColCName)-6);
                Site := XT.Node['/form/settype6/'+ColEName+'/'].Attributes['colxy'];
                Pixel := XT.Node['/form/settype6/'+ColEName+'/'].Attributes['pixel'];
                if SiteRec= '' then   //記錄位置
                  SiteRec := Site
                else
                  SiteRec := SiteRec+'@'+Site;
 Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel) then
                begin
                  ////有填寫////
                  if not FileExists(ImageSavePath+CaseID+'ScanMemo.dat') then
                  begin
                    ErrStr:=Format(OMRErrInfo[8].Info,[ColCName]);   //XX文件XX欄位填寫時,需寫備註
                    OMRErr2ini(CaseID,ErrStr,ImageSavePath+CaseID+'\upload\'+OMRFile,SiteRec,'','',Anchor,Anchor1,False,OMRErrInfo[8].Ignore,OMRErrInfo[8].Display);
                    if OMRErrInfo[8].Display then
                      CaseOk := false;
                  end;
                end;
              Until not XT.SubNodes['/form/settype6/'].Next ;
            end;
              //*******有值寫備註*******
              //*******OMR帶值********
              if XT.SubNodes['/form/settype7/'].First then
              Repeat
                ColEName := XT.SubNodes['/form/settype7/'].NodeName;
                ValueXT['/content/'+ColEName+'/@savevalue'] := '';  //先給預設空白
                if XT.SubNodes['/form/settype7/'+ColEName+'/'].First then
                Repeat
                  nodename := XT.SubNodes['/form/settype7/'+ColEName+'/'].NodeName;
                  If nodename <> '@coldesc' then
                  begin
                    Pixel := Strtoint(XT.Node['/form/settype7/'+ColEName+'/'+nodename+'/'].Attributes['pixel']);
                    Site := XT.Node['/form/settype7/'+ColEName+'/'+nodename+'/'].Attributes['colxy'];
                    OMRValue := XT.Node['/form/settype7/'+ColEName+'/'+nodename+'/'].Attributes['getvalue'];
                    //有填就ok
 Display1.Lines.Add(ColEName+' '+ColCName+'   圖像實際點數='+IntToStr(GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt))+' 設定點數='+IntToStr( (Pixel + SafePixel)));
                    if GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site,Bt) > (Pixel + SafePixel)  then
                    begin
                      ValueXT['/content/'+ColEName+'/@savevalue'] := OMRValue;  //有填就換成設定的值
                      Break;
                    end;
                  end;
                Until not XT.SubNodes['/form/settype7/'+ColEName+'/'].Next;
              Until not XT.SubNodes['/form/settype7/'].Next ;
              //*******OMR帶值********
            //end;
          Finally
          if (OMRValue <> '') then
            ValueXT.SaveToFile(ImageSavePath+CaseID+'/GetValue.xml');
          XT.Free;
          RelaXT.Free;
          end;
        end;
        //必填迴圈結束
      Finally
      ValueXT.Free;
      end;
    //end;
  //end;
  Result := CaseOk;
end;
{ ==============================================================================
  方法名稱:OMRErr2ini
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:紀錄 OMR 檢核失敗的詳細資訊。方法根據 Display 旗標決定紀錄方式:若為 T
            rue,則在案件目錄下的 Checkerr.ini 中建立新的錯誤序號區段,詳細紀錄失
            敗原因、檔案路徑、OMR 座標點、關聯檔案及定位點類型,用於後續 UI 呈現;若
            為 False,則僅將錯誤原因字串附加於 CheckMemo.dat 純文字日誌中,作為背
            景紀錄之用。
============================================================================== }
Procedure TCB_IMGPSScanX.OMRErr2ini(CaseID,Reason,FileName,Site,RelaFileName,RelaSite,Anchor,Anchor1:String;Del,Ingnore,Display:Boolean); //OMR檢核失敗寫入ini
var
  ini : Tinifile;
  Errcount : Integer;
  S : TStringlist;
begin
  if Display then
  begin
    ini := Tinifile.Create(ImageSavePath + CaseID+'\upload\Checkerr.ini');
    try
      Errcount := ini.ReadInteger('OMRCount','Count',0);  //透過Errcount來對應
      inc(ErrCount);
      ini.WriteString(inttostr(ErrCount),'Reason',Reason);
      ini.WriteBool(inttostr(ErrCount),'Ingnore',Ingnore);
      ini.writeString(inttostr(ErrCount),'FileName',FileName);
      ini.WriteString(inttostr(ErrCount),'Site',Site);
      ini.WriteString(inttostr(ErrCount),'RelaFileName',RelaFileName);
      ini.WriteString(inttostr(ErrCount),'RelaSite',RelaSite);
      ini.WriteString(inttostr(ErrCount),'Anchor',Anchor);
      ini.WriteString(inttostr(ErrCount),'RelaAnchor',Anchor1);
      ini.WriteBool(inttostr(ErrCount),'Del',Del);
      ini.WriteInteger('OMRCount','Count',ErrCount);
    finally
    ini.Free;
    end;
  end
  Else
  begin
    S := TStringlist.Create;
    try
      if FileExists(ImageSavePath + CaseID+'\CheckMemo.dat') then
        S.LoadFromFile(ImageSavePath + CaseID+'\CheckMemo.dat');
      S.Add(Reason);
      S.SaveToFile(ImageSavePath + CaseID+'\CheckMemo.dat');
    finally
    S.Free;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:OMRErrini2List
  引用相依:
  方法描述:將檢核失敗紀錄從 INI 設定檔載入至 UI 介面。方法會讀取 Checkerr.ini,遍
            歷所有錯誤紀錄,並過濾掉已標記為刪除 (Del) 的項目。將符合條件的錯誤原
            因填入 ErrlistForm 中的 ListView 元件,供使用者查看與修正。若清單中仍
            存在錯誤,會同步停用介面上的上傳按鈕以防止不合規案件送出。
============================================================================== }
Procedure TCB_IMGPSScanX.OMRErrini2List(CaseID:String;ErrlistForm:TErrlistForm); //OMR檢核失敗從ini寫入ListView
var
  ini : Tinifile;
  Errcount : Integer;
  Del : Boolean;
  i : Integer;
begin
  ini := Tinifile.Create(ImageSavePath + CaseID+'\upload\Checkerr.ini');
  try
    Errcount := ini.ReadInteger('OMRCount','Count',0);
    for i := 1 to ErrCount do
    begin
      Del := ini.ReadBool(inttostr(i),'Del',False); //是否被移除了
      if Not Del then
      begin
        With ErrlistForm.ErrListLV.Items.Add do
        begin
          Caption := ini.ReadString(inttostr(i),'Reason','');
          SubItems.Add(inttostr(i));
        end;
      end;
    end;
    if Errlistform.ErrListLV.Items.Count > 0 then
      Errlistform.ImmediateBt.Enabled := False;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:OMRErrini2List
  引用相依:
  方法描述:將 OMR 檢核失敗的記錄從 Checkerr.ini 讀取並顯示在 ListView 中。程序會
            開啟指定案件目錄下的設定檔,讀取錯誤總數後逐一檢查每筆記錄是否已被移
            除(Del 標記)。若記錄有效,則將錯誤原因及索引值新增至傳入的 ErrlistForm
             中的 ErrListLV 列表。
============================================================================== }
Procedure TCB_IMGPSScanX.OMRErrini2List(CaseID:String;ErrlistForm:TErrlistForm); //OMR檢核失敗從ini寫入ListView
var
  ini : Tinifile;
  Errcount : Integer;
  Del : Boolean;
  i : Integer;
begin
  ini := Tinifile.Create(ImageSavePath + CaseID+'\upload\Checkerr.ini');
  try
    Errcount := ini.ReadInteger('OMRCount','Count',0);
    for i := 1 to ErrCount do
    begin
      Del := ini.ReadBool(inttostr(i),'Del',False); //是否被移除了
      if Not Del then
      begin
        With ErrlistForm.ErrListLV.Items.Add do
        begin
          Caption := ini.ReadString(inttostr(i),'Reason','');
          SubItems.Add(inttostr(i));
        end;
      end;
    end;
    if Errlistform.ErrListLV.Items.Count > 0 then
      Errlistform.ImmediateBt.Enabled := False;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:OMRErrini2ListForLog
  引用相依:LoadFromFile
  方法描述:彙整系統中所有活動案件的 OMR 檢核錯誤訊息。方法讀取全域的 CaseList.da
            t,依次遍歷每個案件子目錄下的 Checkerr.ini,收集所有未被移除的錯誤原因
            ,並將其合併為一個完整的文字區塊返回。此功能主要用於產生系統運行日誌,
            方便追蹤與審查多案件的檢核狀態。
============================================================================== }
function TCB_IMGPSScanX.OMRErrini2ListForLog(CaseID: String): String;
var
  ini : Tinifile;
  Errcount : Integer;
  Del : Boolean;
  i,j : Integer;
  ST,CaseList:TStringList;
begin
  Result:='';
  //CaseList.dat
  ST:=TStringList.Create;
  CaseList:=TStringList.Create;
  CaseList.LoadFromFile(ImageSavePath+'CaseList.dat');
  for I := 0 to CaseList.Count - 1 do
  begin
    ini := Tinifile.Create(ImageSavePath + CaseList.Strings[i]+'\upload\Checkerr.ini');
    try
      Errcount := ini.ReadInteger('OMRCount','Count',0);
      for j := 1 to ErrCount do
      begin
        Del := ini.ReadBool(inttostr(j),'Del',False); //是否被移除了
        if Not Del then
        begin
          ST.Add(ini.ReadString(inttostr(j),'Reason','')) ;
        end;
      end;
    finally
    ini.Free;
    end;
  end;
  Result:=ST.Text;
  ST.Free;
  CaseList.Free;
end;
reassemble/CB_IMGPSScanImp.prUpload.pas
比對新檔案
@@ -0,0 +1,800 @@
{ ==============================================================================
  方法名稱:CreateCaseNeedData
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:掃描案件目錄下的 Context.dat 影像清單,自動推導並產生該案件所需的 Doc
            Dir.dat、CaseDocNo.dat 及份數清單,用於修復或重建案件結構。
============================================================================== }
Procedure  TCB_IMGPSScanX.CreateCaseNeedData(Path:String);
var
  FileList,DocNoList,CaseDocNoList,CaseDocNo_CopiesList : TStringlist;
  i,n : Integer;
  Docno : String;
  Exists : Boolean;
begin
  FileList := TStringlist.Create;
  DocNoList := TStringlist.Create;
  CaseDocNoList := TStringlist.Create;
  CaseDocNo_CopiesList := TStringlist.Create;
  try
    if FileExists(Path+'Context.dat') then
    begin
      FileList.LoadFromFile(Path+'Context.dat');
      for i := 0 to FileList.Count - 1 do
      begin
        Docno := FormCode2DocNo(FileName2FormCode(FileList.Strings[i]));
//ShowMessage('Docno='+Docno);
        DocNoList.Add(DocNo);
        Exists := False;
        for n := 0 to CaseDocNoList.Count - 1 do
        begin
          if Docno = CaseDocNoList.Strings[n] then
            Exists := True;
        end;
        if not Exists then
        begin
          CaseDocNoList.Add(DocNo);
          CaseDocNo_CopiesList.Add('1');
        end;
      end;
//ShowMessage('CreateCaseNeedData  DocNoList='+DocNoList.Text);
      DocNoList.SaveToFile(Path+'DocDir.dat');
      CaseDocNoList.SaveToFile(Path+'CaseDocNo.dat');
      CaseDocNo_CopiesList.SaveToFile(Path+'CaseDocNo_Copies.dat')
    end;
  finally
  FileList.Free;
  DocNoList.Free;
  CaseDocNoList.Free;
  CaseDocNo_CopiesList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:Case2upload
  引用相依:DirectoryExists, _DelTree, Str2Dir, CopyFile, FileExists, LoadFromFi
            le, SaveToFile
  方法描述:準備案件上傳用的資料夾結構。將分散在各文件子目錄下的影像檔案複製到單
            一的 Upload 目錄下並重新編號檔名,同時產生彙整後的索引檔與附件。
============================================================================== }
Procedure TCB_IMGPSScanX.Case2upload(CaseID:String);
var
  i,n:Integer;
  OldPath,NewPath,DocDir : String;
  OldFile,NewFile,AttFile : String;
  DocNoList,FileList:TStringlist;
  iFileList,iFile_DocNoList :TStringlist;
  iDocDirList : TStringlist;
  iAttFileList : TStringlist;
begin
  DocNoList := TStringlist.Create;
  FileList := TStringlist.Create;
  iFileList := TStringlist.Create;
  iFile_DocNoList := TStringlist.Create;
  iDocDirList := TStringlist.Create;
  iAttFileList := TStringlist.Create;
  try
    OldPath := ImageSavePath+CaseID+'\';
    NewPath := ImageSavePath+CaseID+'\Upload\';
    if DirectoryExists(NewPath) then
      _DelTree(NewPath);
    str2dir(NewPath);
    CopyFile(PWideChar(OldPath+'CaseDocNo.dat'),PWideChar(NewPath+'CaseDocNo.dat'),False);
    CopyFile(PWideChar(OldPath+'CaseDocNo_Copies.dat'),PWideChar(NewPath+'CaseDocNo_Copies.dat'),False);
    CopyFile(PWideChar(OldPath+'CustomDocNo.ini'),PWideChar(NewPath+'CustomDocNo.ini'),False);
    CopyFile(PWideChar(OldPath+'CaseIndex.dat'),PWideChar(NewPath+'CaseIndex.dat'),False);
    CopyFile(PWideChar(OldPath+'In_Wh.dat'),PWideChar(NewPath+'In_Wh.dat'),False);
    CopyFile(PWideChar(OldPath+'UseCase.ini'),PWideChar(NewPath+'UseCase.ini'),False);
    if FileExists(OldPath+'CaseDocNo.dat') then
    begin
      DocNoList.LoadFromFile(OldPath+'CaseDocNo.dat');
    end
    else
    begin
      DocNoList.SaveToFile(OldPath+'CaseDocNo.dat');
      CopyFile(PWideChar(OldPath+'CaseDocNo.dat'),PWideChar(NewPath+'CaseDocNo.dat'),False);
    end;
    for i := 0 to DocNoList.Count-1 do
    begin
      DocDir := DocNoList.Strings[i];
      OldPath := ImageSavePath+CaseID+'\'+ DocDir+'\';
      FileList.Clear;
      if FileExists(OldPath+'Context.dat') then
      begin
        FileList.LoadFromFile(OldPath+'Context.dat');
        for n := 0 to FileList.Count - 1 do
        begin
          OldFile := FileList.Strings[n];
          NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
          CopyFile(PWideChar(OldPath+OldFile),PWideChar(NewPath+NewFile),False);
          iFileList.Add(NewFile);
          iFile_DocNoList.Add(DocNoDir2DocNo(DocDir));
          iDocDirList.Add(DocDir);
        end;
      end;
    end;
    if DirectoryExists(ImageSavePath+CaseID+'\Attach') then
    begin
      DocDir := 'Attach';
      OldPath := ImageSavePath+CaseID+'\'+ DocDir+'\';
      FileList.Clear;
      if FileExists(OldPath+'Context.dat') then
      begin
        FileList.LoadFromFile(OldPath+'Context.dat');
        for n := 0 to FileList.Count - 1 do
        begin
          OldFile := FileList.Strings[n];
          NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
          CopyFile(PWideChar(OldPath+OldFile),PWideChar(NewPath+NewFile),False);
          iFileList.Add(NewFile);
          iFile_DocNoList.Add(DocNoDir2DocNo(DocDir));
          iDocDirList.Add(DocDir);
        end;
      end;
    end;
    if DirectoryExists(ImageSavePath+CaseID+'\S_Attach') then
    begin
      DocDir := 'S_Attach';
      OldPath := ImageSavePath+CaseID+'\'+ DocDir+'\';
      FileList.Clear;
      if FileExists(OldPath+'Context.dat') then
      begin
        FileList.LoadFromFile(OldPath+'Context.dat');
        for n := 0 to FileList.Count - 1 do
        begin
          OldFile := FileList.Strings[n];
          NewFile := Add_Zoo(iFileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
          CopyFile(PWideChar(OldPath+OldFile),PWideChar(NewPath+NewFile),False);
          iFileList.Add(NewFile);
          iFile_DocNoList.Add(DocNoDir2DocNo(DocDir));
          iDocDirList.Add(DocDir);
        end;
      end;
    end;
    OldPath := ImageSavePath+CaseID+'\';
    if FileExists(OldPath+'AttContext.dat') then
    begin
      iAttFileList.LoadFromFile(OldPath+'AttContext.dat');
      for n := 0 to iAttFileList.Count - 1 do
      begin
        AttFile := iAttFileList.Strings[n];
        CopyFile(PWideChar(OldPath+AttFile),PWideChar(NewPath+AttFile),False);
      end;
      iAttFileList.SaveToFile(NewPath+'AttContext.dat');
    end;
    iFileList.SaveToFile(NewPath+'Context.dat');
    iFile_DocNoList.SaveToFile(NewPath+'Context_DocNo.dat');
    iDocDirList.SaveToFile(NewPath+'DocDir.dat');
  finally
  iFileList.Free;
  iAttFileList.Free;
  iFile_DocNoList.Free;
  DocNoList.Free;
  FileList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:Download2Case
  引用相依:FileExists, CopyFile, LoadFromFile, DirectoryExists, SaveToFile
  方法描述:將下載或匯入的案件結構還原回本系統的多層級目錄結構。包含建立文件子目
            錄、檔案複製並重新編號、以及重建各類索引與份數設定檔。
============================================================================== }
Procedure TCB_IMGPSScanX.Download2Case(SoDir,DeDir:String);
var
  i,n : Integer;
  DocDir:String;
  OldFile,NewFile,AttFile:String;
  DocNoList,FileList : TStringlist;
  iFileList,iFile_DocDirList :TStringlist;
  iAttFileList :TStringlist;
  AA,AA2,AA3,AA4:Boolean;
begin
  if (not FileExists(SoDir+'CaseDocNo.dat')) or (not FileExists(SoDir+'DocDir.dat')) then   //截畫面會沒這些檔
  begin
//ShowMessage('產生必要的文字檔');
    CreateCaseNeedData(SoDir);   //產生必要的文字檔
  end;
  AA:=CopyFile(PWideChar(SoDir+'CaseDocNo.dat'),PWideChar(DeDir+'CaseDocNo.dat'),False);
  AA2:=CopyFile(PWideChar(SoDir+'CaseDocNo_Copies.dat'),PWideChar(DeDir+'CaseDocNo_Copies.dat'),False);
  AA3:=CopyFile(PWideChar(SoDir+'CustomDocNo.ini'),PWideChar(DeDir+'CustomDocNo.ini'),False);
  AA4:=CopyFile(PWideChar(SoDir+'UseCase.ini'),PWideChar(DeDir+'UseCase.ini'),False);
//ShowMessage(BoolToStr(AA)+#10#13+BoolToStr(AA2)+#10#13+BoolToStr(AA3)+#10#13+BoolToStr(AA4));
  if FileExists(SoDir+'DocDir.dat') then     //20170222 新加
  begin
    CopyFile(PWideChar(SoDir+'DocDir.dat'),PWideChar(DeDir+'DocDir.dat'),False);
  end;
  DocNoList := TStringlist.Create;
  FileList := TStringlist.Create;
  iFileList := TStringlist.Create;
  iFile_DocDirList := TStringlist.Create;
  iAttFileList := TStringlist.Create;
  try
    //if Not FileExists(SoDir+'Context.dat') then  Exit;
    //iFileList.LoadFromFile(SoDir+'Context.dat');
    //if iFileList.Count = 0 then Exit;
    if FileExists(SoDir+'Context.dat') then
      iFileList.LoadFromFile(SoDir+'Context.dat');
    if FileExists(SoDir+'DocDir.dat') then
      iFile_DocDirList.LoadFromFile(SoDir+'DocDir.dat');
    if iFileList.Count <> iFile_DocDirList.Count then
    begin
      for i := 0 to iFileList.Count - 1 do
      begin
        if i > iFile_DocDirList.Count -1 then
        begin
          iFile_DocDirList.Add(FormCode2DocNo(FileName2FormCode(iFileList.Strings[i])));
        end;
      end;
    end;
    if FileExists(SoDir+'CaseDocNo.dat') then
      DocNoList.LoadFromFile(SoDir+'CaseDocNo.dat');
    if FileExists(DeDir+'CaseDocNo_Copies.dat') then
      CaseDocNo_CopiesList.LoadFromFile(DeDir+'CaseDocNo_Copies.dat');
    {for i := 0 to DocNoList.Count - 1 do
    begin
      DocDir := DocNoList.Strings[i];
      MkDir(DeDir+DocDir);
    end;}
//ShowMessage('DocNoList='+DocNoList.Text);
    for i := DocNoList.Count - 1 downto 0 do
    begin
      DocDir := DocNoList.Strings[i];
      if not DirectoryExists(DeDir+DocDir) then
      begin
        MkDir(DeDir+DocDir);
        if not FileExists(DeDir+DocDir+'\Context.dat') then
          StringtoFile('',DeDir+DocDir+'\Context.dat');
      end
      else
      begin
//ShowMessage('GGG');
        DocNoList.Delete(i);
        DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
        if i <= CaseDocNo_CopiesList.Count-1  then
        begin
//ShowMessage('KKKK');
          CaseDocNo_CopiesList.Delete(i);
          CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
        end;
      end;
    end;
  //20170221 先註解起來  因為他在補充掃瞄時好像會有顯示的問題
    for i := 0 to iFileList.Count - 1 do
    begin
      OldFile := iFileList.Strings[i];
      DocDir := iFile_DocDirList.Strings[i];
      if (DocDir = 'Attach') or (DocDir = 'S_Attach') then
      begin
        if not DirectoryExists(DeDir+DocDir) then
          MkDir(DeDir+DocDir);
      end;
      FileList.Clear;
      if FileExists(DeDir+DocDir+'\Context.dat') then
      begin
        FileList.LoadFromFile(DeDir+DocDir+'\Context.dat');
      end;
      NewFile := Add_Zoo(FileList.Count+1,3)+FileName2NoQuene_Filename(OldFile);
      CopyFile(PWideChar(SoDir+OldFile),PWideChar(DeDir+DocDir+'\'+NewFile),False);
      FileList.Add(NewFile);
      FileList.SaveToFile(DeDir+DocDir+'\Context.dat');
    end;
    for i := DocNoList.Count -1 downto 0 do
    begin
      if (DocNoList.Strings[i] = 'Attach') or (DocNoList.Strings[i] = 'S_Attach') then
      begin
        DocNoList.Delete(i);
        DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
      end;
    end;
    {if (DocNoList.Count > 0) and ((DocNoList.Strings[DocNoList.Count-1] = 'Attach') or (DocNoList.Strings[DocNoList.Count-1] = 'S_Attach')) then
    begin
      DocNoList.Delete(DocNoList.Count-1);
      DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
    end; }
    CaseDocNo_CopiesList.Clear;
    if FileExists(DeDir+'CaseDocNo_Copies.dat') then
      CaseDocNo_CopiesList.LoadFromFile(DeDir+'CaseDocNo_Copies.dat');
    if DocNoList.Count > CaseDocNo_CopiesList.Count then
    begin
      for i := 0 to DocNoList.Count - 1 do
      begin
        if i > CaseDocNo_CopiesList.Count-1 then
        begin
          CaseDocNo_CopiesList.Add('1');
          //CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
        end;
      end;
    end;
    CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
    {if (not FileExists(DeDir+'CaseDocNo_Copies.dat') then
    begin
      CaseDocNo_CopiesList.Free;
      for i := 0 to DocNoList.Count - 1 do
      begin
        CaseDocNo_CopiesList.Add('1');
        CaseDocNo_CopiesList.SaveToFile(DeDir+'CaseDocNo_Copies.dat');
      end;
    end;}
    if FileExists(SoDir+'AttContext.dat') then
    begin
      iAttFileList.LoadFromFile(SoDir+'AttContext.dat');
      for i := 0 to iAttFileList.Count - 1 do
      begin
        AttFile := iAttFileList.Strings[i];
        CopyFile(PWideChar(SoDir+AttFile),PWideChar(DeDir+AttFile),False);
      end;
      iAttFileList.SaveToFile(DeDir+'AttContext.dat');
    end;
    if FMode='ESCAN' then
    begin
      InitExistImgList(DeDir);
    end;
  finally
  iFileList.Free;
  FileList.Free;
  DocNoList.Free;
  iFile_DocDirList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetCaseFormID
  引用相依:LoadFromFile
  方法描述:從案件目錄的 Context.dat 檔案中搜尋並回傳該案件的主表單代碼(FormID)。
            程序會遍歷影像清單,提取各檔案的表單代碼,並排除特定的分案頁代碼,直到
            找到符合條件的主表單代碼為止。
============================================================================== }
Function TCB_IMGPSScanX.GetCaseFormID(Path:String):String;  //取案件的主FormID
var i,n : Integer;
    FileFormID : String;
begin
  Result := '';
  ContextList.LoadFromFile(Path+'Context.dat');
  for I := 0 to ContextList.Count - 1 do
  begin
    FileFormID := FileName2FormCode(ContextList.Strings[i]);
    if DivPageFormIDList.IndexOf(FileFormID)<>-1 then //20170509 跳過分案頁的formid
    begin
      Continue;
    end;
    if FindDivFormCode(FileFormID) then
    begin
      Result := FileFormID;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:CreateFormID_FormName
  引用相依:SaveToFile
  方法描述:遍歷 ContextList,提取每個檔案的表單代號與名稱並格式化為「代號_名稱」,
            最後存成 FormCode_Name.dat 供上傳使用。
============================================================================== }
Procedure TCB_IMGPSScanX.CreateFormID_FormName(Path,CaseID:String);  //產生FormID_FormName.dat
var i : Integer;
    S : TStringlist;
    FormID : String;
    FormName : String;
begin
  S := TStringlist.Create;
  try
    for I := 0 to ContextList.Count - 1 do
    begin
      FormID := FileName2FormCode(ContextList.Strings[i]);
      FormName := FormCode2FormName(CaseID,FormID);
      S.Add(FormID+'_'+FormName);
    end;
    S.SaveToFile(Path + 'FormCode_Name.dat',TEnCoding.UTF8);
  finally
  S.Free;
  end;
end;
{ ==============================================================================
  方法名稱:CreateDocNo_DocName
  引用相依:SaveToFile
  方法描述:產生包含文件代號與名稱的對應檔 DocNo_Name.dat。首先執行案件內文件去重
            ,接著遍歷 CaseDocNoList 取得對應名稱,針對不需分組的文件會在名稱前加
            上星號標記,最後將結果以 UTF-8 編碼儲存。
============================================================================== }
Procedure TCB_IMGPSScanX.CreateDocNo_DocName(Path,CaseID:String);  //產生DocNo_DocName.dat
var
  i : Integer;
  S : TStringlist;
  Doc_Name : String;
begin
  S := TStringlist.Create;
  try
    DistinctDocNoinCase(Path);
    for i := 0 to CaseDocNoList.Count - 1 do
    begin
      Doc_Name := CaseDocNoList.Strings[i]+'_'+DocNo2DocName(CaseID,CaseDocNoList.Strings[i]);
      if not DocnoNeedGroup(CaseDocNoList.Strings[i]) Then  //不用分組的加*號給智豪
        Doc_Name := '*'+Doc_Name;
      S.Add(Doc_Name);
    end;
    S.SaveToFile(Path+'DocNo_Name.dat',TEnCoding.UTF8);
  finally
  S.Free;
  end;
end;
{ ==============================================================================
  方法名稱:CreateIn_WH
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:產生在席文件清單檔 In_Wh.dat。讀取案件的文件目錄清單後,比對全域的在席
            文件清單(IN_WH_DocNoList),若文件代號匹配或屬於特定系統目錄(ZZZZZ),則
            將其加入清單並儲存,用於標記需留存實體的文件。
============================================================================== }
Procedure TCB_IMGPSScanX.CreateIn_WH(CaseID:String);  //產生In_WH.dat
var
  i,n : Integer;
  DocDirList,In_WH_List : TStringlist;
  iDocNo : String;
begin
  DocDirList := TStringlist.Create;
  In_WH_List := TStringlist.Create;
  try
    if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
      DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    for i := 0 to DocDirList.Count - 1 do
    begin
      iDocNo := DocNoDir2DocNo(DocDirList.Strings[i]);
      for n := 0 to IN_WH_DocNoList.Count - 1 do
      begin
        if (iDocNo = IN_WH_DocNoList.Strings[n]) or (Copy(iDocNo,1,5)='ZZZZZ') then
        begin
          In_WH_List.Add(DocDirList.Strings[i]);
          Break;
        end;
      end;
    end;
    In_WH_List.SaveToFile(ImageSavePath+CaseID+'\In_Wh.dat');
  finally
  DocDirList.Free;
  In_WH_List.Free;
  end;
end;
{ ==============================================================================
  方法名稱:CreateDocNo_Info
  引用相依:FileExists, LoadFromFile
  方法描述:產生案件內標準文件(非自訂)的彙總資訊字串。方法讀取 CaseDocNo.dat,針對
            每個非 'ZZZZZ' 開頭的文件編號,計算其在案件中的總份數、累計總頁數,並檢
            查編輯狀態(異動旗標)。結果以「編號[Tab]份數[Tab]頁數[Tab]狀態」的格式逐
            行組成,作為案件上傳時與伺服器比對資料完整性的核心依據。
============================================================================== }
Function TCB_IMGPSScanX.CreateDocNo_Info(CaseID:String):String; //產生 DocNo[tab]份數[tab]總頁數[tab]是否異動[換行]DocNo[tab]份數[tab]總頁數[tab]是否異動
var
  i,n : Integer;
  DocDirList,DocDir_CopiesList,FileList,C_DocNoList : TStringlist;
  DocNo,iDocDir,iDocNo,iEdit:String;
  icopys,ipages : integer;
  S,S1 : TStringlist;
  Str : String;
begin
  DocDirList := TStringlist.Create;
  DocDir_CopiesList := TStringlist.Create;
  FileList := TStringlist.Create;
  C_DocNoList := TStringlist.Create;
  try
    Str := '';
    if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
    DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    if DocDirList.Count =0 then exit;//20170222 新加
    DocDir_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
    while DocDirList.Count > 0 do
    begin
      iDocDir := DocDirList.Strings[0];
      DocNo := DocNoDir2DocNo(iDocDir);
      if Copy(iDocDir,1,5) <> 'ZZZZZ' then   //不為自定文件
      begin
        //icopys := 1;
        icopys := GetDocNoCount(CaseID,DocNo);
        ipages := GetDocDir_Page(CaseID,iDocDir);
        iEdit := GetDocNoEdit(CaseID,DocNo,'');
        for i := DocDirList.Count - 1 downto 1 do
        begin
          iDocDir := DocDirList.Strings[i];
          iDocNo := DocNoDir2DocNo(iDocDir);
          if iDocNo = DocNo then
          begin
            //inc(icopys);
            ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
            DocDirList.Delete(i);
          end;
        end;
        if str = '' then
          Str := Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocNo,iCopys,iPages,iEdit])
        else
          Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocNo,iCopys,iPages,iEdit]);
      end;
      DocDirList.Delete(0);
    end;
  finally
  DocDirList.Free;
  DocDir_CopiesList.Free;
  FileList.Free;
  C_DocNoList.Free;
  end;
  Result := Str;
  {S := TStringlist.Create;
  S1 := TStringlist.Create;
  try
    S.LoadFromFile(Path+'Context.dat');
    S1.LoadFromFile(Path+'Context_DocNo.dat');
    for i := 0 to CaseDocNoList.Count - 1 do
    begin
      iDocNo := CaseDocNoList.Strings[i];
      iCopys := GetDocNo_Count(Path,iDocNo);
      iPages := GetDocNo_Page(Path,iDocNo);
      if str = '' then
        Str := Format('%s,%d,%d',[iDocNo,iCopys,iPages])
      else
        Str := Str+';'+ Format('%s,%d,%d',[iDocNo,iCopys,iPages]);
    end;
    Result := Str;
  finally
  S.Free;
  S1.Free;
  end; }
end;
{ ==============================================================================
  方法名稱:CreateCustDocNo_Info
  引用相依:FileExists, LoadFromFile
  方法描述:產生案件內自訂文件的彙總資訊字串。方法專門處理代碼開頭為 'ZZZZZ' 的文
            件目錄,透過 GetCustomDocName 取得使用者定義的文件名稱,並彙整其總份數
            、總頁數與編輯異動狀態。最終格式與標準文件一致,但首位欄位改為顯示自訂
            名稱,確保自訂類別的文件也能正確被伺服器識別與儲存。
============================================================================== }
Function TCB_IMGPSScanX.CreateCustDocNo_Info(CaseID:String):String; //產生自訂文件 DocName[tab]份數[tab]總頁數[tab]是否異動[#13#10]DocName[tab]份數[tab]總頁數[tab]是否異動
var
  i,n : Integer;
  DocDirList,FileList : TStringlist;
  DocNo,DocName,iDocDir,iDocNo,iEdit:String;
  icopys,ipages : integer;
  S,S1 : TStringlist;
  Str : String;
begin
  DocDirList := TStringlist.Create;
  FileList := TStringlist.Create;
  try
    Str := '';
    if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
    DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
//ShowMessage(DocDirList.Text);
    while DocDirList.Count > 0 do
    begin
      iDocDir := DocDirList.Strings[0];
      DocNo := DocNoDir2DocNo(iDocDir);
      if Copy(iDocDir,1,5) = 'ZZZZZ' then   //是自定文件
      begin
        //icopys := 1;
        DocName := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
        icopys := GetDocNoCount(CaseID,DocNo);
        ipages := GetDocDir_Page(CaseID,iDocDir);
        iEdit := GetDocNoEdit(CaseID,DocNo,DocName);
        for i := DocDirList.Count - 1 downto 1 do
        begin
          iDocDir := DocDirList.Strings[i];
          iDocNo := DocNoDir2DocNo(iDocDir);
          if iDocNo = DocNo then
          begin
            //inc(icopys);
            ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
            DocDirList.Delete(i);
          end;
        end;
        DocName := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
        if str = '' then
          Str := Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocName,iCopys,iPages,iEdit])
        else
          Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%d'+#9+'%s',[DocName,iCopys,iPages,iEdit]);
      end;
      DocDirList.Delete(0);
    end;
  finally
  DocDirList.Free;
  FileList.Free;
  end;
  Result := Str;
end;
{ ==============================================================================
  方法名稱:CreateDocnoFrom_Info
  引用相依:FileExists, LoadFromFile
  方法描述:產生被引進的保管袋文件詳細資訊字串。程序遍歷案件的文件目錄,排除自定義
            文件後,取得各文件的份數、總頁數、異動狀態及來源案件編號(UseCase)。若同
            一文件來自多個目錄,則會累加數據,最後產出以 Tab 分隔的文件資訊清單。
============================================================================== }
Function TCB_IMGPSScanX.CreateDocnoFrom_Info(CaseID:String):String; //產生被引進的保管袋文件資訊  Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
var
  i,n : Integer;
  DocDirList,DocDir_CopiesList,FileList : TStringlist;
  DocNo,iDocDir,iDocNo,iEdit:String;
  FromCaseID : string;
  icopys,ipages : integer;
  S,S1 : TStringlist;
  Str : String;
begin
  DocDirList := TStringlist.Create;
  DocDir_CopiesList := TStringlist.Create;
  FileList := TStringlist.Create;
  try
    Str := '';
    if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
    DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    if DocDirList.Count=0 then exit;//20170222 新加
    DocDir_CopiesList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
    while DocDirList.Count > 0 do
    begin
      iDocDir := DocDirList.Strings[0];
      DocNo := DocNoDir2DocNo(iDocDir);
      if (Copy(iDocDir,1,5) <> 'ZZZZZ') then   //不為自定文件
      begin
        //icopys := 1;
        //icopys := GetDocNoCount(CaseID,DocNo);
        icopys := GetDocDirCopies(CaseID,iDocDir);
        ipages := GetDocDir_Page(CaseID,iDocDir);
        iEdit := GetDocNoEdit(CaseID,DocNo,'');
        FromCaseID := GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir);
        if FromCaseID <> '' then
        begin
          for i := DocDirList.Count - 1 downto 1 do
          begin
            iDocDir := DocDirList.Strings[i];
            iDocNo := DocNoDir2DocNo(iDocDir);
            if (iDocNo = DocNo) and (GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir)<>'') then
            begin
              FromCaseID := GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir);
              //inc(icopys);
              icopys := icopys + GetDocDirCopies(CaseID,iDocDir);
              ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
              DocDirList.Delete(i);
            end;
          end;
          if str = '' then
            Str := Format('%s'+#9+'%d'+#9+'%s',[DocNo,iCopys,FromCaseID])
          else
            Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%s',[DocNo,iCopys,FromCaseID]);
        end;
      end;
      DocDirList.Delete(0);
    end;
  finally
  DocDirList.Free;
  DocDir_CopiesList.Free;
  FileList.Free;
  end;
  Result := Str;
end;
{ ==============================================================================
  方法名稱:CreateCustDocNoFrom_Info
  引用相依:FileExists, LoadFromFile
  方法描述:產出自定義文件的引進資訊字串。專門處理前綴為 "ZZZZZ" 的目錄,提取自定
            義文件名稱、份數及來源案件。與保管袋文件類似,會執行重複合併並統計總頁
            數,最後產出格式化的資訊字串。
============================================================================== }
Function TCB_IMGPSScanX.CreateCustDocNoFrom_Info(CaseID:String):String; //產生被引進的自定文件資訊  Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
var
  i,n : Integer;
  DocDirList,FileList : TStringlist;
  DocNo,DocName,iDocDir,iDocNo,iEdit:String;
  FromCaseID : string;
  icopys,ipages : integer;
  S,S1 : TStringlist;
  Str : String;
begin
  DocDirList := TStringlist.Create;
  FileList := TStringlist.Create;
  try
    Str := '';
    if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
    DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
    while DocDirList.Count > 0 do
    begin
      iDocDir := DocDirList.Strings[0];
      DocNo := DocNoDir2DocNo(iDocDir);
      if Copy(iDocDir,1,5) = 'ZZZZZ' then   //是自定文件
      begin
        //icopys := 1;
        //icopys := GetDocNoCount(CaseID,DocNo);
        icopys := GetDocDirCopies(CaseID,iDocDir);
        ipages := GetDocDir_Page(CaseID,iDocDir);
        iEdit := GetDocNoEdit(CaseID,DocNo,DocName);
        FromCaseID := GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir);
        if FromCaseID <> '' then
        begin
          for i := DocDirList.Count - 1 downto 1 do
          begin
            iDocDir := DocDirList.Strings[i];
            iDocNo := DocNoDir2DocNo(iDocDir);
            if (iDocNo = DocNo) and (GetUseCase('F',ImageSavePath+CaseID+'\',iDocDir)<>'') then
            begin
              FromCaseID := GetUseCase('F',DisplayPath,iDocDir);
              //inc(icopys);
              ipages := ipages + GetDocDir_Page(CaseID,iDocDir);
              DocDirList.Delete(i);
            end;
          end;
          DocName := GetCustomDocName(ImageSavePath+CaseID+'\',DocNo);
          if str = '' then
            Str := Format('%s'+#9+'%d'+#9+'%s',[DocName,iCopys,FromCaseID])
          else
            Str := Str+#13#10+ Format('%s'+#9+'%d'+#9+'%s',[DocName,iCopys,FromCaseID]);
        end;
      end;
      DocDirList.Delete(0);
    end;
  finally
  DocDirList.Free;
  FileList.Free;
  end;
  Result := Str;
end;
{ ==============================================================================
  方法名稱:CreateAttach_Info
  引用相依:
  方法描述:判斷案件是否存在附加電子檔。透過檢查附加檔案目錄的總頁數是否大於 0,回
            傳 "Y" 或 "N"。
============================================================================== }
Function TCB_IMGPSScanX.CreateAttach_Info(CaseID:String):String; //產生是否有Attach Y:有 N:沒有
begin
  Result := 'N';
  if GetDocDir_Page(CaseID,AttName) > 0 Then
    Result := 'Y';
end;
reassemble/CB_IMGPSScanImp.preview.pas
比對新檔案
@@ -0,0 +1,467 @@
{ ==============================================================================
  方法名稱:ShapeName2PreViewISBName
  引用相依:
  方法描述:將 TShape 元件的名稱轉換為對應的預覽影像捲軸盒(PreViewISB)名稱。
============================================================================== }
Function TCB_IMGPSScanX.ShapeName2PreViewISBName(SP:TShape):String; //轉出指定PreViewISBName
begin
  Result := ISBName+Copy(SP.Name,3,length(SP.Name)-2);
end;
{ ==============================================================================
  方法名稱:CreatePreViewISB
  引用相依:
  方法描述:動態建立指定數量的縮圖預覽組件。首先清空既有的預覽組件,接著在 ScrollB
            ox1 中為每個縮圖建立一個 TPanel 作為容器,並在其內嵌入一個 TImageScro
            llBox。設定組件的對齊方式、預設縮放模式及多項事件處理函式(如 Click, Mo
            useMove, DragDrop 等),並掛載右鍵選單。
============================================================================== }
Procedure TCB_IMGPSScanX.CreatePreViewISB(Count:Integer);
var
  ISB : TImageScrollBox;
  Panel : TPanel;
  i,W,H : Integer;
  myDate : TDateTime;
begin
  FreePreViewISB;
  ScrollBox1.HorzScrollBar.Visible := False;
  W := 150;
  H := 250;
  for I := 1 to Count do
  begin
    if FindComponent('M_Pl'+inttostr(i))=nil then
    begin
      Panel := TPanel.Create(Self);
      Panel.Name := 'M_Pl'+inttostr(i);//FormatDateTime('yyyymmddhhnnsszzz', now)
      Panel.Left := 4;
      Panel.Top := (i-1)*H+(6*i);
      Panel.Height := H;
      Panel.Width := W;
      Panel.Parent := ScrollBox1;
      Panel.Caption :='';
      if FindComponent(ISBName+inttostr(i))=nil then
      begin
        ISB := TImageScrollBox.Create(Self);
        ISB.Name := ISBName+inttostr(i);
        ISB.Parent := Panel;
        ISB.Align := alClient;
        ISB.ZoomMode := zmFullPage;
        ISB.DragMode := dmAutomatic;
        ISB.MouseMode := mmuser;
        ISB.OnImageClick := ISBClick;
        ISB.OnImageMouseMove := ISBMouseMove;
        ISB.PopupMenu := PopupMenu6;
        ISB.OnImageMouseDown := ISBImageMouseDown;
        ISB.OnImageMouseUp := ISBImageMouseUp;
        ISB.OnEndDrag := ISBEndDrag;
        ISB.OnDragDrop := ISBDragDrop;
        ISB.OnDragOver := ISBDragOver;
      end;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FreePreViewISB
  引用相依:
  方法描述:釋放所有與縮圖預覽相關的動態組件。遍歷所有組件,尋找名稱中包含特定前綴
            (如 ISBName, M_Pl, SP)的 TImageScrollBox、TPanel 與 TShape 並執行 Fre
            e 動作。最後呼叫 ProcessMessages 確保 UI 資源正確釋放。
============================================================================== }
Procedure TCB_IMGPSScanX.FreePreViewISB;
var
  i : Integer;
begin
try
  For i:= ComponentCount -1 downto 0 do
  begin
    IF (Components[i] is TImageScrollBox) and (Components[i]<>nil) Then
    begin
      IF Pos(ISBName,Components[i].Name) > 0 Then
        Components[i].Free;
    end
    Else If (Components[i] is TPanel) and  (Components[i]<>nil) Then
    begin
      IF Pos('M_Pl',Components[i].Name) > 0  Then
        Components[i].Free;
    end
    Else If (Components[i] is TShape) and (Components[i]<>nil) Then
    begin
      IF Pos('SP',Components[i].Name) > 0  Then
        Components[i].Free;
    end;
  end;
  Application.ProcessMessages;
except on E: Exception do
end;
  //showmessage(inttostr(Count));
end;
{ ==============================================================================
  方法名稱:FitPreViewISB
  引用相依:
  方法描述:自動調整所有預覽縮圖面板的高度與位置。遍歷所有已建立的預覽組件(ISB),
            根據每個影像實際顯示的高度(DisplayedGraphic.Height)動態設定其父面板
            的高度,並依序由上而下排列,確保縮圖之間緊密銜接。
============================================================================== }
Procedure TCB_IMGPSScanX.FitPreViewISB;
var
  i : Integer;
  iISB : TImageScrollBox;
  iPanel : TPanel;
  T,H : Integer;
begin
  T := 0;
  i := 1;
  while FindComponent(ISBName+inttostr(i)) <> nil do
  begin
    iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
    iISB.Parent.Height := 250;
    iISB.Parent.Top := T+4;
    iISB.Parent.Height := iISB.DisplayedGraphic.Height;
    H := iISB.Parent.Height;
    T := iISB.Parent.Top+H;
    inc(i);
  end;
  {For i:= 1 to Count do
  begin
    if TImageScrollBox(FindComponent(ISBName+inttostr(i))) = nil then Break;
    iISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
    iISB.Parent.Height := H;
    iISB.Parent.Top := T+4;
    iISB.Parent.Height := iISB.DisplayedGraphic.Height;
    H := iISB.Parent.Height;
    T := iISB.Parent.Top+H;
  end;}
end;
{ ==============================================================================
  方法名稱:PaintShape
  引用相依:
  方法描述:在預覽縮圖周圍繪製藍色選取框(TShape)。若僅傳入單一影像(ToImg 為 nil),
            則只在該影像位置建立選取框;若傳入起點與終點影像,則會在範圍內的所有影
            像組件上建立選取框。框線寬度設為 3 且顏色為藍色,用於視覺化標記選取狀
            態。
============================================================================== }
Procedure TCB_IMGPSScanX.PaintShape(FromImg,ToImg:TImageScrollBox); //畫有被選取的影像
var
  i,F_No,T_No : Integer;
  SP : TShape;
  ISB : TImageScrollBox;
  Function GetImgNo(iISB:TImageScrollBox):Integer;
  begin
    Result := strtoint(Copy(iISB.Name,length(ISBName)+1,length(iISB.Name)-length(ISBName))); //'PreViewISB'
  end;
begin
  IF ToImg = nil Then   //只畫單一個
  begin
    ISB := TImageScrollBox(FindComponent(ISBName+inttostr(GetImgNo(FromImg))));
    if TShape(FindComponent('SP'+inttostr(GetImgNo(FromImg)))) = nil then
    begin
    SP := TShape.Create(self);
    SP.Pen.Color := clblue;
    SP.Pen.Width := 3;
    SP.Parent := ScrollBox1;
    SP.Name := 'SP'+inttostr(GetImgNo(FromImg));
    SP.Left := ISB.Parent.Left-4;
    SP.Top := ISB.Parent.Top -4;
    SP.Width := ISB.Parent.Width + 8;
    SP.Height := ISB.Parent.Height + 8;
    end;
  end
  Else
  begin
    FreeShapeobj(nil);
    IF GetImgNo(FromImg) <= GetImgNo(ToImg) Then
    begin
      F_No := GetImgNo(FromImg);
      T_No := GetImgNo(ToImg);
    end
    Else
    begin
      F_No := GetImgNo(ToImg);
      T_No := GetImgNo(FromImg);
    end;
    For i := F_No to T_No do
    begin
      ISB := TImageScrollBox(FindComponent(ISBName+inttostr(i)));
      SP := TShape.Create(self);
      SP.Pen.Color := clblue;
      SP.Pen.Width := 3;
      SP.Parent := ScrollBox1;
      SP.Name := 'SP'+inttostr(i);
      SP.Left := ISB.Parent.Left-4;
      SP.Top := ISB.Parent.Top -4;
      SP.Width := ISB.Parent.Width + 8;
      SP.Height := ISB.Parent.Height + 8;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:FreeShapeobj
  引用相依:
  方法描述:刪除縮圖上的選取標記(TShape)。若傳入的 SelectISB 為 nil,則會刪除所有
            名稱前綴為 "SP" 的選取框組件;若指定了特定的影像組件,則僅刪除與該影像
            對應的選取框。
============================================================================== }
Procedure TCB_IMGPSScanX.FreeShapeobj(SelectISB : TImageScrollBox);
var
  i : Integer;
begin
  IF SelectISB = nil then //全Free;
  begin
    For i:= ComponentCount -1 downto 0 do
    begin
      IF Components[i] is TShape Then
      begin
        IF Pos('SP',Components[i].Name) > 0  Then
          Components[i].Free;
      end;
    end;
  end
  Else  //只Free指定的
  begin
    TShape(FindComponent('SP'+Copy(SelectISB.Name,length(ISBName)+1,length(SelectISB.Name)-length(ISBName)))).Free;
  end;
end;
{ ==============================================================================
  方法名稱:ISBClick
  引用相依:Image_Smooth, LoadFromFile
  方法描述:處理縮圖點擊事件,支援組合鍵選取。若按下 Shift 鍵則執行連選(PaintShape
             範圍選取);若按下 Control 鍵則切換單選狀態;一般點擊則清除舊選取並重
            新標記。點擊後會從選取的縮圖載入原圖至主顯示區(ISB1),並視需要執行影像
            平滑化處理。
============================================================================== }
Procedure TCB_IMGPSScanX.ISBClick(Sender : TObject);
var
  v,ln:Integer;
begin
  if (GetKeyState(VK_SHIFT) < 0) Then
  begin
    PaintShape(SelectISB,TImageScrollBox(Sender));
    SelectISB := TImageScrollBox(Sender);
  end
  Else if (GetKeyState(VK_CONTROL) < 0) Then
  begin
    SelectISB := TImageScrollBox(Sender);
    IF TShape(FindComponent('SP'+Copy(SelectISB.Name,length(ISBName)+1,length(SelectISB.Name)-length(ISBName)))) = nil Then
      PaintShape(SelectISB,nil)
    else
      FreeShapeobj(SelectISB);
  end
  Else
  begin
    FreeShapeobj(nil);
    SelectISB := TImageScrollBox(Sender);
    PaintShape(SelectISB,nil);
  end;
  GetSelectImageFile;
  v := length(ISBName);
  ln := length(SelectISB.Name);
  SelectPage := Strtoint(Copy(SelectISB.Name,v+1,ln-v));
  ISB1.ZoomMode := zmFittoPage;
//ShowMessage('SelectISB.FileName='+SelectISB.FileName);
  //if SelectISB.FileName='' then exit;
  ISB1.LoadFromFile(SelectISB.FileName,1);
  if (ISB1.Graphic.ImageFormat <> ifBlackWhite) and (SmoothCB.Checked)then
    Image_Smooth(ISB1.Graphic);
  ISB1.Redraw(True);
  ISB1Click(ISB1);
end;
{ ==============================================================================
  方法名稱:ISBMouseMove
  引用相依:
  方法描述:處理縮圖區的滑鼠移動事件。當處於拖曳狀態且滑鼠移動至已選取的影像(有 S
            P 標記)時,觸發組件的 BeginDrag 開始執行拖放操作。
============================================================================== }
Procedure TCB_IMGPSScanX.ISBMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  //Edit1.SetFocus;
  if Draging then
  begin
    if not (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
    begin
      SelectISB.BeginDrag(False);
      Draging := False;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:ISBImageMouseDown
  引用相依:LoadFromFile
  方法描述:處理縮圖預覽影像的滑鼠按下事件。當按下左鍵時,將 Draging 標記設為 True
             以利後續拖曳判斷。若未處於拖曳中,則根據是否按下 Shift 或 Control 鍵,
            執行範圍選取、加選或單選操作。選取後會更新 SelectPage,並在主顯示區(ISB
            1)同步載入對應的影像檔案。
============================================================================== }
procedure TCB_IMGPSScanX.ISBImageMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
var
  v,ln:Integer;
begin
  if Button = TMouseButton(mbLeft) Then
  begin
    Draging := True;
    //if SelectISB <> nil then
    //if not Draging then
    //begin
  end;
  //end;
  {if not (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
  begin
    //Showmessage('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)));
    if (Button = TMouseButton(mbLeft)) and (GetKeyState(VK_CONTROL) >= 0) then
    begin
      if SelectISB <> nil then
        SelectISB.BeginDrag(False);
    end;
  end;
  //if (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
  //begin
  //else
  //begin
  if not Draging then
  begin
    if (GetKeyState(VK_SHIFT) < 0) Then
    begin
      PaintShape(SelectISB,TImageScrollBox(Sender));
      SelectISB := TImageScrollBox(Sender);
    end
    Else if (GetKeyState(VK_CONTROL) < 0) Then
    begin
      SelectISB := TImageScrollBox(Sender);
      IF TShape(FindComponent('SP'+Copy(SelectISB.Name,length(ISBName)+1,length(SelectISB.Name)-length(ISBName)))) = nil Then
        PaintShape(SelectISB,nil)
      else
        FreeShapeobj(SelectISB);
    end
    Else
    begin
      FreeShapeobj(nil);
      SelectISB := TImageScrollBox(Sender);
      PaintShape(SelectISB,nil);
    end;
    v := length(ISBName);
    ln := length(SelectISB.Name);
    SelectPage := Strtoint(Copy(SelectISB.Name,v+1,ln-v));
    ISB1.ZoomMode := zmFittoPage;
    ISB1.LoadFromFile(SelectISB.FileName,1);
    ISB1Click(ISB1);
  end;
  //end;
  //end
  //Else
  //begin
  //end; }
  {if (Button = TMouseButton(mbRight)) and (TShape(FindComponent('SP'+Copy(TImageScrollBox(Sender).Name,length(ISBName)+1,length(TImageScrollBox(Sender).Name)-length(ISBName)))) = nil) then
  begin
    //ISBClick(Sender);
  end;
  if (Button = TMouseButton(mbLeft)) then
  begin
  end; }
end;
{ ==============================================================================
  方法名稱:ISBImageMouseUp
  引用相依:
  方法描述:處理縮圖預覽影像的滑鼠放開事件,將拖曳標記 Draging 重置為 False。
============================================================================== }
procedure TCB_IMGPSScanX.ISBImageMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
begin
  Draging := False;
end;
{ ==============================================================================
  方法名稱:ISBEndDrag
  引用相依:
  方法描述:當影像拖放操作結束時,觸發 TreeView1Click 事件以更新樹狀結構與顯示介
            面。
============================================================================== }
procedure TCB_IMGPSScanX.ISBEndDrag(Sender, Target: TObject; X, Y: Integer);
begin
  TreeView1Click(self);
end;
{ ==============================================================================
  方法名稱:ISBDragDrop
  引用相依:
  方法描述:執行縮圖拖放後的影像移動操作。根據來源與目標影像的原始掃描頁碼,呼叫 M
            oveImage_Drag 調整檔案在目錄中的順序。
============================================================================== }
procedure TCB_IMGPSScanX.ISBDragDrop(Sender, Source: TObject; X, Y: Integer);
var
  fp,tp : Integer;
begin
  fp := FileName2ScanPage(TimageScrollBox(Source).FileName);
  tp := FileName2ScanPage(TimageScrollBox(Sender).FileName);
  MoveImage_Drag(DisplayPath+NowDocDir+'\',fp,tp );
end;
{ ==============================================================================
  方法名稱:ISBDragOver
  引用相依:
  方法描述:判斷拖放操作是否可接受。僅在來源為影像組件、檔案路徑不同且樹狀結構選取
            在文件層級(Level 2)時,才允許執行拖放。
============================================================================== }
procedure TCB_IMGPSScanX.ISBDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
var
  So : Boolean;
begin
  {if (TObject(Source) is TImageScrollBox) and (TObject(Sender) is TImageScrollBox) then
  begin
    Label3.Caption := TImageScrollBox(Source).FileName+#13+TImageScrollBox(Sender).FileName;
  end;  }
  So := False;
  if TObject(Source) is TImageScrollBox then
    So := True;
  Accept := True;
  if not So
    or (TImageScrollBox(Source).FileName = TImageScrollBox(Sender).FileName)
    or (TreeView1.Selected.Level <> 2)
    Then
      Accept := False;
end;
reassemble/bloc/caseManager.pas
比對新檔案
@@ -0,0 +1,60 @@
{ ==============================================================================
  方法名稱:SetUseCase
  引用相依:
  方法描述:管理案件間的文件引用紀錄。此方法使用 Tinifile 操作案件目錄下的 UseCas
            e.ini 檔案。當 Mode 為 'A' (Add) 時,會在指定的 DocDir 區段下紀錄來源
            案件 (FROM_CASEID) 與目標案件 (TO_CASEID) 的引用關係;當 Mode 為 'D'
            (Delete) 時,則會移除該目錄對應的引用資訊。這用於追蹤不同案件間影像資
            源的重複利用情況。
============================================================================== }
Procedure TCB_IMGPSScanX.SetUseCase(Mode:Char;Path,DocDir,FormCaseID,ToCaseID:String);   //記錄引用其他案件 A:加入 D:刪掉
var
  ini : Tinifile;
begin
  ini := Tinifile.Create(Path+'UseCase.ini');
  try
    case Mode of
      'A':begin
            ini.WriteString(DocDir,'FROM_CASEID',FormCaseID);
            ini.WriteString(DocDir,'TO_CASEID',ToCaseID);
          end;
      'D':begin
            ini.EraseSection(DocDir);
          end;
    end;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetUseCase
  引用相依:
  方法描述:取得指定目錄的文件引用資訊。方法讀取 UseCase.ini 設定檔,根據 Mode 參
            數返回對應的案件 ID:模式 'F' 返回被引用的來源案件 ID (FROM_CASEID),
            模式 'T' 返回執行引用的目標案件 ID (TO_CASEID)。若查無紀錄則返回空字
            串。
============================================================================== }
Function TCB_IMGPSScanX.GetUseCase(Mode:Char;Path,DocDir:String):String;  //F:取被引用 To:引用
var
  ini : Tinifile;
begin
  ini := Tinifile.Create(Path+'UseCase.ini');
  try
    case Mode of
      'F':begin
            Result := ini.ReadString(DocDir,'FROM_CASEID','');
          end;
      'T':begin
            Result := ini.ReadString(DocDir,'TO_CASEID','');
          end;
    end;
  finally
  ini.Free;
  end;
end;
reassemble/bloc/entityMapping.pas
比對新檔案
@@ -0,0 +1,59 @@
{ ==============================================================================
  方法名稱:BarCode2CaseID
  引用相依:
  方法描述:從目前掃瞄到的條碼清單中提取案件編號 (CaseID)。方法會遍歷條碼暫存對象
             (MpsBarcodeinf),並將第一個長度正好等於預設 CaseIDLength 的條碼值視
            為合法的案件編號返回。若遍歷結束仍未找到符合長度限制的條碼,則返回空字
            串。
============================================================================== }
Function TCB_IMGPSScanX.BarCode2CaseID : String; //Barcode依規則轉成CaseID
var
  i : Integer;
  iCaseID : String;
begin
  Result := ''; //沒找到
  iCaseID := '';
  for i := 1 to MpsBarcodeinf.Count  do    //20180920 拿掉-1
  begin
    if (Length(MpsBarcodeinf.text[i]) = CaseIDLength) then
    begin
      iCaseID := MpsBarcodeinf.text[i];
      Result := iCaseID;
      Break;
    end;
  end;
end;
{ ==============================================================================
  方法名稱:BarCode2FormID
  引用相依:
  方法描述:從目前掃瞄到的條碼清單中識別有效的表單代碼 (FormID)。方法會過濾長度符
            合 FormIDLength 的條碼,並呼叫 FormIDAppear 驗證其格式。若初步驗證通過
            ,會進一步呼叫 FormIDExists 確認該代碼在系統中已註冊且可用。返回第一個
            完全符合條件的表單代碼,否則返回空。
============================================================================== }
Function TCB_IMGPSScanX.BarCode2FormID : String; //Barcode依規則轉成FormID
var
  i : Integer;
  FormID : String;
begin
  Result := ''; //沒找到
  FormID := '';
  for i := 1 to MpsBarcodeinf.Count  do
  begin
    if (Length(MpsBarcodeinf.Text[i]) = FormIDLength) then
    begin
      FormID := MpsBarcodeinf.text[i];
      if not FormIDAppear(FormID) then
        FormID := '';
    end;
    if (FormID <> '') and FormIDExists(FormID,False,0) then   //有可用的FormID就離開
    begin
      Result := FormID;
      Break;
    end;
  end;
end;
reassemble/img/anchor.pas
比對新檔案
@@ -0,0 +1,68 @@
{ ==============================================================================
  方法名稱:GetSiteOMR
  引用相依:GetSiteOMR, FindPoint, Get_OMR, LoadFromFile
  方法描述:在指定影像文件的特定座標執行 OMR (光學標記辨識)。核心邏輯包含:
            1. 檢查並載入影像檔(若尚未載入),並呼叫 ClearLine 初始化黑白緩衝區。
            2. 讀取影像的 DPI 與寬高資訊。
            3. 使用 CM_Str2Rect 將 Site 字串轉為 TRect 矩陣,並參考定位點 (UpLPoi
            nt) 進行位移計算。
            4. 限制辨識區域座標不超出影像邊界。
            5. 呼叫 Get_OMR 對黑白圖形緩衝區執行辨識並返回結果值(通常為 1 或 0)。
            此方法是自動化資料檢核的重要工具。
============================================================================== }
function TCB_IMGPSScanX.GetSiteOMR(FileName,Site:String;bt: Integer): Integer;
var
  OMRRect : TRect;
  Xdpi,Ydpi : Integer;
  W,H : Integer;
begin
  Result := 0;
//ShowMessage('GetSiteOMR');
  IF (ImageScrollBox1.FileName <> FileName) and (FileName <> '') then
  begin
//ShowMessage('11111'+ImageScrollBox1.FileName+#10#13+FileName);
    ImageScrollBox1.LoadFromFile(FileName,1);
{
ShowMessage('UpLPoint='+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+#10#13+
'UpRPoint='+IntToStr(UpRPoint.X)+','+IntToStr(UpRPoint.Y)+#10#13+
'DownLPoint='+IntToStr(DownLPoint.X)+','+IntToStr(DownLPoint.Y)+#10#13+
'DownRPoint='+IntToStr(DownRPoint.X)+','+IntToStr(DownRPoint.Y));
    FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,'');
ShowMessage('UpLPoint='+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+#10#13+
'UpRPoint='+IntToStr(UpRPoint.X)+','+IntToStr(UpRPoint.Y)+#10#13+
'DownLPoint='+IntToStr(DownLPoint.X)+','+IntToStr(DownLPoint.Y)+#10#13+
'DownRPoint='+IntToStr(DownRPoint.X)+','+IntToStr(DownRPoint.Y));
}
    ClearLine(ISB_BW.Graphic,bt);
    ISB_BW.Redraw(True);
    Application.ProcessMessages;
  end;
  If ImageScrollBox1.FileName <> '' Then
  begin
//ShowMessage('22222'+ImageScrollBox1.FileName);
    Xdpi := ImagescrollBox1.Graphic.XDotsPerInch;
    Ydpi := ImagescrollBox1.Graphic.YDotsPerInch;
    H := ImageScrollBox1.Graphic.Height;
    W := ImageScrollBox1.Graphic.Width;
//ShowMessage('Xdpi='+IntToStr(Xdpi)+#10#13+'Ydpi='+IntToStr(Ydpi)+#10#13+'H='+IntToStr(H)+#10#13+'W='+IntToStr(W)+#10#13);
//ShowMessage('Site='+Site);
    OMRRect := CM_Str2Rect(Site,Xdpi,UpLPoint);
Display1.Lines.Add('UpLPoint=('+IntToStr(UpLPoint.X)+','+IntToStr(UpLPoint.Y)+');'+Site+';'+IntToStr(OMRRect.Left)+','+IntToStr(OMRRect.top)+','+IntToStr(OMRRect.Right)+','+IntToStr(OMRRect.Bottom));
    if OMRRect.Left < 0 then
      OMRRect.Left := 0;
    if OMRRect.Top < 0  then
      OMRRect.Top := 0;
    if OMRRect.Right > ImageScrollBox1.Graphic.Width then
      OMRRect.Right := ImageScrollBox1.Graphic.Width;
    if OMRRect.Bottom > ImageScrollBox1.Graphic.Height then
      OMRRect.Bottom := ImageScrollBox1.Graphic.Height;
    result := Get_OMR(ISB_BW.Graphic,OMRRect);
//ShowMessage('result='+IntToStr(result));
  end;
end;
reassemble/img/transformer.pas
比對新檔案
@@ -0,0 +1,165 @@
{ ==============================================================================
  方法名稱:ImageReSize_FormID
  引用相依:ImageReSize_FormID, FindPoint, CheckSize, LoadFromFile, SaveToFile,
            FileExists, LoadFileGetMD5
  方法描述:根據表單的十字定位點或邊框 (ANCHOR/FRAME) 對掃瞄影像進行縮放調整。流
            程如下:
            1. 從 FORM_INF_List 取得表單預設高寬與定位類型。
            2. 載入對應案件下的影像檔,若為補件模式則跳過原有圖檔。
            3. 呼叫 FindPoint 尋找影像中的十字線或邊框。
            4. 呼叫 CheckSize 計算偏移與縮放比例。
            5. 呼叫 ImageResize 執行實際調整。
            6. 成功縮放後,記錄檔案 MD5 並儲存更新後的影像,同時將操作記錄寫入 ReS
            ize.dat;若定位點遺失或辨識錯誤,則記錄於 AnchorError.dat。
============================================================================== }
Procedure TCB_IMGPSScanX.ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放
var
  FormID : String;
  DH,DW : String;
  NowW,NowH : Integer;
  ANCHOR : String; //是否有十字線
  SizeStr : String;
  S : TStringlist;
  v,v1:Integer;
  IsRecordMD5:Boolean;
begin
  IsRecordMD5:=False;
  FormID := FileName2FormCode(FileName);
  if FormID = '' then Exit;
  IF FindSQLData(FORM_INF_List,'T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.ANCHOR','T1.FORM_ID',FormID,0,FindResult) then
  begin
    DH := GetFindResult('T1.FORM_HEIGHT');
    DW := GetFindResult('T1.FORM_WIDTH');
    ANCHOR := UpperCase(GetFindResult('T1.ANCHOR'));
    ANCHOR := Index2Anchor(ANCHOR);
Display1.Lines.Add(FormID+','+DH+','+DW);
//ShowMessage('AAAAAAAAA');
    if ((ANCHOR = 'ANCHOR') or (ANCHOR = 'FRAME')) and (DH <> '') and (DW <> '') then  //有十字定位點
    begin
//ShowMessage('BBBBBBB');
      ImageScrollBox1.LoadFromFile(ImageSavePath+CaseID+'\Upload\'+FileName,1);
      if (FWH_category='N') and  ISExistImg(ImageSavePath+CaseID+'\Upload\'+FileName) then
      begin
        Exit;//20171103  補件  原有的圖不作resize
      end;
      //FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH);
      FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH,ANCHOR);
      SizeStr := CheckSize(ISB_BW,UpLPoint,UpRPoint,DownLPoint,DW,DH);
      ImageResize(ImageScrollBox1.Graphic,ISB_BW.Graphic.Width,ISB_BW.Graphic.Height);
      FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH,ANCHOR);
      v := 5;
      v1 := length(SizeStr);
      IF (SizeStr <> '') and (Copy(SizeStr,1,v) <> 'ERROR') then
      begin
//ShowMessage('CCCCC');
        if (ISExistImg(ImageSavePath+CaseID+'\Upload\'+FileName)) and (reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\Upload\'+FileName))=-1) then
        begin
          IsRecordMD5:=True;
        end;
        ImageScrollBox1.SaveToFile(ImageSavePath+CaseID+'\Upload\'+FileName);
        if IsRecordMD5 then
        begin
          reSizeExistImgList.add(LoadFileGetMD5(ImageSavePath+CaseID+'\Upload\'+FileName));
        end;
//showmessage(ImageSavePath+CaseID+'\Upload\'+FileName);
        S := TStringlist.Create;                     ///20110422拿掉 換成上傳才做
        if FileExists(ImageSavePath+CaseID+'\Upload\ReSize.dat') then
          S.LoadFromFile(ImageSavePath+CaseID+'\Upload\ReSize.dat');
        //S.Add(FormCode2FormName(FormID)+' '+SizeStr);
        S.Add(FileName+','+SizeStr+#8+DateTimetoStr(Now));
        S.SaveToFile(ImageSavePath+CaseID+'\Upload\ReSize.dat');
        S.Free;
      end;
      if (Copy(SizeStr,1,v) = 'ERROR') then   //未找到三個定位點
      begin
        S := TStringlist.Create;
        if FileExists(ImageSavePath+CaseID+'\Upload\AnchorError.dat') then
          S.LoadFromFile(ImageSavePath+CaseID+'\Upload\AnchorError.dat');
        S.Add(FileName+'-->'+Copy(SizeStr,V+1,V1-v));
        S.SaveToFile(ImageSavePath+CaseID+'\Upload\AnchorError.dat');
        S.Free;
      end;
      ImageScrollBox1.FileName := '';
    end;
  end;
end;
{ ==============================================================================
  方法名稱:ImageReSize_tmp
  引用相依:ImageReSize_tmp, CheckSize, LoadFromFile, SaveToFile
  方法描述:針對暫存影像檔案執行十字定位點縮放處理。此方法是 ImageReSize_FormID
            的簡化版本,主要針對暫存檔 (FileName) 與指定的 FormID。邏輯包含從資料
            庫清單查詢表單尺寸與定位模式,若符合 ANCHOR 或 FRAME 類型,則載入影像
            並呼叫 CheckSize 檢查是否需要調整。若偵測到影像存在偏移或比例差異(Siz
            eStr 非空),則將調整後的影像直接覆蓋儲存回原始路徑。
============================================================================== }
Procedure TCB_IMGPSScanX.ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)
var
  DH,DW : String;
  ANCHOR : String; //是否有十字線
  SizeStr : String;
  S : TStringlist;
begin
  IF FindSQLData(FORM_INF_List,'T1.FORM_HEIGHT,T1.FORM_WIDTH,T1.ANCHOR','T1.FORM_ID',FormID,0,FindResult) then
  begin
    DH := GetFindResult('T1.FORM_HEIGHT');
    DW := GetFindResult('T1.FORM_WIDTH');
    ANCHOR := UpperCase(GetFindResult('T1.ANCHOR'));
    ANCHOR := Index2Anchor(ANCHOR);
    if ((ANCHOR = 'ANCHOR') or (ANCHOR = 'FRAME')) and (DH <> '') and (DW <> '') then  //有十字定位點
    begin
      ImageScrollBox1.LoadFromFile(FileName,1);
      SizeStr := CheckSize(ImageScrollBox1,UpLPoint,UpRPoint,DownLPoint,DW,DH);
      IF SizeStr <> '' then
      begin
        ImageScrollBox1.SaveToFile(FileName);
      end;
      ImageScrollBox1.FileName := '';
    end;
  end;
end;
{ ==============================================================================
  方法名稱:CheckNeedCrop
  引用相依:TDibGraphic, CheckNeedCrop
  方法描述:判斷掃瞄影像是否為 A3 尺寸並需要進行切割(Crop)。判定邏輯有二:首先,檢
            查影像寬度是否大於 4 倍的 DPI 閥值,藉此初步判斷為大尺寸掃瞄件;其次,
            遍歷目前的條碼清單 (MpsBarcodeinf),統計有效的表單代碼 (FormID) 數量。
            如果影像寬度達標且有效表單數量正好為 2,則返回 True。這代表此張大圖實
            際上是由兩份 A4 表單併排掃瞄而成,後續需依此旗標進行影像分割處理。
============================================================================== }
Function TCB_IMGPSScanX.CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
Var
  i,FormIDCount : Integer;
begin
  Result := False;
  FormIDCount := 0;
  if (Graphic.Width > (4 * Graphic.XDotsPerInch)) {or (Graphic.Height > (15 * Graphic.YDotsPerInch))} then
  //if (Graphic.Width > (6 * Graphic.XDotsPerInch)) then
  begin
    for I := 1 to MpsBarcodeinf.Count do
    begin
      if (Length(MpsBarcodeinf.Text[i])=FormIDLength) and FormIDExists(MpsBarcodeinf.Text[i],False,0) then
      begin
        inc(FormIDCount);
      end;
    end;
  end;
//ShowMessage('FormIDCount='+IntToStr(FormIDCount)+#10#13+'MpsBarcodeinf.count='+IntToStr(MpsBarcodeinf.count));
  if FormIDCount = 2 then
  begin
    Result := True;
  end;
end;
reassemble/scan/twain.pas
比對新檔案
@@ -0,0 +1,880 @@
{ ==============================================================================
  方法名稱:StatrTwainScan
  引用相依:TTiffGraphic, StatrTwainScan, Scanner, Scanner.OpenSource, Scanner.C
            loseSource, OnAcquire, Scanner.AcquireWithSourceOpen
  方法描述:啟動 TWAIN 掃瞄流程。此方法首先檢查掃瞄器驅動是否已安裝,接著初始化 Sc
            anInfo 結構並設定掃瞄參數(如 DPI、影像格式、是否顯示 UI、雙面掃瞄模式、
            亮度與對比)。流程中會開啟掃瞄來源,呼叫 AcquireWithSourceOpen 執行實際
            掃瞄作業,並利用 try...finally 確保不論掃瞄成功與否,最終都會關閉掃瞄
            來源並釋放資源。
============================================================================== }
procedure TCB_IMGPSScanX.StatrTwainScan;
var ScanInfo    : TScanInfo;
   i : Integer;
begin
  if not Scanner.IsConfigured then
  begin
    ShowMessage(_Msg('TWAIN 掃瞄驅動尚未安裝'));
    Exit;
  end;
  FillChar(ScanInfo, SizeOf(ScanInfo), 0);
  ScanInfo.MultiPage := True;
  ScanInfo.ImageCount := 0;
  ScanInfo.Graphic := TTiffGraphic.Create;
  try
    ISB := nil; //規零
//ShowMessage(IntToStr(ScanDpi));
    Scanner.RequestedXDpi := ScanDpi;
    Scanner.RequestedYDpi := ScanDpi;
    Scanner.RequestedImageFormat := ScanColor;
    Scanner.ShowUI := TwainShowUI;
    Try
      Scanner.OpenSource;
      Scanner.Duplex := ScanDuplex; //雙面
      if FMode='SAMPLESCAN' then
        Scanner.Duplex:=False;
      //Scanner.FEEDERENABLED  := not ScanFlatCB.Checked;     // 先拿掉平台
      If ScanImgSetUse Then
      begin
        Scanner.ScanBrightness := ScanBright;
        Scanner.ScanContrast := ScanContrast;
      end;
    except
      Showmessage(_Msg('掃瞄器發生錯誤!!'));
      Scanner.CloseSource;
      Exit;
    end;
    try
      Try
        Scanner.AcquireWithSourceOpen( OnAcquire, LongInt(@ScanInfo));
      Except
        Scanner.CloseSource;
      end;
    finally
      Scanner.CloseSource;
    end;
  finally
  Scanner.CloseSource;
  ScanInfo.Graphic.Free;
  end;
end;
{ ==============================================================================
  方法名稱:OnAcquire
  引用相依:TTiffGraphic, TJpegGraphic, OnAcquire
  方法描述:掃瞄影像獲取後的回呼處理函數。核心邏輯包含:
            1. 將獲取的 DIB 句柄轉為影像對象並設定 DPI。
            2. 依影像格式執行對應處理:黑白影像會進行條碼辨識、依條碼角度旋轉、影像
            反向、傾斜矯正及清黑邊;全彩或灰階影像則設定 JPEG 壓縮品質。
            3. 檢查是否需要進行 A3 切割為 A4 的處理。
            4. 透過 Deletepage 檢查並過濾空白頁(依據檔案大小)。
            5. 對於有效影像,更新 UI 顯示並呼叫 PageEnd 決定儲存路徑與檔名,最後依
            副檔名儲存為 TIFF 或 JPEG 並呼叫 PageDone 完成頁面流程。
============================================================================== }
procedure TCB_IMGPSScanX.OnAcquire( const DibHandle    : THandle;
                               const XDpi         : Word;
                               const YDpi         : Word;
                               const CallBackData : LongInt );
var
  pScanInfo  : TpScanInfo;
  SaveFileName : String;
  SaveStream     : TFileStream;
  strResults : TBarcodeStringResult;
  DeleteStm  : TMemoryStream;
  isDelete   : Boolean;
  iGraphic,iGraphic_First,iGraphic_sec : TTiffGraphic;
  iRect : TRect;
  JpgGr : TJpegGraphic;
  i : Integer;
  TagTxt : String;
  function Deletepage(Graphic:TDibGraphic;BlankSize:Integer):Boolean;
  begin
    DeleteStm  := TMemoryStream.Create;
    DeleteStm.Seek(0,soFromBeginning);
    Graphic.AppendToStream(DeleteStm);
    //DeleteStm.LoadFromFile(Path+'temp.tif');
    //Isb1.Graphic.SaveToStream(DeleteStm);
    //Isb1.Graphic.AppendToStream(DeleteStm);
    if DeleteStm.Size < BlankSize Then
      Result:= True
    Else
      Result := False;
    DeleteStm.Free;
    //DeleteFile(Path+'temp.tif');
  end;
begin
  pScanInfo := TpScanInfo(CallBackData);
  isDelete    := False;
  if pScanInfo^.MultiPage then
  begin
    pScanInfo^.Graphic.AssignFromDibHandle(DibHandle);
    pScanInfo^.Graphic.XDotsPerInch := XDpi;
    pScanInfo^.Graphic.YDotsPerInch := YDpi;
    TagTxt := 'height:'+inttostr(pScanInfo^.Graphic.Height)+',width:'+inttostr(pScanInfo^.Graphic.Width);
    if pScanInfo^.Graphic.ImageFormat = ifBlackWhite then
    begin
      ImageScrollBox1.Graphic.Assign(pScanInfo^.Graphic);
      ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
      pScanInfo^.Graphic.Compression := tcGroup4;
      MpsGetBarcode(pScanInfo^.Graphic,MpsBarcodeinf);
      For i := 1 to MpsBarcodeinf.count do
      begin
        If (MpsBarcodeinf.r180[i] <> 0) and (Length(MpsBarcodeinf.Text[i])=FormIDLength) Then
        begin
          Rotate(pScanInfo^.Graphic,MpsBarcodeinf.r180[i]);
          MpsGetBarcode(pScanInfo^.Graphic,MpsBarcodeinf);  //旋轉後再重取一次條碼資訊
          Break;
        end;
      end;
      //影像反向
      IF ScannerReverse then
        NegativeImg(pScanInfo^.Graphic);
      //傾斜矯正
      IF ScanDeskew Then
        DeskewImg(pScanInfo^.Graphic);
      //清黑邊
      IF BoardClear then
        CleanupBorder(pScanInfo^.Graphic);
    end
    else if pScanInfo^.Graphic.ImageFormat = ifTrueColor then
    begin
        //Ext := '.jpg';
        ImageScrollBox1.Graphic.Assign(pScanInfo^.Graphic);
        //ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
        MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);
        For i := 1 to MpsBarcodeinf.count do
        begin
          If (MpsBarcodeinf.r180[i] <> 0) and (Length(MpsBarcodeinf.Text[i])=FormIDLength) Then
          begin
            Rotate(ISB_BW.Graphic,MpsBarcodeinf.r180[i]);
            MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);  //旋轉後再重取一次條碼資訊
            Break;
          end;
        end;
        pScanInfo^.Graphic.Compression := tcJpeg;
        pScanInfo^.Graphic.JpegQuality := FJpgCompression;
    end
    else if pScanInfo^.Graphic.ImageFormat = ifColor256 Then
    begin
      //Ext := '.jpg';
      ConvertToGray(pScanInfo^.Graphic);
      pScanInfo^.Graphic.Compression := tcJpeg;
      pScanInfo^.Graphic.JpegQuality := FJpgCompression;
    end
    else if pScanInfo^.Graphic.ImageFormat = ifGray256 Then
    begin
      //Ext := '.jpg';
      ImageScrollBox1.Graphic.Assign(pScanInfo^.Graphic);
      ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
      MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);
      For i := 1 to MpsBarcodeinf.count do
      begin
        If (MpsBarcodeinf.r180[i] <> 0) and (Length(MpsBarcodeinf.Text[i])=FormIDLength) Then
        begin
          Rotate(ISB_BW.Graphic,MpsBarcodeinf.r180[i]);
          MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);  //旋轉後再重取一次條碼資訊
          Break;
        end;
      end;
      pScanInfo^.Graphic.Compression := tcJpeg;
      pScanInfo^.Graphic.JpegQuality := FJpgCompression;
//ShowMessage(IntToStr(pScanInfo^.Graphic.JpegQuality));
//if pScanInfo^.Graphic.Compression = tcJpeg then
//begin
//ShowMessage('jpg');
//end;
    end
    else
    begin
      //Ext := '.tif';
      pScanInfo^.Graphic.Compression := tcPackBits;
    end;
  end;
  //Application.ProcessMessages;
  iGraphic_First := TTiffGraphic.Create;
  iGraphic_sec := TTiffGraphic.Create;
  //iGraphic := TTiffGraphic.Create;
  try
    iGraphic_First.Assign(pScanInfo^.Graphic);
    //Application.ProcessMessages;
    if CheckNeedCrop(iGraphic_First) Then
    begin
      iRect.Left := pScanInfo^.Graphic.Width div 2;    //先取左邊的影像
      iRect.Top := 0;
      iRect.Right := pScanInfo^.Graphic.Width;
      iRect.Bottom := pScanInfo^.Graphic.Height;
      CropImg(iGraphic_First,iRect);
      iGraphic_Sec.Assign(pScanInfo^.Graphic);         //再取右邊的影像
      iRect.Left := 0;
      iRect.Top := 0;
      iRect.Right := pScanInfo^.Graphic.Width div 2;
      iRect.Bottom := pScanInfo^.Graphic.Height;
      CropImg(iGraphic_Sec,iRect);
    end;
    //iGraphic.Assign(iGraphic_First);
    iGraphic := iGraphic_First;
    if iGraphic.ImageFormat=ifGray256 then  //20180104
    begin
      iGraphic.Compression:=tcJPEG;
      iGraphic.JpegQuality:=FJpgCompression;
    end;
    if iGraphic.ImageFormat=ifTrueColor then  //20180104
    begin
      iGraphic.Compression:=tcJPEG;
      iGraphic.JpegQuality:=FJpgCompression;
    end;
//ShowMessage('WTF');
    while not iGraphic.IsEmpty do
    begin
      //Application.ProcessMessages;
      IF (not DeviceDelete) or (not Deletepage(iGraphic,DeviceDeleteSize)) Then
      begin
        ImageScrollBox1.Graphic.Assign(iGraphic);
        ImageScrollBox1NewGraphic(ImageScrollBox1.Graphic);
        MpsGetBarcode(ISB_BW.Graphic,MpsBarcodeinf);
        For i := 1 To MpsBarcodeinf.Count Do
        Begin
          If MpsBarcodeinf.r180[i] <> 0 Then // 依條碼角度轉影像
          Begin
            Rotate(iGraphic, MpsBarcodeinf.r180[i]);
            Break;
          End;
        End;
        if iGraphic.ImageFormat=ifGray256 then  //20180104 因此旋轉後變為回packbits 所以要改為jpeg
        begin
          iGraphic.Compression:=tcJPEG;
          iGraphic.JpegQuality:=FJpgCompression;
        end;
        if iGraphic.ImageFormat=ifTrueColor then
        begin
          iGraphic.Compression:=tcJPEG;
          iGraphic.JpegQuality:=FJpgCompression;
        end;
        PageEnd;
        IF PEFileName <> '' Then
        begin
          IF LowerCase(ExtractFileExt(PEFileName)) = '.tif' Then
          begin
            if FileExists( PEFileName ) then
              SaveStream := TFileStream.Create( PEFileName ,fmOpenReadWrite)
            Else
              SaveStream := TFileStream.Create( PEFileName ,fmCreate );
            try
              SaveStream.Seek(0, soFromBeginning);
              iGraphic.AppendToStream(SaveStream);
            finally
              SaveStream.Free;
            end;
          end
          Else IF LowerCase(ExtractFileExt(PEFileName)) = '.jpg' Then
          begin
            if FileExists( PEFileName ) then
              DeleteFile(PEFileName);
            //SaveStream := TFileStream.Create( PEFileName ,fmCreate );
            JpgGr := TJpegGraphic.Create;
            try
              JpgGr.Assign(iGraphic);
              JpgGr.SaveQuality := FJpgCompression;
              //JpgGr.AppendToStream(SaveStream);
              JpgGr.SaveToFile(PEFileName);
            finally
              JpgGr.Free;
              //SaveStream.Free;
            end;
          end;
          PageDone;
        end;
      end;
      if iGraphic = iGraphic_First then
        iGraphic := iGraphic_Sec
      else
        iGraphic.Assign(nil);
      //iGraphic.Assign(iGraphic_Sec);
    end;
  finally
  //iGraphic.Free;
  iGraphic_First.Free;
  iGraphic_Sec.Free;
  end;
end;
{ ==============================================================================
  方法名稱:PageDone
  引用相依:LoadFromFile, PageDone
  方法描述:完成單頁影像處理後的 UI 更新邏輯。此方法會遞增掃瞄影像總計數,並根據目
            前的掃瞄模式(新建、取代、插入或取樣)將儲存好的影像檔載入到對應的 Image
            ScrollBox 元件中。在新建模式下,還會根據 ScanImgShowMode 設定決定影像
            顯示的品質(反鋸齒開啟與否)與縮放模式(zmFittopage),確保使用者能即時預
            覽掃瞄結果。
============================================================================== }
procedure TCB_IMGPSScanX.PageDone;
Var
  ISB,NowISB : TImageScrollBox;
begin
  inc(Scaninfo.ImageCount);
  case ScanMode of
    smNew:
      begin
        if ScanImgShowMode = 0 then  //清楚顯示
        begin
          ISB := FindISB2View(VMode);
          ISB.AntiAliased := True;
          ISB.ZoomMode := zmFittopage;
          ISB.LoadFromFile(PEFileName,1);
        end
        Else if ScanImgShowMode = 1 then  //模糊顯示
        begin
          ISB := FindISB2View(VMode);
          ISB.AntiAliased := False;
          ISB.ZoomMode := zmFittopage;
          ISB.LoadFromFile(PEFileName,1);
        end
        Else if ScanImgShowMode = 1 then  //不顯示
        begin
        end
      end;
    smReplace:
      begin
        DisplayISB.LoadFromFile(PEFileName,1);
      end;
    smInsert:
      begin
        ISB := FindISB2View(VMode);
        ISB.ZoomMode := zmFittopage;
        ISB.LoadFromFile(PEFileName,1);
      end;
    smSample:
      begin
        ISB := FindISB2View(VMode);
        ISB.ZoomMode := zmFittopage;
        ISB.LoadFromFile(PEFileName,1);
      end;
    smRTS:
      begin
      end;
  end;
end;
{ ==============================================================================
  方法名稱:PageEnd
  引用相依:GetNoNameCase, DirectoryExists, _DelTree, Str2Dir, SaveToFile, PageE
            nd
  方法描述:管理掃瞄影像的儲存路徑與檔案命名規則。主要邏輯如下:
            1. 辨識條碼以取得 FormID,並判斷是否為導引頁或分案頁。
            2. 若偵測到分案頁,會重置計數並嘗試取得新的案件編號(CaseID)。
            3. 確定儲存目錄,包含處理「分份數」邏輯(依 DocNoNeedDiv 決定是否建立新
            子目錄)。
            4. 根據目前頁數與 FormID 產生標準化的檔名(如補零序號_FormID.tif)。
            5. 更新 ContextList(影像索引資訊)並在掃瞄新案件時更新 TreeView UI 結
            構。此方法確保每張影像都能正確歸類到對應的案件與文件目錄下。
============================================================================== }
procedure TCB_IMGPSScanX.PageEnd;
Var
  i,n : Integer;
  SampleFormID : String;
  DocNo,FormID,FormVersion : String;
  BarStr : String;
begin
  case ScanMode of
    smNew:
      begin
        ScanSaveFilename := '';
        DocNo:='';
        FormID:='';
        FormVersion:='';
        PEFileName := '';
        //if not FindNoSaveBarCode then   //沒有不儲存影像的條碼
        //begin
          if FormID = '' then
          begin
            FormID := BarCode2FormID; //取出FormID
          end;
          if (FormID <> '') and ISDivPageFormID(FormID) then
          begin
            NowDivPageFormID := FormID;
          end;
          if (FormID <> '') and ISGuideFormID(FormID) then
          begin
            NowGuideFormID := FormID;
          end;
//ShowMessage('NowGuideFormID='+NowGuideFormID);
          if (not (FindDivFormCode(FormID))) and (NowGuideFormID <> '') {and (FormID = '')} then
            FormID := NowGuideFormID;
          DocNo := FormCode2DocNo(FormID);
//ShowMessage('FormID='+FormID);
//ShowMessage('ISDivPageFormID(FormID)='+BoolToStr(ISDivPageFormID(FormID),true));
//ShowMessage('FindDivFormCode(FormID)='+BoolToStr(FindDivFormCode(FormID),true));
//ShowMessage('A NowDivPageFormID='+NowDivPageFormID+#10#13+'FormID='+FormID+#10#13+'ScanCaseno='+ScanCaseno);
          if (FormID <>'') and FindDivFormCode(FormID) and (NowDivPageFormID <> '')  Then  //只找分案頁上的案件條碼
          begin
            ScanInfo.ImageCount := 0;
            ClearView(1);
            ContextList.Clear;
            Context_DocnoList.Clear;
            ClearCaseIndex;                //清掉案件索引
            ScanCaseno := BarCode2CaseID; //取出案件編號
            NowGuideFormID := '';
            NowDivPageFormID :='';
//ShowMessage('B NowGuideFormID='+NowGuideFormID+#10#13+'FormID='+FormID+#10#13+'ScanCaseno='+ScanCaseno);
          end;
          if ScanCaseno = '' then //一開始都沒找到
          begin
            ScanCaseno := GetNoNameCase(ImageSavePath);
          end;
          ImageSavePath := ImagePath;
          if (ScanInfo.ImageCount = 0) then
          begin
            if DirectoryExists(ImageSavePath + ScanCaseno+'\') then
            begin
              _DelTree(ImageSavePath + ScanCaseno+'\');
              SetCaseList('D',-1,ScanCaseno);
            end;
          end;
          ScanPath := ImageSavePath+ScanCaseno+'\';
          Str2Dir(ScanPath);
          ScanDocDir := FindLastestDocDir(ScanCaseno,DocNo);
//ShowMessage('AA ScanDocDir='+ScanDocDir);
//ShowMessage('BB ScanDocDir='+ScanDocDir);
          if DocNoNeedDiv(DocNo)then   //要分份數
          begin
            //Showmessage(DocNo+#13+FormCode2Page(FormID)+#13+inttostr(GetDocDir_Page(ScanCaseno,ScanDocDir))+#13+ScanDocDir);
            if ((FormCode2Page(FormID) = '01') and (GetDocDir_Page(ScanCaseno,ScanDocDir)>0))  or (ScanDocDir = '') then
            begin
              //ScanInfo.ImageCount := 0;
              ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
            end;
          end
          Else        //不分份數
          begin
            if DocNo <> '' then
              ScanDocDir := DocNo
            else      //Attach 附件
              ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
          end;
          //ScanDocDir := GetDocNoDir(ImageSavePath+ScanCaseno+'\',DocNo);
          if FirstDocDir = '' then
            FirstDocDir := ScanDocDir;
          ScanPath := ImageSavePath+ScanCaseno+'\'+ScanDocdir+'\';
          //Showmessage(ScanPath);
          if (not DirectoryExists(ScanPath)) and (ScanDocdir <> AttName) then
          begin
            //Showmessage('ADD:'+ScanCaseno+','+ScanDocdir);
            SetDocNoList('A',-1,ScanCaseno,ScanDocdir,'1');
          end;
          Str2Dir(ScanPath);
          ScanSaveFilename := FormID;
          Str2Dir(ScanPath);
          if ScanSaveFilename = '' then //附件
            ScanSaveFilename:= Add_Zoo(GetDocDir_Page(ScanCaseNo,ScanDocDir)+1,3)+ext
            //ScanSaveFilename:= Add_Zoo(ScanInfo.ImageCount+1,3)+ext
          Else
            ScanSaveFilename := Add_Zoo(GetDocDir_Page(ScanCaseNo,ScanDocDir)+1,3)+'_'+ScanSaveFilename+ext;
          if not FindNoSaveBarCode then   //沒有不儲存影像的條碼
          begin
            if ScanInfo.ImageCount = 0 then
            begin
              SetCaseList('A',-1,ScanCaseno);
              WriteCaseIndex(ImageSavePath + ScanCaseno+'\');  //寫入案件索引
              MyTreeNode1 := TreeView1.Items.AddChild(NewTreenode,ScanCaseno);
              MyTreenode1.ImageIndex := 2;
              MyTreenode1.SelectedIndex := 2;
              Application.ProcessMessages;
            end;
            SetContextList('A',-1,ScanCaseno,ScanDocDir,ScanSaveFilename);
          //ContextList.Add(ScanSaveFilename);
          //ContextList.SaveToFile(ScanPath+'Context.dat');
            PEFileName := ScanPath+ScanSaveFilename;
          end;
      end;
    smReplace:
      begin
        if ScanInfo.ImageCount = 0  then
        begin
          DeleteFile(ScanPath+ScanSaveFilename);
          PEFileName := ScanPath+ScanSaveFilename;
        end;
      end;
    smInsert:
      begin
        ScanSaveFilename := '';
        FormID := BarCode2FormID; //取出FormID
        if (FormID <> '') and ISGuideFormID(FormID) then   //20170510 註解 因為DSCAN 會全擠在導引頁下
          NowGuideFormID := FormID;
        if (NowGuideFormID <> '') {and (FormID = '')} then  //20170510 註解  因為DSCAN 會全擠在導引頁下
          FormID := NowGuideFormID;
        DocNo := FormCode2DocNo(FormID);
        ScanDocDir := FindLastestDocDir(ScanCaseno,DocNo);
        if (FMode='ESCAN') and (FModeName=_Msg('補件掃描')) then    //20180207 加入的特殊邏輯
        begin
          ScanDocDir := FindLastestDocDirForPage(ScanCaseno, DocNo,FormID);
        end;
        if (DocNoNeedDiv(DocNo)) then   //要分份數
        begin
          if TreeView1.Selected = MyTreeNode1 then   //20170421 掃瞄插頁時選則在案號上才要分份數 選在FormID上就不分份數
          begin
            if ((FormCode2Page(FormID) = '01') and (GetDocDir_Page(ScanCaseno,ScanDocDir)>0)) or (ScanDocDir = '') then
            begin
              ScanInfo.ImageCount := 0;
              ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
            end;
          end;
        end
        Else        //不分份數
        begin
          if DocNo <> '' then
            ScanDocDir := DocNo
          else      //Attach 附件
            ScanDocDir := DocNo2DocNoDir(ImageSavePath + ScanCaseno+'\',DocNo);
        end;
        if FirstDocDir = '' Then
          FirstDocDir := ScanDocDir;
        ScanPath := ImageSavePath+ScanCaseno+'\'+ScanDocdir+'\';
        if (not DirectoryExists(ScanPath)) and (ScanDocdir <> 'Attach') and (ScanDocdir <> 'S_Attach') then
          SetDocNoList('A',-1,ScanCaseno,ScanDocdir,'1');
        ScanSaveFilename := FormID;
        Str2Dir(ScanPath);
        if ScanSaveFilename = '' then //附件
          ScanSaveFilename:= Add_Zoo(GetDocDir_Page(ScanCaseno,ScanDocdir)+1,3)+ext
        Else
          ScanSaveFilename := Add_Zoo(GetDocDir_Page(ScanCaseno,ScanDocdir)+1,3)+'_'+ScanSaveFilename+ext;
        //ContextList.Add(ScanSaveFilename);
        //ContextList.SaveToFile(ScanPath+'Context.dat');
        SetContextList('A',-1,ScanCaseno,ScanDocDir,ScanSaveFilename);
        //Showmessage(ScanPath+ScanSaveFilename);
        //Showmessage('Stop');
        PEFileName := ScanPath+ScanSaveFilename;
      end;
    smSample:
      begin
        if ScanInfo.ImageCount = 0  then
        begin
          DeleteFile(ScanPath+ScanSaveFilename);
          PEFileName := ScanPath+ScanSaveFilename;
          BarStr := '';
          for i := 1 to MpsBarCodeinf.Count do
          begin
            BarStr := BarStr + MpsBarCodeinf.Text[i];
          end;
          Showmessage(_Msg('辨識到的BarCode:')+#13+BarStr);
        end;
      end;
    smRTS:
      begin
      end;
  end;
  Application.ProcessMessages;
end;
{ ==============================================================================
  方法名稱:R_W_Scanini
  引用相依:Scanner
  方法描述:讀取或寫入掃瞄設定檔(FBScan.ini)。此方法使用 Tinifile 物件處理掃瞄相
            關參數的 I/O 作業。當 Mode 為 'R' 時,從設定檔讀取包含空白頁刪除設定、
            影像反向、清黑邊、旋轉角度、傾斜矯正、亮度對比以及 UI 顯示模式等參數;當
            Mode 為 'W' 時,則將目前的系統變數值回寫至設定檔中,以利下次啟動時恢復
            使用者的個性化設定。
============================================================================== }
Procedure TCB_IMGPSScanX.R_W_Scanini(Mode:Char); //'R'讀取;'W'寫入
var
  ini : Tinifile;
begin
  ini := Tinifile.Create(ScaniniPath+'FBScan.ini');
  try
    case Mode of
    'R':begin
          DeviceDelete := ini.ReadBool('DeviceDelete','Mode',Def_DeviceDelete);
          DeviceDeleteSize := ini.ReadInteger('DeviceDelete','Size_New',Def_DeviceDeleteSize);
          ScannerReverse := ini.ReadBool('Scanner','Reverse',Def_ScannerReverse);
          BoardClear := ini.ReadBool('Scanner','BoardClear',Def_BoardClear);
          //ScanDpi := ini.ReadInteger('Scanner','Dpi',Def_ScanDpi);
          //ScanDuplex := ini.ReadBool('Scanner','Duplex',Def_ScanDuplex);
          ScanRotate := ini.ReadInteger('Scanner','ScanRotate',Def_ScanRotate);
          ScanDeskew := ini.ReadBool('Scanner','ScanDeskew',Def_ScanDeskew);
          ScanBright := ini.ReadInteger('Scanner','ScanBright',Def_ScanBright);
          ScanContrast := ini.ReadInteger('Scanner','ScanContrast',Def_ScanContrast);
          ScanImgShowMode := ini.ReadInteger('Scanner','ScanImgShowMode',Def_ScanImgShowMode);
          ScanImgSetUse := ini.ReadBool('Scanner','ScanImgSetUse',Def_ScanImgSetUse);  //20101110 BA說掃瞄器廠商有調設定要新增此選項是否啟動
        end;
    'W':begin
          ini.WriteBool('DeviceDelete','Mode',DeviceDelete);
          ini.WriteInteger('DeviceDelete','Size_New',DeviceDeleteSize);
          ini.WriteBool('Scanner','Reverse',ScannerReverse);
          ini.WriteBool('Scanner','BoardClear',BoardClear);
          //ini.ReadInteger('Scanner','Dpi',ScanDpi);
          //ini.WriteBool('Scanner','Duplex',ScanDuplex);
          ini.WriteInteger('Scanner','ScanRotate',ScanRotate);
          ini.WriteBool('Scanner','ScanDeskew',ScanDeskew);
          ini.WriteInteger('Scanner','ScanBright',ScanBright);
          ini.WriteInteger('Scanner','ScanContrast',ScanContrast);
          ini.WriteInteger('Scanner','ScanImgShowMode',ScanImgShowMode);
          ini.WriteBool('Scanner','ScanImgSetUse',ScanImgSetUse);  //20101110 BA說掃瞄器廠商有調設定要新增此選項是否啟動
        end;
    end;
  finally
  ini.Free;
  end;
end;
{ ==============================================================================
  方法名稱:GetDefScanIni
  引用相依:Rotate, FJpgCompression, Scanner
  方法描述:從資料庫參數清單(WORK_INF_List)初始化並設定掃瞄的系統預設值。流程首先
            設定一組程式內建的預設數值,隨後遍歷 WORK_INF_List 並比對 PARA_NO 關
            鍵字,動態更新包含:空白頁判斷大小、影像是否反相、清黑邊、掃瞄 DPI、雙面掃
            瞄開啟、影像旋轉角度、傾斜矯正、亮度對比、影像儲存路徑、導引頁與分案頁代
            碼列表、以及 JPEG 壓縮品質等關鍵參數。這使得掃瞄行為可以透過後台設定進
            行彈性調整。
============================================================================== }
Procedure TCB_IMGPSScanX.GetDefScanIni; //取得掃瞄的預設值
var
  i : Integer;
  PARA_NO,PARA_CONTENT: String;
begin
  Def_DeviceDelete := True;
  Def_DeviceDeleteSize := 3072;  //20120821 改成3000(出現)
  Def_ScannerReverse := False;
  Def_BoardClear := False;
  Def_ScanDpi := 300;
  Def_ScanDuplex := True;
  Def_ScanRotate := 0;
  Def_ScanDeskew := False;
  Def_ScanImgSetUse := False;
  Def_ScanBright := 0;
  Def_ScanContrast := 0;
  Def_ScanImgShowMode := 2;
  for i := 0 to WORK_INF_List.Count - 1 do
  begin
    IF GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BLANKDEL_USE' Then   //空白頁啟動
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if UpperCase(PARA_CONTENT) ='Y'  then
        Def_DeviceDelete := True
      Else
        Def_DeviceDelete := False;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BLANKDEL_SIZE' Then  //空白頁Size
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if PARA_CONTENT = ''  then
        Def_DeviceDeleteSize := 0
      Else
        Def_DeviceDeleteSize := Strtoint(PARA_CONTENT);
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_REVERSE' Then  //是否需反相
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if UpperCase(PARA_CONTENT) ='Y'  then
        Def_ScannerReverse := True
      Else
        Def_ScannerReverse := False;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BOARDCLEAR' Then  //是否清黑邊
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if UpperCase(PARA_CONTENT) ='Y'  then
        Def_BoardClear := True
      Else
        Def_BoardClear := False;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_DPI' Then  //掃瞄DPI
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if PARA_CONTENT = ''  then
        Def_ScanDpi := 300
      else
        Def_ScanDpi := Strtoint(PARA_CONTENT);
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_DUPLEX' Then  //是否雙面掃瞄
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if UpperCase(PARA_CONTENT) ='Y'  then
        Def_ScanDuplex := True
      Else
        Def_ScanDuplex := False;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_ROTATE_MODE' Then //掃瞄時旋轉角度
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if PARA_CONTENT = '0' then
        Def_ScanRotate := 0
      Else if PARA_CONTENT = '1' then
        Def_ScanRotate := 270
      Else if PARA_CONTENT = '2' then
        Def_ScanRotate := 180
      Else if PARA_CONTENT = '3' then
        Def_ScanRotate := 90
      Else
        Def_ScanRotate := 0;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_DESKEW' Then //是否傾斜矯正
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if UpperCase(PARA_CONTENT) ='Y'  then
        Def_ScanDeskew := True
      Else
        Def_ScanDeskew := False;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_IMGSET_USE' Then  //是否使用亮度對比設定
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if UpperCase(PARA_CONTENT) ='Y'  then
        Def_ScanImgSetUse := True
      else
        Def_ScanImgSetUse := False;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_BRIGHT' Then //亮度
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if PARA_CONTENT =''  then
        Def_ScanBright := 0
      Else
        Def_ScanBright := strtoint(PARA_CONTENT);
      if (Def_ScanBright > 255) or (Def_ScanBright < -255) then
        Def_ScanBright := 0;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_CONTRAST' Then //對比
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if PARA_CONTENT =''  then
        Def_ScanContrast := 0
      Else
        Def_ScanContrast := strtoint(PARA_CONTENT);
      if (Def_ScanContrast > 255) or (Def_ScanContrast < -255) then
        Def_ScanContrast := 0;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_SHOW_MODE' Then
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      if PARA_CONTENT = '0' then
        Def_ScanImgShowMode := 0
      Else if PARA_CONTENT = '1' then
        Def_ScanImgShowMode := 1
      Else if PARA_CONTENT = '2' then
        Def_ScanImgShowMode := 2
      Else
        Def_ScanImgShowMode := 0;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'CASE_IN_TIME' Then     //取進件截止時間
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      ScanDenialTime := PARA_CONTENT;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_HINT' Then     //掃描提示字串
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      ScanDenialHint := PARA_CONTENT;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'NO_SAVE_FORM_ID' Then     //掃描不存檔之表單代號
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      NoSaveBarCodeList.CommaText := PARA_CONTENT;
    end
    Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'LOCAL_PATH' Then     //本機端路徑
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      ImagePath:= PARA_CONTENT;
    end
    Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'GUIDEFORMID' Then     //當導引頁的表單
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      GuideFormIDList.CommaText := PARA_CONTENT;
    end
    Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'DIVPAGEFORMID' Then     //當分案頁的表單
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      DivPageFormIDList.CommaText := PARA_CONTENT;
    end
    Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'FILE_COMPRESSION' Then     //20171211 jpg to tif 壓縮比
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      FJpgCompression := StrToInt(PARA_CONTENT);
    end
    Else if UpperCase(GetSQLData(WORK_INF_List,'PARA_NO',i)) = 'MAX_UPLOAD_SIZE' Then     //取得 上傳大小的限制(MB)
    begin
      PARA_CONTENT := GetSQLData(WORK_INF_List,'PARA_CONTENT',i);
      FMaxUploadSize := PARA_CONTENT;
    end;
  end;
  ScanDuplex := Def_ScanDuplex;
end;
{ ==============================================================================
  方法名稱:initkscan
  引用相依:initkscan, Scanner, Scanner.OpenSource, Scanner.CloseSource
  方法描述:初始化並偵測掃瞄器硬體能力。此方法會先將雙面掃瞄勾選框(ScanDuplexCB)
            設為停用,接著嘗試開啟掃瞄來源(OpenSource),檢查掃瞄器是否支援雙面掃瞄
            功能(DuplexCap > 0)。如果硬體支援,則啟用 UI 上的勾選框供使用者選擇。最
            後確保關閉掃瞄來源,若過程中發生異常,會呼叫 DataLoading(False,True)
            停止載入狀態提示。
============================================================================== }
procedure TCB_IMGPSScanX.initkscan;
begin
  ScanDuplexCB.Enabled := False;
  if Scanner.IsConfigured then
  begin
    try
      Scanner.OpenSource;
      IF Scanner.DuplexCap > 0 Then
      begin
        ScanDuplexCB.Enabled := True;
      end;
      {IF Scanner.FEEDERCAP Then
        ScanFlatCB.Enabled := True; }
    Except
      DataLoading(False,True);
      Exit;
    end;
    Scanner.CloseSource;
  end;
end;
reassemble/transp/fileClient.pas
比對新檔案
@@ -0,0 +1,161 @@
{ ==============================================================================
  方法名稱:GetFtpinfo
  引用相依:
  方法描述:向伺服器請求案件上傳所需的 FTP 連線資訊。核心邏輯:
            1. 發送包含案件編號與動作代碼的 HTTP POST 請求至後台 Servlet。
            2. 解析伺服器回傳結果,若回傳 'nodata' 則維持 tsNone 模式;若回傳成功,
            則根據標籤判斷是否啟用 FTP 模式 (tsFtp)。
            3. 若為 FTP 模式,會進一步解析並呼叫 DecodeFtpInfo 對包含連線協定、IP、
            Port、帳號及密碼的加密字串進行解密,並存入系統全域變數中。
============================================================================== }
Function TCB_IMGPSScanX.GetFtpinfo(CaseID,Action:String):Boolean;
var
  SendData : String;
  Procedure DecodeFtpInfo(EncryStr:String);
  var
    FtpStr : String;
    ftpinfoList : TStringlist;
  begin
    if EncryStr = '' then Exit;
    ftpinfoList := TStringlist.Create;
    try
      FtpStr := En_DecryptionStr_Base64('D',EncryStr,MpsKey);
      SplitString('!@!',FtpStr,ftpinfoList);
      if ftpinfoList[0] = 'ftps' then
        FFtpProtocol := fpftps
      else if ftpinfoList[0] = 'ftp' then
        FFtpProtocol := fpftp;
      FFtpIP := ftpinfoList[1];
      FFtpPort := strtoint(ftpinfoList[2]);
      FFtpID := ftpinfoList[3];
      FFtpPwd := ftpinfoList[4];
    finally
    ftpinfoList.Free;
    end;
  end;
begin
  Result := True;
  SendData:='product='+FWork_no+'&case_no='+CaseID+'&department='+FUserUnit+'&action='+Action;
  If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/ftps',SendData,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF (memo1.Lines.Strings[0] = '1') Then
  begin
    if memo1.Lines.Strings[1]='nodata' then   //nodata 為正常可繼續的判斷
    begin
      TransMode := tsNone;
      Result := True;
      Exit;
    end
    else
    begin
      HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
      Result := False;
      Exit;
    end;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end
  else if (memo1.Lines.Strings[0] <> '0') then//不認識的字串
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[0];
    Result := False;
    Exit;
  end;
  TransMode := tsHttp;
  FFtpExtraPath := '';
  if memo1.Lines.Strings[0] = '0' then
  begin
    if memo1.Lines.Strings[2] = 'Y' then   //要使用FTP
      TransMode := tsFtp;
    if memo1.Lines.Count > 3 then
    begin
      FFtpExtraPath := memo1.Lines.Strings[3];
      DecodeFtpInfo(memo1.Lines.Strings[4]);
    end;
  end;
end;
{ ==============================================================================
  方法名稱:SetFtpInfo
  引用相依:SetFtpInfo, IIS_Ftp
  方法描述:將 FTP 連線參數與事件回呼設定至 FTP 傳輸元件 (IIS_Ftp)。此方法會將先
            前取得並解碼的連線資訊(如 FTP IP、帳號、密碼、路徑、連接埠)指派給 IIS_Ft
            p 物件,並根據協定類型設定是否開啟 SSL/TLS 以及被動模式 (Passive)。此
            外,也會關聯各項事件處理器(如 SSLError, CertificateValidate, TextData
            Line 等),以監控傳輸過程中的通訊狀態。
============================================================================== }
Procedure TCB_IMGPSScanX.SetFtpInfo;     //餵入FTP資訊
begin
  IIS_Ftp.Display1 := Display1;
  IIS_Ftp.FTPSClient1 := FTPSClient1;
  IIS_Ftp.ElMemoryCertStorage := ElMemoryCertStorage;
  IIS_Ftp.Display1 := Display1;
  IIS_Ftp.Ftpip := FFtpIP;
  IIS_Ftp.Ftpuserid := FFtpID;
  IIS_Ftp.FtpPwd := FFtpPwd;
  IIS_Ftp.FtpPath := FFtpRootPath;
  IIS_Ftp.FtpPort := FFtpPort;
  IIS_Ftp.FtpSSL := True;
  IIS_Ftp.FtpPassive := True;
  if FFtpProtocol = fpftp then
     IIS_Ftp.FtpSSL := False;
  IIS_Ftp.FtpEncryptDataChannel := true;
  FTPSClient1.OnControlReceiveAsString := IIS_Ftp.EventHandlers.ControlReceiveAsString;
  FTPSClient1.OnControlSendAsString := IIS_Ftp.EventHandlers.ControlSendAsString;
  FTPSClient1.OnSSLError := IIS_Ftp.EventHandlers.SSLError;
  FTPSClient1.OnCertificateValidate := IIS_Ftp.EventHandlers.CertificateValidate;
  FTPSClient1.OnTextDataLine := IIS_Ftp.EventHandlers.TextDataLine;
  {Showmessage(Format('Ftpip:%s'+#13
              +'Ftpid:%s'+#13
              +'Ftppwd:%s'+#13
              +'Ftppath:%s'+#13
              +'Ftpport:%s'+#13
              ,[FFtpIP,FFtpid,FFtpPwd,Ftppath,inttostr(Ftpport)]));}
end;
{ ==============================================================================
  方法名稱:FtpCaseComplete
  引用相依:FtpCaseComplete, ProcessServlet_FormData
  方法描述:通知後台伺服器 FTP 案件上傳已完成。方法會將包含案件狀態的上傳數據發送
            至特定的 Servlet 介面。邏輯包含檢查 HTTP 通訊是否成功、解析伺服器回傳
            的結果代碼,並處理可能的登入過期(Session Timeout)情況。若執行失敗,會將
            錯誤原因記錄至 HttpErrStr,供後續 UI 顯示錯誤訊息。
============================================================================== }
Function TCB_IMGPSScanX.FtpCaseComplete(SendData:String):Boolean;
begin
  Result := True;
  If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/caseupload',SendData,FReWrite,Memo1,False) Then
  begin
    HttpErrStr := _Msg('錯誤代碼:')+inttostr(HttpError.HttpErrorCode)+','+HttpError.HttpReason;
    Result := False;
    Exit;
  end;
  IF (memo1.Lines.Strings[0] = '1') or (memo1.Lines.Strings[0] <> '0') Then
  begin
    HttpErrStr := _Msg('錯誤原因:')+memo1.Lines.Strings[1];
    Result := False;
    Exit;
  end
  Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
  begin
    HttpErrStr := _Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入');
    Result := False;
    Exit;
  end;
end;
reassemble/transp/payloadArchiver.pas
比對新檔案
@@ -0,0 +1,130 @@
{ ==============================================================================
  方法名稱:ZipMainFile
  引用相依:FileExists, LoadFromFile
  方法描述:將案件的主要圖檔與所有中繼資料檔案打包壓縮為 ZIP。流程如下:
            1. 遍歷影像清單 (ContextList) 與附件清單 (AttContextList) 加入實體圖
            檔。
            2. 自動偵測並加入多種系統紀錄檔,包含索引檔 (Context.dat)、掃瞄清單 (s
            canlist.dat)、縮放紀錄 (ReSize.dat)、案件分類資訊 (CaseDocNo_Copies.da
            t) 及跨案引用設定 (UseCase.ini) 等。
            3. 檢查是否存在特殊壓縮檔 (FirstImg.zip) 並併入。
            4. 呼叫 ExeCuteZip 執行壓縮作業,確保上傳時案件資料的完整性。
============================================================================== }
Procedure TCB_IMGPSScanX.ZipMainFile(SoPath,DePath,ZipName:String);
var
  ZipFileList : TStringlist;
  n : Integer;
begin
  ZipFileList := TStringlist.Create;
  try
    if fileExists(DePath+ZipName) then
      DeleteFile(DePath+ZipName);
    {if FileExists(SoPath+'ReSize.dat') then
      DeleteFile(SoPath+'ReSize.dat');}
    //Showmessage(SoPath+#13+ContextList.Text);
    for n := 0 to ContextList.Count - 1 do
    begin
      {WriteResize(SoPath+ContextList.Strings[n],SoPath+'ReSize.dat');}
      ZipFileList.Add(SoPath+ContextList.Strings[n]);
      if FileExists(SoPath+'@'+ContextList.Strings[n]) then
        ZipFileList.Add(SoPath+'@'+ContextList.Strings[n]);
    end;
    if FileExists(SoPath+'Context.dat') then
      ZipFileList.Add(SoPath+'Context.dat');
    AttContextList.Clear;
    if FileExists(SoPath+'ATTContext.dat') then
      AttContextList.LoadFromFile(SoPath+'ATTContext.dat');
    for n := 0 to AttContextList.Count - 1 do
    begin
      ZipFileList.Add(SoPath+AttContextList.Strings[n]);
    end;
    if FileExists(SoPath+'ATTContext.dat') then
      ZipFileList.Add(SoPath+'ATTContext.dat');
    if FileExists(SoPath+'Context_DocNo.dat') then
      ZipFileList.Add(SoPath+'Context_DocNo.dat');
    if FileExists(SoPath+'scanlist.dat') then
      ZipFileList.Add(SoPath+'scanlist.dat');
    if FileExists(SoPath+'FormCode_Name.dat') then
      ZipfileList.Add(SoPath+'FormCode_Name.dat');
    if FileExists(SoPath+'DocNo_Name.dat') then
      ZipfileList.Add(SoPath+'DocNo_Name.dat');
    if FileExists(SoPath+'ReSize.dat') then
      ZipfileList.Add(SoPath+'ReSize.dat');
    if FileExists(SoPath+'FormIDReplace.dat') then
      ZipfileList.Add(SoPath+'FormIDReplace.dat');
    if FileExists(SoPath+'AnchorError.dat') then
      ZipfileList.Add(SoPath+'AnchorError.dat');
    if FileExists(SoPath+'CaseDocNo.dat') then
      ZipfileList.Add(SoPath+'CaseDocNo.dat');
    if FileExists(SoPath+'CaseDocNo_Copies.dat') then
      ZipfileList.Add(SoPath+'CaseDocNo_Copies.dat');
    if FileExists(SoPath+'CustomDocNo.ini') then
      ZipfileList.Add(SoPath+'CustomDocNo.ini');
    if FileExists(SoPath+'DocDir.dat') then
      ZipfileList.Add(SoPath+'DocDir.dat');
    if FileExists(SoPath+'In_Wh.dat') then
      ZipfileList.Add(SoPath+'In_Wh.dat');
    if FileExists(SoPath+'UseCase.ini') then
      ZipfileList.Add(SoPath+'UseCase.ini');
    if FileExists(SoPath+'FirstImg.zip') then//20170315 加的
    begin
      ZipfileList.Add(SoPath+'FirstImg.zip');
    end;
    ExeCuteZip(DePath+ZipName,SoPath,ZipFileList,False,False);
    //Showmessage('111');
  finally
  ZipFileList.Free;
  end;
end;
{ ==============================================================================
  方法名稱:ZipMaskFile
  引用相依:FileExists
  方法描述:壓縮遮罩影像檔及其相關設定檔。此方法會從指定遮罩路徑 (MarkPath) 收集
            與影像索引 (ContextList) 對應的遮罩圖檔,同時併入基本的案件資訊檔(如
            Context.dat, scanlist.dat, DocNo_Name.dat)以及系統預設的錯誤與授權圖
            檔(Err.jpg, auth.jpg)。最後將這些檔案統一壓縮至目標路徑,供後續遮罩影
            像的上傳作業使用。
============================================================================== }
Procedure TCB_IMGPSScanX.ZipMaskFile(SoPath,MarkPath,DePath,ZipName:String); //壓縮遮罩影像檔
var
  ZipFileList : TStringlist;
  n : Integer;
begin
  ZipFileList := TStringlist.Create;
  try
    if fileExists(DePath+ZipName) then
      DeleteFile(DePath+ZipName);
    for n := 0 to ContextList.Count - 1 do
    begin
      ZipFileList.Add(MarkPath+ContextList.Strings[n]);
    end;
    if FileExists(SoPath+'Context.dat') then
      ZipFileList.Add(SoPath+'Context.dat');
    if FileExists(SoPath+'scanlist.dat') then
      ZipFileList.Add(SoPath+'scanlist.dat');
    if FileExists(SoPath+'FormCode_Name.dat') then
      ZipfileList.Add(SoPath+'FormCode_Name.dat');
    if FileExists(SoPath+'DocNo_Name.dat') then
      ZipfileList.Add(SoPath+'DocNo_Name.dat');
    if FileExists(SoPath+'ReSize.dat') then
      ZipfileList.Add(SoPath+'ReSize.dat');
    if FileExists(SoPath+'Err.jpg') then
      ZipfileList.Add(SoPath+'Err.jpg');
    if FileExists(SoPath+'auth.jpg') then
      ZipfileList.Add(SoPath+'auth.jpg');
    ExeCuteZip(DePath+ZipName,SoPath,ZipFileList,False,False);
  finally
  ZipFileList.Free;
  end;
end;
reassemble/view/listView.pas
比對新檔案
@@ -0,0 +1,77 @@
{ ==============================================================================
  方法名稱:PageLVClick
  引用相依:
  方法描述:處理影像列表點擊。選取項目後同步更新 ScrollBar1 的位置。
============================================================================== }
procedure TCB_IMGPSScanX.PageLVClick(Sender: TObject);
begin
  IF PageLV.Selected = nil Then Exit;
  PageLVclear := False;
  ScrollBar1.Position := PageLV.Selected.Index+1;
  PageLVclear := True;
end;
{ ==============================================================================
  方法名稱:PageLVKeyUp
  引用相依:
  方法描述:處理影像列表按鍵放開事件。若有選取項目,則同步更新 ScrollBar1 的位置。
============================================================================== }
procedure TCB_IMGPSScanX.PageLVKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  IF PageLV.Selected = nil Then Exit;
  ScrollBar1.Position := PageLV.Selected.Index+1;
end;
{ ==============================================================================
  方法名稱:PageLVMouseDown
  引用相依:
  方法描述:處理影像列表滑鼠按下事件。若是右鍵,則選取該項目並彈出右鍵選單。
============================================================================== }
procedure TCB_IMGPSScanX.PageLVMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  IF Button = TMouseButton(MbRight) Then
  begin
    If PageLV.GetItemAt(X,Y) = nil then Exit;
    PageLV.Selected := PageLV.GetItemAt(X,Y);
    PageLVClick(self);
    PageLV.PopupMenu.Popup(Mouse.CursorPos.X ,Mouse.CursorPos.Y);
  end;
end;
{ ==============================================================================
  方法名稱:AttListBoxClick
  引用相依:
  方法描述:處理附加檔案列表點擊,若有選取則啟用刪除按鈕。
============================================================================== }
procedure TCB_IMGPSScanX.AttListBoxClick(Sender: TObject);
begin
  DelAttFileLB.Enabled := False;
  if AttListBox.ItemIndex >= 0 then
    DelAttFileLB.Enabled := True;
end;
{ ==============================================================================
  方法名稱:AttListBoxDblClick
  引用相依:FileExists
  方法描述:處理附加檔案列表連按兩下,呼叫 ShellExecute 開啟檔案。
============================================================================== }
procedure TCB_IMGPSScanX.AttListBoxDblClick(Sender: TObject);
var
  AttFile : String;
begin
  if AttListBox.ItemIndex < 0 then Exit;
  AttFile := HTTPEncode(UTF8Encode(AttListBox.Items.Strings[AttListBox.ItemIndex]));
  if FileExists(DisplayPath+AttFile) then
    ShellExecute(Application.Handle,'open',PChar(DisplayPath+AttFile),nil,nil,SW_SHOW)
  else
    Showmessage(Format(_Msg('找不到檔案:%s'),[AttFile]));
end;
reassemble/view/misc.pas
比對新檔案
檔案太大
reassemble/view/msger.pas
比對新檔案
@@ -0,0 +1,66 @@
{ ==============================================================================
  方法名稱:StatusBar1DblClick
  引用相依:
  方法描述:處理狀態列連按兩下事件。用於切換測試功能按鈕及除錯訊息視窗(Memo1/Disp
            lay1)的顯示,支援搭配 Control 鍵切換授權匯出/匯入功能。
============================================================================== }
procedure TCB_IMGPSScanX.StatusBar1DblClick(Sender: TObject);
begin
  Button3.Visible := not Button3.Visible;
  Button4.Visible := not Button4.Visible;
  if (GetKeyState(VK_CONTROL) < 0) Then
  begin
    ExportBt.Visible := not ExportBt.Visible;
    ImportBt.Visible := not ImportBt.Visible;
  end
  Else
  begin
    Memo1.Visible := not Memo1.Visible;
    Display1.Visible := not Display1.Visible;
  end;
end;
{ ==============================================================================
  方法名稱:DataLoading
  引用相依:
  方法描述:控制資料載入時的 UI 狀態。啟用載入時會切換滑鼠游標為等待狀態、顯示提示
            面板(Panel22 或 Panel8),並禁用主要的操作面板(Panel1/Panel2);關閉時則
            恢復正常狀態。支援使用計時器(Timer2)來顯示動態提示。
============================================================================== }
Procedure TCB_IMGPSScanX.DataLoading(Loading:Boolean;UseTimer:Boolean);  //資料載入中要停止點選的動作
begin
  If Loading Then
  begin
    Screen.Cursor := -11;
    if UseTimer then
    begin
      Panel22.Caption := ShowText;
      Panel22.Left := (Panel9.Width div 2) - (Panel22.Width div 2);
      Panel22.Top := (Panel9.Height div 2) - (Panel22.Height div 2);
      Panel22.Visible := True;
      Timer2.Enabled := True;
    end
    Else
    begin
      Panel8.Left := (Panel9.Width div 2) - (Panel8.Width div 2);
      Panel8.Top := (Panel9.Height div 2) - (Panel8.Height div 2);
      Panel8.Visible := True;
    end;
    Application.ProcessMessages;
    Panel1.Enabled := False;
    Panel2.Enabled := False;
  end
  Else
  begin
    Panel22.Visible := False;
    Panel8.Visible := False;
    Timer2.Enabled := False;
    Panel1.Enabled := True;
    Panel2.Enabled := True;
    Screen.Cursor := 0;
  end;
end;
reassemble/view/popupMenu.pas
比對新檔案
@@ -0,0 +1,2020 @@
{ ==============================================================================
  方法名稱:PM401Click
  引用相依:GetNoNameCase, Str2Dir, RenameFile, SaveToFile, FileExists, LoadFrom
            File
  方法描述:影像列表右鍵選單功能:從指定頁面分出新案。確認使用者選取的分案起點(不
            能為第一頁)後,取得新的流水案號並建立目錄。將原案件中該頁碼之後的所有
            影像檔案更名並搬移至新案目錄,同步更新原案與新案的 Context.dat 與 Cas
            eIndex.dat。完成後重新載入影像列表並提示完成。
============================================================================== }
procedure TCB_IMGPSScanX.PM401Click(Sender: TObject);
var
  i : Integer;
  FromIndex : Integer;
  CaseID : String;
  NewPath : String;
  OldName,NewName:String;
  S : TStringlist;
begin
  S := TStringlist.Create;
  try
    FromIndex := PageLv.ItemIndex;
    if FromIndex = 0 then
    begin
      Showmessage(_Msg('不能從第1頁分案'));
      Exit;
    end;
    If MessageDlg(Format(_Msg('是否確定從%d頁分出新案'),[PageLV.ItemIndex+1]),Mtconfirmation,[mbyes,mbcancel],0) = mrcancel Then Exit;
    ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
    CaseID := GetNoNameCase(ImageSavePath);
    NewPath := ImageSavePath + CaseID+'\';
    Str2Dir(NewPath);
    for i := FromIndex to ContextList.Count - 1 do
    begin
      OldName := ContextList.Strings[i];
      //NewName := Add_Zoo(S.Count+1,3)+Copy(OldName,4,length(OldName)-3);
      NewName := Add_Zoo(S.Count+1,3)+FileName2NoQuene_Filename(OldName);
      ReNameFile(DisplayPath+OldName,NewPath+NewName);
      S.Add(NewName);
      S.SaveToFile(NewPath+'Context.dat');
    end;
    for i := ContextList.Count - 1 downto FromIndex do
    begin
      ContextList.Delete(i);
      ContextList.SaveToFile(DisplayPath+'Context.dat');
    end;
    SetCaseList('I',MyTreeNode1.IndexOf(MyTreeNode2)+1,CaseID);
    if FileExists(DisplayPath+'CaseIndex.dat') then  //把原經辦代號取出來再寫入新件裡
    begin
      S.LoadFromFile(DisplayPath+'CaseIndex.dat');
    end;
    DisplayPath := '';
    ClearCaseIndex;
    WriteCaseIndex(NewPath);
  finally
  S.Free;
  end;
  LoadImgFile;
  Showmessage(_Msg('分案完成'));
end;
{ ==============================================================================
  方法名稱:PM402Click
  引用相依:
  方法描述:將影像列表(PageLV)中的所有項目設為選取狀態。
============================================================================== }
procedure TCB_IMGPSScanX.PM402Click(Sender: TObject);
var
  i : Integer;
begin
  for i := 0 to PageLV.Items.Count - 1 do
  begin
    PageLV.Items.Item[i].Selected := True;
  end;
end;
{ ==============================================================================
  方法名稱:PM403Click
  引用相依:
  方法描述:將影像列表(PageLV)中的所有項目設為取消選取狀態。
============================================================================== }
procedure TCB_IMGPSScanX.PM403Click(Sender: TObject);
var
  i : Integer;
begin
  for i := 0 to PageLV.Items.Count - 1 do
  begin
    PageLV.Items.Item[i].Selected := False;
  end;
end;
{ ==============================================================================
  方法名稱:PM404Click
  引用相依:
  方法描述:影像列表右鍵選單功能:文件歸類。開啟 TDocListForm 顯示可用的表單清單供
            使用者選擇。確認後根據當前 TreeView 的選取層級(案件級別、文件級別或特
            定表單),呼叫 PageReplaceFormID 將影像重新歸類至選定的表單類型。歸類完
            成後重新繪製樹狀結構並清空檢核記錄,最後回到原先選取的節點。
============================================================================== }
procedure TCB_IMGPSScanX.PM404Click(Sender: TObject);
var
  i : Integer;
  DocListForm : TDocListForm;
  OldName,NewName,Ext : String;
  FormID,FormName : String;
  PreNode2Name : String;
begin
  PreNode2Name := '';
  if TreeView1.Selected.Parent = MyTreeNode1 then
    PreNode2Name:= GetNode2Name(MyTreeNode2);
  ShowText := _Msg('文件歸類中,請稍候');
  DataLoading(True,True);
  DocListForm := TDocListForm.Create(self);
  try
    InitialLanguage(PatchDlg); //載入多國語言
    for i := 1 to FORM_INF_List.Count - 1 do
    begin
      FormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
      FormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
      if (FormID <> NowFormCode) and FormIDExists(FormID,True,0) then
      begin
        DocListForm.FormIDList.Add(FormID+'#@#'+FormName);
        With DocListForm.DocLV.Items.Add do
        begin
          Caption := FormID;
          SubItems.Add(FormName);
        end;
      end;
    end;
    if DocListForm.ShowModal = mrOk then
    begin
      FormID := DocListForm.DocLV.Selected.Caption;
      if (TreeView1.Selected.Level=1) then
      begin
        PageReplaceFormID(DisplayPath,'ALL',FormID);
      end
      Else if (TreeView1.Selected.Level=2) and (NowFormCode = '') then
        PageReplaceFormID(DisplayPath,'',FormID)
      Else
      begin
        PageReplaceFormID(DisplayPath,NowFormCode,FormID);
      end;
      //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
      //DrawDocItem1(MytreeNode1,Doc_Inf_List,NowCaseno);  //201408280改
      DrawDocItem2(MytreeNode1,NowCaseno);
      ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
      //Showmessage(_Msg('歸類完成'));  //20101103 User要求拿掉
      if PreNode2Name <> '' then  // 回到原本點選的文件節點上
      begin
        for i := 0 to MyTreeNode1.Count - 1 do
        begin
          if GetNode2Name(MyTreeNode1.Item[i]) = PreNode2Name then
          begin
            TreeView1.Selected := MyTreeNode1.Item[i];
            Break;
          end;
        end;
      end;
      TreeView1click(self);
    end;
  finally
  DocListForm.Free;
  DataLoading(False,False);
  end;
end;
{ ==============================================================================
  方法名稱:PM601Click
  引用相依:FileExists, LoadFromFile, DirectoryExists, CopyFile, SaveToFile, Del
            eteImageFile, RenameFile, ReSortFileName
  方法描述:縮圖瀏覽區右鍵選單功能:文件歸類。針對所有被選取(由 Shape 標記)的影像,
            開啟 TDocListForm 選擇目標表單。核心邏輯包含:判斷目標文件是否需要區分
            份數、自動產生新的文件目錄或沿用既有目錄、根據檔案序號產生新檔名、執行
            檔案複製並更新 ContextList。最後刪除原檔案、重新排序原目錄並重新繪製樹
            狀結構。
============================================================================== }
procedure TCB_IMGPSScanX.PM601Click(Sender: TObject);
var
  i : Integer;
  DocListForm : TDocListForm;
  OldName,NewName,Ext : String;
  FormID,FormName,DocNo,DocDir : String;
  PreNode2Name : String;
  iFormID : String;
  iISBName : String;
  iISB : TImageScrollBox;
  GoAtt : Boolean;
  AttLv : Integer;
  ST1 :TStringList;
begin
  PreNode2Name := '';
  ST1:=TStringList.Create;
  if TreeView1.Selected.Parent = MyTreeNode1 then
    PreNode2Name:= GetNode2Name(MyTreeNode2);
  ShowText := _Msg('文件歸類中,請稍候');
LogFile1.LogToFile(logTimeString+'縮圖  歸類開始');
  DataLoading(True,True);
  GoAtt := False;
  if (MytreeNode2 <> nil) and (Pos('Attach',MyTreeNode2.Text)>0) then
  begin
    AttLv := TreeView1.Selected.Level;
    GoAtt := True;
  end;
  DocListForm := TDocListForm.Create(self);
  try
    InitialLanguage(DocListForm); //載入多國語言
    //InitialLanguage(PatchDlg); //載入多國語言
    DocListForm.CheckBox1.Visible:=False;
    for i := 1 to FORM_INF_List.Count - 1 do
    begin
      FormID :=  GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
      FormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
      DocNo := GetSQLData(FORM_INF_List,'T1.DOC_NO',i)+GetSQLData(FORM_INF_List,'T1.DOC_VERSION',i);
      if not FormIDAppear(FormID) then Continue;   //20170816 先秀全部
      //Showmessage(FORM_INF_List.Text);
      //showmessage(inttostr(FORM_INF_List.Count)+#13+inttostr(self.Doc_Inf_List.Count));
      if (FormID <> FileName2FormCode(DisplayISB.FileName)) and FormIDExists(FormID,False,i) then
      begin
        DocListForm.FormIDList.Add(FormID+'#@#'+FormName);
        With DocListForm.DocLV.Items.Add do
        begin
          Caption := FormID;
          SubItems.Add(FormName);
        end;
      end;
    end;
    if DocListForm.ShowModal = mrOk then
    begin
      for i := 0 to ComponentCount -1 do
      begin
        if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
        begin
          iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
          iISB := TImageScrollBox(FindComponent(iISBName));
          OldName := ExtractFileName(iISB.FileName);
          Ext := ExtractFileExt(OldName);
          if DocListForm.CheckBox1.Checked then
          begin
            FormID := DocListForm.Edit1.Text;
            DocNo := GetNewCustomDocNo(DisplayPath,FormID);
          end
          else
          begin
            FormID := DocListForm.DocLV.Selected.Caption;
            DocNo := FormCode2DocNo(FormID);
          end;
          if DocNoDir2DocNo(Path2DocDir(ExtractFilePath(iISB.FileName),NowCaseno)) = DocNo then
            DocDir := Path2DocDir(ExtractFilePath(iISB.FileName),NowCaseNo)
          Else
            DocDir := FindLastestDocDir(NowCaseno,DocNo);
//ShowMessage('DocNoNeedDiv(DocNo)='+BoolToStr(DocNoNeedDiv(DocNo),true));
//ShowMessage('DocDir='+DocDir);
          if DocNoNeedDiv(DocNo) then   //要分份數
          begin
            if ((FormCode2Page(FormID) = '01') and (GetDocDir_Page(NowCaseno,DocDir)>0)) or (DocDir = '') then
            begin
              DocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',DocNo);
            end
            else
            begin //20171016  真對補件影響 所加的判斷
              ST1.Clear;
              if FileExists(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat') then
              begin
                ST1.LoadFromFile(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat');
                if (ST1.Count > 0) and ISExistImg(ImageSavePath + NowCaseno+'\'+DocDir+'\'+ST1.Strings[0]) then   //20181210 多增加判斷ST1>0 否則會有機會出現List out of bound  Hong
                begin
                  DocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',DocNo);
                end;
              end;
            end;
          end
          Else        //不分份數
          begin
            if DocNo <> '' then
              DocDir := DocNo
            else      //Attach 附件
              DocDir := DocNo2DocNoDir(ImageSavePath + NowCaseno+'\',DocNo);
          end;
          if (not DirectoryExists(ImageSavePath + NowCaseno+'\'+DocDir+'\')) and (DocDir <> AttName) then
            SetDocNoList('A',-1,NowCaseno,DocDir,'1');
          {if DocDir = '' then
          begin
            DocDir := DocNo;
            if DocNoNeedDiv(DocNo) then
              DocDir:=DocNo2DocNoDir(ImageSavePath+NowCaseno+'\',DocNo);
            SetDocNoList('A',-1,NowCaseno,DocDir);
          end; }
LogFile1.LogToFile(logTimeString+'縮圖  FormID='+FormID);
          if Not DirectoryExists(ImageSavePath+NowCaseno+'\'+DocDir) then
            Mkdir(ImageSavePath+NowCaseno+'\'+DocDir);
          ContextList.Clear;
          if FileExists(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat') then
            ContextList.LoadFromFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat');
          NewName := Add_Zoo(ContextList.Count+1,3)+'_'+FormID+Ext;
          CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);
          {ContextList.Add(NewName);
          ContextList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat'); }
          SetContextList('A',-1,NowCaseNo,DocDir,NewName);
          DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
          //RenameFile(iISB.FileName,ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName);
          //ReNameContext(iISB.FileName,OldName,NewName);
        end;
      end;
//ShowMessage('KKKK');
      ReSortFileName(ExtractFilePath(iISB.FileName));
      DrawDocItem2(MytreeNode1,NowCaseno);
      ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
      if GoAtt then
      begin
        GotoAttach(AttLv);
      end;
      TreeView1click(self);
    end;
  finally
  DataLoading(False,False);
  DocListForm.Free;
  ST1.Free;
  end;
end;
{ ==============================================================================
  方法名稱:PM602Click
  引用相依:Str2Dir, FileExists, LoadFromFile, CopyFile, SaveToFile, DeleteImage
            File, ReSortFileName
  方法描述:縮圖瀏覽區右鍵選單功能:歸類至自定義文件。彈出對話框要求使用者輸入新文
            件名稱,檢核名稱是否重複後產生新的自定義文件編號。接著將所有選取的影像
            複製到新建立的文件目錄下,更新 ContextList並刪除原檔案。最後重新排序並
            刷新樹狀顯示。
============================================================================== }
procedure TCB_IMGPSScanX.PM602Click(Sender: TObject);
var
  FileList:TStringlist;
  SavePath : String;
  DocDir : String;
  CustomDocName : String;
  CustomDocNo : String;
  i : Integer;
  OldName,NewName,Ext : String;
  FormID,FormName,DocNo : String;
  PreNode2Name : String;
  iFormID : String;
  iISBName : String;
  iISB : TImageScrollBox;
  GoAtt : Boolean;
  AttLv : Integer;
begin
  GoAtt := False;
  if (MytreeNode2 <> nil) and (Pos('Attach',MyTreeNode2.Text)>0) then
  begin
    AttLv := TreeView1.Selected.Level;
    GoAtt := True;
  end;
  if InputQuery(_Msg('輸入其他文件名稱'),_Msg('文件名稱'),CustomDocName) then
  begin
    if FindCustomDocName(DisplayPath,CustomDocName) then
    begin
      Showmessage(Format(_Msg('文件名稱:"%s"己存在'),[CustomDocName]));
      Exit;
    end;
    CustomDocNo := GetNewCustomDocNo(DisplayPath,CustomDocName);
  end;
  if CustomDocNo = '' then Exit;
  DocDir := CustomDocNo;
LogFile1.LogToFile(logTimeString+'縮圖 歸類自訂文件 DocDir='+DocDir);
  SavePath := ImageSavePath+NowCaseNo+'\'+DocDir+'\';
  Str2Dir(SavePath);
  SetDocNoList('A',-1,NowCaseNo,DocDir,'1');
  FileList := TStringlist.Create;
  try
  FileList.Clear;
  if FileExists(SavePath+'Context.dat') then
    FileList.LoadFromFile(SavePath+'Context.dat');
    for i := 0 to ComponentCount -1 do
    begin
      if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
      begin
        iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
        iISB := TImageScrollBox(FindComponent(iISBName));
        OldName := ExtractFileName(iISB.FileName);
        Ext := ExtractFileExt(OldName);
        NewName := Add_Zoo(FileList.Count+1,3)+'_'+GetCustomFormID(ImageSavePath+NowCaseNo+'\',CustomDocNo)+ext;
        //Showmessage(iISB.FileName+#13+ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName);
        CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);
        SetContextList('A',-1,NowCaseno,DocDir,NewName);
        FileList.Add(NewName);
        {FileList.Add(NewName);
        FileList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat');}
        DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
      end;
    end;
  finally
  FileList.Free;
  end;
  ReSortFileName(ExtractFilePath(iISB.FileName));
  DrawDocItem2(MytreeNode1,NowCaseno);
  ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
  if GoAtt then
  begin
    GotoAttach(AttLv);
  end;
  TreeView1click(self);
  MyTreeNode1.Expand(True);
end;
{ ==============================================================================
  方法名稱:PM604Click
  引用相依:DeskewImg, SaveToFile, LoadFromFile
  方法描述:縮圖瀏覽區右鍵選單功能:自動去偏斜(Deskew)。遍歷所有選取的影像元件,對
            其 Graphic 執行 DeskewImg 操作,重新繪製並將結果存回原檔案。
============================================================================== }
procedure TCB_IMGPSScanX.PM604Click(Sender: TObject);
var
  i : Integer;
  iISBName : String;
  iISB : TImageScrollBox;
begin
  //Showmessage(inttostr(ComponentCount));
  for i := 0 to ComponentCount -1 do
  begin
    if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
    begin
      //Showmessage(Components[i].Name);
      iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
      iISB := TImageScrollBox(FindComponent(iISBName));
      DeskewImg(iISB.Graphic);
      iISB.Redraw(True);
      iISB.SaveToFile(iISB.FileName);
      DisplayISB.LoadFromFile(DisplayISB.FileName,1);
    end;
  end;
  //TreeView1Click(nil);
end;
{ ==============================================================================
  方法名稱:PM605Click
  引用相依:DeleteImageFile, ReSortFileName
  方法描述:縮圖瀏覽區右鍵選單功能:刪除影像。在使用者確認後,遍歷所有選取的影像元
            件,呼叫 DeleteImageFile 刪除實際檔案。刪除完成後,執行檔案重新排序(ReS
            ortFileName),更新樹狀結構上的頁數統計文字,並刷新顯示。
============================================================================== }
procedure TCB_IMGPSScanX.PM605Click(Sender: TObject);
var
  i : Integer;
  iISBName,OldName : String;
  iISB : TImageScrollBox;
begin
  if MessageDlg(_Msg('是否確定刪除??'),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
  for i := 0 to ComponentCount -1 do
  begin
    if (Components[i] is TShape) and (copy(Components[i].Name,1,2)='SP') then
    begin
      //Showmessage(Components[i].Name);
      iISBName := ShapeName2PreViewISBName(TShape(Components[i]));
      iISB := TImageScrollBox(FindComponent(iISBName));
//ShowMessage('iISB.FileName='+iISB.FileName);
//ShowMessage(ExtractFilePath(iISB.FileName)+','+ExtractFileName(iISB.FileName)+','+NowCaseNo);
//      if (FMode = 'ESCAN') and (FModeName<>'異動件') then
//      begin
//        if ISExistImg(iISB.FileName) then
//        begin
//          ShowMessage(_Msg('此圖為非當次掃瞄,不可刪除'));
//          Exit;
//        end;
//      end;
LogFile1.LogToFile(logTimeString+'縮圖刪除 iISB.FileName='+iISB.FileName);
      DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
    end;
  end;
//ShowMessage('iISB.FileName='+iISB.FileName);
  ReSortFileName(ExtractFilePath(iISB.FileName));
  DrawDocItem2(MytreeNode1,NowCaseno);
  MyTreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
  NewTreeNodeRefresh;
  ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
  TreeView1click(self);
end;
{ ==============================================================================
  方法名稱:PM101Click
  引用相依:_DelTree, DirectoryExists, DeleteDocNoFile
  方法描述:處理樹狀結構(TreeView)的右鍵刪除選單。根據選取的節點類型(新掃瞄件、案
            件、文件或表單)執行不同範圍的刪除:包含刪除實體目錄、清空影像清單、更新
            案件索引及檢核記錄。針對異動模式(ESCAN),若刪除後無影像則會重建空案件
            以維持結構。
============================================================================== }
procedure TCB_IMGPSScanX.PM101Click(Sender: TObject);
var
  P,v,v1,v2,ln,i : Integer;
  iDocDir,iDocNo : String;
begin
LogFile1.LogToFile(logTimeString+'Tree 按下刪除');
  if TreeView1.Selected = NewTreeNode then  //全刪  //新掃描件
  begin
LogFile1.LogToFile(logTimeString+'Tree 全部刪除');
    If Messagedlg(_Msg('是否刪除所有案件?'),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
    clearView(1);
    Application.ProcessMessages;
    _DelTree(ImageSavePath);
    if (FMode = 'ESCAN') then
    begin
      MkDir(ImageSavePath+FCaseID);
      CreateEmptyCase(ImageSavePath,FCaseID);
    end;
    LoadImgFile;
    Showmessage(_Msg('刪除完成'));
  end
  Else if TreeView1.Selected = MyTreeNode1 then       //案件編號
  begin
LogFile1.LogToFile(logTimeString+'Tree 案件編號刪除 NowCaseno='+NowCaseno);
    If Messagedlg(Format(_Msg('編號(%s)是否刪除?'),[NowCaseno]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
    clearView(1);
    Application.ProcessMessages;
    if (FMode = 'ESCAN') then
    begin
      for i := 0 to MyTreeNode1.Count - 1 do
      begin
        MyTreenode2 := MyTreeNode1.Item[i];
        v := Posend('{',MyTreenode2.Text);
        v1 := Posend('}',MyTreenode2.Text);
        v2 := posend('-',MyTreenode2.Text);
        ln := length(MyTreenode2.Text);
        iDocDir := Copy(MyTreeNode2.Text,v+1,v1-v-1);
        iDocNo := DocNoDir2DocNo(iDocDir);
        _DelTree(ImageSavePath+NowCaseno+'\'+iDocDir);
        SetUseCase('D',ImageSavePath+NowCaseno+'\',iDocDir,'','');
        SetDocNoList('D',-1,NowCaseNo,iDocDir,'');
        if (Copy(iDocNo,1,5)='ZZZZZ') then   //20140703 刪除自定文件時要刪ini檔資料
          DeleteCustomDocDir(ImageSavePath+NowCaseno+'\',iDocDir);
      end
    end
    Else
    begin
      _DelTree(DisplayPath);
      SetCaseList('D',NewTreeNode.IndexOf(MyTreeNode1),'');
    end;
    ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
    if (FMode = 'ESCAN') then
    begin
      if not DirectoryExists(ImageSavePath+FCaseID) then
      begin
        MkDir(ImageSavePath+FCaseID);
        CreateEmptyCase(ImageSavePath,FCaseID);
      end;
    end;
    LoadImgFile;
  end
  Else if TreeView1.Selected = MyTreeNode2 then       //文件層
  begin
    If Messagedlg(Format(_Msg('文件(%s)是否刪除?'),[DocNo2DocName(NowCaseno,NowDocNo)]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
    ClearView(1);
    Application.ProcessMessages;
//ShowMessage(NowDocDir);
LogFile1.LogToFile(logTimeString+'Tree 文件層號刪除 NowDocDir='+NowDocDir);
    if (Length(NowDocDir)=8) or (NowDocDir=AttName) then
    begin
//ShowMessage('DeleteDocNoFileForESCAN');
      DeleteDocNoFileForESCAN(ImageSavePath+NowCaseno+'\'+NowDocDir,NowDocDir);
    end
    else
    begin
      _DelTree(ImageSavePath+NowCaseno+'\'+NowDocDir);
      SetDocNoList('D',-1,NowCaseNo,NowDocDir,'');
    end;
    SetUseCase('D',ImageSavePath+NowCaseno+'\',NowDocDir,'','');
    if (Copy(NowDocNo,1,5)='ZZZZZ') then   //20140703 刪除自定文件時要刪ini檔資料
      DeleteCustomDocDir(ImageSavePath+NowCaseno+'\',NowDocDir);
    DrawDocItem2(MytreeNode1,NowCaseno);
    MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
    ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
    NewTreeNodeRefresh;
  end
  Else if TreeView1.Selected = MyTreeNode3 then       //FormID層
  begin
    If Messagedlg(Format(_Msg('文件(%s)是否刪除?'),[NowFormName]),mtconfirmation,[mbyes,mbcancel],0) = mrcancel then Exit;
LogFile1.LogToFile(logTimeString+'Tree FormID層號刪除 NowFormCode='+NowFormCode);
    DeleteFormCodeFile(NowCaseNo,NowDocDir,NowFormCode);
    SetRecordEditedDocDir('A',NowCaseNo,NowDocDir);
    DrawDocItem2(MytreeNode1,NowCaseno);
    MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseNo)]);
    ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
    NewTreeNodeRefresh;
  end;
end;
{ ==============================================================================
  方法名稱:PM102Click
  引用相依:DirectoryExists, RenameFile
  方法描述:處理「修改案件編號」右鍵選單。彈出輸入盒要求輸入新編號並驗證長度與是否
            重複。確認修改後,先清空當前影像顯示,接著執行磁碟目錄更名並更新案件清
            單文字。最後重新繪製該案件的文件樹狀結構並提示完成。
============================================================================== }
procedure TCB_IMGPSScanX.PM102Click(Sender: TObject);
var
  NewCaseID,ShowNewCaseID,ShowNowCaseID : String;
  i,P,v : Integer;
  InputOk : Boolean;
begin
  VMode := 0;
  GoViewMode;
  ISB1.ZoomMode := zmFitWidth;
  NewCaseID := InputBox(_Msg('修改案件編號'),_Msg('新案件編號'),'');
  ShowNewCaseID := NewCaseID;
  ShowNowCaseID := NowCaseno;
  if NewCaseID = '' then Exit;
  IF Length(NewCaseID)<>CaseIDLength Then
  begin
    Showmessage(_Msg('輸入格式錯誤'));
    Exit;
  end;
  if DirectoryExists(ImageSavePath+NewCaseID) then
  begin
    Showmessage(NewCaseID+_Msg('己存在,無法修改'));
    Exit;
  end;
  if Messagedlg(Format(_Msg('是否將%s改為%s'),[ShowNowCaseID,ShowNewCaseID]),Mtconfirmation,[mbyes,mbcancel],0) = mrcancel then
    Exit;
  ClearView(1);
  RenameFile(ImageSavePath+NowCaseno,ImageSavePath+NewCaseID);
  SetCaseList('E',NewTreeNode.IndexOf(MyTreeNode1),NewCaseID);
  //P := ContextList.Count;
  MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NewCaseID,GetCasePage(ImageSavePath,NewCaseID)]);
  //DrawDocItem(MyTreeNode1,FORM_INF_List,NewCaseID);
  DrawDocItem2(MytreeNode1,NewCaseID);
  Showmessage(_Msg('修改完成'));
end;
{ ==============================================================================
  方法名稱:PM103Click
  引用相依:
  方法描述:處理樹狀結構的「掃瞄/追加掃瞄」右鍵選單。根據選取的節點層級,決定是啟動
            全新的案件掃瞄程序(NewScanBtnClick)或是針對現有案件進行追加掃瞄(AddS
            canBtnclick),並在日誌中記錄操作行為。
============================================================================== }
procedure TCB_IMGPSScanX.PM103Click(Sender: TObject);
begin
  if TreeView1.Selected = nil then Exit;
  {if Treeview1.Selected = NewTreeNode then
  begin
    ShowMessage('AAAAA');
  end;
  if Treeview1.Selected = MyTreeNode1 then
  begin
    ShowMessage('BBBBB');
  end;
  if Treeview1.Selected = MyTreeNode2 then
  begin
    ShowMessage('CCCCC');
  end;
  if Treeview1.Selected = MyTreeNode3 then
  begin
    ShowMessage('DDDDD');
  end;
  }
  if (Treeview1.Selected = NewTreeNode) {or (Treeview1.Selected = MyTreeNode1)} then
  begin
//ShowMessage('NewScanBtnClick');
LogFile1.LogToFile(logTimeString+'Tree NewScanBtnClick');
    NewScanBtnClick(self)
  end
  Else
  begin
//ShowMessage('AddScanBtnclick');
LogFile1.LogToFile(logTimeString+'Tree AddScanBtnclick');
    AddScanBtnclick(self);
  end;
end;
{ ==============================================================================
  方法名稱:PM104Click
  引用相依:TTiffGraphic, TJpegGraphic, FJpgCompression, DeskewImg, ConvertToBW,
             MpsGetBarcode, Rotate, CheckNeedCrop, CropImg, ifBlackWhite, tcGrou
            p4, ifColor25, ConvertToGray, tcJpeg, ifTrueColor, ifGray256, SaveQu
            ality, FindFirst, LoadFromFile, SaveToFile, DirectoryExists, _DelTre
            e, GetNoNameCase, Str2Dir, FileExists
  方法描述:處理「匯入影像檔案」右鍵選單。開啟檔案對話框選取 TIF/JPG/PNG 檔,並檢查
            檔案大小是否超過限制。核心流程包含:計算總頁數、逐頁載入、執行自動去偏斜
            (Deskew)、條碼辨識以判斷 FormID、處理 A3 切圖(左右分割)、將影像轉換為對
            應格式(黑白轉 TIF G4,彩色/灰階轉 JPG)並寫入磁碟,最後更新索引、樹狀結
            構與頁數統計。
============================================================================== }
Procedure TCB_IMGPSScanX.PM104Click(Sender: TObject);
Var
  i, n, m, ii, P, v, v1, page, imageCount: Integer;
  FName: String;
  CaseID, DocNo, FormID: String;
  DocDir: String;
  SavePath, SaveFilename: String;
  ISB: TImageScrollBox;
  FileRec: TSearchrec;
  iGraphic, iGraphic_First, iGraphic_sec: TTiffGraphic;
  iRect : TRect;
  JpgGr : TJpegGraphic;
  SaveStream     : TFileStream;
  SaveStreamA:TFileStream;
  SaveStreamB:TFileStream;
  cooom:integer;
Begin
  OpenDialog1.Filter := 'Image files|*.TIF;*.JPG;*.PNG';
  If OpenDialog1.Execute Then
  Begin
    ISB := TImageScrollBox.Create(self);
try
    ShowText := _Msg('檔案加入中,請稍候');
LogFile1.LogToFile(logTimeString+'檔案加入中開始');
    DataLoading(True, True);
    If TreeView1.Selected = Nil Then
      Exit;
    FName := OpenDialog1.FileName;
    FindFirst(FName, faAnyfile, FileRec);
    If FFileSizeLimit = 0 Then
    Begin
      FFileSizeLimit := 5 * 1024;
    End;
//FFileSizeLimit:=20*5*1024;
//ShowMessage(IntToStr(FileRec.Size)+','+IntToStr(FFileSizeLimit * 1024));
    If FileRec.Size > FFileSizeLimit * 1024 Then // 檢查檔案大小
    Begin
      ShowMessage(Format(_Msg('目前檔案大小為 %.3f MB,已超過單一檔案匯入限制%1.f MB'),[FileRec.Size / (1024*1024),FFileSizeLimit/1024]));
      {ShowMessage(Format('目前檔案大小為 %.3f MB', [FileRec.Size / (1024*1024)]) +
        ',已超過單一檔案匯入限制'+Format('%.1f',[FFileSizeLimit/1024])+'MB');}
      FindClose(FileRec);
      DataLoading(false, false);
      Exit;
    End;
    //MessageDlg()
    //cooom:=StrToInt(InputBox('輸入百分比','輸入百分比',''));
    cooom:=FJpgCompression;//20171211彩色tif採jpg壓縮的比例
    FindClose(FileRec);
    CaseID := NowCaseno;
    imageCount := 0;
    P := ISB.ImageCountFromFile(OpenDialog1.FileName);
    For i := 1 To P Do
    Begin
      ShowText := Format(_Msg('檔案加入中,請稍候(%d/%d)'),[i,p]);
      //ShowText := _Msg('檔案加入中,請稍候')+'(' + inttostr(i) + '/' + inttostr(P) + ')';
      DataLoading(True, True);
      ISB.LoadFromFile(FName, i);
      DeskewImg(ISB.Graphic);
      ISB_BW.Graphic.Assign(ISB.Graphic); //20180104
      If ISB.Graphic.ImageFormat <> ifBlackWhite Then   //20180104
      begin
        ConvertToBW(ISB_BW.Graphic);
      end;
      ///ISB_BW.SaveToFile('KKKKKKKK.tif');
      iGraphic_First := TTiffGraphic.Create;
      iGraphic_sec := TTiffGraphic.Create;
      //ShowMessage(IntToStr(iGraphic_First.Palette.palNumEntries)); //彩色 會為0  黑白 為2
      MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf); //判斷A3 有用FormID 所以要先辨條碼
      For n := 1 To MpsBarcodeinf.Count Do
      Begin
        If (MpsBarcodeinf.r180[n] <> 0) and (Length(MpsBarcodeinf.Text[n])=FormIDLength) Then // 依條碼角度轉影像
        Begin
          Rotate(ISB.Graphic, MpsBarcodeinf.r180[n]);
          //MpsGetBarcode(iGraphic_First, MpsBarcodeinf);
          Break;
        End;
      End;
      iGraphic_First.Assign(ISB.Graphic);
      //有必要的話先把影像轉正 再開始切圖
      If CheckNeedCrop(iGraphic_First) Then
      Begin
        // 先取右邊的影像
        iRect.Left := ISB.Graphic.Width Div 2;
        iRect.Right := ISB.Graphic.Width;
        iRect.Top := 0;
        iRect.Bottom := ISB.Graphic.Height;
        CropImg(iGraphic_First, iRect);
        iGraphic_sec.Assign(ISB.Graphic);
        // 再取左邊的影像
        iRect.Left := 0;
        iRect.Right := ISB.Graphic.Width Div 2;
        iRect.Top := 0;
        iRect.Bottom := ISB.Graphic.Height;
        CropImg(iGraphic_sec, iRect);
      End;
      ISB.Graphic.Clear;  //20220711  Hong 覺得ISB後面沒有到了,先清掉減少記憶體使用
      iGraphic := iGraphic_First;
      While Not iGraphic.IsEmpty Do
      Begin
        If (TreeView1.Selected = NewTreeNode) Or
          (TreeView1.Selected = MyTreeNode1) Then
        Begin
          SaveFilename := '';
          ISB_BW.Graphic.Assign(iGraphic); //20180104
          If iGraphic.ImageFormat <> ifBlackWhite Then   //20180104
          begin
            ConvertToBW(ISB_BW.Graphic);
          end;
          MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf);
//ShowMessage(IntToStr(MpsBarcodeinf.Count));
          For n := 1 To MpsBarcodeinf.Count Do
          Begin
            If (MpsBarcodeinf.r180[n] <> 0) and (Length(MpsBarcodeinf.Text[n])=FormIDLength) Then // 依條碼角度轉影像
            Begin
              Rotate(iGraphic, MpsBarcodeinf.r180[n]);
              MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf);
              Break;
            End;
          End;
//ShowMessage('XXX '+IntToStr(MpsBarcodeinf.Count));
          FormID := BarCode2FormID;
//ShowMessage('FormID='+FormID);
          // 取出FormID
          SaveFilename := FormID;
          If (TreeView1.Selected = NewTreeNode) Then
          Begin
            If FindDivFormCode(FormID) Then // 只找分案頁上的案件條碼
            Begin
              imageCount := 0;
              ClearView(1);
              ContextList.Clear;
              CaseID := BarCode2CaseID;
              If DirectoryExists(ImageSavePath + CaseID + '\') Then
              Begin
                _DelTree(ImageSavePath + CaseID + '\');
                SetCaseList('D', -1, CaseID);
              End;
            End;
            If CaseID = '' Then
            Begin
              CaseID := GetNoNameCase(ImageSavePath);
              ContextList.Clear;
            End;
          End;
          SavePath := ImageSavePath + CaseID + '\';
          Str2Dir(SavePath);
          DocNo := FormCode2DocNo(FormID);
          DocDir := FindLastestDocDir(CaseID, DocNo);
          if (FMode='ESCAN') and (FModeName=_Msg('補件掃描')) then
          begin
            DocDir := FindLastestDocDirForPage(CaseID, DocNo,FormID);
//ShowMessage('DocDir='+DocDir);
          end;
          If DocNoNeedDiv(DocNo) Then // 要分份數
          Begin
            If ((FormCode2Page(FormID) = '01') And
              (GetDocDir_Page(CaseID, DocDir) > 0)) Or (DocDir = '') Then
              begin
                DocDir := DocNo2DocNoDir(ImageSavePath + CaseID + '\', DocNo);
              end;
          End
          Else // 不分份數
          Begin
            If DocNo <> '' Then
              DocDir := DocNo
            Else // Attach 附件
              DocDir := DocNo2DocNoDir(ImageSavePath + CaseID + '\', DocNo);
          End;
          If (Not DirectoryExists(ImageSavePath + CaseID + '\' + DocDir + '\'))
            And (DocDir <> AttName) Then
            SetDocNoList('A', -1, CaseID, DocDir, '1');
          SavePath := ImageSavePath + CaseID + '\' + DocDir + '\';
          Str2Dir(SavePath);
          ContextList.Clear;
          If FileExists(SavePath + 'Context.dat') Then
            ContextList.LoadFromFile(SavePath + 'Context.dat');
          WriteCaseIndex(ImageSavePath + CaseID + '\');
          // 寫入案件索引
          If SaveFilename = '' Then // 附件
            SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + ext
          Else
            SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + '_' +
              SaveFilename + ext;
          For n := 1 To MpsBarcodeinf.Count Do
          Begin
            If (MpsBarcodeinf.r180[n] <> 0) and (Length(MpsBarcodeinf.Text[n])=FormIDLength) Then // 依條碼角度轉影像
            Begin
              Rotate(iGraphic, MpsBarcodeinf.r180[n]);
              MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf);
              Break;
            End;
          End;
//ShowMessage(IntToStr(iGraphic.Palette.palNumEntries));
          if iGraphic.ImageFormat = ifBlackWhite then   //20200806 出現無法匯入,是因color256無法壓JPEG,待報會後再開啟
          begin
            SaveFilename := changefileext(SaveFilename,'.tif');    //20240320 Hong 調整黑白存tif
            iGraphic.Compression:=tcGroup4;
          end
          else if iGraphic.ImageFormat= ifColor256 then
          begin
            SaveFilename := changefileext(SaveFilename,'.jpg');    //20240320 Hong 調整Color256存jpg
            ConverttoGray(iGraphic);
            iGraphic.Compression:=tcJPEG;
            iGraphic.JpegQuality:=cooom;
          end
          else if (iGraphic.ImageFormat = ifTrueColor) or (iGraphic.ImageFormat = ifGray256) then
          begin
            SaveFilename := changefileext(SaveFilename,'.jpg');    //20240320 Hong 調整彩色灰階存jpg
            iGraphic.Compression:=tcJPEG;
            iGraphic.JpegQuality:=cooom;
          end
          else
          begin
            iGraphic.Compression:=tcLZW;
          end;
          {if (iGraphic.Palette.palNumEntries = 0) or (iGraphic.Palette.palNumEntries = 256) then  //20171130 彩色 會為0  黑白 為2  灰階256     //20200806拿掉
          begin
            iGraphic.Compression:=tcJPEG;
            iGraphic.JpegQuality:=cooom;
          end;}
          If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.tif' Then
          Begin
            If FileExists(SavePath + SaveFilename) Then
              SaveStream := TFileStream.Create(SavePath + SaveFilename, fmOpenReadWrite)
            Else
              SaveStream := TFileStream.Create(SavePath + SaveFilename, fmCreate);
            Try
              SaveStream.Seek(0, soFromBeginning);
              iGraphic.AppendToStream(SaveStream);
            Finally
              SaveStream.Free;
            End;
          End
          Else If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.jpg' Then
          Begin
            If FileExists(SavePath + SaveFilename) Then
              DeleteFile(SavePath + SaveFilename);
            // SaveStream := TFileStream.Create( PEFileName ,fmCreate );
            JpgGr := TJpegGraphic.Create;
            Try
              JpgGr.Assign(iGraphic);
              JpgGr.SaveQuality := 30;
              // JpgGr.AppendToStream(SaveStream);
              JpgGr.SaveToFile(SavePath + SaveFilename);
            Finally
              JpgGr.Free;
              // SaveStream.Free;
            End;
          End;
          SetContextList('A', -1, CaseID, DocDir, SaveFilename);
          If (TreeView1.Selected = NewTreeNode) Then
          Begin
            If imageCount = 0 Then
            Begin
              SetCaseList('A', -1, CaseID);
              MyTreeNode1 := TreeView1.Items.AddChild(NewTreeNode, CaseID);
              MyTreeNode1.ImageIndex := 2;
              MyTreeNode1.SelectedIndex := 2;
              Application.ProcessMessages;
            End;
          End;
          inc(imageCount);
          // DrawDocItem1(MytreeNode1,Doc_Inf_List,CaseID);
          // DrawDocItem(MyTreeNode1,FORM_INF_List,CaseID);
        End
        Else If TreeView1.Selected = MyTreeNode3 Then
        Begin
          SavePath := ImageSavePath + CaseID + '\' + NowDocDir + '\';
          ContextList.Clear;
          If FileExists(ImageSavePath + CaseID + '\' + NowDocDir +
            '\Context.dat') Then
            ContextList.LoadFromFile(ImageSavePath + CaseID + '\' + NowDocDir +
              '\Context.dat');
          If NowFormCode <> '' Then
            SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + '_' +
              NowFormCode + ext
          Else
            SaveFilename := Add_Zoo(ContextList.Count + 1, 3) + ext;
          For n := 1 To MpsBarcodeinf.Count Do
          Begin
            If MpsBarcodeinf.r180[n] <> 0 Then // 依條碼角度轉影像
            Begin
              Rotate(iGraphic, MpsBarcodeinf.r180[n]);
              MpsGetBarcode(iGraphic, MpsBarcodeinf);
              Break;
            End;
          End;
          if (iGraphic.Palette.palNumEntries = 0) or (iGraphic.Palette.palNumEntries = 256) then  //20171130 彩色 會為0  黑白 為2
          begin
            iGraphic.Compression:=tcJPEG;
            iGraphic.JpegQuality:=cooom;
          end;
          If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.tif' Then
          Begin
            If FileExists(SavePath + SaveFilename) Then
              SaveStream := TFileStream.Create(SavePath + SaveFilename,
                fmOpenReadWrite)
            Else
              SaveStream := TFileStream.Create(SavePath + SaveFilename,
                fmCreate);
            Try
              SaveStream.Seek(0, soFromBeginning);
              iGraphic.AppendToStream(SaveStream);
            Finally
              SaveStream.Free;
            End;
          End
          Else
          Begin
            If LowerCase(ExtractFileExt(SavePath + SaveFilename)) = '.jpg' Then
            Begin
              If FileExists(SavePath + SaveFilename) Then
                DeleteFile(SavePath + SaveFilename);
              // SaveStream := TFileStream.Create( PEFileName ,fmCreate );
              JpgGr := TJpegGraphic.Create;
              Try
                JpgGr.Assign(iGraphic);
                JpgGr.SaveQuality := cooom;
                // JpgGr.AppendToStream(SaveStream);
                JpgGr.SaveToFile(SavePath + SaveFilename);
              Finally
                JpgGr.Free;
                // SaveStream.Free;
              End;
            End;
          End;
          // ISB.SaveToFile(SavePath+SaveFilename);
          ContextList.Add(SaveFilename);
          ContextList.SaveToFile(SavePath + 'Context.dat');
        End;
        if iGraphic = iGraphic_First then
          iGraphic := iGraphic_Sec
        else
          iGraphic.Assign(nil);
      End //While 結束
    End;
    ClearErrini(CaseID, MyTreeNode1);
    // 清掉檢核記錄
    If (TreeView1.Selected = MyTreeNode1) Or
      (TreeView1.Selected = NewTreeNode) Then
    Begin
      LoadImgFile;
    End
    Else
    Begin
      DrawDocItem2(MyTreeNode1, CaseID);
      // 長出文件名稱的樹並傳回是否有申請書的影像
      page := GetCasePage(ImageSavePath, CaseID);
      // ShowMessage('page='+IntToStr(page));
      MyTreeNode1.Text := Format(_Msg('%s-%d頁'), [CaseID, page]);
    End;
    // ShowMessage('AAAA');
    NewTreeNodeRefresh;
    Application.ProcessMessages;
    DataLoading(false, false);
finally
ISB.Free;
iGraphic_First.Free;
iGraphic_sec.Free;
end;
  End;
End;
{ ==============================================================================
  方法名稱:PM106Click
  引用相依:CopyFile, LoadFromFile, SaveToFile
  方法描述:處理「複製文件」右鍵選單。開啟對話框供使用者選擇來源文件與目標案件。使用
            者確認後,遍歷目標案件並將符合條件的來源影像複製到目標目錄下,同步產生
            新的序號檔名、更新目標案件的 Context.dat 並清空其檢核記錄。
============================================================================== }
procedure TCB_IMGPSScanX.PM106Click(Sender: TObject);
var
  i,n,x,v,v1 : Integer;
  CopyFormID,Copy2Caseno,CopyFileName : String;
  S : TStringlist;
begin
  ShowText := _Msg('複製文件中,請稍候');
  DataLoading(True,True);
  DocCopyForm := TDocCopyForm.Create(Self);
  S := TStringlist.Create;
  try
    InitialLanguage(DocCopyForm); //載入多國語言
    DocCopyForm.CopyFromGB.Caption := NowCaseno+DocCopyForm.CopyFromGB.Caption;
    IF NewTreenode.Count = 1 Then
    begin
      Showmessage(_Msg('沒有其他可複製的文件'));
      Exit;
    end;
    For i := 0 to MyTreeNode1.Count -1 do
    begin
      v := Pos('-',MyTreeNode1.Item[i].Text);
      v1 := pos('{',MyTreeNode1.Item[i].Text);
      if V1 > 0 then
      begin
        CopyFormID := Copy(MyTreeNode1.Item[i].Text,1,v-1);
        DocCopyForm.CheckListBox1.Items.Add(CopyFormID);
      end;
    end;
    For i := 0 to NewTreenode.Count -1 do
    begin
      v := Posend('-',NewTreeNode.Item[i].Text);
      Copy2Caseno := Copy(NewTreeNode.Item[i].Text,1,v-1);
      IF Copy2Caseno <> NowCaseno Then
      begin
        DocCopyForm.CheckListBox2.Items.Add(Copy2Caseno);
      end;
    end;
    if DocCopyForm.ShowModal = mrok then
    begin
      If MessageDlg(_Msg('是否確定要將勾選的文件複製到勾選的編號裡?'),MtConfirmation,[Mbyes,mbcancel],0) = mrCancel Then
        Exit;
      ShowText := _Msg('複製中,請稍候');
      DataLoading(True,True);
      For i := 0 to DocCopyForm.CheckListBox2.Count -1 do
      begin
        IF DocCopyForm.CheckListBox2.Checked[i] Then
        begin
          S.Clear;
          Copy2Caseno := DocCopyForm.CheckListBox2.Items.Strings[i];
          ClearErrini(Copy2Caseno,MyTreeNode1);  //清掉檢核記錄
          S.LoadFromFile(ImageSavePath + Copy2Caseno +'\Context.dat');
          For n := 0 to DocCopyForm.CheckListBox1.Count -1 do  //文件
          begin
            If DocCopyForm.CheckListBox1.Checked[n] Then
            begin
              //v:= Posend('{',DocCopyForm.CheckContextList.Strings[n]);
              //v1 := Posend('}',DocCopyForm.CheckContextList.Strings[n]);
              //CopyFormID := Copy(DocCopyForm.CheckContextList.Strings[n],1,v-1);
              CopyFormID := DocCopyForm.CheckListBox1.Items.Strings[n];
              IF v = 0 Then
                CopyFormID := '';
              For x := 0 to ContextList.Count -1 do
              begin
                //Showmessage(CopyFormCode);
                //IF CopyFormID <> '' then   //有文件代號
               // begin
                  if FileName2FormCode(ContextList.Strings[x])=CopyFormID  then
                  begin
                    //CopyFileName := Add_Zoo(S.Count+1,3)+ Copy(ContextList.Strings[x],4,length(ContextList.Strings[x])-3);
                    CopyFileName := Add_Zoo(S.Count+1,3)+ FileName2NoQuene_Filename(ContextList.Strings[x]);
                    CopyFile(PWideChar(DisplayPath+ContextList.Strings[x]),PWidechar(ImageSavePath + Copy2Caseno+'\'+CopyFileName),False);
                    S.Add(CopyFileName);
                    S.SaveToFile(ImageSavePath + Copy2Caseno +'\Context.dat');
                  end;
               // end
              end;
            end;
          end;
        end;
      end;
      DataLoading(False,False);
      Showmessage(_Msg('複製完成!!'));
      LoadImgFile;
    end;
  finally
  DocCopyForm.Free;
  DataLoading(False,False);
  S.Free;
  end;
end;
{ ==============================================================================
  方法名稱:PM107Click
  引用相依:
  方法描述:觸發右鍵選單中的備註點擊事件。
============================================================================== }
procedure TCB_IMGPSScanX.PM107Click(Sender: TObject);
begin
  WNoteBtnClick(nil);
end;
{ ==============================================================================
  方法名稱:PM108Click
  引用相依:
  方法描述:處理樹狀結構的「文件歸類」右鍵選單。開啟對話框顯示表單清單,使用者可選擇
            歸類至既有文件或新增自定義文件。若為自定義,則驗證名稱後取得新編號。隨
            後執行 FormIDReplace 搬移影像檔案、更新索引、清空檢核記錄並刷新樹狀結
            構顯示。
============================================================================== }
procedure TCB_IMGPSScanX.PM108Click(Sender: TObject);
var
  i : Integer;
  DocListForm : TDocListForm;
  OldName,NewName,Ext : String;
  NewFormID,NewFormName,CustomDocNo : String;
begin
  DocListForm := TDocListForm.Create(self);
  try
LogFile1.LogToFile(logTimeString+'Tree 歸類開始');
    InitialLanguage(DocListForm); //載入多國語言
    DocListForm.CheckBox1.Visible:=True;
    for i := 1 to FORM_INF_List.Count - 1 do
    begin
      NewFormID := GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
      NewFormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
      if not FormIDAppear(NewFormID) then Continue;   //20170816 先秀全部的
      if (NewFormID <> FileName2FormCode(DisplayISB.FileName)) and FormIDExists(NewFormID,False,i) then
      begin
        DocListForm.FormIDList.Add(NewFormID+'#@#'+NewFormName);
        With DocListForm.DocLV.Items.Add do
        begin
          Caption := NewFormID;
          SubItems.Add(GetSQLData(FORM_INF_List,'T1.FORM_DESC',i));
        end;
      end;
    end;
    if DocListForm.ShowModal = mrOk then
    begin
      if not (DocListForm.DocLV.Selected=nil) then
         NewFormID := DocListForm.DocLV.Selected.Caption;
      if DocListForm.CheckBox1.Checked then
      begin
        //歸類到自訂文件
        NewFormID:=DocListForm.Edit1.Text;
        if Trim(DocListForm.Edit1.Text)='' then
        begin
          Showmessage(_Msg('未輸入文件名稱'));
          Exit;
        end;
        if FindCustomDocName(DisplayPath,NewFormID) then
        begin
          Showmessage(Format(_Msg('文件名稱:"%s"己存在'),[NewFormID]));
          Exit;
        end;
        if NowFormCode <> AttName then
        begin
          If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[FormCode2FormName(NowCaseNo,NowFormCode),NewFormID]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
            Exit;
        end
        Else
        begin
          If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[_Msg('附件')+MyTreeNode3.Text,FormCode2FormName(NowCaseNo,NewFormID)]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
            Exit;
        end;
        CustomDocNo := GetNewCustomDocNo(DisplayPath,NewFormID);
//ShowMessage('CustomDocNo='+CustomDocNo);
LogFile1.LogToFile(logTimeString+'Tree 歸類到自訂文件 CustomDocNo='+CustomDocNo);
        ShowText := _Msg('歸類中,請稍侯');
        DataLoading(True,True);
        FormIDReplace(NowCaseNo,NowDocDir,NowFormCode,CustomDocNo+'010101A');
      end
      else
      begin
        //歸類到既有文件
        if NowFormCode <> AttName then
        begin
          If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[FormCode2FormName(NowCaseNo,NowFormCode),FormCode2FormName(NowCaseNo,NewFormID)]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
            Exit;
        end
        Else
        begin
          If Messagedlg(Format(_Msg('是否將"%s"的所有影像歸類成"%s"'),[_Msg('附件')+MyTreeNode3.Text,FormCode2FormName(NowCaseNo,NewFormID)]),MtConfirmation,[mbyes,mbcancel],0) = mrcancel Then
            Exit;
        end;
        ShowText := _Msg('歸類中,請稍侯');
        DataLoading(True,True);
//ShowMessage('NowDocDir='+NowDocDir);
LogFile1.LogToFile(logTimeString+'Tree 歸類到既有文件 NewFormID='+NewFormID);
        FormIDReplace(NowCaseNo,NowDocDir,NowFormCode,NewFormID);
      end;
      ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
      DrawDocItem2(MytreeNode1,NowCaseno);
      DataLoading(False,False);
      TreeView1.Selected := MyTreeNode1;
      TreeView1Click(self);
    end;
  finally
  DocListForm.Free;
  end;
end;
{ ==============================================================================
  方法名稱:PM109Click
  引用相依:SaveToFile
  方法描述:處理「案件 OMR 檢核」右鍵選單。清空當前顯示並開啟檢核進度,呼叫 OMRCheck
            Case 對案件執行光學劃記辨識檢核。若檢核成功則建立 OMRCheckOk.dat 標記
            檔,最後重新載入影像、刷新樹狀結構並提示檢核完成。
============================================================================== }
procedure TCB_IMGPSScanX.PM109Click(Sender: TObject);
var
  S : TStringlist;
  CaseID : String;
begin
  //if TreeView1.Selected = nil then Exit;
  //if TreeView1.Selected = NewTreeNode then Exit;
  CaseID := NowCaseno;
  S := TStringlist.Create;
  try
    ClearView(1);
    ShowText := CaseID+_Msg('檢核中,請稍候');
    DataLoading(True,True);
    ShowText := CaseID+_Msg('檢核中,請稍候');
    DataLoading(True,True);
    If OMRCheckCase(CaseID) then  //有成功
    begin
      S.Add('Y');
      S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
    end;
      //MyTreeNode2ReFresh(CaseID);
    LoadImgFile;
    TreeView1Click(nil);
    DataLoading(False,False);
  finally
  S.Free;
  end;
  Showmessage(_Msg('檢核完成'));
end;
{ ==============================================================================
  方法名稱:PM110Click
  引用相依:Str2Dir
  方法描述:處理「新增其他文件」右鍵選單。彈出對話框要求輸入自定義名稱,驗證無誤後產
            生新的文件編號並在案件目錄下建立實體子目錄。隨後將新目錄加入清單並重
            新繪製樹狀結構,最後自動展開新建立的節點。
============================================================================== }
procedure TCB_IMGPSScanX.PM110Click(Sender: TObject);
var
  CustomDocName : String;
  CustomDocNo : String;
  DocDir : String;
  SavePath : String;
  ST1:TStringList;
begin
  if InputQuery(_Msg('輸入其他文件名稱'),_Msg('文件名稱'),CustomDocName) then
  begin
    if CustomDocName <> '' then
    begin
      if FindCustomDocName(DisplayPath,CustomDocName) then
      begin
        Showmessage(Format('文件名稱:"%s"己存在',[CustomDocName]));
        Exit;
      end;
      ST1:=TStringList.Create;
      CustomDocNo := GetNewCustomDocNo(DisplayPath,CustomDocName);
      DocDir := CustomDocNo;
      SavePath := ImageSavePath+NowCaseNo+'\'+DocDir+'\';
      Str2Dir(SavePath);
      SetDocNoList('A',-1,NowCaseNo,DocDir,'1');
      DrawDocItem2(MytreeNode1,NowCaseno);
      MyTreeNode1.Expand(True);
    end;
  end;
end;
{ ==============================================================================
  方法名稱:PM111Click
  引用相依:
  方法描述:處理「修改文件份數」右鍵選單。取得當前份數並供使用者修改(範圍 1-9999)。
            若份數有變動則執行驗證(如分份文件限制),確認後更新 SetDocDirCopies 設
            定並標記文件已編輯,最後刷新樹狀結構統計。
============================================================================== }
procedure TCB_IMGPSScanX.PM111Click(Sender: TObject);
var
  oldCopies,NewCopies : Integer;
  copies : String;
begin
  oldCopies := GetDocDirCopies(NowCaseno,NowDocDir);
  try
    NewCopies := Strtoint(inputBox(_Msg('修改份數'),_Msg('請輸入修改後的份數'),inttostr(oldCopies)));
  except
    Showmessage(_Msg('輸入錯誤'));
    Exit;
  end;
  if (NewCopies <= 0) and (NewCopies >= 10000) then
  begin
    Showmessage(_Msg('輸入範圍錯誤'));
    Exit;
  end;
  if (oldCopies <> NewCopies) and (NewCopies > 0) and (NewCopies < 10000) then
  begin
    if DocNoNeedDiv(NowDocNo) and (NewCopies = 1) and (MessageDlg(_Msg('修改至1份後此文件將無法再進行份數修改,是否確定??'),mtConfirmation,[mbyes,mbcancel],0)= mrcancel) then
      Exit;
    SetDocDirCopies(NowCaseno,NowDocDir,NewCopies);
    SetRecordEditedDocDir('A',NowCaseNo,NowDocDir);
    DrawDocItem2(MytreeNode1,NowCaseno);
    Showmessage(_Msg('修改完成'));
  end;
end;
{ ==============================================================================
  方法名稱:PM301Click
  引用相依:ifBlackWhite
  方法描述:將掃瞄模式設定為黑白(ifBlackWhite)並指定副檔名為 .tif。
============================================================================== }
procedure TCB_IMGPSScanX.PM301Click(Sender: TObject);
begin
  ScanColor := ifBlackWhite;
  ScanDpi := Def_ScanDpi;
  Ext := '.tif';
  PM301.Checked := True;
end;
{ ==============================================================================
  方法名稱:PM302Click
  引用相依:ifGray256
  方法描述:將掃瞄模式設定為灰階(ifGray256)並指定副檔名為 .jpg。
============================================================================== }
procedure TCB_IMGPSScanX.PM302Click(Sender: TObject);
begin
  ScanColor := ifGray256;
  Ext := '.jpg';
  ScanDpi := 200;
  //Ext := '.tif';
  PM302.Checked := True;
end;
{ ==============================================================================
  方法名稱:PM303Click
  引用相依:ifTrueColor
  方法描述:將掃瞄模式設定為全彩(ifTrueColor)並指定副檔名為 .jpg。
============================================================================== }
procedure TCB_IMGPSScanX.PM303Click(Sender: TObject);
begin
  ScanColor := ifTrueColor;
  Ext := '.jpg';     //20130326 yuu說理賠改存jpg
  ScanDpi := 200;
  //Ext := '.tif';
  PM303.Checked := True;
end;
{ ==============================================================================
  方法名稱:PM501Click
  引用相依:
  方法描述:將影像縮放模式設為「符合寬度」並開啟反鋸齒。
============================================================================== }
procedure TCB_IMGPSScanX.PM501Click(Sender: TObject);
begin
  DisplayISB.ZoomMode := zmFitWidth;
  DisplayISB.AntiAliased := True;
  SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
end;
{ ==============================================================================
  方法名稱:PM502Click
  引用相依:
  方法描述:將影像縮放模式設為「符合高度」並開啟反鋸齒。
============================================================================== }
procedure TCB_IMGPSScanX.PM502Click(Sender: TObject);
begin
  DisplayISB.ZoomMode := zmFitHeight;
  DisplayISB.AntiAliased := True;
  SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
end;
{ ==============================================================================
  方法名稱:PM503Click
  引用相依:
  方法描述:將影像縮放模式設為「符合頁面」並開啟反鋸齒。
============================================================================== }
procedure TCB_IMGPSScanX.PM503Click(Sender: TObject);
begin
  DisplayISB.ZoomMode := zmFittoPage;
  DisplayISB.AntiAliased := True;
  SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
end;
{ ==============================================================================
  方法名稱:PM504Click
  引用相依:
  方法描述:將影像縮放模式設為「原始大小」並開啟反鋸齒。
============================================================================== }
procedure TCB_IMGPSScanX.PM504Click(Sender: TObject);
begin
  DisplayISB.ZoomMode := zmOriginalSize;
  DisplayISB.AntiAliased := True;
  SetScrollData(DisplayISB,DisplayISB.HorzScrollBar.Position,DisplayISB.VertScrollBar.Position,DisplayISB.ZoomPercent);
end;
{ ==============================================================================
  方法名稱:PM505Click
  引用相依:StatrTwainScan
  方法描述:處理「掃瞄替換此頁」右鍵選單。檢查當前影像後,設定掃瞄模式為 smReplace
            並指定儲存路徑與檔名為當前顯示之影像。啟動 StatrTwainScan 掃瞄以覆蓋
            原檔案,完成後清空該案件的檢核記錄。
============================================================================== }
procedure TCB_IMGPSScanX.PM505Click(Sender: TObject);
begin
  if DisplayISB.FileName = '' then Exit;
  Panel1.Enabled := False;
  Panel2.Enabled := False;
  ScanMode := smReplace;
  ScanInfo.ImageCount := 0;
  ScanPath := DisplayPath;
  ScanCaseno := '';
  ScanSaveFilename := ExtractFileName(DisplayISB.FileName);
  Try
    StatrTwainScan;
  Except
    Panel1.Enabled := True;
    Panel2.Enabled := True;
  end;
  Panel1.Enabled := True;
  Panel2.Enabled := True;
  ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
end;
{ ==============================================================================
  方法名稱:PM507Click
  引用相依:RenameFile
  方法描述:處理影像區域的「文件歸類」右鍵選單。彈出對話框供使用者選取目標表單,隨後
            根據選取的 FormID 產生新的序號檔名。執行 RenameFile 進行實際更名並同
            步更新 Context.dat。最後重新整理樹狀結構、清空檢核記錄並使焦點回到原文
            件節點。
============================================================================== }
procedure TCB_IMGPSScanX.PM507Click(Sender: TObject);
var
  i : Integer;
  DocListForm : TDocListForm;
  OldName,NewName,Ext : String;
  FormID,FormName,DocNo : String;
  PreNode2Name : String;
  iFormID : String;
begin
  PreNode2Name := '';
  if TreeView1.Selected.Parent = MyTreeNode1 then
    PreNode2Name:= GetNode2Name(MyTreeNode2);
  ShowText := _Msg('文件歸類中,請稍候');
  DataLoading(True,True);
  DocListForm := TDocListForm.Create(self);
  try
    InitialLanguage(PatchDlg); //載入多國語言
    for i := 1 to FORM_INF_List.Count - 1 do
    begin
      FormID :=  GetSQLData(FORM_INF_List,'T1.FORM_ID',i);
      FormName := GetSQLData(FORM_INF_List,'T1.FORM_DESC',i);
      DocNo := GetSQLData(FORM_INF_List,'T1.DOC_NO',i)+GetSQLData(FORM_INF_List,'T1.DOC_VERSION',i);
      //Showmessage(FORM_INF_List.Text);
      //showmessage(inttostr(FORM_INF_List.Count)+#13+inttostr(self.Doc_Inf_List.Count));
      if (FormID <> FileName2FormCode(DisplayISB.FileName)) and FormIDExists(FormID,False,i) then
      begin
        DocListForm.FormIDList.Add(FormID+'#@#'+FormName);
        With DocListForm.DocLV.Items.Add do
        begin
          Caption := FormID;
          SubItems.Add(FormName);
        end;
      end;
    end;
    if DocListForm.ShowModal = mrOk then
    begin
      OldName := ExtractFileName(DisplayISB.FileName);
      Ext := ExtractFileExt(OldName);
      //NewName := Copy(OldName,1,3)+'_'+TransRealFormID(DocListForm.DocLV.Selected.Caption)+Ext;
      NewName := Add_Zoo(FileName2ScanPage(OldName),3)+'_'+DocListForm.DocLV.Selected.Caption+Ext;
      RenameFile(DisplayPath+OldName,DisplayPath+NewName);
      ReNameContext(DisplayPath,OldName,NewName);
      //DrawDocItem1(MytreeNode1,Doc_Inf_List,NowCaseno);  //201408280改
      DrawDocItem2(MytreeNode1,NowCaseno);
      //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
      ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
      if PreNode2Name <> '' then  // 回到原本點選的文件節點上
      begin
        for i := 0 to MyTreeNode1.Count - 1 do
        begin
          if GetNode2Name(MyTreeNode1.Item[i]) = PreNode2Name then
          begin
            TreeView1.Selected := MyTreeNode1.Item[i];
            Break;
          end;
        end;
      end;
      TreeView1click(self);
      //Showmessage(_Msg('歸類完成')); //20101103 User要求拿掉
    end;
  finally
  DataLoading(False,False);
  DocListForm.Free;
  end;
end;
{ ==============================================================================
  方法名稱:PM508Click
  引用相依:_DelTree, SaveToFile, ReSortFileName, LoadFromFile, FileExists
  方法描述:處理影像區域的「刪除影像」右鍵選單。若案件僅剩一張影像則詢問是否刪除整
            個案件目錄。否則,在確認後從影像清單中移除該項目、刪除實體檔案並呼叫 Re
            SortFileName 重新排序。最後刷新樹狀統計文字、清空檢核記錄並更新顯示。
============================================================================== }
procedure TCB_IMGPSScanX.PM508Click(Sender: TObject);
var
  P : Integer;
  inx:Integer;
begin
  if DisplayISB.FileName = '' then Exit;
  if (ContextList.Count = 1) and ((FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'ISCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN')) then
  begin
    if Messagedlg(Format(_Msg('刪除後(%s)案件無影像,將刪除此案件,是否確定刪除?'),[NowCaseno]),mtconfirmation,[mbyes,mbcancel],0) = mrCancel then Exit;
    _DelTree(DisplayPath);
    SetCaseList('D',NewTreeNode.IndexOf(MyTreeNode1),'');
    LoadImgFile;
  end
  Else
  begin
    if Messagedlg(_Msg('是否確定刪除?'),mtconfirmation,[mbyes,mbcancel],0) = mrCancel then Exit;
    inx := ContextList.IndexOf(ExtractFileName(DisplayISB.FileName));
    ContextList.Delete(inx);
    ContextList.SaveToFile(ImageSavePath + NowCaseno+'\Context.dat');
    Context_DocnoList.Delete(inx);
    Context_DocnoList.SaveToFile(ImageSavePath + NowCaseno+'\Context_DocNo.dat');
    DeleteFile(DisplayISB.FileName);
    ReSortFileName(DisplayPath);
    ContextList.LoadFromFile(ImageSavePath + NowCaseno+'\Context.dat');
    Context_DocnoList.LoadFromFile(ImageSavePath + NowCaseno+'\Context_DocNo.dat');
    if FileExists(ImageSavePath + NowCaseno+'\CustomDocNo.dat') then
      Cust_DocNoList.LoadFromFile(ImageSavePath + NowCaseno+'\CustomDocNo.dat');
    //DrawDocItem1(MytreeNode1,Doc_Inf_List,NowCaseno);  //201408280改
    DrawDocItem2(MytreeNode1,NowCaseno);
    //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
    P := ContextList.Count;
    MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,p]);
    ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
    NewTreeNodeRefresh;
    TreeView1Click(self);
  end;
  //Showmessage(_Msg('刪除完成'));  //20101101 User要求拿掉
end;
{ ==============================================================================
  方法名稱:PM509Click
  引用相依:
  方法描述:觸發「從此分案」功能,內部轉呼叫 PM401Click。
============================================================================== }
procedure TCB_IMGPSScanX.PM509Click(Sender: TObject);
begin
  PM401Click(nil);
end;
{ ==============================================================================
  方法名稱:PM510Click
  引用相依:DeskewImg, SaveToFile
  方法描述:對當前 Graphic 執行去偏斜處理後存回原檔案。
============================================================================== }
procedure TCB_IMGPSScanX.PM510Click(Sender: TObject);
begin
  DeskewImg(DisplayISB.Graphic);
  DisplayISB.SaveToFile(DisplayISB.FileName);
  ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
end;
{ ==============================================================================
  方法名稱:PopupMenu1Popup
  引用相依:
  方法描述:處理樹狀結構右鍵選單彈出時的動態項目控制。根據選取節點的層級(根、案件、
            文件、表單)與系統模式(如 FMode、FImgDelete 權限等)動態設定各項選單(刪
            除、修改、掃瞄加入、歸類、檢核等)的可見度與可用性。例如在文件層會受影像引
            用狀態限制刪除功能。
============================================================================== }
procedure TCB_IMGPSScanX.PopupMenu1Popup(Sender: TObject);
begin
  PM101.Visible := False;   //刪除
  PM102.Visible := False;   //修改案件編號
  PM103.Visible := False;   //掃瞄器加入影像
  PM104.Visible := False;   //檔案加入影像
  PM106.Visible := False;   //複製文件至其他編號
  PM107.Visible := False;   //寫備註
  PM108.Visible := False;   //歸類
  PM109.Visible := False;   //檢核此筆
  PM110.Visible := False;   //新增自訂文件
  PM111.Visible := False;   //修改份數
  if (FMode = 'SAMPLESCAN') then Exit;
  if TreeView1.Selected = nil then Exit;
  if TreeView1.Selected = NewTreeNode  then     //新掃瞄件
  begin
    if (FMode = 'NSCAN') then
    begin
//ShowMessage('AAAA');
      PM101.Visible := True;   //刪除
      PM103.Visible := True;   //掃瞄器加入影像
      PM104.Visible := True;   //檔案加入影像
    end;
    if FModeName=_Msg('異動件') then
    begin
      PM101.Visible := True;
    end;
//    if FMode='ESCAN' then
//    begin
//      PM101.Visible := True;
//    end;
  end
  Else if TreeView1.Selected = MyTreeNode1 then    //案件層
  begin
    PM101.Visible := True;   //刪除
    if FImgDelete='Y' then
    begin
      PM101.Visible:=True;
    end;
    if FImgDelete='N' then
    begin
      PM101.Visible:=false;
    end;
    if FMode='ESCAN' then
      PM101.Visible:=false;
    if FModeName=_Msg('異動件') then
    begin
      PM101.Visible := True;
    end;
    if not CaseDelete_Enable(NowCaseno) then //
      PM101.Enabled := False
    else
      PM101.Enabled := True;
    PM103.Visible := True;   //掃瞄器加入影像
    //PM107.Visible := True;   //寫備註
    //PM109.Visible := True;   //檢核此筆
//    if FCustDocYN <> 'N' Then
//      PM110.Visible := True;   //新增自訂文件  20170914 先不在tree 中做自訂文件  讓user在縮圖做
    PM104.Visible := True;   //檔案加入影像
    if (FMode = 'NSCAN') then
    begin
      PM102.Visible := True;   //修改案件編號
    end;
//    if FMode='ESCAN' then
//    begin
//      PM101.Visible := True;
//    end;
  end
  Else if TreeView1.Selected = MyTreeNode2 then    //文件層
  begin
    PM101.Visible := True;   //刪除
    //PM107.Visible := True;   //寫備註
    //PM109.Visible := True;   //檢核此筆
//    if FCustDocYN <> 'N' Then
//      PM110.Visible := True;   //新增自訂文件
    if FImgDelete='Y' then
    begin
      PM101.Visible:=True;
    end;
    if FImgDelete='N' then
    begin
      PM101.Visible:=false;
    end;
    if FModeName=_Msg('異動件') then
    begin
      PM101.Visible := True;
    end;
    if GetUseCase('T',DisplayPath,NowDocDir) <> '' then   //沒有被引用走的
      PM101.Enabled := False    //刪除
    Else
      PM101.Enabled := True;   //刪除
    if ((GetDocDirCopies(NowCaseno,NowDocDir) > 1) or (not DocNoNeedDiv(NowDocNo)) or (Copy(NowDocNo,1,5)='ZZZZZ')) and (NowDocNo<> 'Attach') and (NowDocNo<> 'S_Attach') then
      PM111.Visible := True;   //修改份數
    if (FMode = 'NSCAN') then
      PM102.Visible := True;   //修改案件編號
//    if FMode='ESCAN' then
//    begin
//      PM101.Visible := True;
//    end;
  end
  Else if TreeView1.Selected = MyTreeNode3 then    //表單層
  begin
    PM101.Visible := True;   //刪除
    PM104.Visible := True;   //檔案加入影像
    PM108.Visible := True;   //歸類
    PM103.Visible := True;   //掃瞄器加入影像
//    if FCustDocYN <> 'N' Then
//      PM110.Visible := True;   //新增自訂文件
    if GetFormIDPage(ContextList,NowFormCode) < 1 Then
    begin
      PM108.Visible := False;   //歸類
    end;
    if FImgDelete='Y' then
    begin
      PM101.Visible:=True;
    end;
    if FImgDelete='N' then
    begin
      PM101.Visible:=false;
    end;
    if FModeName=_Msg('異動件') then
    begin
      PM101.Visible := True;
    end;
    if GetUseCase('T',DisplayPath,NowDocDir) <> '' then   //被引用走的
    begin
      PM101.Enabled := False;   //刪除
      PM104.Enabled := False;   //檔案加入影像
      PM108.Enabled := False;   //歸類
    end
    Else
    begin
      PM101.Enabled := True;   //刪除
      PM104.Enabled := True;   //檔案加入影像
      PM108.Enabled := True;   //歸類
    end;
    if (FMode = 'NSCAN') then
    begin
      PM102.Visible := True;   //修改案件編號
    end;
  end;
end;
{ ==============================================================================
  方法名稱:PopupMenu4Popup
  引用相依:
  方法描述:處理影像列表右鍵選單彈出邏輯。僅在樹狀結構選取文件或表單層級時顯示全
            選、取消全選及歸類功能,並特別判斷「分出新案」在非重掃模式下才可見。
============================================================================== }
procedure TCB_IMGPSScanX.PopupMenu4Popup(Sender: TObject);
begin
  PM401.Visible := False;
  PM402.Visible := False;
  PM403.Visible := False;
  PM404.Visible := False;
  if FMode = 'SAMPLESCAN' then Exit;
  if (TreeView1.Selected.Level =2) or (TreeView1.Selected.Level =3) then
  begin
    PM402.Visible := True;
    PM403.Visible := True;
    PM404.Visible := True;
  end;
  PM401.Visible := True;
  if (TreeView1.Selected <> MyTreeNode2) or (FMode = 'RSCAN') then
    PM401.Visible := False;
end;
{ ==============================================================================
  方法名稱:PopupMenu5Popup
  引用相依:
  方法描述:處理影像顯示區域右鍵選單彈出邏輯。當有載入影像時啟用各類縮放選單項目,
            並根據樹狀選取層級與掃瞄模式決定是否顯示「分出新案」功能。
============================================================================== }
procedure TCB_IMGPSScanX.PopupMenu5Popup(Sender: TObject);
begin
  PM501.Visible := False;
  PM502.Visible := False;
  PM503.Visible := False;
  PM504.Visible := False;
  PM505.Visible := False;
  PM506.Visible := False;
  PM507.Visible := False;
  PM508.Visible := False;
  PM509.Visible := False;
  PM510.Visible := False;
  if FMode = 'SAMPLESCAN' then Exit;
  if (DisplayISB.FileName <> '') then
  begin
    PM501.Visible := True;
    PM502.Visible := True;
    PM503.Visible := True;
    PM504.Visible := True;
    //PM505.Visible := True;
    //PM506.Visible := True;
    //PM507.Visible := True;
    //PM508.Visible := True;
    //PM509.Visible := True;
    //PM510.Visible := True;
  end;
  if (TreeView1.Selected <> MyTreeNode2) or (FMode = 'RSCAN') or (FMode = 'ESCAN') then
    PM509.Visible := False;
end;
{ ==============================================================================
  方法名稱:PopupMenu6Popup
  引用相依:
  方法描述:處理縮圖區右鍵選單彈出邏輯。動態設定歸類、自定義文件及刪除項目的可見度
            。若選取附件目錄則開啟特殊功能。同時根據權限設定與影像引用狀態(UseCase
            )限制歸類與刪除功能的可用性。
============================================================================== }
procedure TCB_IMGPSScanX.PopupMenu6Popup(Sender: TObject);
begin
  PM601.Visible := True;  //歸類
  PM602.Visible := True;  //自行定義文件名稱
  PM603.Visible := False;  //掃描替換此頁
  PM604.Visible := False;  //歪斜矯正
  PM605.Visible := True;  //刪除
//  if FMode='ESCAN' then
//  begin
//    PM601.Visible := False;  //歸類
//    PM602.Visible := False;  //自行定義文件名稱
//    PM603.Visible := False;  //掃描替換此頁
//    PM604.Visible := False;  //歪斜矯正
//    PM605.Visible := False;  //刪除
//  end;
  if ((NowDocNo = 'Attach') or (NowDocNo = 'S_Attach')) and (FCustDocYN <> 'N') then
  begin
    PM602.Visible := True;  //自行定義文件名稱
    //PM603.Visible := True;  //掃描替換此頁
    PM604.Visible := True;  //歪斜矯正
    PM601.Visible := True;  //歸類
    PM605.Visible := True;  //刪除
  end;
  if  FModeName<>_Msg('異動件') then
  begin
    if (FImgDelete='Y') then
    begin
      PM605.Enabled:=True;
    end;
    if FImgDelete='N' then
    begin
      PM605.Enabled:=false;
    end;
  end;
  if CheckSelectImg_UseCase(DisplayPath,NowCaseNo) then //選擇的影像不可有引用的
  begin
    PM601.Enabled := False;  //歸類
    PM605.Enabled := False;  //刪除
  end;
end;
reassemble/view/scrollView.pas
比對新檔案
@@ -0,0 +1,314 @@
{ ==============================================================================
  方法名稱:ISB1Click
  引用相依:
  方法描述:影像滾輪盒(ISB)的點擊處理。更新當前顯示的 ISB 對象,調整 Shape1 標記框
            的位置以框選當前 ISB。根據 ISB 名稱與捲軸位置計算並更新 PageLV 清單中
            的選取狀態(NowPage 與 ItemIndex)。
============================================================================== }
procedure TCB_IMGPSScanX.ISB1Click(Sender: TObject);
var
  p : Integer;
begin
  DisplayISB := TImageScrollBox(Sender);
  Shape1.Left := TPanel(TImageScrollBox(Sender).Parent).Left - Seg;
  Shape1.Top := TPanel(TImageScrollBox(Sender).Parent).Top - Seg;
  P := strtoint(copy(DisplayISB.Name,4,1)) + ScrollBar1.Position-2;
  if P <= PageLV.Items.Count-1 then
  begin
    if PageLVclear then
    begin
      PageLV.ClearSelection;
    end;
    NowPage := p+1;
    PageLV.ItemIndex := P;
  end;
  //DisplayISB.SetFocus;
end;
{ ==============================================================================
  方法名稱:ISB1EndScroll
  引用相依:
  方法描述:當影像滾輪盒停止捲動時觸發。呼叫 SetScrollData 將當前的水平/垂直捲軸
            位置與縮放百分比存回緩存中,以維持影像顯示的一致性。
============================================================================== }
procedure TCB_IMGPSScanX.ISB1EndScroll(Sender: TObject);
var
  ISB : TImageScrollBox;
begin
  ISB := TImageScrollBox(Sender);
  SetScrollData(ISB,ISB.HorzScrollBar.Position,ISB.VertScrollBar.Position,ISB.ZoomPercent);
  {if (TImageScrollBox(Sender) = MpsViewX1) and SortMode then
  begin
    ReczoomPercent := MpsViewX1.ZoomPercent;
    RecHozPos := MpsViewX1.HorzScrollBarPos;
    RecVerPos := MpsViewX1.VertScrollBarPos;
  end;}
end;
{ ==============================================================================
  方法名稱:ISB1Enter
  引用相依:
  方法描述:當滑鼠進入影像滾輪盒區域時,強制將焦點設為 ISB1。
============================================================================== }
procedure TCB_IMGPSScanX.ISB1Enter(Sender: TObject);
begin
  ISB1.SetFocus;
end;
{ ==============================================================================
  方法名稱:ISB1ImageMouseDown
  引用相依:LoadFromFile
  方法描述:影像滑鼠按下事件。設定當前 DisplayISB 並視情況取得焦點,更新 Shape1 的
            選取框位置。同步更新 PageLV 的選取頁面。若處於特定模式(NowClick = -1)
            且按下左鍵,則啟動影像的拖曳操作(BeginDrag)。此外也會處理旋轉模式下的
            影像載入。
============================================================================== }
procedure TCB_IMGPSScanX.ISB1ImageMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  p : Integer;
begin
  DisplayISB := TImageScrollBox(Sender);
  if NowClick<>0 then
    DisplayISB.SetFocus;
  Shape1.Left := TPanel(TImageScrollBox(Sender).Parent).Left - Seg;
  Shape1.Top := TPanel(TImageScrollBox(Sender).Parent).Top - Seg;
  P := strtoint(copy(DisplayISB.Name,4,1)) + ScrollBar1.Position-2;
  if P <= PageLV.Items.Count-1 then
  begin
    NowPage := p+1;
    PageLV.ClearSelection;
    PageLV.ItemIndex := P;
    //PageLV.Selected := PageLV.Items.Item[PageLV.ItemIndex];
  end;
  if (NowClick = -1) and (Button=TMouseButton(mbLeft)) and (DisplayISB.FileName <> '') then
  begin
    {for P := 1 to 8 do
    begin
      TImageScrollBox(FindComponent('ISB'+inttostr(p))).Enabled := False;
    end; }
    DisplayISB.BeginDrag(True);
  end;
  case TImageScrollBox(Sender).MouseMode of
    mmR90,mmR180,mmR270:
    begin
      TImageScrollBox(Sender).LoadFromFile(TImageScrollBox(Sender).FileName,1);
    end;
  end;
end;
{ ==============================================================================
  方法名稱:ISB1ImageMouseMove
  引用相依:
  方法描述:影像滑鼠移動事件。根據當前是否有載入影像檔案,動態切換滑鼠模式(MouseMo
            de)。若無檔案則設為使用者模式(mmUser),否則根據 NowClick 狀態呼叫 View
            MouseMode 切換至對應的檢視模式。
============================================================================== }
procedure TCB_IMGPSScanX.ISB1ImageMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
   //Edit1.SetFocus;
  //TImageScrollBox(Sender).SetFocus;
  if TImageScrollBox(Sender).FileName = '' then
    TImageScrollBox(Sender).MouseMode := mmUser
  Else
    ViewMouseMode(NowClick);
  ISB1.AlwaysShowAnnotations := False;
//  if TImageScrollBox(Sender).FileName = '' then
//  begin
////ShowMessage('AAA');
//Label3.Caption:='FileName='+TImageScrollBox(Sender).FileName+'  time='+FormatDateTime('yyyy/mm/dd HH:MM:SS', now);
//    TImageScrollBox(Sender).MouseMode := mmUser
//  end
//  Else
//  begin
//Label3.Caption:='FileName='+TImageScrollBox(Sender).FileName;
//    ViewMouseMode(NowClick);
//  end;
end;
{ ==============================================================================
  方法名稱:ISB1ImageMouseUp
  引用相依:TJpegGraphic, SaveQuality, SaveToFile
  方法描述:影像滑鼠放開事件。處理多種滑鼠模式:在 mmDelete 模式下觸發刪除功能;在
            旋轉模式(mmR90等)下儲存旋轉後的影像檔案,並同步更新預覽圖(SelectISB)
            與清空檢核記錄。最後針對縮放或拖曳模式更新捲軸位置數據。
============================================================================== }
procedure TCB_IMGPSScanX.ISB1ImageMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
Var
  p : Integer;
  ISB : TImageScrollBox;
begin
  case TImageScrollBox(Sender).MouseMode of
    mmDelete:
    begin
      PM508Click(Self);
    end;
    mmR90,mmR180,mmR270:
    begin
      if TImageScrollBox(Sender).Graphic.ImageFormat <> ifBlackWhite then
      begin
        TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveQuality := 30;
        TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveToFile(TImageScrollBox(Sender).FileName);
      end
      Else
        TImageScrollBox(Sender).SaveToFile(TImageScrollBox(Sender).FileName);
      SelectISB.Graphic.Assign(TImageScrollBox(Sender).Graphic);
      SelectISB.Redraw(True);
      FitPreViewISB;
      ISBClick(SelectISB);
      ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
    end;
  end;
  ISB := TImageScrollBox(Sender);
  if (ISB.MouseMode = mmZoom) or (ISB.MouseMode = mmDrag) then
    SetScrollData(ISB,ISB.HorzScrollBar.Position,ISB.VertScrollBar.Position,ISB.ZoomPercent);
end;
{ ==============================================================================
  方法名稱:ScrollBox1MouseEnter
  引用相依:
  方法描述:當滑鼠進入捲軸區域時,自動將焦點設定至 ScrollBox1。
============================================================================== }
procedure TCB_IMGPSScanX.ScrollBox1MouseEnter(Sender: TObject);
begin
ScrollBox1.SetFocus;
end;
{ ==============================================================================
  方法名稱:FindISB2View
  引用相依:
  方法描述:根據檢視模式,在畫面中尋找下一個可顯示影像的 TImageScrollBox。遍歷 ISB
            1-ISB8,檢查 FileName 是否為空;若已滿則會清空特定位置影像並重新開始,
            確保影像載入有對應視窗。
============================================================================== }
Function TCB_IMGPSScanX.FindISB2View(Vmode:Integer):TImageScrollBox; //找空的ISB來顯示
var
  i,n : Integer;
  ISB : TImageScrollBox;
begin
  case Vmode of
    0 : n := 1;
    1 : n := 2;
    2 : n := 4;
    3 : n := 6;
    4 : n := 8;
  end;
  for i := 1 to 8 do
  begin
    if i > n then Break;
    ISB := TImageScrollBox(FindComponent('ISB'+inttostr(i)));
    if (i = n) and (ISB.FileName <> '') then
    begin
      clearView(i);
      Result := ISB1;
    end
    Else if ISB.FileName = '' then
      Result := ISB;
  end;
end;
{ ==============================================================================
  方法名稱:ImageScrollBox1NewGraphic
  引用相依:TDibGraphic, ConvertToBW
  方法描述:當載入新影像時觸發。將當前 Graphic 內容同步至黑白影像處理元件(ISB_BW)
            ,若原始影像非黑白格式則執行 ConvertToBW 轉換。
============================================================================== }
procedure TCB_IMGPSScanX.ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
begin
  IF ImageScrollBox1.Graphic.Empty Then Exit;
  ISB_BW.Graphic.Assign(ImageScrollBox1.Graphic);
  If ImageScrollBox1.Graphic.ImageFormat <> ifBlackWhite Then
  begin
    ConvertToBW(ISB_BW.Graphic);
  end;
end;
{ ==============================================================================
  方法名稱:GetScrollData
  引用相依:
  方法描述:根據傳入的影像捲軸盒(ISB)名稱,從 ScrollRec 陣列中提取其儲存的水平、垂
            直捲軸位置及縮放比例。
============================================================================== }
Procedure TCB_IMGPSScanX.GetScrollData(ISB:TImageScrollBox;Var HS,VS:Integer;Var iRate:Single);
var
  index : Integer;
begin
  index := strtoint(copy(ISB.Name,4,1));
  HS := ScrollRec[Index].HScroll;
  VS := ScrollRec[Index].VScroll;
  iRate := ScrollRec[Index].Rate;
end;
{ ==============================================================================
  方法名稱:SetScrollData
  引用相依:
  方法描述:將指定的水平、垂直捲軸位置與縮放比例存入對應影像視窗索引的 ScrollRec
            記錄中。
============================================================================== }
Procedure TCB_IMGPSScanX.SetScrollData(ISB:TImageScrollBox;HS,VS:Integer;iRate:Single);
var
  index : Integer;
begin
  index := strtoint(copy(ISB.Name,4,1));
  ScrollRec[Index].HScroll := HS;
  ScrollRec[Index].VScroll := VS;
  ScrollRec[Index].Rate := iRate;
end;
{ ==============================================================================
  方法名稱:FindMpsView
  引用相依:
  方法描述:根據當前的檢視模式(Vmode),在 8 個影像視窗中尋找適合載入下一個影像的
            視窗組件。函式會根據 1x1 到 4x2 的佈局決定搜尋上限,優先回傳檔名為空的
            視窗;若視窗已滿,則清空指定位置的顯示並回傳主視窗 ISB1。
============================================================================== }
Function TCB_IMGPSScanX.FindMpsView(Vmode: Integer):TImageScrollBox;
var
  i,n : Integer;
  ISB : TImageScrollBox;
begin
  case Vmode of
    0 : n := 1;
    1 : n := 2;
    2 : n := 4;
    3 : n := 6;
    4 : n := 8;
  end;
  for i := 1 to 8 do
  begin
    if i > n then Break;
    ISB := TImageScrollBox(FindComponent('ISB'+inttostr(i)));
    if (i = n) and (ISB.FileName <> '') then
    begin
      clearView(i);
      Result := ISB1;
    end
    Else if ISB.FileName = '' then
      Result := ISB;
  end;
end;
reassemble/view/toolBar.pas
比對新檔案
@@ -0,0 +1,1104 @@
{ ==============================================================================
  方法名稱:WNoteBtnClick
  引用相依:FileExists, LoadFromFile, SaveToFile
  方法描述:開啟備註編輯視窗。首先初始化多國語言並從 MEMO_INF_List 載入註記範本資
            訊。若存在 Scan_Memo.dat,則讀取既有的註記內容。顯示 TSortMemoForm 供使
            用者編輯,確認後將編輯結果存回 Scan_Memo.dat。最後視需要觸發 CaseHelpB
            tnClick 以更新狀態。
============================================================================== }
procedure TCB_IMGPSScanX.WNoteBtnClick(Sender: TObject);
var
  i,n,v,v1:Integer;
  SortMemoForm : TSortMemoForm;
  M_Content,M_ID,M_Name : String;
  S : TStringlist;
begin
  ShowText := _Msg('備註輸入中,請稍候');
  DataLoading(True,True);
  SortMemoForm := TSortMemoForm.Create(Self);
  S := TStringlist.Create;
  try
    InitialLanguage(SortMemoForm); //載入多國語言
    SortMemoForm.ContentList := TStringlist.Create;      //註記內容
    SortMemoForm.MemoIDList := TStringlist.Create;       //註記代號
    SortMemoForm.MemoNameList := TStringlist.Create;     //註記名稱
    for i := 1 to MEMO_INF_List.Count - 1 do
    begin
      M_Content := GetSQLData(MEMO_INF_List,'T1.MEMO_CONTENT',i);
      M_ID := GetSQLData(MEMO_INF_List,'T1.MEMO_TYPE',i);
      M_Name := GetSQLData(MEMO_INF_List,'T2.MEMO_TYPE_NAME',i);
      SortMemoForm.ComboBox1.Items.Add(M_Name+'-->'+M_Content);
      SortMemoForm.ContentList.Add(M_Content);   //註記內容
      SortMemoForm.MemoIDList.Add(M_ID);         //註記代號
      SortMemoForm.MemoNameList.Add(M_Name);     //註記名稱
    end;
    if FileExists(DisplayPath+'Scan_Memo.dat') then
    begin
      S.LoadFromFile(DisplayPath+'Scan_Memo.dat');
      for I := 0 to S.Count - 1 do
      begin
        v := Pos(',',S.Strings[i]);
        v1 := length(S.Strings[i]);
        M_ID := copy(S.Strings[i],1,v-1);
        M_Name := MemoInfoTransfer('ID',M_ID,SortMemoForm.MemoIDList,SortMemoForm.MemoNameList);
        M_Content := copy(S.Strings[i],v+1,v1-v);
        SortMemoForm.ResoureMemo.Add(M_Name+'-->'+M_Content);
        With SortMemoForm.MemoLV.Items.Add do
        begin
          Caption := M_Content;
          SubItems.Add(M_Name);
        end;
      end;
    end;
    if SortMemoForm.ShowModal = mrOk then
    begin
      S.Clear;
      for I := 0 to SortMemoForm.MemoLV.Items.Count - 1 do
      begin
        M_Content := SortMemoForm.MemoLV.Items.Item[i].Caption;
        M_Name := SortMemoForm.MemoLV.Items.Item[i].SubItems.Strings[0];
        M_ID := MemoInfoTransfer('NAME',M_Name,SortMemoForm.MemoIDList,SortMemoForm.MemoNameList);
        S.Add(M_ID+','+M_Content);
      end;
      S.SaveToFile(DisplayPath+'Scan_Memo.dat');
    end;
    SortMemoForm.ContentList.Free;       //註記內容
    SortMemoForm.MemoIDList.Free;        //註記代號
    SortMemoForm.MemoNameList.Free;      //註記名稱
  finally
  SortMemoForm.Free;
  S.Free;
  DataLoading(False,False);
  if Ch_WriteNote then
  begin
    Ch_WriteNote := False;
    CaseHelpBtnClick(self);
    ErrIndex := 0;
  end;
  end;
end;
{ ==============================================================================
  方法名稱:FC0Click
  引用相依:
  方法描述:工具列功能按鈕 0 的點擊處理。若重複點擊則關閉影像顯示(DesableImage),
            否則啟用索引為 0 的影像顯示(EnableImage)並更新 NowClick 狀態。
============================================================================== }
procedure TCB_IMGPSScanX.FC0Click(Sender: TObject);
begin
  IF NowClick = 0 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(0 ,Sender);
  NowClick := 0;
end;
{ ==============================================================================
  方法名稱:FC1Click
  引用相依:
  方法描述:工具列功能按鈕 1 的點擊處理。若重複點擊則關閉影像顯示,否則啟用索引為
            1 的影像顯示並更新 NowClick 狀態。
============================================================================== }
procedure TCB_IMGPSScanX.FC1Click(Sender: TObject);
begin
  IF NowClick = 1 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(1 ,Sender);
  NowClick := 1;
end;
{ ==============================================================================
  方法名稱:FC2Click
  引用相依:
  方法描述:工具列功能按鈕 2 的點擊處理。若重複點擊則關閉影像顯示,否則啟用索引為
            2 的影像顯示並更新 NowClick 狀態。
============================================================================== }
procedure TCB_IMGPSScanX.FC2Click(Sender: TObject);
begin
  IF NowClick = 2 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(2,Sender);
  NowClick := 2;
end;
{ ==============================================================================
  方法名稱:FC3Click
  引用相依:
  方法描述:工具列功能按鈕 3 的點擊處理。若重複點擊則關閉影像顯示,否則啟用索引為
            3 的影像顯示並更新 NowClick 狀態。
============================================================================== }
procedure TCB_IMGPSScanX.FC3Click(Sender: TObject);
begin
  IF NowClick = 3 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(3 ,Sender);
  NowClick := 3;
end;
{ ==============================================================================
  方法名稱:FC4Click
  引用相依:
  方法描述:工具列功能按鈕 4 的點擊處理。若重複點擊則關閉影像顯示,否則啟用索引為
            4 的影像顯示並更新 NowClick 狀態。
============================================================================== }
procedure TCB_IMGPSScanX.FC4Click(Sender: TObject);
begin
  IF NowClick = 4 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(4 ,Sender);
  NowClick := 4;
end;
{ ==============================================================================
  方法名稱:FC5Click
  引用相依:
  方法描述:工具列功能按鈕 5 的點擊處理。若重複點擊則關閉影像顯示,否則啟用索引為
            5 的影像顯示並更新 NowClick 狀態。
============================================================================== }
procedure TCB_IMGPSScanX.FC5Click(Sender: TObject);
begin
  IF NowClick = 5 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(5 ,Sender);
  NowClick := 5;
end;
{ ==============================================================================
  方法名稱:FC6Click
  引用相依:
  方法描述:工具列功能按鈕 6 的點擊處理。目前的實作已註解掉原有的影像啟用邏輯,改
            為直接呼叫 PM605Click(nil),即觸發右鍵選單中的刪除影像功能。
============================================================================== }
procedure TCB_IMGPSScanX.FC6Click(Sender: TObject);
begin
  {IF NowClick = 6 Then
  begin
    DesableImage;
    Exit;
  end;
  EnableImage(6 ,Sender);
  NowClick := 6;}
  PM605Click(nil);
end;
{ ==============================================================================
  方法名稱:NewScanBtnClick
  引用相依:StatrTwainScan
  方法描述:點擊「新案掃瞄」按鈕的處理。首先檢查初始化狀態。針對重掃(RSCAN)、異動(ESC
            AN)或重掃指定件(DSCAN),會自動選取新件節點並觸發追加掃瞄。若是全新掃瞄
            ,則重設掃瞄模式與路徑,清空清單,最後呼叫 StatrTwainScan 啟動掃瞄程序,
            並在結束後重新載入影像檔案。
============================================================================== }
procedure TCB_IMGPSScanX.NewScanBtnClick(Sender: TObject);
begin
  IF not InitialOk Then
  begin
    Showmessage(_msg('資訊尚未下載完成,請稍候或重新進入'));
    Exit;
  end;
LogFile1.LogToFile(logTimeString+'掃瞄開始');
  if (FMode = 'RSCAN') or (FMode = 'ESCAN') or (FMode = 'DSCAN') then
  begin
    if NewTreeNode.Count > 0 then
    begin
      TreeView1.Selected := NewTreeNode.Item[0];
      TreeView1click(nil);
      FirstDocDir := '';
      NowGuideFormID := '';
      NowDivPageFormID :='';
      AddScanBtnclick(nil);
    end;
  end
  Else
  begin
    TreeView1.Selected := NewTreeNode;
    NewTreeNode.Expand(False);
    TreeView1Click(self);
    Panel1.Enabled := False;
    Panel2.Enabled := False;
    ScanMode := smNew;
    ScanInfo.ImageCount := 0;
    ScanPath := '';
    ScanCaseno := '';
    NowGuideFormID := '';
    NowDivPageFormID :='';
    ClearView(1);
    ContextList.Clear;
    Try
      StatrTwainScan;
LogFile1.LogToFile(logTimeString+'掃瞄結束');
    Except
      Panel1.Enabled := True;
      Panel2.Enabled := True;
    end;
    Panel1.Enabled := True;
    Panel2.Enabled := True;
    LoadImgFile;
  end;
end;
{ ==============================================================================
  方法名稱:NextPageBtnClick
  引用相依:
  方法描述:處理「下一頁」按鈕點擊。若有選取影像,則呼叫 NextPage 跳轉至下一頁,並判
            斷選取影像的位置是否超出目前滾輪區域的高度,若是則自動調整 ScrollBox1
             的垂直捲軸位置,以確保新頁面影像能正確顯示在視線範圍內。
============================================================================== }
procedure TCB_IMGPSScanX.NextPageBtnClick(Sender: TObject);
var
  page : Integer;
begin
  {page := ScrollBar1.Position;
  Case Vmode of
    0   : Inc(page);
    1   : Page := Page + 2;
    2   : Page := Page + 4;
    3   : Page := Page + 6;
    4   : Page := Page + 8;
  end;
  IF page <= ScrollBar1.Max Then
  begin
    ScrollBar1.Position := page;
  end;}
  if selectISB = nil then Exit;
  NextPage(SelectPage);
  if SelectISB.Parent.Top+SelectISB.Parent.Height+4 > scrollBox1.Height  then
    ScrollBox1.VertScrollBar.Position := scrollBox1.VertScrollBar.Position + (SelectISB.Parent.Top+SelectISB.Parent.Height-ScrollBox1.Height+8);
end;
{ ==============================================================================
  方法名稱:OptionBtnClick
  引用相依:Scanner
  方法描述:處理「掃瞄參數設定」按鈕點擊。首先確認系統初始化是否完成,接著建立 TPatc
            hDlg 對話框並載入多國語言。將目前的掃瞄設定(如自動刪除空白頁、DPI、單/
            雙面、反白、去邊、去偏斜、亮度、對比、旋轉角度及顯示模式等)同步至對話框。使
            用者完成設定後,將新參數存回系統變數,並呼叫 R_W_ScanIni 將設定寫入設
            定檔。
============================================================================== }
procedure TCB_IMGPSScanX.OptionBtnClick(Sender: TObject);
var
  PatchDlg : TPatchDlg;
  i : Integer;
begin
  IF not InitialOk Then
  begin
    Showmessage(_msg('資訊尚未下載完成,請稍候或重新進入'));
    Exit;
  end;
  ShowText := _Msg('掃瞄參數設定中,請稍候');
  DataLoading(True,True);
  PatchDlg := TPatchDlg.Create(self);
  try
    InitialLanguage(PatchDlg); //載入多國語言
    PatchDlg.BlankuseCB.Checked := DeviceDelete;
    if PatchDlg.BlankuseCB.Checked then
      PatchDlg.SpinEdit5.Enabled := True
    else
      PatchDlg.SpinEdit5.Enabled := False;
    PatchDlg.SpinEdit5.Value := DeviceDeleteSize;
    For i := 0 to PatchDlg.ComboBox1.Items.Count -1 do
    begin
      If inttostr(ScanDpi) = PatchDlg.ComboBox1.Items.Strings[i] Then
        PatchDlg.ComboBox1.ItemIndex := i;
    end;
    PatchDlg.DuplexCB.Checked := ScanDuplex;
    PatchDlg.ReverseCB.Checked := ScannerReverse;
    PatchDlg.BorderCB.Checked := BoardClear;
    PatchDlg.DeskewCB.Checked := ScanDeskew;
    PatchDlg.ImgSetUseCB.Checked := ScanImgSetUse;
    PatchDlg.SpinEdit1.Value := ScanBright;
    PatchDlg.SpinEdit2.Value := ScanContrast;
    case ScanRotate of
      0  : PatchDlg.ScanRotateRG.ItemIndex := 0;
      270 : PatchDlg.ScanRotateRG.ItemIndex := 1;
      180 : PatchDlg.ScanRotateRG.ItemIndex := 2;
      90 : PatchDlg.ScanRotateRG.ItemIndex := 3;
    end;
    Case ScanImgShowMode of
      0 :  PatchDlg.ScanShowRG.ItemIndex := 0;
      1 :  PatchDlg.ScanShowRG.ItemIndex := 1;
      2 :  PatchDlg.ScanShowRG.ItemIndex := 2;
    end;
    If PatchDlg.ShowModal = mrOk then
    begin
      DeviceDelete := PatchDlg.BlankuseCB.Checked;
      DeviceDeleteSize := PatchDlg.SpinEdit5.Value;
      ScanDpi := Strtoint(PatchDlg.ComboBox1.Text);
      ScannerReverse := PatchDlg.ReverseCB.Checked;
      BoardClear := PatchDlg.BorderCB.Checked;
      ScanDeskew := PatchDlg.DeskewCB.Checked;
      ScanDuplex := PatchDlg.DuplexCB.Checked;
      ScanImgSetUse := PatchDlg.ImgSetUseCB.Checked;
      ScanBright := PatchDlg.SpinEdit1.Value;
      ScanContrast := PatchDlg.SpinEdit2.Value;
      Case PatchDlg.ScanRotateRG.ItemIndex of
        0:ScanRotate := 0;
        1:ScanRotate := 270;
        2:ScanRotate := 180;
        3:ScanRotate := 90;
      end;
      Case PatchDlg.ScanShowRG.ItemIndex of
        0:ScanImgShowMode := 0;
        1:ScanImgShowMode := 1;
        2:ScanImgShowMode := 2;
      end;
      R_W_ScanIni('W');
      ScanDuplexCB.Checked := ScanDuplex;
    end;
  finally
  PatchDlg.Free;
  DataLoading(False,False);
  end;
end;
{ ==============================================================================
  方法名稱:PrePageBtnClick
  引用相依:
  方法描述:處理「上一頁」按鈕點擊。跳轉至前一頁並判斷影像位置,若向上超出捲軸區域則
            自動滾動垂直捲軸,將影像帶入可見區域。
============================================================================== }
procedure TCB_IMGPSScanX.PrePageBtnClick(Sender: TObject);
var
  page : Integer;
begin
  {page := ScrollBar1.Position;
   Case Vmode of
    0   : dec(page);
    1   : Page := Page - 2;
    2   : Page := Page - 4;
    3   : Page := Page - 6;
    4   : Page := Page - 8;
  end;
  IF page >= ScrollBar1.min Then
  begin
    ScrollBar1.Position := page;
  end
  Else
    ScrollBar1.Position := 1;  }
  if selectISB = nil then Exit;
  PriorPage(SelectPage);
  if (SelectISB.Parent.Top-4) < 0 then
    scrollBox1.VertScrollBar.Position := scrollBox1.VertScrollBar.Position + SelectISB.Parent.Top-4;
      //ISBClick(TImageScrollBox(FindComponent(ISBName+'1')));
end;
{ ==============================================================================
  方法名稱:SampleScanBtnClick
  引用相依:FileExists, LoadFromFile, SaveToFile, StatrTwainScan, upFile
  方法描述:處理「範本掃瞄」按鈕點擊。切換為範本模式並引導使用者輸入 FormID,掃瞄後
            產生 TIF 與 JPG 影像。隨後透過 HTTPS 將範本上傳至伺服器,上傳過程中會
            嚴格檢查網路狀態、Session 有效性與伺服器回傳結果。
============================================================================== }
procedure TCB_IMGPSScanX.SampleScanBtnClick(Sender: TObject);
var
  SampleFormID : String;
  SendData : String;
  buttonSelected : Integer;
begin
  ScanMode := smSample;
  ClearView(1);
  Vmode := 0;  //切成單頁
  GoViewMode;
  ScanInfo.ImageCount := 0;
  ScanPath := SamplePath;
  ScanCaseno := '';
  ContextList.Clear;
  ShowText := _Msg('範本掃描中,請稍候');
  DataLoading(True,True);
  SampleFormID := UpperCase(InputBox(_Msg('範本檔掃瞄輸入畫面'),_Msg('請輸入文件編號'),''));
  if SampleFormIDList.IndexOf(SampleFormID)<>-1 then
  begin
    // Show a custom dialog
    buttonSelected := messagedlg(SampleFormID+_Msg('已有範本,是否取代?'),mtCustom,
                                [mbYes,mbCancel], 0);
    if buttonSelected = mrCancel then
    begin
      DataLoading(false,false);
      Exit;
    end;
  end;
  if SampleFormID <> '' then
  begin
    if FormIDExists(SampleFormID,False,0) then
    begin
      ScanSaveFilename :=  SampleFormID + '.tif';
    end
    Else
    begin
      Showmessage(Format(_Msg('FormID:%s尚未註冊'),[SampleFormID]));
      Panel1.Enabled := True;
      Panel2.Enabled := True;
      DataLoading(false,false);
      Exit;
    end;
    SampleAnchorMode := FormID2Anchor(SampleFormID);
    Panel1.Enabled := False;
    Panel2.Enabled := False;
//ShowMessage('AAAAA');
    Try
      StatrTwainScan;
    Except
    Panel1.Enabled := True;
    Panel2.Enabled := True;
    end;
    if (ISB1.FileName <> '') and FileExists(SamplePath+SampleFormID+'.tif') then
    begin
      ShowText := _Msg('範本傳送中,請稍候');
      DataLoading(True,True);
      //多存一份jpg
      ImageScrollBox1.LoadFromFile(SamplePath+SampleFormID+'.tif',1);
      BWTif2Jpg(ImageScrollBox1.Graphic);
      ImageScrollBox1.SaveToFile(SamplePath+SampleFormID+'.jpg');
      //多存一份jpg
      NowWork_No := FormCode2WorkNo(SampleFormID);
      SendData := 'data='+FData+'&verify='+FVerify+'&work_no='+FWork_no+'&file_name='+SampleFormID+'.tif';
      if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',SamplePath+SampleFormID+'.tif',FReWrite,Memo1,False) then
      begin
        Showmessage(_Msg('傳送範本檔案時,網路發生錯誤!!')+_MSg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+')');
        DataLoading(False,False);
        Exit;
      end;
      if memo1.Lines.Strings[0] = '1' then
      begin
        Showmessage(_Msg('傳送範本檔案時,網路發生錯誤!!')+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
        DataLoading(False,False);
        Exit;
      end
      Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
      begin
        Showmessage(_Msg('傳送範本檔案時,網路發生錯誤!!')+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
        DataLoading(False,False);
        Exit;
      end;
      if FileExists(SamplePath+SampleFormID+'.jpg') then   //傳送JPG影像
      begin
        SendData := 'data='+FData+'&verify='+FVerify+'&work_no='+FWork_no+'&file_name='+SampleFormID+'.jpg';
        if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',SamplePath+SampleFormID+'.jpg',FReWrite,Memo1,False) then
        begin
          Showmessage(_Msg('傳送範本檔案(JPG)時,網路發生錯誤!!')+_MSg('錯誤代碼:')+Inttostr(HttpError.HttpErrorCode)+' '+HttpError.HttpReason+')');
          DataLoading(False,False);
          Exit;
        end;
        if memo1.Lines.Strings[0] = '1' then
        begin
          Showmessage(_Msg('傳送範本檔案(JPG)時,網路發生錯誤!!')+_Msg('錯誤原因:')+memo1.Lines.Strings[1]);
          DataLoading(False,False);
          Exit;
        end
        Else if Pos('<script type="text/javascript" src="scripts/CW00/login.js"></script>',Memo1.Lines.Text) > 0 then
        begin
          Showmessage(_Msg('傳送範本檔案(JPG)時,網路發生錯誤!!')+_Msg('錯誤原因:')+_Msg('閒置過久或被登出,請重新登入'));
          DataLoading(False,False);
          Exit;
        end;
      end;
      Showmessage(_Msg('傳送完成'));
    end;
  end;
  DataLoading(False,False);
end;
{ ==============================================================================
  方法名稱:SelectScanBtnClick
  引用相依:SelectScanner, scanner.SelectScanner, Scanner
  方法描述:開啟系統掃瞄器選擇視窗。
============================================================================== }
procedure TCB_IMGPSScanX.SelectScanBtnClick(Sender: TObject);
begin
  Panel1.Enabled := False;
  Panel2.Enabled := False;
  scanner.SelectScanner;
  Panel1.Enabled := True;
  Panel2.Enabled := True;
end;
{ ==============================================================================
  方法名稱:AddScanBtnClick
  引用相依:StatrTwainScan
  方法描述:處理「追加掃瞄」按鈕點擊。檢查狀態後設定掃瞄模式為 smInsert(插入模式),
            初始化掃瞄參數並啟動 StatrTwainScan。完成後重新繪製樹狀結構、更新筆數
            統計並清空檢核記錄,最後自動選取新文件節點。
============================================================================== }
procedure TCB_IMGPSScanX.AddScanBtnClick(Sender: TObject);
var
  P,v : Integer;
begin
  IF not InitialOk Then
  begin
    Showmessage(_Msg('資訊尚未下載完成,請稍候或重新進入'));
    Exit;
  end;
  if MyTreeNode1 = nil then
  begin
    Showmessage(_Msg('請先選擇案件'));
    Exit;
  end;
  Panel1.Enabled := False;
  Panel2.Enabled := False;
  ScanMode := smInsert;
  ScanInfo.ImageCount := ContextList.Count;
  ScanPath := DisplayPath;
  ScanCaseno := NowCaseno;
  ScanDocDir := NowDocDir;
  Try
    StatrTwainScan;
  Except
    Panel1.Enabled := True;
    Panel2.Enabled := True;
  end;
  Panel1.Enabled := True;
  Panel2.Enabled := True;
  DrawDocItem2(MytreeNode1,NowCaseno);
  //DrawDocItem(MytreeNode1,FORM_INF_List,NowCaseno);
  //P := ContextList.Count;
  GetCase_PageCount(CaseCount,PageCount);
  v := Pos('-',NewTreeNode.Text);
  NewTreeNode.Text := Format(_Msg('%s-共%d筆共%d頁'),[Copy(NewTreeNode.Text,1,v-1),CaseCount,PageCount]);
  MytreeNode1.Text := Format(_Msg('%s-%d頁'),[NowCaseno,GetCasePage(ImageSavePath,NowCaseno)]);
  ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
  SetDocDirtoSelected(MyTreeNode1,FirstDocDir);
  TreeView1Click(self);
end;
{ ==============================================================================
  方法名稱:CaseHelpBtnClick
  引用相依:
  方法描述:處理檢核失敗(補件/更正)按鈕點擊。開啟 TErrlistForm 顯示 OMR 檢核錯誤
            清單供使用者操作。若使用者完成更正並按確定,則會根據目前模式(ISCAN/NSC
            AN 等)將更新後的影像資料上傳至伺服器,並在完成後重新載入影像、提示使用
            者。
============================================================================== }
procedure TCB_IMGPSScanX.CaseHelpBtnClick(Sender: TObject);
var
  ErrlistForm : TErrlistForm;
  S : TStringlist;
  UpFormID : String;
  Anchor : String;
begin
  ShowText := _Msg('處理檢核失敗中,請稍候');
  DataLoading(True,True);
LogFile1.LogToFile(logTimeString+'處理檢核失敗中開始');
  ErrlistForm := TErrlistForm.Create(Self);
  RejectCase := False;
  S := TStringlist.Create;
  try
    InitialLanguage(ErrlistForm);
    Application.ProcessMessages;
    ErrlistForm.LogFile1.LogFile:=LogFile1.LogFile;
    ErrlistForm.DeleteBt.Caption := ErrlistForm.DeleteBt.Caption+'(&D)';
    ErrlistForm.iniPath := ImageSavePath + NowCaseNo+'\upload\';
    OMRErrini2List(NowCaseno,ErrlistForm);
    ErrlistForm.ErrListLV.ItemIndex := ErrIndex;
    ErrlistForm.Timer1.Enabled := true;
    if ErrlistForm.ShowModal = mrok then
    begin
      TransPath := ImageSavePath+NowCaseNo+'\upload\';
      if FMode = 'ISCAN' then
        TransPath :=  ImageSavePath + NowCaseNo+'\DownTemp\';
      ShowText := NowCaseNo+_Msg('資料上傳中,請稍候');
      DataLoading(True,True);
      if FMode = 'ISCAN' then
      begin
        If Not TransCaseID(TransPath,NowCaseNo,True) Then  //傳送案件
        begin
          DataLoading(False,False);
          Exit;
        end;
      end
      Else
      begin
        If Not TransCaseID(TransPath,NowCaseNo,True) Then  //傳送案件
        begin
          DataLoading(False,False);
          Exit;
        end;
      end;
      CaseHelpBtn.Visible := False;
      LoadImgFile;
      if (FMode='NSCAN') or (FMode='DSCAN') then
      begin
        Showmessage(NowCaseNo+_Msg('影像上傳完成。此案已進入下一流程。'));
      end;
      if FMode='ESCAN' then
      begin
        Showmessage(NowCaseNo+_Msg('影像已補件完成。'));
      end;
      DataLoading(False,False);
    end
    Else
    begin
      MyTreeNode2ReFresh(NowCaseNo);
    end;
  finally
  ErrlistForm.Free;
  DataLoading(False,False);
  S.Free;
  end;
end;
{ ==============================================================================
  方法名稱:CheckCaseBtnClick
  引用相依:SaveToFile
  方法描述:執行所有案件的批次檢核。遍歷 NewTreeNode 下的所有案件,對尚未檢核通過(
            ImageIndex 不為 7 或 5)的案件呼叫 OMRCheckCase 進行檢核。若檢核成功則
            建立 OMRCheckOk.dat 標記檔。最後刷新影像與樹狀顯示。
============================================================================== }
procedure TCB_IMGPSScanX.CheckCaseBtnClick(Sender: TObject);
Var
  CaseID : String;
  i,n,v : Integer;
  S : TStringlist;
begin
  //if TreeView1.Selected = nil then Exit;
  //if TreeView1.Selected = NewTreeNode then Exit;
  Displaypath := '';  //20130327 修正報價單號會錯置的問題
  S := TStringlist.Create;
  try
    ClearView(1);
    ShowText := CaseID+_Msg('檢核中,請稍候');
    DataLoading(True,True);
    For i := 0 to NewTreeNode.Count -1 do
    begin
      v := posend('-',NewTreenode.Item[i].Text);
      CaseID := Copy(NewTreenode.Item[i].Text,1,v-1);
      ShowText := CaseID+_Msg('檢核中,請稍候');
      DataLoading(True,True);
      if (NewTreenode.Item[i].ImageIndex <> 7) and (NewTreenode.Item[i].ImageIndex <> 5) then  //檢核完成的不再檢核
      begin
        If OMRCheckCase(CaseID) then  //有成功
        begin
          S.Add('Y');
          S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
        end;
      end;
      //MyTreeNode2ReFresh(CaseID);  //原本是OMR單一案件,後改成OMR全部案件 所以這個要mark
    end;
    LoadImgFile;
    TreeView1Click(nil);
    DataLoading(False,False);
  finally
  S.Free;
  end;
  Showmessage(_Msg('檢核完成'));
end;
{ ==============================================================================
  方法名稱:SpeedButton14Click
  引用相依:Rotate, TJpegGraphic, SaveQuality, LoadFromFile, SaveToFile
  方法描述:處理工具列按鈕點擊,執行影像逆時針旋轉 90 度(即旋轉 270 度)。程序會重
            新載入影像、執行旋轉、根據影像格式(JPG 則設定品質為 30)儲存回原檔案,最
            後更新主顯示區與縮圖區,並重新調整縮圖佈局。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton14Click(Sender: TObject);
var
  Count : Integer;
begin
  if not ISB1.Graphic.IsEmpty  then
  begin
    ISB1.LoadFromFile(ISB1.FileName,1);
    Rotate(ISB1.Graphic,270);
    if ISB1.Graphic.ImageFormat <> ifBlackWhite then
    begin
      TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
      TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
    end
    Else
      ISB1.SaveToFile(ISB1.FileName);
    ISB1.Redraw(True);
    SelectISB.Graphic.Assign(ISB1.Graphic);
    SelectISB.Redraw(True);
    FitPreViewISB;
    ISBClick(SelectISB);
  end;
end;
{ ==============================================================================
  方法名稱:SpeedButton15Click
  引用相依:Rotate, TJpegGraphic, SaveQuality, LoadFromFile, SaveToFile
  方法描述:處理工具列按鈕點擊,執行影像旋轉 180 度。程序重新載入檔案後執行旋轉操
            作,並依據格式存檔。完成後同步更新主畫面與預覽圖,確保顯示一致性。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton15Click(Sender: TObject);
begin
  if not ISB1.Graphic.IsEmpty  then
  begin
    ISB1.LoadFromFile(ISB1.FileName,1);
    Rotate(ISB1.Graphic,180);
    if ISB1.Graphic.ImageFormat <> ifBlackWhite then
    begin
      TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
      TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
    end
    Else
      ISB1.SaveToFile(ISB1.FileName);
    ISB1.Redraw(True);
    SelectISB.Graphic.Assign(ISB1.Graphic);
    SelectISB.Redraw(True);
    FitPreViewISB;
    ISBClick(SelectISB);
  end;
end;
{ ==============================================================================
  方法名稱:SpeedButton16Click
  引用相依:Rotate, TJpegGraphic, SaveQuality, LoadFromFile, SaveToFile
  方法描述:處理工具列按鈕點擊,執行影像順時針旋轉 90 度。載入影像後執行旋轉並儲存
            ,針對非黑白影像會設定 JPG 壓縮品質。最後重新繪製相關顯示元件並觸發點
            擊事件。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton16Click(Sender: TObject);
begin
  if not ISB1.Graphic.IsEmpty  then
  begin
    ISB1.LoadFromFile(ISB1.FileName,1);
    Rotate(ISB1.Graphic,90);
    if ISB1.Graphic.ImageFormat <> ifBlackWhite then
    begin
      TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
      TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
    end
    Else
      ISB1.SaveToFile(ISB1.FileName);
    ISB1.Redraw(True);
    SelectISB.Graphic.Assign(ISB1.Graphic);
    SelectISB.Redraw(True);
    FitPreViewISB;
    ISBClick(SelectISB);
  end;
end;
{ ==============================================================================
  方法名稱:SpeedButton17Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為「符合高度」(zmFitHeight)。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton17Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmFitHeight;
end;
{ ==============================================================================
  方法名稱:SpeedButton18Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為「符合寬度」(zmFitWidth)。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton18Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmFitWidth;
end;
{ ==============================================================================
  方法名稱:SpeedButton19Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為「原始大小」(zmOriginalSize)。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton19Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmOriginalSize;
end;
{ ==============================================================================
  方法名稱:SpeedButton20Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為「符合頁面」(zmFittoPage)。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton20Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmFittoPage;
end;
{ ==============================================================================
  方法名稱:SpeedButton21Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為自定義百分比,並將比例設為 50%。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton21Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmPercent;
  ISB1.ZoomPercent := 50;
end;
{ ==============================================================================
  方法名稱:SpeedButton22Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為自定義百分比,並將比例設為 25%。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton22Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmPercent;
  ISB1.ZoomPercent := 25;
end;
{ ==============================================================================
  方法名稱:SpeedButton3Click
  引用相依:
  方法描述:將主影像顯示區的縮放模式設定為「全頁顯示」(zmFullPage)。
============================================================================== }
procedure TCB_IMGPSScanX.SpeedButton3Click(Sender: TObject);
begin
  ISB1.ZoomMode := zmFullPage;
end;
{ ==============================================================================
  方法名稱:TransBtnClick
  引用相依:LoadFromFile
  方法描述:處理工具列「上傳」按鈕的點擊事件。執行完整的前置檢查(包含案件配號、歸類、
            收件時間限制等),接著遍歷所有案件執行 OMR 檢核與 ReSize,最後呼叫 Tran
            sCaseID 將案件封裝傳送至伺服器。上傳結束後會顯示成功/失敗的統計報告。
============================================================================== }
procedure TCB_IMGPSScanX.TransBtnClick(Sender: TObject);
Var
  CaseID : String;
  i,n,v: Integer;
  ZipFileList : TStringlist;
  CaseTrans : Integer; //-1:失敗 0:可 1:不行
  SuccessCount,ReCasecount,CheckErrCount : Integer;
  TransMsg : String;
  AreaStr : String;
  S : TStringlist;
  CheckStr : String;
  uploadMsg:String;//20171122 新增 配合不同mode下要秀不能上傳訊息
begin
  IF not InitialOk Then
  begin
    Showmessage(_msg('資訊尚未下載完成,請稍候或重新進入'));
    Exit;
  end;
LogFile1.LogToFile(logTimeString+'按下上傳');
  ClearView(1);
  CaseHelpBtn.Visible := False;
  DisplayPath := '';
  ClearCaseIndex;
  RejectCase := False;
  uploadMsg:='';
  if not CheckCaseID_OK then  //檢查是否有未配號的案件
  begin
    Showmessage(_Msg('尚有「無案件編號」之案件,無法上傳'));
    Exit;
  end;
  if not CheckCaseAttach_OK then  //20170911檢查是否有未歸類的案件
  begin
    Showmessage(_Msg('尚有未歸類文件,無法上傳'));
    Exit;
  end;
  if NewTreeNode.Count = 0  then
  begin
    Showmessage(_Msg('無影像需傳送'));
    Exit;
  end;
  SuccessCount := 0;
  ReCasecount := 0;
  CheckErrCount := 0;
  if (FMode = 'NSCAN') and (not CheckScanDenialTime) then
  begin
    if Messagedlg(Format(_Msg('己超過收件時間(%s),預定作業日為下個營業日,是否繼續上傳??'),[ScanDenialTime]),mtConfirmation,[mbyes,mbcancel],0)=mrcancel then Exit;
  end;
  ShowText := _Msg('資料上傳中,請稍候');
  DataLoading(True,True);
  For i := 0 to NewTreeNode.Count -1 do
  begin
    v := posend('-',NewTreenode.Item[i].Text);
    CaseID := Copy(NewTreenode.Item[i].Text,1,v-1);
    ShowText := CaseID+_Msg('資料上傳中,請稍候');
    DataLoading(True,True);
    CreateIn_WH(CaseID);    //產生入庫文件文字檔 In_Wh.dat
    Case2upload(CaseID);   //產生原影像結構
    TransPath := ImageSavePath+CaseID+'\Upload\';
    {if FMode = 'ESCAN' then    //20140320 yuu說拿掉此檢查
    begin
      S := TStringlist.Create;
      try
        S.LoadFromFile(TransPath + 'Context.dat');
        if S.Count = 0 then
        begin
          Showmessage(_Msg('無影像檔無法傳送'));
          DataLoading(False,False);
          LoadImgFile;
          Exit;
        end;
      finally
      s.Free;
      end;
    end;}
    if (FMode = 'NSCAN') or (FMode = 'DSCAN')  then //20170406 待掃瞄也要問一下
    begin
      /////訊問是否可上傳/////
      CaseTrans := CaseAsk(CaseID);
      //Showmessage('記得改回來');
      //CaseTrans := 0;
      /////訊問是否可上傳////
    end
    Else  ///不是新件、重掃件、異動件的不查
    begin
      CaseTrans := 0;
    end;
    if CaseTrans = -1 then  //失敗
    begin
      Showmessage(_Msg('')+HttpErrStr+'.');
      DataLoading(False,False);
      LoadImgFile;
      Exit;
    end;
    if CaseTrans = 1 then
    begin
      ////重複處理/////
      Inc(ReCasecount);
      ////重複處理/////
      Continue;
    end
    Else if CaseTrans = 0 then   //可以傳送
    begin
      ///////檢核//////  20100927 User改為搬至外面做  ///20101019 User又改回上傳要做
      //if FMode = 'NSCAN' then  //20101019改成讀設定那些模式要做那些檢核
      //begin
       ///依十字定位點縮放////
       CaseReSize(CaseID);   //所以影像再做一次縮放
       ////依十字定位點縮放///////   }
        if (FMode <> 'FSCAN') then
        begin
          if (NewTreenode.Item[i].ImageIndex <> 7) and (NewTreenode.Item[i].ImageIndex <> 5) then  //檢核完成的不再檢核
          begin
            ShowText := CaseID+_Msg('檢核中,請稍候');
            DataLoading(True,True);
            If not OMRCheckCase(CaseID) then  //進檢核
            begin
              Inc(CheckErrCount);
              Continue;
            end;
          end;
          if (NewTreenode.Item[i].ImageIndex = 5) then
          begin
            Inc(CheckErrCount);
            Continue;
          end;
        end;
      //end;
      ///////檢核//////
      ShowText := CaseID+_Msg('資料上傳中,請稍候');
      DataLoading(True,True);
//ShowMessage('退出');DataLoading(False,False);Exit;
      If Not TransCaseID(TransPath,CaseID,True) Then  //傳送案件
      begin
        DataLoading(False,False);
        LoadImgFile;
        Exit;
      end;
      Inc(SuccessCount);
    end;
  end;
  DataLoading(False,False);
  TransMsg := Format(_Msg('成功件【%d】件'),[SuccessCount]);
  if ReCasecount > 0 then
    TransMsg := TransMsg + #13#10 + Format(_Msg('無法上傳件【%d】件'),[ReCasecount]);
  if CheckErrCount > 0 then
  begin
    TransMsg := TransMsg + #13#10 + Format(_Msg('檢核失敗件【%d】件,請先點選「案件編號」,再點選「問號」查看錯誤原因'),[CheckErrCount]);
LogFile1.LogToFile(logTimeString+'檢核失敗原因:'+OMRErrini2ListForLog(''));
  end;
  if (FMode = 'DSCAN') and (SuccessCount = 1)  then
  begin
    uploadMsg:=NowCaseNo+_Msg('影像上傳完成。此案已進入下一流程');
  end;
  if (FMode='ESCAN') and (FModeName=_Msg('補件掃描')) and (SuccessCount = 1) then
  begin
    uploadMsg:=NowCaseNo+_Msg('影像已補件完成');
  end;
//ShowMessage('uploadMsg='+uploadMsg);
  if uploadMsg<>'' then
  begin
    ShowMessage(uploadMsg);
  end
  else
  begin
    Showmessage(_Msg('傳送完成')+#13#10+TransMsg);
  end;
  LoadImgFile;
  if (FMode = 'ESCAN') and (SuccessCount = 1) then
  begin
    if FEvents <> nil Then
    begin
      FEvents.OnClosePage;
    end;
  end;
  if (FMode = 'DSCAN') and (SuccessCount = 1) then
  begin
    if FEvents <> nil Then
    begin
      FEvents.OnClosePage;
    end;
  end;
end;
reassemble/view/treeView.pas
比對新檔案
@@ -0,0 +1,822 @@
{ ==============================================================================
  方法名稱:DrawDocItem2
  引用相依:FileExists, LoadFromFile, DirectoryExists
  方法描述:在樹狀結構中繪製指定案件的文件與表單節點。讀取 CaseDocNo.dat 取得文件
            清單,逐一建立文件節點並根據引用狀態設定圖示。接著在文件節點下建立表單
            節點,區分制式表單與自定義表單。包含入庫過濾與附件處理,是樹狀 UI 呈現
            的核心。
============================================================================== }
Function TCB_IMGPSScanX.DrawDocItem2(CaseNode : TTreenode;Caseno:String):Boolean;  //畫出文件名稱的Tree
Var
  i,n,m : Integer;
  DocNode,FormNode : TTreeNode;
  DocNoPage,FormPage : Integer;
  DocNoCopies : Integer;
  DocNo,iDocNo : String;
  DocVer : String;
  FileList : TStringlist;
  FormID,iFormID : String;
  FormName : String;
  CaseDocNoList,CaseDocNo_CopiesList,StrList : TStringlist;
  iiDocNo,iiFormID,iiDocVer : String;
  ST1:TStringList;
begin
  Result := False;
  FileList := TStringlist.Create;
  CaseDocNoList := TStringlist.Create;
  CaseDocNo_CopiesList := TStringlist.Create;
  StrList := TStringlist.Create;
  ST1:=TStringList.Create;
LogFile1.LogToFile(logTimeString+'產文件樹開始');
  try
    CaseNode.ImageIndex := 1;
    CaseNode.SelectedIndex := 1;
    While CaseNode.Count > 0 do  //全刪
    begin
      CaseNode.Item[0].Delete;
    end;
    CaseDocNoList.Clear;
    if FileExists(ImageSavePath+Caseno+'\CaseDocNo.dat') then
      CaseDocNoList.LoadFromFile(ImageSavePath+Caseno+'\CaseDocNo.dat');
    if FileExists(ImageSavePath+Caseno+'\CaseDocNo_Copies.dat') then
      CaseDocNo_CopiesList.LoadFromFile(ImageSavePath+Caseno+'\CaseDocNo_Copies.dat');
    for i := 0 to CaseDocNoList.Count - 1 do
    begin
      FileList.Clear;
      //Showmessage(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\Context.dat');
      if FileExists(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\Context.dat') then
        FileList.LoadFromFile(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\Context.dat');
      iDocNo := DocNoDir2DocNo(CaseDocNoList.Strings[i]);
      ST1.Clear;
LogFile1.LogToFile(logTimeString+'FileList.Text='+FileList.CommaText);
      if (FWH_category='N') and (FIs_In_Wh='Y') then
      begin
        for n := 0 to FileList.Count - 1 do
        begin
          if ISExistImg(ImageSavePath+Caseno+'\'+CaseDocNoList.Strings[i]+'\'+FileList.Strings[n]) then
          begin
            ST1.Add(FileList.Strings[n]);
          end;
        end;
        for n := 0 to ST1.Count - 1 do
        begin
          if (FileList.IndexOf(ST1.Strings[n])<>-1) and (not DocNoIs_In_WH(iDocNo)) then
          begin
            FileList.Delete(FileList.IndexOf(ST1.Strings[n]));
          end;
        end;
      end
      Else
        if not DocNoAppear(iDocNo) then Continue;  //20180925 Hong覺得應該加這段
LogFile1.LogToFile(logTimeString+'WH_category='+FWH_category+',Is_In_Wh='+FIs_In_Wh+',FileList.Text='+FileList.CommaText);
      if FileList.Count=0 then Continue;
      DocNoCopies := Strtoint(CaseDocNo_CopiesList.Strings[i]);
      DocNoPage := FileList.Count;
      iDocNo := DocNoDir2DocNo(CaseDocNoList.Strings[i]);
//Showmessage(iDocNo);
//Showmessage(DocNo2DocName(Caseno,iDocNo));
//ShowMessage('FileList='+FileList.Text);
      {if (((FIs_In_Wh  = 'Y') and (not DocNoIs_In_WH(iDocNo))) or   //入庫掃描不看非入庫文件
         ((FIs_In_Wh  = 'N') and (DocNoIs_In_WH(iDocNo)))) and
         ((iDocNo <> 'Attach') and (Copy(iDocNo,1,5)<>'ZZZZZ')) then     //非入庫掃描不看入庫文件
      begin
        Continue;
      end;}
      //if not DocNoAppear(iDocNo) then Continue;
      //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('頁'),[CaseDocNoList.Strings[i],DocNo2DocName(Caseno,iDocNo),DocNoPage]));
      //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[CaseDocNoList.Strings[i],DocNo2DocName(Caseno,iDocNo),DocNoCopies]));
//ShowMessage('iDocNo='+iDocNo);
      DocNode := TreeView1.Items.AddChild(CaseNode,Format(_Msg('%s{%s}-%d份'),[DocNo2DocName(Caseno,iDocNo),CaseDocNoList.Strings[i],DocNoCopies]));
      if GetUseCase('F',ImageSavePath+Caseno+'\',CaseDocNoList.Strings[i]) <> '' Then
      begin
        DocNode.ImageIndex := 8;
        DocNode.SelectedIndex := 8;
      end
      Else if GetUseCase('T',ImageSavePath+Caseno+'\',CaseDocNoList.Strings[i]) <> '' Then
      begin
        DocNode.ImageIndex := 9;
        DocNode.SelectedIndex := 9;
      end
      Else
      begin
        DocNode.ImageIndex := 2;
        DocNode.SelectedIndex := 2;
      end;
      if ((Pos('ZZZZZ',DocNode.Text) = 0) and (Pos('YYYYY',DocNode.Text) = 0)) and (FileList.Count =0) then  //制式文件
      begin
        for n := 1 to LASTEST_FORM_INF_List.Count - 1 do
        begin
          StrList := SplitString('!@!',LASTEST_FORM_INF_List.Strings[n]);
          iiFormID := StrList.Strings[0];
          iiDocNo := StrList.Strings[1];
          if iiDocNo = iDocNo then
          begin
            FormID := iiFormID;
            FormPage := GetFormIDPage(FileList,FormID);
            FormName := FormCode2FormName(Caseno,FormID);
            //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
            FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
            FormNode.ImageIndex := 4;
            FormNode.SelectedIndex := 4;
            DocNode.AlphaSort(True);
          end;
        end;
      end
      else if (Pos('ZZZZZ',DocNode.Text) > 0) or (Pos('YYYYY',DocNode.Text) > 0) then //自訂文件
      begin
        FormID := GetCustomFormID(ImageSavePath+Caseno+'\',CaseDocNoList.Strings[i]);
        //showmessage(FileList.Text);
        FormPage := GetFormIDPage(FileList,FormID);
        FormName := FormCode2FormName(Caseno,FormID);
        //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
        //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
        FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
        FormNode.ImageIndex := 4;
        FormNode.SelectedIndex := 4;
        DocNode.AlphaSort(True);
      end;
      SortDocDir_FormID(Caseno,CaseDocNoList.Strings[i]);  //檔名依FormID排序
      for n := 0 to FileList.Count - 1 do
      begin
        FormID := FileName2FormCode(FileList.Strings[n]);
        DocVer := FormCode2Version(FormID);
        DocNo := FormCode2DocNo(FormID);
        if CheckFormIDExists(DocNode,FormID) then Continue;
        //Showmessage(FormID+#13+DocNo+#13+DocVer);
        for m := 0 to FormID_List.Count - 1 do
        begin
          iiFormID := FormID_List.Strings[m];
          iiDocNo := DocNo_List.Strings[m];
          iiDocVer := FormCode2Version(iiFormID);
          if (iiDocNo = DocNo) and (iiDocVer = DocVer) then
          begin
            //Showmessage(iiFormID+#13+iiDocNo+#13+iiDocVer);
            FormID := iiFormID;
            FormPage := GetFormIDPage(FileList,FormID);
            FormName := FormCode2FormName(Caseno,FormID);
            //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
            //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
            FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
            FormNode.ImageIndex := 4;
            FormNode.SelectedIndex := 4;
            DocNode.AlphaSort(True);
          end;
        end;
        //if not CheckFormIDExists(DocNode,FormID) then
        //begin
         // Application.ProcessMessages;
         // FormPage := GetFormIDPage(FileList,FormID);
         /// FormName := FormCode2FormName(Caseno,FormID);
         /// FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
         // FormNode.ImageIndex := 4;
         // FormNode.SelectedIndex := 4;
        //end;
      end;
    end;
    if DirectoryExists(ImageSavePath+Caseno+'\'+AttName) then
    begin
      FileList.Clear;
      if FileExists(ImageSavePath+Caseno+'\'+AttName+'\Context.dat') then
        FileList.LoadFromFile(ImageSavePath+Caseno+'\'+AttName+'\Context.dat')
      Else
      begin
        Rmdir(ImageSavePath+Caseno+'\'+AttName);
        Exit;
      end;
      DocNoPage := FileList.Count;
      iDocNo := DocNoDir2DocNo(AttName);
      //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[AttName,DocNo2DocName(Caseno,iDocNo),1]));
      DocNode := TreeView1.Items.AddChild(CaseNode,Format(_Msg('%s{%s}-%d份'),[DocNo2DocName(Caseno,iDocNo),AttName,1]));
      DocNode.ImageIndex := 2;
      DocNode.SelectedIndex := 2;
      for n := 0 to FileList.Count - 1 do
      begin
        FormID := FileName2FormCode(FileList.Strings[n]);
        if not CheckFormIDExists(DocNode,FormID) then
        begin
          FormPage := GetFormIDPage(FileList,FormID);
          FormName := FormCode2FormName(Caseno,FormID);
          //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
          //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
          FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
          FormNode.ImageIndex := 4;
          FormNode.SelectedIndex := 4;
        end;
      end;
    end;
    if FModeName='件' then  //20170904 先裝死  因為異動 同時存在兩種附件太難寫
    begin
      if DirectoryExists(ImageSavePath+Caseno+'\Attach') then
      begin
        FileList.Clear;
        if FileExists(ImageSavePath+Caseno+'\Attach'+'\Context.dat') then
          FileList.LoadFromFile(ImageSavePath+Caseno+'\Attach'+'\Context.dat')
        Else
        begin
          Rmdir(ImageSavePath+Caseno+'\Attach');
          Exit;
        end;
        DocNoPage := FileList.Count;
        iDocNo := DocNoDir2DocNo(AttName);
        //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[AttName,DocNo2DocName(Caseno,iDocNo),1]));
        //DocNode := TreeView1.Items.AddChild(CaseNode,Format('%s{%s}-%d'+_msg('份'),[DocNo2DocName(Caseno,iDocNo),'Attach',1]));
        DocNode := TreeView1.Items.AddChild(CaseNode,Format(_Msg('%s{%s}-%d份'),[DocNo2DocName(Caseno,iDocNo),'Attach',1]));
        DocNode.ImageIndex := 2;
        DocNode.SelectedIndex := 2;
        for n := 0 to FileList.Count - 1 do
        begin
          FormID := FileName2FormCode(FileList.Strings[n]);
          if not CheckFormIDExists(DocNode,FormID) then
          begin
            FormPage := GetFormIDPage(FileList,FormID);
            FormName := FormCode2FormName(Caseno,FormID);
            //FormNode := TreeView1.Items.AddChild(DocNode,FormID+'{'+FormName+'}-'+inttostr(FormPage)+_msg('頁'));
            //FormNode := TreeView1.Items.AddChild(DocNode,FormName+'{'+FormID+'}-'+inttostr(FormPage)+_msg('頁'));
            FormNode := TreeView1.Items.AddChild(DocNode,Format(_Msg('%s{%s}-%d頁'),[FormName,FormID,FormPage]));
            FormNode.ImageIndex := 4;
            FormNode.SelectedIndex := 4;
          end;
        end;
      end;
    end;
LogFile1.LogToFile(logTimeString+'產文件樹結束');
  Finally
  FileList.Free;
  CaseDocNoList.Free;
  CaseDocNo_CopiesList.Free;
  StrList.Free;
  ST1.Free;
  end;
end;
{ ==============================================================================
  方法名稱:TreeView1Click
  引用相依:FileExists, LoadFromFile
  方法描述:處理樹狀結構(TreeView)的點擊事件,是切換顯示內容的核心入口。根據點擊的
            層級(案件、文件、表單),重置全域變數並設定對應的 DisplayPath、NowDocNo
            與 NowFormCode。接著載入並顯示該層級對應的影像與附件清單,同時動態調整
            按鈕與選單的可用性。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1Click(Sender: TObject);
Var
  v,v1,v2,v3,ln : Integer;
  i,page : Integer;
  F : TSearchrec;
begin
  ScanMode := smNew;
  IF TreeView1.Selected = nil Then Exit;
  Scrollbar1.Position := 1;
  Scrollbar1.Max := 1;
  DisplayPath := '';
  NowCaseno := '';
  NowDocDir := '';
  NowDocNo := '';
  NowFormCode := '';
  NowFormName := '';
  NowPage := 0;
  NowShowFileList.Clear;
  StatusBar1.Panels[2].Text := '';
  ClearCaseIndex;
  PageLv.Items.Clear;  //頁數清單
  //Panel18.Enabled:= False;
  AttListBox.Items.Clear;
  AddAttFileLB.Enabled := False;
  DelAttFileLB.Enabled := False;
  UseOldCaseLb.Visible := False;
  PM107.Visible := False; //備註功能
  CaseHelpBtn.Visible := False; //檢核失敗原因鈕
  Panel5.Visible := True;
  ContextList.Clear;
  SortMode := false;
  ISB1.ZoomMode := zmFullPage;
  IF TreeView1.Selected.Parent <> nil Then
  begin
    if TreeView1.Selected.Parent = NewTreenode then  //點在案件上
    begin
      //Panel18.Enabled := True;
      PM107.Visible := True; //備註功能
      MyTreeNode1 := TreeView1.Selected;
      MyTreeNode2 := nil;
      MyTreeNode3 := nil;
      v := Posend('-',MyTreenode1.Text);
      v1 := Length(MyTreenode1.Text);
      NowCaseNo := Copy(TreeView1.Selected.Text,1,v-1);
      if (FMode = 'ESCAN') and (FOldCaseInfo <> '') then
        UseOldCaseLb.Visible := True;
      ClearView(1);
      DisplayPath := ImageSavePath+NowCaseNo+'\';
      if FLoanDoc_Enable = 'Y' then
      begin
        AddCredit1RG.Enabled := True;
      end;
      ReadCaseIndex(DisplayPath);
      If FileExists(DisplayPath+'\upload\Checkerr.ini') and (not FileExists(DisplayPath+'\upload\OMRCheckOk.dat')) Then
        CaseHelpBtn.Visible := True;
      IF FileExists(DisplayPath+'CaseDocNo.dat') Then
      begin
        CaseDocNoList.LoadFromFile(DisplayPath+'CaseDocNo.dat');
        view_image_DocNo(DisplayPath,'ShowAll','',1);
      end;
      if FileExists(DisplayPath+'CustomDocNo.dat') then
        Cust_DocNoList.LoadFromFile(DisplayPath+'CustomDocNo.dat');
      Page := ContextList.Count;
      For i := 1 to page do
      begin
        With PageLV.Items.Add do
        begin
          Caption := Add_Zoo(i,3);
        end;
      end;
      If Page > 0 then
        ScrollBar1.Max := page;
      MyTreeNode1.Expand(True);
    end
    Else If TreeView1.Selected.Parent.Parent  = NewTreenode Then    //點在文件上
    begin
      MyTreeNode1 := TreeView1.Selected.Parent;
      MyTreeNode2 := TreeView1.Selected;
      MyTreeNode3 := nil;
      v := Pos('-',MyTreenode1.Text);
      NowCaseNo := Copy(MyTreenode1.Text,1,v-1);
      v := Posend('{',MyTreenode2.Text);
      v1 := Posend('}',MyTreenode2.Text);
      v2 := posend('-',MyTreenode2.Text);
      ln := length(MyTreenode2.Text);
      NowDocDir := Copy(MyTreeNode2.Text,v+1,v1-v-1);
      NowDocNo := DocNoDir2DocNo(NowDocDir);
      page :=Strtoint(Copy(MyTreeNode2.Text,v2+1,ln-v2-1));
      if (FMode = 'ESCAN') and (FOldCaseInfo <> '') then
        UseOldCaseLb.Visible := True;
      ClearView(1);
      DisplayPath := ImageSavePath+NowCaseNo+'\';
      if GetUseCase('F',DisplayPath,NowDocDir) <> '' then
        StatusBar1.Panels[2].Text := Format(_Msg('從%s引用'),[GetUseCase('F',DisplayPath,NowDocDir)]);
      if GetUseCase('T',DisplayPath,NowDocDir) <> '' then
        StatusBar1.Panels[2].Text := Format(_Msg('被%s引用'),[GetUseCase('T',DisplayPath,NowDocDir)]);
      if FLoanDoc_Enable = 'Y' then
      begin
        AddCredit1RG.Enabled := True;
      end;
      ReadCaseIndex(DisplayPath);
      If FileExists(DisplayPath+'Checkerr.ini') and (not FileExists(DisplayPath+'OMRCheckOk.dat')) Then
        CaseHelpBtn.Visible := True;
      If Page > 0 then
        ScrollBar1.Max := page;
      For i := 1 to page do
      begin
        With PageLV.Items.Add do
        begin
          Caption := Add_Zoo(i,3);
        end;
      end;
      If FileExists(DisplayPath+'Checkerr.ini') and (not FileExists(DisplayPath+'OMRCheckOk.dat')) Then
        CaseHelpBtn.Visible := True;
      IF FileExists(DisplayPath+NowDocDir+'\Context.dat') Then
      begin
        ContextList.LoadFromFile(DisplayPath+NowDocDir+'\Context.dat');
        //Context_DocnoList.LoadFromFile(DisplayPath+'Context_Docno.dat');
        view_image_DocNo(DisplayPath,NowDocDir,'',Page);
      end;
      if FileExists(DisplayPath+'CustomDocNo.dat') then
        Cust_DocNoList.LoadFromFile(DisplayPath+'CustomDocNo.dat');
       MyTreeNode1.Expand(True);
    end
    Else If (NewTreenode <> nil) and (TreeView1.Selected.Parent.Parent.Parent  = NewTreenode) Then //點在表單上
    begin
      //NoteBtn.Visible := True; //備註功能
      //Panel18.Enabled := True;
      ClearView(1);
      PM107.Visible := True; //備註功能
      MyTreeNode1 := TreeView1.Selected.Parent.Parent;
      MyTreeNode2 := TreeView1.Selected.Parent;
      MyTreeNode3 := TreeView1.Selected;
      v := Posend('-',MyTreenode1.Text);
      NowCaseNo := Copy(MyTreenode1.Text,1,v-1);
      if (FMode = 'ESCAN') and (FOldCaseInfo <> '') then
        UseOldCaseLb.Visible := True;
      v := Posend('{',MyTreenode2.Text);
      v1 := Posend('}',MyTreenode2.Text);
      v2 := posend('-',MyTreenode2.Text);
      ln := length(MyTreenode2.Text);
      NowDocDir := Copy(MyTreeNode2.Text,v+1,v1-v-1);
      NowDocNo := DocNoDir2DocNo(NowDocDir);
      v := Posend('{',MyTreenode3.Text);
      v1 := Posend('}',MyTreeNode3.Text);
      v2 := Posend('-',MyTreeNode3.Text);
      ln := Length(MyTreeNode3.Text);
      if v>0 then
      begin
        NowFormCode := Copy(MyTreeNode3.Text,v+1,v1-v-1);
        if (NowFormCode = 'Attach') or (NowFormCode = 'S_Attach') then
          NowFormCode := '';
        NowFormName := Copy(MyTreeNode3.Text,v+1,v1-v-1);
        page := strtoint(Copy(MyTreeNode3.Text,v2+1,ln-v2-1));
      end
      Else  //點在附件的頁數
      begin
        NowFormCode := '';
        page := 1;
      end;
      DisplayPath := ImageSavePath+NowCaseNo+'\';
      if GetUseCase('F',DisplayPath,NowDocDir) <> '' then
        StatusBar1.Panels[2].Text := Format(_Msg('從%s引用'),[GetUseCase('F',DisplayPath,NowDocDir)]);
      if GetUseCase('T',DisplayPath,NowDocDir) <> '' then
        StatusBar1.Panels[2].Text := Format(_Msg('被%s引用'),[GetUseCase('T',DisplayPath,NowDocDir)]);
      if FLoanDoc_Enable = 'Y' then
      begin
        AddCredit1RG.Enabled := True;
      end;
      ReadCaseIndex(DisplayPath);
      If FileExists(DisplayPath+'Checkerr.ini') and (not FileExists(DisplayPath+'OMRCheckOk.dat')) Then
        CaseHelpBtn.Visible := True;
      If Page > 0 then
        ScrollBar1.Max := page;
      For i := 1 to page do
      begin
        With PageLV.Items.Add do
        begin
          Caption := Add_Zoo(i,3);
        end;
      end;
      If FileExists(DisplayPath+NowDocDir+'\Context.dat') Then
      begin
        ContextList.LoadFromFile(DisplayPath+NowDocDir+'\Context.dat');
        view_image_DocNo(DisplayPath,NowDocDir,NowFormCode,Page);
        //view_image_FormCode(DisplayPath,NowFormCode,1,1);
      end;
      if FileExists(DisplayPath+'CustomDocNo.dat') then
        Cust_DocNoList.LoadFromFile(DisplayPath+'CustomDocNo.dat');
    end;
    MyTreeNode1.Expand(True);
    AddAttFileLB.Enabled := True;
    if FileExists(DisplayPath+'ATTContext.dat') then
    begin
      LoadAttFile(NowCaseno);
    end;
  end
  Else     //點在NewTreenode or MyTreenode1 上
  begin
    ClearView(1);
    MyTreeNode1 := nil;
    MyTreeNode2 := nil;
    MyTreeNode3 := nil;
  end;
  TreeView1.Selected.MakeVisible;
  CaseList.Clear;
  if FileExists(ImageSavePath + 'CaseList.dat') then
    CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
  //CountCaseno;
  //CountCaseCount;
  Application.ProcessMessages;
end;
{ ==============================================================================
  方法名稱:TreeView1DragDrop
  引用相依:RenameFile, CopyFile, DeleteImageFile, LoadFromFile, SaveToFile, _De
            lTree, ReSortFileName
  方法描述:處理樹狀結構的拖放操作,實現影像的快速歸類或跨案件移動。當使用者將影像
            縮圖拖至樹狀節點時,程序會判斷目標層級,執行實際的檔案搬移(Copy/Delete
            )與更名,同步更新 Context.dat 索引檔案,並重新整理樹狀顯示與筆數統計。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  NewCaseno,NewDocNo,NewDocDir,NewFormCode,NewFormName : String;
  NewPath,NewFileName:String;
  OldFileName : String;
  iTreeNode1,iTreeNode2,iTreeNode3: TTreeNode;
  i,v,v1,v2 : Integer;
  PreIndex,Precount,NowCount:Integer;
  GoAtt : Boolean;
  AttLv : Integer;
begin
  NewCaseno := '';
  NewFormCode := '';
  NewFormName := '';
  Precount := MyTreeNode1.Count;
  PreIndex := -1;
  GoAtt := False;
  if (MytreeNode2 <> nil) and (Pos('Attach',MyTreeNode2.Text)>0) then
  begin
    AttLv := TreeView1.Selected.Level;
    GoAtt := True;
  end;
  if TTreeView(Sender).GetNodeAt(X,Y).Level =2 then
  begin
    iTreeNode2 := TTreeView(Sender).GetNodeAt(X,Y);
    iTreeNode1 := iTreeNode2.Parent;
    v := Pos('-',iTreenode1.Text);
    v1 := Length(iTreenode1.Text);
    NewCaseNo := Copy(iTreeNode1.Text,1,v-1);
    v := Posend('{',iTreeNode2.Text);
    v1 := Posend('}',iTreeNode2.Text);
    NewDocNo := Copy(iTreeNode2.Text,v+1,v1-v-1);
    NewPath := ImagePath+NewCaseNo+'\';
    OldFileName := ExtractFileName(DisplayISB.FileName);
    if Copy(NewDocNo,1,5) = 'ZZZZZ' then  //自訂文件
    begin
      NewFileName := Add_Zoo(FileName2ScanPage(OldFileName),3)+'_'+NewDocNo+'0000000'+ExtractFileExt(OldFileName);
      NewFormCode := NewDocNo+'0000000';
      {ReNameFile(DisplayISB.FileName,NewPath+NewFileName);
      ReNameContext(DisplayPath,OldFileName,NewFileName);
      MyTreeNode2ReFresh(NowCaseno);
      TreeView1Click(nil);}
    end;
    //NewFileName := Add_Zoo(GetCasePage(ImagePath,NewCaseno)+1,3)+FileName2NoQuene_Filename(OldFileName);
  end
  Else if TTreeView(Sender).GetNodeAt(X,Y).Level =3 then
  begin
    OldFileName := ExtractFileName(DisplayISB.FileName);
    iTreeNode1 := TTreeView(Sender).GetNodeAt(X,Y).Parent.Parent;
    iTreeNode2 := TTreeView(Sender).GetNodeAt(X,Y).Parent;
    iTreeNode3 := TTreeView(Sender).GetNodeAt(X,Y);
    v := Pos('-',iTreenode1.Text);
    v1 := Length(iTreenode1.Text);
    NewCaseNo := Copy(iTreeNode1.Text,1,v-1);
    v := Pos('{',iTreeNode2.Text);
    v1 := Pos('}',iTreeNode2.Text);
    NewDocDir := Copy(iTreeNode2.Text,v+1,v1-v-1);
    v := Pos('{',iTreeNode3.Text);
    v1 := Pos('}',iTreeNode3.Text);
    NewFormName := Copy(iTreeNode3.Text,1,v-1);
    NewFormCode := Copy(iTreeNode3.Text,v+1,v1-v-1);
    IF v = 0 Then
    begin
      NewFormCode := '';
      v := Posend('-',iTreeNode3.Text);
      NewFormName := Copy(iTreeNode3.Text,1,v1-1);
    end;
    NewPath := ImagePath+NewCaseNo+'\'+NewDocDir+'\';
    if NewPath = DisplayPath Then  //同案件
    begin
      if NewFormCode <> '' then
        //NewFileName := Copy(OldFileName,1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
        NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
      Else
        //NewFileName := Copy(OldFileName,1,3)+ExtractFileExt(OldFileName)
        NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+ExtractFileExt(OldFileName);
    end
    else   //不同案件
    begin
      if NewFormCode <> '' then
        //NewFileName := Copy(OldFileName,1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
        NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
      Else
        //NewFileName := Copy(OldFileName,1,3)+ExtractFileExt(OldFileName)
        NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir),3)+ExtractFileExt(OldFileName);
    end;
  end;
  //Showmessage('a');
  for I := 0 to NowSelectFileList.Count - 1 do
  begin
    OldFileName := NowSelectFileList.Strings[i];
    if NewFormCode <> '' then
      //NewFileName := Copy(OldFileName,1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
      NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir)+1,3)+'_'+NewFormCode+ExtractFileExt(OldFileName)
    Else
      //NewFileName := Copy(OldFileName,1,3)+ExtractFileExt(OldFileName)
      NewFileName := Add_Zoo(GetDocDir_Page(NewCaseNo,NewDocDir)+1,3)+ExtractFileExt(OldFileName);
    if NewCaseNo = NowCaseNo then  //同案件不改順序
    begin
      CopyFile(PWideChar(OldFileName),PwideChar(NewPath+NewFileName),False);
      SetContextList('A',-1,NewCaseNo,NewDocDir,NewFileName);
      DeleteImageFile(ExtractFilePath(OldFileName),ExtractFileName(OldFileName),NowCaseNo);
      TreeView1.Selected := MyTreeNode1;
      //ReNameFile(DisplayPath + OldFileName,NewPath+NewFileName);
      //ReNameContext(DisplayPath,OldFileName,NewFileName);
      //MyTreeNode2ReFresh(NowCaseno);
      //TreeView1Click(nil);
    end
    Else
    begin
      //Showmessage(DisplayMpsView.FileName+#13+NewPath+NewFileName);
      ContextList.LoadFromFile(DisplayPath+'Context.dat');
      if (ContextList.Count = 1) and ((FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') or (FMode = 'ISCAN')) then
      begin
        if Messagedlg(Format(_Msg('移動後(%s)案件無影像,將刪除此案件,是否確定移動?'),[NowCaseno]),mtconfirmation,[mbyes,mbcancel],0) = mrCancel then Exit;
      end;
      CopyFile(PWideChar(DisplayISB.FileName),PWideChar(NewPath+NewFileName),False);
      ContextList.LoadFromFile(NewPath+'Context.dat');
      ContextList.Add(NewFileName);
      ContextList.SaveToFile(NewPath+'Context.dat');
      //Showmessage('1');
      iTreeNode2.Text := Format(_Msg('%s-%d頁'),[NewCaseNo,GetCasePage(ImagePath,NewCaseNo)]);
      //Showmessage('2');
      //DrawDocItem(iTreeNode1,FORM_INF_List,NewCaseNo);
      //DrawDocItem1(MytreeNode1,Doc_Inf_List,NewCaseno);   20140820改
      DrawDocItem2(MytreeNode1,NewCaseno);
      //Showmessage('3');
      ClearErrini(NewCaseNo,iTreeNode1);
      ContextList.LoadFromFile(DisplayPath+'Context.dat');
      if (ContextList.Count = 1) and ((FMode = 'NSCAN') or (FMode = 'ASCAN') or (FMode = 'DSCAN') or (FMode = 'SSCAN') or (FMode = 'MSCAN') or (FMode = 'RI_SCAN') or (FMode = 'ISCAN')) then
      begin
        _DelTree(DisplayPath);
        SetCaseList('D',MyTreeNode1.IndexOf(MyTreeNode2),'');
        LoadImgFile;
      end
      Else
      begin
        ContextList.Delete(ContextList.IndexOf(ExtractFileName(DisplayISB.FileName)));
        ContextList.SaveToFile(DisplayPath+'Context.dat');
        DeleteFile(DisplayISB.FileName);
        ReSortFileName(DisplayPath);
        ClearErrini(NowCaseNo,MyTreeNode1);
        MyTreeNode2ReFresh(NowCaseno);
        //MyTreeNode3ReFresh(NowCaseno);
        ContextList.LoadFromFile(DisplayPath+'Context.dat');
        NowCount := MyTreeNode1.Count;
        if PreCount = NowCount then
        begin
          TreeView1.Selected := MyTreeNode1.Item[PreIndex];
          TreeView1Click(nil);
        end
        Else
        begin
          TreeView1.Selected := MyTreeNode1;
          TreeView1Click(nil);
        end;
      end;
    end;
  end;
  for I := 0 to NowSelectFileList.Count - 1 do
  begin
    OldFileName := NowSelectFileList.Strings[i];
    ReSortFileName(ExtractFilePath(OldFileName));
  end;
  DrawDocItem2(MytreeNode1,NowCaseno);
  ClearErrini(NowCaseno,MyTreeNode1);  //清掉檢核記錄
  if GoAtt then
  begin
    GotoAttach(AttLv);
  end;
  //TreeView1Click(nil);
end;
{ ==============================================================================
  方法名稱:TreeView1DragOver
  引用相依:
  方法描述:判斷樹狀結構拖放操作的有效性。程序會檢核來源影像的表單代碼與目標節點
            的屬性,限制只能將影像拖入特定的表單層級(Level 3),且排除已存在的相同
            表單、附件目錄或未註冊的文件類型。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
var
  NewNode : TTreeNode;
  ImgFormCode : String;
  ImgDocNo : String;
  So : Boolean;
begin
  ImgFormCode := FileName2FormCode(ExtractFileName(DisplayISB.FileName));
  ImgDocNo := Path2DocDir(ExtractFilePath(DisplayISB.FileName),NowCaseno);
  //ImgDocNo := FileName2NowDcoNo(ExtractFileName(DisplayISB.FileName),ContextList,Context_DocnoList);
  NewNode := TTreeView(Sender).GetNodeAt(X,Y);
  //Label3.Caption := format('%d/%s/%s',[NewNode.Level,ImgDocNo,Node2DocNo(NewNode)]);
  So := False;
  if TObject(Source) is TImageScrollBox then
    So := True;
  Accept := True;
  if not So
    or(NewNode=nil)
    or((NewNode.Level<>3))
    or((NewNode.Level =3) and (((ImgFormCode=Node3FormID(NewNode)) and (ImgDocNo = Node3DocNo(NewNode))) or (Node3DocNo(NewNode)='')))
    or(Pos(_Msg('Attach'),Newnode.Text)>0)
    Then
      Accept := False;
  {if not So
    or(NewNode=nil)
    or((NewNode.Level <>2) and (NewNode.Level<>3))
    or((NewNode.Level =2) and ((ImgDocNo = Node2DocNo(NewNode))or(Node2DocNo(NewNode)='')or (copy(Node2DocNo(NewNode),1,5)<>'ZZZZZ')))
    or((NewNode.Level =3) and ((ImgFormCode=Node3FormID(NewNode)) or (ImgDocNo = Node3DocNo(NewNode)) or (Node3DocNo(NewNode)='')))
    or(Pos(_Msg('未註冊文件'),Newnode.Text)>0)
     Then
      Accept := False;}
end;
{ ==============================================================================
  方法名稱:TreeView1KeyUp
  引用相依:
  方法描述:處理樹狀結構的按鍵放開事件。若有選取子節點,則觸發 TreeView1Click 重新
            載入影像顯示,否則清空視窗。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  IF TreeView1.Selected.Parent <> nil Then
  begin
    TreeView1Click(nil);
  end
  else
  begin
    ClearView(1);
  end;
end;
{ ==============================================================================
  方法名稱:TreeView1MouseDown
  引用相依:
  方法描述:處理樹狀結構滑鼠按下事件。若是右鍵按下,則自動選取該位置的節點以便後續
            彈出對應的開單選單。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  IF Button = TMouseButton(MbRight) Then
  begin
    MDown := True;
    If TreeView1.GetNodeAt(X,Y) = nil then Exit;
    TreeView1.Selected := TreeView1.GetNodeAt(X,Y);
  end;
end;
{ ==============================================================================
  方法名稱:TreeView1MouseEnter
  引用相依:
  方法描述:當滑鼠進入樹狀結構區域時,自動將焦點(Focus)設定至 TreeView1。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1MouseEnter(Sender: TObject);
begin
TreeView1.SetFocus;
end;
{ ==============================================================================
  方法名稱:TreeView1MouseMove
  引用相依:
  方法描述:處理樹狀結構滑鼠移動事件,目前實作已註解相關代碼。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  //TreeView1.SetFocus;
  {UnRegisterHotKey(Handle, HotKeyId1);
  UnRegisterHotKey(Handle, HotKeyId2); }
end;
{ ==============================================================================
  方法名稱:TreeView1MouseUp
  引用相依:
  方法描述:處理樹狀結構滑鼠放開事件。若為右鍵點擊且有選取節點,則觸發 TreeView1Cl
            ick 並彈出與節點層級對應的右鍵選單。
============================================================================== }
procedure TCB_IMGPSScanX.TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  IF Button = TMouseButton(MbRight) Then
  begin
    If TreeView1.GetNodeAt(X,Y) = nil then Exit;
    if MDown then
    begin
      TreeView1Click(self);
      TreeView1.PopupMenu.Popup(Mouse.CursorPos.X ,Mouse.CursorPos.Y);
    end;
    Application.ProcessMessages; //需加這行,不然有些全域變數會沒變到
    MDown:= False;
  end;
end;
scripts/batch_dfm_to_web.js
比對新檔案
@@ -0,0 +1,52 @@
const fs = require('fs');
const path = require('path');
// 讀取設定檔與樣板
const configPath = path.join(__dirname, '../doc/curtis/prompt/dfm_to_web/dfm_to_web_requirement.json');
const templatePath = path.join(__dirname, '../doc/curtis/prompt/dfm_to_web/dfm_to_web_prompt_template.md');
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
const template = fs.readFileSync(templatePath, 'utf8');
// 產生每個檔案的專屬 prompt
const outputDir = path.join(__dirname, '../doc/curtis/prompt/dfm_to_web');
if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
}
console.log('Generating individual prompts based on requirement.json...');
config.forEach(item => {
    // 從路徑中萃取檔名
    const dfm_filename = path.basename(item.dfm);
    const pas_filename = path.basename(item.pas);
    const png_filename = path.basename(item.png);
    const vue_filename = path.basename(item.vue);
    const ts_filename = path.basename(item.ts);
    // 取得元件名稱 (不含副檔名)
    const componentName = path.parse(item.vue).name;
    // 取代樣板中的佔位符
    let promptContent = template
        .replace(/\{\{dfm\}\}/g, item.dfm)
        .replace(/\{\{pas\}\}/g, item.pas)
        .replace(/\{\{png\}\}/g, item.png)
        .replace(/\{\{vue\}\}/g, item.vue)
        .replace(/\{\{ts\}\}/g, item.ts)
        .replace(/\{\{dfm_filename\}\}/g, dfm_filename)
        .replace(/\{\{pas_filename\}\}/g, pas_filename)
        .replace(/\{\{png_filename\}\}/g, png_filename)
        .replace(/\{\{vue_filename\}\}/g, vue_filename)
        .replace(/\{\{ts_filename\}\}/g, ts_filename);
    // 寫入專屬的 prompt 檔案
    const promptFilePath = path.join(outputDir, `dfm_to_web_prompt_${componentName}.md`);
    fs.writeFileSync(promptFilePath, promptContent, 'utf8');
    console.log(`Created: ${promptFilePath}`);
});
console.log('\n--- Usage ---');
console.log('You can now ask the AI:');
console.log('"Please execute the conversion based on the requirements in @/doc/curtis/prompt/dfm_to_web/generated_prompts/prompt_PatchFom.md"');
scripts/dist/CB_IMGPSScanImp.pas.bk.image.csv
比對新檔案
@@ -0,0 +1,103 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"Global_Or_Interface","CB_IMGPSScanImp.pas.bk","9","TDibGraphic","","EnDiGrph, { for TDibGraphic }"
[V],"Global_Or_Interface","CB_IMGPSScanImp.pas.bk","80","TTiffGraphic","","Graphic    : TTiffGraphic;"
[V],"ImageScrollBox1NewGraphic","CB_IMGPSScanImp.pas.bk","393","TDibGraphic","","procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);"
[V],"Button6Click","CB_IMGPSScanImp.pas.bk","598","Rotate","","BarCodeRotate : Integer; //條碼要轉的角度"
[V],"Button6Click","CB_IMGPSScanImp.pas.bk","615","FJpgCompression","","FJpgCompression:integer;// 20171211 jpg to tif çš„壓縮率"
[V],"GetSiteOMR","CB_IMGPSScanImp.pas.bk","674","GetSiteOMR","","function GetSiteOMR(FileName, Site: String;bt: Integer): Integer;"
[V],"ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","742","ImageReSize_FormID","","Procedure ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放"
[V],"ImageReSize_tmp","CB_IMGPSScanImp.pas.bk","743","ImageReSize_tmp","","Procedure ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)"
[V],"CheckNeedCrop","CB_IMGPSScanImp.pas.bk","804","TDibGraphic","","Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像"
[V],"CheckNeedCrop","CB_IMGPSScanImp.pas.bk","804","CheckNeedCrop","","Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像"
[V],"Initialize","CB_IMGPSScanImp.pas.bk","1044","TDibGraphic","","EnPrint,  { for TEnvisionPrintMode, TDibGraphicPrinter }"
[V],"TCB_IMGPSScanX.ISB1ImageMouseUp","CB_IMGPSScanImp.pas.bk","1505","TJpegGraphic","","TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.ISB1ImageMouseUp","CB_IMGPSScanImp.pas.bk","1505","SaveQuality","","TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.PM604Click","CB_IMGPSScanImp.pas.bk","2315","DeskewImg","","DeskewImg(iISB.Graphic);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2799","TTiffGraphic","","iGraphic, iGraphic_First, iGraphic_sec: TTiffGraphic;"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2801","TJpegGraphic","","JpgGr : TJpegGraphic;"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2838","FJpgCompression","","cooom:=FJpgCompression;//20171211彩色tif採jpg壓縮的比例"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2850","DeskewImg","","DeskewImg(ISB.Graphic);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2856","ConvertToBW","","ConvertToBW(ISB_BW.Graphic);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2866","MpsGetBarcode","","MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf); //判斷A3 æœ‰ç”¨FormID æ‰€ä»¥è¦å…ˆè¾¨æ¢ç¢¼"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2871","Rotate","","Rotate(ISB.Graphic, MpsBarcodeinf.r180[n]);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2879","CheckNeedCrop","","If CheckNeedCrop(iGraphic_First) Then"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2886","CropImg","","CropImg(iGraphic_First, iRect);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3000","ifBlackWhite","","if iGraphic.ImageFormat = ifBlackWhite then   //20200806 å‡ºç¾ç„¡æ³•匯入,是因color256無法壓JPEG,待報會後再開啟"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3003","tcGroup4","","iGraphic.Compression:=tcGroup4;"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3005","ifColor25","","else if iGraphic.ImageFormat= ifColor256 then"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3008","ConvertToGray","","ConverttoGray(iGraphic);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3009","tcJpeg","","iGraphic.Compression:=tcJPEG;"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3012","ifTrueColor","","else if (iGraphic.ImageFormat = ifTrueColor) or (iGraphic.ImageFormat = ifGray256) then"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3012","ifGray256","","else if (iGraphic.ImageFormat = ifTrueColor) or (iGraphic.ImageFormat = ifGray256) then"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","3050","SaveQuality","","JpgGr.SaveQuality := 30;"
[V],"TCB_IMGPSScanX.PM301Click","CB_IMGPSScanImp.pas.bk","3475","ifBlackWhite","","ScanColor := ifBlackWhite;"
[V],"TCB_IMGPSScanX.PM302Click","CB_IMGPSScanImp.pas.bk","3483","ifGray256","","ScanColor := ifGray256;"
[V],"TCB_IMGPSScanX.PM303Click","CB_IMGPSScanImp.pas.bk","3492","ifTrueColor","","ScanColor := ifTrueColor;"
[V],"TCB_IMGPSScanX.PM510Click","CB_IMGPSScanImp.pas.bk","3664","DeskewImg","","DeskewImg(DisplayISB.Graphic);"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4402","TTiffGraphic","","ScanInfo.Graphic := TTiffGraphic.Create;"
[V],"TCB_IMGPSScanX.OnAcquire","CB_IMGPSScanImp.pas.bk","4455","TTiffGraphic","","iGraphic,iGraphic_First,iGraphic_sec : TTiffGraphic;"
[V],"TCB_IMGPSScanX.OnAcquire","CB_IMGPSScanImp.pas.bk","4457","TJpegGraphic","","JpgGr : TJpegGraphic;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4460","TDibGraphic","","function Deletepage(Graphic:TDibGraphic;BlankSize:Integer):Boolean;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4487","ifBlackWhite","","if pScanInfo^.Graphic.ImageFormat = ifBlackWhite then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4492","tcGroup4","","pScanInfo^.Graphic.Compression := tcGroup4;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4493","MpsGetBarcode","","MpsGetBarcode(pScanInfo^.Graphic,MpsBarcodeinf);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4498","Rotate","","Rotate(pScanInfo^.Graphic,MpsBarcodeinf.r180[i]);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4506","NegativeImg","","NegativeImg(pScanInfo^.Graphic);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4509","DeskewImg","","DeskewImg(pScanInfo^.Graphic);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4512","CleanupBorder","","CleanupBorder(pScanInfo^.Graphic);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4514","ifTrueColor","","else if pScanInfo^.Graphic.ImageFormat = ifTrueColor then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4529","tcJpeg","","pScanInfo^.Graphic.Compression := tcJpeg;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4530","FJpgCompression","","pScanInfo^.Graphic.JpegQuality := FJpgCompression;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4532","ifColor25","","else if pScanInfo^.Graphic.ImageFormat = ifColor256 Then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4535","ConvertToGray","","ConvertToGray(pScanInfo^.Graphic);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4539","ifGray256","","else if pScanInfo^.Graphic.ImageFormat = ifGray256 Then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4566","tcPackBits","","pScanInfo^.Graphic.Compression := tcPackBits;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4571","TTiffGraphic","","iGraphic_First := TTiffGraphic.Create;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4577","CheckNeedCrop","","if CheckNeedCrop(iGraphic_First) Then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4583","CropImg","","CropImg(iGraphic_First,iRect);"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4656","TJpegGraphic","","JpgGr := TJpegGraphic.Create;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4659","SaveQuality","","JpgGr.SaveQuality := FJpgCompression;"
[V],"TCB_IMGPSScanX.GetSiteOMR","CB_IMGPSScanImp.pas.bk","5173","GetSiteOMR","","function TCB_IMGPSScanX.GetSiteOMR(FileName,Site:String;bt: Integer): Integer;"
[V],"TCB_IMGPSScanX.GetSiteOMR","CB_IMGPSScanImp.pas.bk","5191","FindPoint","","FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,'');"
[V],"TCB_IMGPSScanX.GetSiteOMR","CB_IMGPSScanImp.pas.bk","5222","Get_OMR","","result := Get_OMR(ISB_BW.Graphic,OMRRect);"
[V],"TCB_IMGPSScanX.GetDefScanIni","CB_IMGPSScanImp.pas.bk","5366","Rotate","","Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_ROTATE_MODE' Then //掃瞄時旋轉角度"
[V],"TCB_IMGPSScanX.GetDefScanIni","CB_IMGPSScanImp.pas.bk","5462","FJpgCompression","","FJpgCompression := StrToInt(PARA_CONTENT);"
[V],"TCB_IMGPSScanX.CaseReSize","CB_IMGPSScanImp.pas.bk","6336","ImageReSize_FormID","","ImageReSize_FormID(CaseID,FileName);  //依十字定位點做縮放"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6343","ImageReSize_FormID","","Procedure TCB_IMGPSScanX.ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6376","FindPoint","","//FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH);"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6379","CheckSize","","SizeStr := CheckSize(ISB_BW,UpLPoint,UpRPoint,DownLPoint,DW,DH);"
[V],"TCB_IMGPSScanX.ImageReSize_tmp","CB_IMGPSScanImp.pas.bk","6421","ImageReSize_tmp","","Procedure TCB_IMGPSScanX.ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)"
[V],"TCB_IMGPSScanX.ImageReSize_tmp","CB_IMGPSScanImp.pas.bk","6437","CheckSize","","SizeStr := CheckSize(ImageScrollBox1,UpLPoint,UpRPoint,DownLPoint,DW,DH);"
[V],"TCB_IMGPSScanX.ImageScrollBox1NewGraphic","CB_IMGPSScanImp.pas.bk","6447","TDibGraphic","","procedure TCB_IMGPSScanX.ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);"
[V],"TCB_IMGPSScanX.ImageScrollBox1NewGraphic","CB_IMGPSScanImp.pas.bk","6453","ConvertToBW","","ConvertToBW(ISB_BW.Graphic);"
[V],"TCB_IMGPSScanX.ScanGrayCBClick","CB_IMGPSScanImp.pas.bk","8573","ifGray256","","ScanColor:=ifGray256;"
[V],"TCB_IMGPSScanX.ScanGrayCBClick","CB_IMGPSScanImp.pas.bk","8579","ifBlackWhite","","ScanColor := ifBlackWhite;"
[V],"TCB_IMGPSScanX.ScanGrayCBClick","CB_IMGPSScanImp.pas.bk","8591","ifTrueColor","","ScanColor := ifTrueColor ;"
[V],"TCB_IMGPSScanX.initParameter","CB_IMGPSScanImp.pas.bk","9290","ifBlackWhite","","ScanColor := ifBlackWhite;"
[V],"TCB_IMGPSScanX.initParameter","CB_IMGPSScanImp.pas.bk","9295","ifGray256","","ScanColor := ifGray256 ;"
[V],"TCB_IMGPSScanX.initParameter","CB_IMGPSScanImp.pas.bk","9301","ifTrueColor","","ScanColor := ifTrueColor ;"
[V],"TCB_IMGPSScanX.SmoothCBClick","CB_IMGPSScanImp.pas.bk","9927","Image_Smooth","","Image_Smooth(ISB1.Graphic);"
[V],"TCB_IMGPSScanX.Case2Mask","CB_IMGPSScanImp.pas.bk","9962","FindPoint","","//ParserPoint(CropMpsV.FindPoint(Anchor));"
[V],"TCB_IMGPSScanX.CheckNeedCrop","CB_IMGPSScanImp.pas.bk","9996","TDibGraphic","","Function TCB_IMGPSScanX.CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像"
[V],"TCB_IMGPSScanX.CheckNeedCrop","CB_IMGPSScanImp.pas.bk","9996","CheckNeedCrop","","Function TCB_IMGPSScanX.CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像"
[V],"TCB_IMGPSScanX.PrintImg","CB_IMGPSScanImp.pas.bk","10223","TDibGraphic","","GraphicPrinter : TDibGraphicPrinter;"
[V],"PrintWithManualPrintJob","CB_IMGPSScanImp.pas.bk","10241","TDibGraphic","","property of the TDibGraphicPrinter object is used to specify the"
[V],"PrintWithAutoPrintJob","CB_IMGPSScanImp.pas.bk","10274","TDibGraphic","","GraphicPrinter := TDibGraphicPrinter.Create;"
[V],"TCB_IMGPSScanX.OMRCheckCase","CB_IMGPSScanImp.pas.bk","12510","ImageReSize_FormID","","ImageReSize_FormID(CaseID,OMRFile);"
[V],"TCB_IMGPSScanX.OMRCheckCase","CB_IMGPSScanImp.pas.bk","12545","GetSiteOMR","","//Showmessage(ColCName +','+ inttostr(OMRMpsV1.GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site))+','+inttostr(Pixel + SafePixel));"
[V],"TCB_IMGPSScanX.OMRCheckCase","CB_IMGPSScanImp.pas.bk","12548","FindPoint","","//FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,ANCHOR);"
[V],"TCB_IMGPSScanX.view_image_DocNo","CB_IMGPSScanImp.pas.bk","13278","DpiResize","","DpiResize(ISB.Graphic,36,False);"
[V],"TCB_IMGPSScanX.SpeedButton14Click","CB_IMGPSScanImp.pas.bk","13407","Rotate","","Rotate(ISB1.Graphic,270);"
[V],"TCB_IMGPSScanX.SpeedButton14Click","CB_IMGPSScanImp.pas.bk","13410","TJpegGraphic","","TJpegGraphic(ISB1.Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.SpeedButton14Click","CB_IMGPSScanImp.pas.bk","13410","SaveQuality","","TJpegGraphic(ISB1.Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.SpeedButton15Click","CB_IMGPSScanImp.pas.bk","13428","Rotate","","Rotate(ISB1.Graphic,180);"
[V],"TCB_IMGPSScanX.SpeedButton15Click","CB_IMGPSScanImp.pas.bk","13431","TJpegGraphic","","TJpegGraphic(ISB1.Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.SpeedButton15Click","CB_IMGPSScanImp.pas.bk","13431","SaveQuality","","TJpegGraphic(ISB1.Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.SpeedButton16Click","CB_IMGPSScanImp.pas.bk","13449","Rotate","","Rotate(ISB1.Graphic,90);"
[V],"TCB_IMGPSScanX.SpeedButton16Click","CB_IMGPSScanImp.pas.bk","13452","TJpegGraphic","","TJpegGraphic(ISB1.Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.SpeedButton16Click","CB_IMGPSScanImp.pas.bk","13452","SaveQuality","","TJpegGraphic(ISB1.Graphic).SaveQuality := 30;"
[V],"TCB_IMGPSScanX.ISBClick","CB_IMGPSScanImp.pas.bk","13729","Image_Smooth","","Image_Smooth(ISB1.Graphic);"
[V],"TCB_IMGPSScanX.Timer1Timer","CB_IMGPSScanImp.pas.bk","14919","FJpgCompression","","FJpgCompression:=50;"
[V],"TCB_IMGPSScanX.Set_scancolor","CB_IMGPSScanImp.pas.bk","16357","ifBlackWhite","","ScanColor := ifBlackWhite;"
[V],"TCB_IMGPSScanX.Set_scancolor","CB_IMGPSScanImp.pas.bk","16367","ifGray256","","ScanColor := ifGray256 ;"
[V],"TCB_IMGPSScanX.Set_scancolor","CB_IMGPSScanImp.pas.bk","16372","ifTrueColor","","ScanColor := ifTrueColor ;"
scripts/dist/CB_IMGPSScanImp.pas.bk.io.csv
比對新檔案
@@ -0,0 +1,359 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"ReSortFileName_New","CB_IMGPSScanImp.pas.bk","726","ReSortFileName","","Procedure ReSortFileName_New(Path:String); //檔名重新排序"
[V],"ReSortFileName","CB_IMGPSScanImp.pas.bk","727","ReSortFileName","","Procedure ReSortFileName(Path:String); //檔名重新排序"
[V],"ReSortFileName2Scanlist","CB_IMGPSScanImp.pas.bk","728","ReSortFileName","","Procedure ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat"
[V],"DeleteImageFile","CB_IMGPSScanImp.pas.bk","733","DeleteImageFile","","Procedure DeleteImageFile(Path,FileName,CaseID:String); // åˆªé™¤æª”案"
[V],"DeleteDocNoFile","CB_IMGPSScanImp.pas.bk","735","DeleteDocNoFile","","Function DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件"
[V],"DeleteShowFile","CB_IMGPSScanImp.pas.bk","736","DeleteShowFile","","Procedure DeleteShowFile(Path:String); //刪除顯示中的影像"
[V],"GetNoNameCase","CB_IMGPSScanImp.pas.bk","756","GetNoNameCase","","Function GetNoNameCase(Path:string):String; //取未配號XXXX"
[V],"_DelTreeForExistImg","CB_IMGPSScanImp.pas.bk","901","_DelTree","","procedure _DelTreeForExistImg(ASourceDir:String);   //2017 åˆªé™¤å‰ç¢ºèª æœ‰èˆŠå½±åƒå—Ž"
[V],"DeleteDocNoFileForESCAN","CB_IMGPSScanImp.pas.bk","904","DeleteDocNoFile","","function DeleteDocNoFileForESCAN(Path, DocNo: String): Boolean;     //2017 ç¢ºèªæ˜¯å¦æœ‰æœªæ­¸é¡žæ–‡ä»¶"
[V],"TCB_IMGPSScanX.WNoteBtnClick","CB_IMGPSScanImp.pas.bk","1200","FileExists","","if FileExists(DisplayPath+'Scan_Memo.dat') then"
[V],"TCB_IMGPSScanX.WNoteBtnClick","CB_IMGPSScanImp.pas.bk","1202","LoadFromFile","","S.LoadFromFile(DisplayPath+'Scan_Memo.dat');"
[V],"TCB_IMGPSScanX.WNoteBtnClick","CB_IMGPSScanImp.pas.bk","1229","SaveToFile","","S.SaveToFile(DisplayPath+'Scan_Memo.dat');"
[V],"TCB_IMGPSScanX.InitExistImgList","CB_IMGPSScanImp.pas.bk","1349","LoadFromFile","","ST1.LoadFromFile(casepath+'Download\Context.dat');"
[V],"TCB_IMGPSScanX.ISB1ImageMouseDown","CB_IMGPSScanImp.pas.bk","1458","LoadFromFile","","TImageScrollBox(Sender).LoadFromFile(TImageScrollBox(Sender).FileName,1);"
[V],"TCB_IMGPSScanX.ISB1ImageMouseUp","CB_IMGPSScanImp.pas.bk","1506","SaveToFile","","TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveToFile(TImageScrollBox(Sender).FileName);"
[V],"TCB_IMGPSScanX.DestroyEvent","CB_IMGPSScanImp.pas.bk","1750","_DelTree","","_Deltree(ImagePath);"
[V],"TCB_IMGPSScanX.PM401Click","CB_IMGPSScanImp.pas.bk","1945","GetNoNameCase","","CaseID := GetNoNameCase(ImageSavePath);"
[V],"TCB_IMGPSScanX.PM401Click","CB_IMGPSScanImp.pas.bk","1947","Str2Dir","","Str2Dir(NewPath);"
[V],"TCB_IMGPSScanX.PM401Click","CB_IMGPSScanImp.pas.bk","1954","RenameFile","","ReNameFile(DisplayPath+OldName,NewPath+NewName);"
[V],"TCB_IMGPSScanX.PM401Click","CB_IMGPSScanImp.pas.bk","1956","SaveToFile","","S.SaveToFile(NewPath+'Context.dat');"
[V],"TCB_IMGPSScanX.PM401Click","CB_IMGPSScanImp.pas.bk","1964","FileExists","","if FileExists(DisplayPath+'CaseIndex.dat') then  //把原經辦代號取出來再寫入新件裡"
[V],"TCB_IMGPSScanX.PM401Click","CB_IMGPSScanImp.pas.bk","1966","LoadFromFile","","S.LoadFromFile(DisplayPath+'CaseIndex.dat');"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2159","FileExists","","if FileExists(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat') then"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2161","LoadFromFile","","ST1.LoadFromFile(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2176","DirectoryExists","","if (not DirectoryExists(ImageSavePath + NowCaseno+'\'+DocDir+'\')) and (DocDir <> AttName) then"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2193","CopyFile","","CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2195","SaveToFile","","ContextList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat'); }"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2197","DeleteImageFile","","DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2198","RenameFile","","//RenameFile(iISB.FileName,ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName);"
[V],"TCB_IMGPSScanX.PM601Click","CB_IMGPSScanImp.pas.bk","2203","ReSortFileName","","ReSortFileName(ExtractFilePath(iISB.FileName));"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2259","Str2Dir","","Str2Dir(SavePath);"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2264","FileExists","","if FileExists(SavePath+'Context.dat') then"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2265","LoadFromFile","","FileList.LoadFromFile(SavePath+'Context.dat');"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2278","CopyFile","","CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2282","SaveToFile","","FileList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat');}"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2283","DeleteImageFile","","DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);"
[V],"TCB_IMGPSScanX.PM602Click","CB_IMGPSScanImp.pas.bk","2289","ReSortFileName","","ReSortFileName(ExtractFilePath(iISB.FileName));"
[V],"TCB_IMGPSScanX.PM604Click","CB_IMGPSScanImp.pas.bk","2317","SaveToFile","","iISB.SaveToFile(iISB.FileName);"
[V],"TCB_IMGPSScanX.PM604Click","CB_IMGPSScanImp.pas.bk","2318","LoadFromFile","","DisplayISB.LoadFromFile(DisplayISB.FileName,1);"
[V],"TCB_IMGPSScanX.PM605Click","CB_IMGPSScanImp.pas.bk","2350","DeleteImageFile","","DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);"
[V],"TCB_IMGPSScanX.PM605Click","CB_IMGPSScanImp.pas.bk","2354","ReSortFileName","","ReSortFileName(ExtractFilePath(iISB.FileName));"
[V],"TCB_IMGPSScanX.PM101Click","CB_IMGPSScanImp.pas.bk","2585","_DelTree","","_DelTree(ImageSavePath);"
[V],"TCB_IMGPSScanX.PM101Click","CB_IMGPSScanImp.pas.bk","2628","DirectoryExists","","if not DirectoryExists(ImageSavePath+FCaseID) then"
[V],"TCB_IMGPSScanX.PM101Click","CB_IMGPSScanImp.pas.bk","2645","DeleteDocNoFile","","//ShowMessage('DeleteDocNoFileForESCAN');"
[V],"TCB_IMGPSScanX.DocNoIsExistImg","CB_IMGPSScanImp.pas.bk","2685","FileExists","","if FileExists(DocNopath+'\Context.dat') then   /////20190319 Hong ç•¶æœ‰ç©ºçš„Docno目錄時會掛掉,增加這行"
[V],"TCB_IMGPSScanX.DocNoIsExistImg","CB_IMGPSScanImp.pas.bk","2686","LoadFromFile","","ST.loadFromfile(DocNopath+'\Context.dat');"
[V],"TCB_IMGPSScanX._DelTreeForExistImg","CB_IMGPSScanImp.pas.bk","2702","_DelTree","","procedure TCB_IMGPSScanX._DelTreeForExistImg(ASourceDir:String);"
[V],"TCB_IMGPSScanX.PM102Click","CB_IMGPSScanImp.pas.bk","2732","DirectoryExists","","if DirectoryExists(ImageSavePath+NewCaseID) then"
[V],"TCB_IMGPSScanX.PM102Click","CB_IMGPSScanImp.pas.bk","2741","RenameFile","","RenameFile(ImageSavePath+NowCaseno,ImageSavePath+NewCaseID);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2819","FindFirst","","FindFirst(FName, faAnyfile, FileRec);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2849","LoadFromFile","","ISB.LoadFromFile(FName, i);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2858","SaveToFile","","///ISB_BW.SaveToFile('KKKKKKKK.tif');"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2934","DirectoryExists","","If DirectoryExists(ImageSavePath + CaseID + '\') Then"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2936","_DelTree","","_DelTree(ImageSavePath + CaseID + '\');"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2942","GetNoNameCase","","CaseID := GetNoNameCase(ImageSavePath);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2947","Str2Dir","","Str2Dir(SavePath);"
[V],"TCB_IMGPSScanX.PM104Click","CB_IMGPSScanImp.pas.bk","2979","FileExists","","If FileExists(SavePath + 'Context.dat') Then"
[V],"TCB_IMGPSScanX.PM106Click","CB_IMGPSScanImp.pas.bk","3190","CopyFile","","CopyFormID,Copy2Caseno,CopyFileName : String;"
[V],"TCB_IMGPSScanX.PM106Click","CB_IMGPSScanImp.pas.bk","3238","LoadFromFile","","S.LoadFromFile(ImageSavePath + Copy2Caseno +'\Context.dat');"
[V],"TCB_IMGPSScanX.PM106Click","CB_IMGPSScanImp.pas.bk","3260","SaveToFile","","S.SaveToFile(ImageSavePath + Copy2Caseno +'\Context.dat');"
[V],"TCB_IMGPSScanX.PM109Click","CB_IMGPSScanImp.pas.bk","3400","SaveToFile","","S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');"
[V],"TCB_IMGPSScanX.PM110Click","CB_IMGPSScanImp.pas.bk","3433","Str2Dir","","Str2Dir(SavePath);"
[V],"TCB_IMGPSScanX.PM507Click","CB_IMGPSScanImp.pas.bk","3588","RenameFile","","RenameFile(DisplayPath+OldName,DisplayPath+NewName);"
[V],"TCB_IMGPSScanX.PM508Click","CB_IMGPSScanImp.pas.bk","3625","_DelTree","","_DelTree(DisplayPath);"
[V],"TCB_IMGPSScanX.PM508Click","CB_IMGPSScanImp.pas.bk","3634","SaveToFile","","ContextList.SaveToFile(ImageSavePath + NowCaseno+'\Context.dat');"
[V],"TCB_IMGPSScanX.PM508Click","CB_IMGPSScanImp.pas.bk","3638","ReSortFileName","","ReSortFileName(DisplayPath);"
[V],"TCB_IMGPSScanX.PM508Click","CB_IMGPSScanImp.pas.bk","3639","LoadFromFile","","ContextList.LoadFromFile(ImageSavePath + NowCaseno+'\Context.dat');"
[V],"TCB_IMGPSScanX.PM508Click","CB_IMGPSScanImp.pas.bk","3641","FileExists","","if FileExists(ImageSavePath + NowCaseno+'\CustomDocNo.dat') then"
[V],"TCB_IMGPSScanX.PM510Click","CB_IMGPSScanImp.pas.bk","3665","SaveToFile","","DisplayISB.SaveToFile(DisplayISB.FileName);"
[V],"TCB_IMGPSScanX.SampleScanBtnClick","CB_IMGPSScanImp.pas.bk","4009","FileExists","","if (ISB1.FileName <> '') and FileExists(SamplePath+SampleFormID+'.tif') then"
[V],"TCB_IMGPSScanX.SampleScanBtnClick","CB_IMGPSScanImp.pas.bk","4014","LoadFromFile","","ImageScrollBox1.LoadFromFile(SamplePath+SampleFormID+'.tif',1);"
[V],"TCB_IMGPSScanX.SampleScanBtnClick","CB_IMGPSScanImp.pas.bk","4016","SaveToFile","","ImageScrollBox1.SaveToFile(SamplePath+SampleFormID+'.jpg');"
[V],"TCB_IMGPSScanX.AddAttFileLBClick","CB_IMGPSScanImp.pas.bk","4179","FileExists","","if FileExists(ImageSavePath+NowCaseno+'\'+AddFile) then"
[V],"TCB_IMGPSScanX.AddAttFileLBClick","CB_IMGPSScanImp.pas.bk","4187","CopyFile","","CopyFile(Pchar(OpenDialog1.Files.Strings[i]),Pchar(ImageSavePath+NowCaseno+'\'+AddFile),False);"
[V],"TCB_IMGPSScanX.AttListBoxDblClick","CB_IMGPSScanImp.pas.bk","4264","FileExists","","if FileExists(DisplayPath+AttFile) then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4466","LoadFromFile","","//DeleteStm.LoadFromFile(Path+'temp.tif');"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4640","FileExists","","if FileExists( PEFileName ) then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4661","SaveToFile","","JpgGr.SaveToFile(PEFileName);"
[V],"TCB_IMGPSScanX.PageDone","CB_IMGPSScanImp.pas.bk","4697","LoadFromFile","","ISB.LoadFromFile(PEFileName,1);"
[V],"TCB_IMGPSScanX.PageEnd","CB_IMGPSScanImp.pas.bk","4788","GetNoNameCase","","ScanCaseno := GetNoNameCase(ImageSavePath);"
[V],"TCB_IMGPSScanX.PageEnd","CB_IMGPSScanImp.pas.bk","4793","DirectoryExists","","if DirectoryExists(ImageSavePath + ScanCaseno+'\') then"
[V],"TCB_IMGPSScanX.PageEnd","CB_IMGPSScanImp.pas.bk","4795","_DelTree","","_DelTree(ImageSavePath + ScanCaseno+'\');"
[V],"TCB_IMGPSScanX.PageEnd","CB_IMGPSScanImp.pas.bk","4801","Str2Dir","","Str2Dir(ScanPath);"
[V],"TCB_IMGPSScanX.PageEnd","CB_IMGPSScanImp.pas.bk","4859","SaveToFile","","//ContextList.SaveToFile(ScanPath+'Context.dat');"
[V],"TCB_IMGPSScanX.ExportBtClick","CB_IMGPSScanImp.pas.bk","4995","SaveToFile","","S.SaveToFile(LngPath+'mps.dat');"
[V],"TCB_IMGPSScanX.ExportBtClick","CB_IMGPSScanImp.pas.bk","5000","FileExists","","if FileExists(LngPath+'mps.zip') then"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5036","Str2Dir","","str2dir(ZipPath);"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5039","FileExists","","if not FileExists(ZipPath+'mps.dat') then"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5044","LoadFromFile","","S.LoadFromFile(ZipPath+'mps.dat');"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5054","RenameFile","","RenameFile(ZipPath+S.Strings[i],ZipPath+LicName);"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5085","_DelTree","","_DelTree(ZipPath);"
[V],"TCB_IMGPSScanX.GetSiteOMR","CB_IMGPSScanImp.pas.bk","5185","LoadFromFile","","ImageScrollBox1.LoadFromFile(FileName,1);"
[V],"TCB_IMGPSScanX.ReNameContext","CB_IMGPSScanImp.pas.bk","6020","SaveToFile","","ContextList.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DeleteImageFile","CB_IMGPSScanImp.pas.bk","6028","DeleteImageFile","","Procedure TCB_IMGPSScanX.DeleteImageFile(Path,FileName,CaseID:String); // åˆªé™¤æª”案  (無法得到DocDir用)"
[V],"TCB_IMGPSScanX.DeleteImageFile","CB_IMGPSScanImp.pas.bk","6042","FileExists","","if FileExists(Path+'Context.dat') then"
[V],"TCB_IMGPSScanX.DeleteImageFile","CB_IMGPSScanImp.pas.bk","6043","LoadFromFile","","FileList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DeleteImageFile","CB_IMGPSScanImp.pas.bk","6049","SaveToFile","","FileList.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DeleteFormCodeFile","CB_IMGPSScanImp.pas.bk","6068","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then"
[V],"TCB_IMGPSScanX.DeleteFormCodeFile","CB_IMGPSScanImp.pas.bk","6069","LoadFromFile","","FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.DeleteFormCodeFile","CB_IMGPSScanImp.pas.bk","6084","DeleteImageFile","","DeleteImageFile(ImageSavePath+CaseID+'\'+DocDir+'\',FileList.Strings[i],CaseID);"
[V],"TCB_IMGPSScanX.DeleteFormCodeFile","CB_IMGPSScanImp.pas.bk","6090","ReSortFileName","","ReSortFileName(ImageSavePath+CaseID+'\'+DocDir+'\');"
[V],"TCB_IMGPSScanX.DeleteFormCodeFile","CB_IMGPSScanImp.pas.bk","6111","SaveToFile","","ContextList.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DeleteDocNoFile","CB_IMGPSScanImp.pas.bk","6115","DeleteDocNoFile","","Function TCB_IMGPSScanX.DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件"
[V],"TCB_IMGPSScanX.DeleteDocNoFile","CB_IMGPSScanImp.pas.bk","6132","SaveToFile","","ContextList.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DeleteDocNoFile","CB_IMGPSScanImp.pas.bk","6134","ReSortFileName","","ReSortFileName(Path);"
[V],"TCB_IMGPSScanX.DeleteDocNoFile","CB_IMGPSScanImp.pas.bk","6135","LoadFromFile","","ContextList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DeleteDocNoFile","CB_IMGPSScanImp.pas.bk","6137","FileExists","","if FileExists(Path+'CustomDocNo.dat') then"
[V],"TCB_IMGPSScanX.DeleteDocNoFileForESCAN","CB_IMGPSScanImp.pas.bk","6141","DeleteDocNoFile","","Function TCB_IMGPSScanX.DeleteDocNoFileForESCAN(Path,DocNo:String):Boolean;  //刪除指定DocNo文件"
[V],"TCB_IMGPSScanX.DeleteDocNoFileForESCAN","CB_IMGPSScanImp.pas.bk","6164","SaveToFile","","ContextList.SaveToFile(Path+'\Context.dat');"
[V],"TCB_IMGPSScanX.DeleteDocNoFileForESCAN","CB_IMGPSScanImp.pas.bk","6165","LoadFromFile","","ContextList.LoadFromFile(Path+'\Context.dat');"
[V],"TCB_IMGPSScanX.DeleteDocNoFileForESCAN","CB_IMGPSScanImp.pas.bk","6169","_DelTree","","_DelTree(Path);"
[V],"TCB_IMGPSScanX.DeleteShowFile","CB_IMGPSScanImp.pas.bk","6175","DeleteShowFile","","Procedure TCB_IMGPSScanX.DeleteShowFile(Path:String); //刪除顯示中的影像"
[V],"TCB_IMGPSScanX.CheckCaseDocNoPage","CB_IMGPSScanImp.pas.bk","6219","LoadFromFile","","S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');"
[V],"TCB_IMGPSScanX.FindFormCodePages","CB_IMGPSScanImp.pas.bk","6287","LoadFromFile","","S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');"
[V],"TCB_IMGPSScanX.CaseReSize","CB_IMGPSScanImp.pas.bk","6326","FileExists","","{if FileExists(ImageSavePath+CaseID+'\ReSize.dat') then"
[V],"TCB_IMGPSScanX.CaseReSize","CB_IMGPSScanImp.pas.bk","6332","LoadFromFile","","S.LoadFromFile(ImageSavePath+CaseID+'\Upload\Context.dat');"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6369","LoadFromFile","","ImageScrollBox1.LoadFromFile(ImageSavePath+CaseID+'\Upload\'+FileName,1);"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6392","SaveToFile","","ImageScrollBox1.SaveToFile(ImageSavePath+CaseID+'\Upload\'+FileName);"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6399","FileExists","","if FileExists(ImageSavePath+CaseID+'\Upload\ReSize.dat') then"
[V],"TCB_IMGPSScanX.ImageReSize_tmp","CB_IMGPSScanImp.pas.bk","6436","LoadFromFile","","ImageScrollBox1.LoadFromFile(FileName,1);"
[V],"TCB_IMGPSScanX.ImageReSize_tmp","CB_IMGPSScanImp.pas.bk","6440","SaveToFile","","ImageScrollBox1.SaveToFile(FileName);"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6486","FileExists","","if fileExists(Path+'Context.dat') then"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6488","LoadFromFile","","ContextList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6588","CopyFile","","CopyFile(PWChar(casepath+'Download\FirstImg.zip'),PWChar(path+'FirstImg.zip'),false);"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6609","FindFirst","","FindFirst(FName, faAnyfile, FileRec);"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6728","_DelTree","","//_DelTree(Path);  //會只刪TransPath"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6859","FileExists","","if FileExists(DPath+CaseID+'.zip') then"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6868","Str2Dir","","Str2Dir(AttPath);"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6877","SaveToFile","","SC.SaveToFile(DPath+'Context.dat');"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6889","LoadFromFile","","SC.LoadFromFile(SPath+'Context.dat');"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6901","DeleteDocNoFile","","DeleteDocNoFile(DPath,DocNo);"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6916","CopyFile","","CopyFile(PWideChar(SPath+OldFName),PWideChar(DPath+NewMainFName),False);"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6930","DirectoryExists","","if DirectoryExists(SPath+'AttFile\') then"
[V],"TCB_IMGPSScanX.Down_Img","CB_IMGPSScanImp.pas.bk","7011","FileExists","","if FileExists(Path+CaseID+'.zip') then"
[V],"TCB_IMGPSScanX.Down_Img","CB_IMGPSScanImp.pas.bk","7020","Str2Dir","","Str2Dir(AttPath);"
[V],"TCB_IMGPSScanX.GetNoNameCase","CB_IMGPSScanImp.pas.bk","7033","GetNoNameCase","","Function TCB_IMGPSScanX.GetNoNameCase(Path:String):String; //取未配號XXXX"
[V],"TCB_IMGPSScanX.GetNoNameCase","CB_IMGPSScanImp.pas.bk","7039","DirectoryExists","","if Not DirectoryExists(Path+_Msg('未配號')+Add_Zoo(i,4)) then"
[V],"TCB_IMGPSScanX.CaseResort","CB_IMGPSScanImp.pas.bk","7057","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.CaseResort","CB_IMGPSScanImp.pas.bk","7171","FileExists","","if FileExists(Path+OldName) then"
[V],"TCB_IMGPSScanX.CaseResort","CB_IMGPSScanImp.pas.bk","7173","RenameFile","","ReNameFile(Path+OldName,Path+NewName);"
[V],"TCB_IMGPSScanX.CaseResort","CB_IMGPSScanImp.pas.bk","7175","SaveToFile","","S.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.CaseResort","CB_IMGPSScanImp.pas.bk","7178","ReSortFileName","","ReSortFileName(Path);"
[V],"TCB_IMGPSScanX.CaseResort2Scanlist","CB_IMGPSScanImp.pas.bk","7195","FileExists","","if FileExists(Path+'Context.dat') then"
[V],"TCB_IMGPSScanX.CaseResort2Scanlist","CB_IMGPSScanImp.pas.bk","7196","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.CaseResort2Scanlist","CB_IMGPSScanImp.pas.bk","7294","RenameFile","","//ReNameFile(Path+OldName,Path+NewName);"
[V],"TCB_IMGPSScanX.CaseResort2Scanlist","CB_IMGPSScanImp.pas.bk","7296","SaveToFile","","S.SaveToFile(Path+'scanlist.dat');"
[V],"TCB_IMGPSScanX.CaseResort2Scanlist","CB_IMGPSScanImp.pas.bk","7299","ReSortFileName","","ReSortFileName2Scanlist(Path);"
[V],"TCB_IMGPSScanX.DistinctDocinCase","CB_IMGPSScanImp.pas.bk","7318","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.DistinctDocNoinCase","CB_IMGPSScanImp.pas.bk","7362","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.ClearErrini","CB_IMGPSScanImp.pas.bk","7392","FileExists","","if FileExists(ImageSavePath+CaseID+'\Checkerr.ini') then"
[V],"TCB_IMGPSScanX.SetCaseList","CB_IMGPSScanImp.pas.bk","7412","FileExists","","if FileExists(ImageSavePath + 'CaseList.dat') then"
[V],"TCB_IMGPSScanX.SetCaseList","CB_IMGPSScanImp.pas.bk","7413","LoadFromFile","","CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');"
[V],"TCB_IMGPSScanX.SetCaseList","CB_IMGPSScanImp.pas.bk","7443","SaveToFile","","CaseList.SaveToFile(ImageSavePath+'CaseList.dat');"
[V],"TCB_IMGPSScanX.SetDocNoList","CB_IMGPSScanImp.pas.bk","7456","FileExists","","if FileExists(ImageSavePath+CaseNo+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.SetDocNoList","CB_IMGPSScanImp.pas.bk","7457","LoadFromFile","","CaseDocNoList.LoadFromFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.SetDocNoList","CB_IMGPSScanImp.pas.bk","7507","SaveToFile","","CaseDocNoList.SaveToFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.SetContextList","CB_IMGPSScanImp.pas.bk","7527","FileExists","","if FileExists(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat') then"
[V],"TCB_IMGPSScanX.SetContextList","CB_IMGPSScanImp.pas.bk","7528","LoadFromFile","","ContextList.LoadFromFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.SetContextList","CB_IMGPSScanImp.pas.bk","7562","SaveToFile","","ContextList.SaveToFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.SetAttContextList","CB_IMGPSScanImp.pas.bk","7571","FileExists","","if FileExists(ImageSavePath+CaseNo+'\AttContext.dat') then"
[V],"TCB_IMGPSScanX.SetAttContextList","CB_IMGPSScanImp.pas.bk","7572","LoadFromFile","","AttContextList.LoadFromFile(ImageSavePath+CaseNo+'\AttContext.dat');"
[V],"TCB_IMGPSScanX.SetAttContextList","CB_IMGPSScanImp.pas.bk","7605","SaveToFile","","AttContextList.SaveToFile(ImageSavePath+CaseNo+'\AttContext.dat');"
[V],"TCB_IMGPSScanX.CreateEmptyCase","CB_IMGPSScanImp.pas.bk","7684","SaveToFile","","S.SaveToFile(Path+CaseID+'\Context.dat');"
[V],"TCB_IMGPSScanX.FormIDReplace","CB_IMGPSScanImp.pas.bk","7749","FileExists","","if FileExists(ImageSavePath + CaseID+'\'+NewDocDir+'\Context.dat') then"
[V],"TCB_IMGPSScanX.FormIDReplace","CB_IMGPSScanImp.pas.bk","7751","LoadFromFile","","ST1.LoadFromFile(ImageSavePath + CaseID+'\'+NewDocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.FormIDReplace","CB_IMGPSScanImp.pas.bk","7795","DirectoryExists","","if Not DirectoryExists(ImageSavePath+CaseID+'\'+NewDocDir) then"
[V],"TCB_IMGPSScanX.FormIDReplace","CB_IMGPSScanImp.pas.bk","7811","CopyFile","","CopyFile(PWideChar(ImageSavePath+CaseID+'\'+DocDir+'\'+OldFile),PWideChar(ImageSavePath+CaseID+'\'+NewDocDir+'\'+NewFile),False);"
[V],"TCB_IMGPSScanX.FormIDReplace","CB_IMGPSScanImp.pas.bk","7827","RenameFile","","ReNameFile(Path+OldFile,Path+NewFile);"
[V],"TCB_IMGPSScanX.FormIDReplace","CB_IMGPSScanImp.pas.bk","7831","SaveToFile","","S.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.ShowFileReplace","CB_IMGPSScanImp.pas.bk","7852","RenameFile","","ReNameFile(Path+OldFile,Path+NewFile);"
[V],"TCB_IMGPSScanX.PageReplaceFormID","CB_IMGPSScanImp.pas.bk","7867","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.PageReplaceFormID","CB_IMGPSScanImp.pas.bk","7891","RenameFile","","ReNameFile(Path+OldFile,Path+NewFile);"
[V],"TCB_IMGPSScanX.PageReplaceFormID","CB_IMGPSScanImp.pas.bk","7899","SaveToFile","","S.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.GetCasePage","CB_IMGPSScanImp.pas.bk","7925","FileExists","","if FileExists(Path+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.GetCasePage","CB_IMGPSScanImp.pas.bk","7926","LoadFromFile","","DocDirList.LoadFromFile(Path+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.SetFile2Case","CB_IMGPSScanImp.pas.bk","8006","LoadFromFile","","S.LoadFromFile(ImageSavePath+CaseID+'\Context.dat');"
[V],"TCB_IMGPSScanX.SetFile2Case","CB_IMGPSScanImp.pas.bk","8008","SaveToFile","","S.SaveToFile(ImageSavePath+CaseID+'\Context.dat');"
[V],"TCB_IMGPSScanX.WriteResize","CB_IMGPSScanImp.pas.bk","8022","LoadFromFile","","ImageScrollBox1.LoadFromFile(ImgName,1);"
[V],"TCB_IMGPSScanX.WriteResize","CB_IMGPSScanImp.pas.bk","8045","FileExists","","if FileExists(TxtName) then"
[V],"TCB_IMGPSScanX.WriteResize","CB_IMGPSScanImp.pas.bk","8049","SaveToFile","","S.SaveToFile(TxtName);"
[V],"TCB_IMGPSScanX.GetCase_PageCount","CB_IMGPSScanImp.pas.bk","8072","FileExists","","if FileExists(ImageSavePath + 'CaseList.dat') then"
[V],"TCB_IMGPSScanX.GetCase_PageCount","CB_IMGPSScanImp.pas.bk","8073","LoadFromFile","","CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');"
[V],"TCB_IMGPSScanX.WriteCaseIndex","CB_IMGPSScanImp.pas.bk","8205","SaveToFile","","S.SaveToFile(Path+'CaseIndex.dat');"
[V],"TCB_IMGPSScanX.ReadCaseIndex","CB_IMGPSScanImp.pas.bk","8221","FileExists","","if FileExists(Path+'CaseIndex.dat') then"
[V],"TCB_IMGPSScanX.ReadCaseIndex","CB_IMGPSScanImp.pas.bk","8223","LoadFromFile","","S.LoadFromFile(Path+'CaseIndex.dat');"
[V],"TCB_IMGPSScanX.ReduceLogFile","CB_IMGPSScanImp.pas.bk","8249","FileExists","","if FileExists(LngPath+'IMGPSCheck.log') then"
[V],"TCB_IMGPSScanX.ReduceLogFile","CB_IMGPSScanImp.pas.bk","8251","LoadFromFile","","ST1.LoadFromFile(LngPath+'IMGPSCheck.log');"
[V],"TCB_IMGPSScanX.ReduceLogFile","CB_IMGPSScanImp.pas.bk","8258","SaveToFile","","ST1.SaveToFile(LngPath+'IMGPSCheck.log');"
[V],"TCB_IMGPSScanX.GetDocNoDir","CB_IMGPSScanImp.pas.bk","8304","DirectoryExists","","until not DirectoryExists(Path+iDocNo);"
[V],"TCB_IMGPSScanX.DocNo2DocNoDir","CB_IMGPSScanImp.pas.bk","8341","DirectoryExists","","until not DirectoryExists(Path+iDocNo);"
[V],"TCB_IMGPSScanX.DocNoDir2Index","CB_IMGPSScanImp.pas.bk","8374","LoadFromFile","","CaseNo_List.LoadFromFile(Path+'CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.ZipMainFile","CB_IMGPSScanImp.pas.bk","8395","FileExists","","if fileExists(DePath+ZipName) then"
[V],"TCB_IMGPSScanX.ZipMainFile","CB_IMGPSScanImp.pas.bk","8412","LoadFromFile","","AttContextList.LoadFromFile(SoPath+'ATTContext.dat');"
[V],"TCB_IMGPSScanX.ZipMaskFile","CB_IMGPSScanImp.pas.bk","8468","FileExists","","if fileExists(DePath+ZipName) then"
[V],"TCB_IMGPSScanX.GetFormatID","CB_IMGPSScanImp.pas.bk","8605","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then"
[V],"TCB_IMGPSScanX.GetFormatID","CB_IMGPSScanImp.pas.bk","8607","LoadFromFile","","S.LoadFromFile(ImageSavePath+CaseID+'\CaseIndex.dat');"
[V],"TCB_IMGPSScanX.CheckCaseBtnClick","CB_IMGPSScanImp.pas.bk","8952","SaveToFile","","S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');"
[V],"TCB_IMGPSScanX.DrawDocItem2","CB_IMGPSScanImp.pas.bk","9012","FileExists","","if FileExists(ImageSavePath+Caseno+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.DrawDocItem2","CB_IMGPSScanImp.pas.bk","9013","LoadFromFile","","CaseDocNoList.LoadFromFile(ImageSavePath+Caseno+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.DrawDocItem2","CB_IMGPSScanImp.pas.bk","9162","DirectoryExists","","if DirectoryExists(ImageSavePath+Caseno+'\'+AttName) then"
[V],"TCB_IMGPSScanX.PrtLbClick","CB_IMGPSScanImp.pas.bk","9320","LoadFromFile","","//ontextList.LoadFromFile(ImageSavePath+NowCaseNo+'\Upload\Context.dat');"
[V],"TCB_IMGPSScanX.UseOldCaseLbClick","CB_IMGPSScanImp.pas.bk","9441","FileExists","","if FileExists(NewPath+'CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.UseOldCaseLbClick","CB_IMGPSScanImp.pas.bk","9442","LoadFromFile","","iDocNoList.LoadFromFile(NewPath+'CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.UseOldCaseLbClick","CB_IMGPSScanImp.pas.bk","9471","DirectoryExists","","if Not DirectoryExists(NewPath+NewDocDir) then"
[V],"TCB_IMGPSScanX.UseOldCaseLbClick","CB_IMGPSScanImp.pas.bk","9501","CopyFile","","CopyFile(PwideChar(OldPath+OldFile),Pwidechar(NewPath+NewDocDir+'\'+NewFile),False);"
[V],"TCB_IMGPSScanX.UseOldCaseLbClick","CB_IMGPSScanImp.pas.bk","9504","SaveToFile","","iFileList.SaveToFile(NewPath+NewDocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.LastInitFormidListCreate","CB_IMGPSScanImp.pas.bk","9538","LoadFromFile","","ST1.LoadFromFile(path+'FormCode_Name.dat');"
[V],"TCB_IMGPSScanX.LoadImgFile","CB_IMGPSScanImp.pas.bk","9604","FileExists","","if FileExists(ImageSavePath + 'CaseList.dat') then"
[V],"TCB_IMGPSScanX.LoadImgFile","CB_IMGPSScanImp.pas.bk","9605","LoadFromFile","","CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');"
[V],"TCB_IMGPSScanX.LoadImgFile","CB_IMGPSScanImp.pas.bk","9617","SaveToFile","","CaseDocNo_CopiesList.SaveToFile(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo_Copies.dat');"
[V],"TCB_IMGPSScanX.LoadImgFile1","CB_IMGPSScanImp.pas.bk","9689","FileExists","","if FileExists(ImageSavePath + 'CaseList.dat') then"
[V],"TCB_IMGPSScanX.LoadImgFile1","CB_IMGPSScanImp.pas.bk","9690","LoadFromFile","","CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');"
[V],"TCB_IMGPSScanX.LoadImgFile1","CB_IMGPSScanImp.pas.bk","9720","SaveToFile","","Context_DocnoList.SaveToFile(ImageSavePath+CaseList.Strings[n]+'\Context_DocNo.dat');"
[V],"TCB_IMGPSScanX.LoadAttFile","CB_IMGPSScanImp.pas.bk","9779","FileExists","","if FileExists(ImageSavePath+CaseID+'\AttContext.dat') then"
[V],"TCB_IMGPSScanX.LoadAttFile","CB_IMGPSScanImp.pas.bk","9781","LoadFromFile","","AttContextList.LoadFromFile(ImageSavePath+CaseID+'\AttContext.dat');"
[V],"TCB_IMGPSScanX.CheckAvailable","CB_IMGPSScanImp.pas.bk","9915","FileExists","","if FileExists(LngPath+'MPSLIC_SCAN.lic') then"
[V],"TCB_IMGPSScanX.Case2Mask","CB_IMGPSScanImp.pas.bk","9946","DirectoryExists","","if DirectoryExists(DePath) then"
[V],"TCB_IMGPSScanX.Case2Mask","CB_IMGPSScanImp.pas.bk","9947","_DelTree","","_DelTree(DePath);"
[V],"TCB_IMGPSScanX.Case2Mask","CB_IMGPSScanImp.pas.bk","9948","Str2Dir","","Str2Dir(DePath);"
[V],"TCB_IMGPSScanX.Case2Mask","CB_IMGPSScanImp.pas.bk","9954","LoadFromFile","","S.LoadFromFile(SoPath+'Context.dat');"
[V],"TCB_IMGPSScanX.Case2Mask","CB_IMGPSScanImp.pas.bk","9964","FileExists","","if FileExists(CheckXmlPath+FWork_no+'\'+FormID+'.xml') then  //沒有Xml就不用遮罩"
[V],"TCB_IMGPSScanX.GetNewCustomDocNo","CB_IMGPSScanImp.pas.bk","10059","FileExists","","if FileExists(Path+'CustomDocNo.dat') then"
[V],"TCB_IMGPSScanX.GetNewCustomDocNo","CB_IMGPSScanImp.pas.bk","10062","LoadFromFile","","S.LoadFromFile(Path+'CustomDocNo.dat');"
[V],"TCB_IMGPSScanX.GetNewCustomDocNo","CB_IMGPSScanImp.pas.bk","10080","SaveToFile","","S.SaveToFile(Path+'CustomDocNo.dat');"
[V],"PrintWithAutoPrintJob","CB_IMGPSScanImp.pas.bk","10285","LoadFromFile","","ImageScrollBox1.LoadFromFile(Path+S.Strings[i],1);"
[V],"TCB_IMGPSScanX.FindLastestDocDir","CB_IMGPSScanImp.pas.bk","10307","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.FindLastestDocDir","CB_IMGPSScanImp.pas.bk","10308","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.FindLastestDocDirForPage","CB_IMGPSScanImp.pas.bk","10335","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.FindLastestDocDirForPage","CB_IMGPSScanImp.pas.bk","10336","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.Create_Cust_DocDir","CB_IMGPSScanImp.pas.bk","10401","DirectoryExists","","if DirectoryExists(ImageSavePath+CaseID+'\'+DocNo+'('+inttostr(DocNo_Ct)+')') then  //存在了"
[V],"TCB_IMGPSScanX.OldCasetoNewCase","CB_IMGPSScanImp.pas.bk","10469","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.OldCasetoNewCase","CB_IMGPSScanImp.pas.bk","10494","SaveToFile","","DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');"
[V],"TCB_IMGPSScanX.ErrFormtoCurrentForm","CB_IMGPSScanImp.pas.bk","10539","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.ErrFormtoCurrentForm","CB_IMGPSScanImp.pas.bk","10545","FileExists","","if FileExists(iPath+'Context.dat') then  //20140909漏加這個判斷造成自訂文件但沒影像會出錯誤訊息"
[V],"TCB_IMGPSScanX.ErrFormtoCurrentForm","CB_IMGPSScanImp.pas.bk","10555","RenameFile","","RenameFile(iPath+OldFile,iPath+NewFile);"
[V],"TCB_IMGPSScanX.ErrFormtoCurrentForm","CB_IMGPSScanImp.pas.bk","10556","SaveToFile","","FileList.SaveToFile(iPath+'Context.dat');"
[V],"TCB_IMGPSScanX.ErrFormtoCurrentForm","CB_IMGPSScanImp.pas.bk","10563","MoveFile","","MoveFile(PWideChar(iPath),PWideChar(iiPath));"
[V],"TCB_IMGPSScanX.SetRecordEditedDocDir","CB_IMGPSScanImp.pas.bk","10583","FileExists","","if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then"
[V],"TCB_IMGPSScanX.SetRecordEditedDocDir","CB_IMGPSScanImp.pas.bk","10584","LoadFromFile","","EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');"
[V],"TCB_IMGPSScanX.SetRecordEditedDocDir","CB_IMGPSScanImp.pas.bk","10599","SaveToFile","","EditedDocDirList.SaveToFile(ImageSavePath+CaseID+'\EditedDocDir.dat');"
[V],"TCB_IMGPSScanX.GetDocDir_Page","CB_IMGPSScanImp.pas.bk","10630","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then"
[V],"TCB_IMGPSScanX.GetDocDir_Page","CB_IMGPSScanImp.pas.bk","10632","LoadFromFile","","FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.Path2DocDir","CB_IMGPSScanImp.pas.bk","10648","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.Path2DocDir","CB_IMGPSScanImp.pas.bk","10649","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.SortDocDir_FormID","CB_IMGPSScanImp.pas.bk","10692","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then"
[V],"TCB_IMGPSScanX.SortDocDir_FormID","CB_IMGPSScanImp.pas.bk","10694","LoadFromFile","","FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.SortDocDir_FormID","CB_IMGPSScanImp.pas.bk","10733","RenameFile","","RenameFile(ImageSavePath+CaseID+'\'+DocDir+'\'+OldName,ImageSavePath+CaseID+'\'+DocDir+'\'+NewName);"
[V],"TCB_IMGPSScanX.SortDocDir_FormID","CB_IMGPSScanImp.pas.bk","10744","SaveToFile","","FileList.SaveToFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');"
[V],"TCB_IMGPSScanX.CreateCaseNeedData","CB_IMGPSScanImp.pas.bk","10807","FileExists","","if FileExists(Path+'Context.dat') then"
[V],"TCB_IMGPSScanX.CreateCaseNeedData","CB_IMGPSScanImp.pas.bk","10809","LoadFromFile","","FileList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.CreateCaseNeedData","CB_IMGPSScanImp.pas.bk","10828","SaveToFile","","DocNoList.SaveToFile(Path+'DocDir.dat');"
[V],"TCB_IMGPSScanX.TransOldCaseFile","CB_IMGPSScanImp.pas.bk","10902","FileExists","","if FileExists(OldCasePath+'UseCase.dat') and FileExists(OldCasePath+'UseCase.ini') then"
[V],"TCB_IMGPSScanX.GetDocNoCount","CB_IMGPSScanImp.pas.bk","11148","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.GetDocNoCount","CB_IMGPSScanImp.pas.bk","11150","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.GetDocDirCopies","CB_IMGPSScanImp.pas.bk","11177","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.GetDocDirCopies","CB_IMGPSScanImp.pas.bk","11178","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.SetDocDirCopies","CB_IMGPSScanImp.pas.bk","11206","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.SetDocDirCopies","CB_IMGPSScanImp.pas.bk","11208","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.SetDocDirCopies","CB_IMGPSScanImp.pas.bk","11216","SaveToFile","","DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');"
[V],"TCB_IMGPSScanX.CaseDelete_Enable","CB_IMGPSScanImp.pas.bk","11377","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.CaseDelete_Enable","CB_IMGPSScanImp.pas.bk","11378","LoadFromFile","","CaseDocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.MoveImage","CB_IMGPSScanImp.pas.bk","11398","LoadFromFile","","FList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.MoveImage","CB_IMGPSScanImp.pas.bk","11403","RenameFile","","Renamefile(Path+Flist.Strings[i],path+'@'+Flist.Strings[i]);"
[V],"TCB_IMGPSScanX.MoveImage","CB_IMGPSScanImp.pas.bk","11435","SaveToFile","","Flist.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.MoveImage","CB_IMGPSScanImp.pas.bk","11438","ReSortFileName","","ReSortFileName(Path);"
[V],"TCB_IMGPSScanX.MoveImage_Drag","CB_IMGPSScanImp.pas.bk","11456","LoadFromFile","","FList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.MoveImage_Drag","CB_IMGPSScanImp.pas.bk","11459","RenameFile","","Renamefile(Path+Flist.Strings[i],path+'@'+Flist.Strings[i]);"
[V],"TCB_IMGPSScanX.MoveImage_Drag","CB_IMGPSScanImp.pas.bk","11493","SaveToFile","","Flist.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.MoveImage_Drag","CB_IMGPSScanImp.pas.bk","11496","ReSortFileName","","ReSortFileName(Path);"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11566","DirectoryExists","","if DirectoryExists(NewPath) then"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11567","_DelTree","","_DelTree(NewPath);"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11568","Str2Dir","","str2dir(NewPath);"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11569","CopyFile","","CopyFile(PWideChar(OldPath+'CaseDocNo.dat'),PWideChar(NewPath+'CaseDocNo.dat'),False);"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11576","FileExists","","if FileExists(OldPath+'CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11578","LoadFromFile","","DocNoList.LoadFromFile(OldPath+'CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.Case2upload","CB_IMGPSScanImp.pas.bk","11582","SaveToFile","","DocNoList.SaveToFile(OldPath+'CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.Download2Case","CB_IMGPSScanImp.pas.bk","11684","FileExists","","if (not FileExists(SoDir+'CaseDocNo.dat')) or (not FileExists(SoDir+'DocDir.dat')) then   //截畫面會沒這些檔"
[V],"TCB_IMGPSScanX.Download2Case","CB_IMGPSScanImp.pas.bk","11690","CopyFile","","AA:=CopyFile(PWideChar(SoDir+'CaseDocNo.dat'),PWideChar(DeDir+'CaseDocNo.dat'),False);"
[V],"TCB_IMGPSScanX.Download2Case","CB_IMGPSScanImp.pas.bk","11708","LoadFromFile","","//iFileList.LoadFromFile(SoDir+'Context.dat');"
[V],"TCB_IMGPSScanX.Download2Case","CB_IMGPSScanImp.pas.bk","11738","DirectoryExists","","if not DirectoryExists(DeDir+DocDir) then"
[V],"TCB_IMGPSScanX.Download2Case","CB_IMGPSScanImp.pas.bk","11748","SaveToFile","","DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.DistinctFormCode","CB_IMGPSScanImp.pas.bk","12218","LoadFromFile","","S.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');"
[V],"TCB_IMGPSScanX.OMRCheckCase","CB_IMGPSScanImp.pas.bk","12420","LoadFromFile","","List.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');"
[V],"TCB_IMGPSScanX.OMRCheckCase","CB_IMGPSScanImp.pas.bk","12515","FileExists","","if not FileExists(CheckXmlPath+FWork_no+'\'+OMRFormCode+'.xml') then  //沒有Xml就不用檢核"
[V],"TCB_IMGPSScanX.OMRCheckCase","CB_IMGPSScanImp.pas.bk","12937","SaveToFile","","ValueXT.SaveToFile(ImageSavePath+CaseID+'/GetValue.xml');"
[V],"TCB_IMGPSScanX.OMRErr2ini","CB_IMGPSScanImp.pas.bk","12981","FileExists","","if FileExists(ImageSavePath + CaseID+'\CheckMemo.dat') then"
[V],"TCB_IMGPSScanX.OMRErr2ini","CB_IMGPSScanImp.pas.bk","12982","LoadFromFile","","S.LoadFromFile(ImageSavePath + CaseID+'\CheckMemo.dat');"
[V],"TCB_IMGPSScanX.OMRErr2ini","CB_IMGPSScanImp.pas.bk","12984","SaveToFile","","S.SaveToFile(ImageSavePath + CaseID+'\CheckMemo.dat');"
[V],"TCB_IMGPSScanX.OMRErrini2ListForLog","CB_IMGPSScanImp.pas.bk","13034","LoadFromFile","","CaseList.LoadFromFile(ImageSavePath+'CaseList.dat');"
[V],"TCB_IMGPSScanX.view_image_FormCode","CB_IMGPSScanImp.pas.bk","13106","LoadFromFile","","ISB.LoadFromFile(Path+ContextList.Strings[i],1);"
[V],"TCB_IMGPSScanX.view_image_DocNo","CB_IMGPSScanImp.pas.bk","13230","FileExists","","if FileExists(ImageSavePath+NowCaseno+'\EditedDocDir.dat') then"
[V],"TCB_IMGPSScanX.view_image_DocNo","CB_IMGPSScanImp.pas.bk","13232","LoadFromFile","","ST1.LoadFromFile(ImageSavePath+NowCaseno+'\EditedDocDir.dat');"
[V],"TCB_IMGPSScanX.view_image_DocNo","CB_IMGPSScanImp.pas.bk","13284","DirectoryExists","","//if DirectoryExists(Path+'Attach') then"
[V],"TCB_IMGPSScanX.SpeedButton14Click","CB_IMGPSScanImp.pas.bk","13406","LoadFromFile","","ISB1.LoadFromFile(ISB1.FileName,1);"
[V],"TCB_IMGPSScanX.SpeedButton14Click","CB_IMGPSScanImp.pas.bk","13411","SaveToFile","","TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);"
[V],"TCB_IMGPSScanX.SpeedButton15Click","CB_IMGPSScanImp.pas.bk","13427","LoadFromFile","","ISB1.LoadFromFile(ISB1.FileName,1);"
[V],"TCB_IMGPSScanX.SpeedButton15Click","CB_IMGPSScanImp.pas.bk","13432","SaveToFile","","TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);"
[V],"TCB_IMGPSScanX.SpeedButton16Click","CB_IMGPSScanImp.pas.bk","13448","LoadFromFile","","ISB1.LoadFromFile(ISB1.FileName,1);"
[V],"TCB_IMGPSScanX.SpeedButton16Click","CB_IMGPSScanImp.pas.bk","13453","SaveToFile","","TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);"
[V],"TCB_IMGPSScanX.ISBClick","CB_IMGPSScanImp.pas.bk","13727","LoadFromFile","","ISB1.LoadFromFile(SelectISB.FileName,1);"
[V],"TCB_IMGPSScanX.ISBImageMouseDown","CB_IMGPSScanImp.pas.bk","13802","LoadFromFile","","ISB1.LoadFromFile(SelectISB.FileName,1);"
[V],"TCB_IMGPSScanX.GetCaseFormID","CB_IMGPSScanImp.pas.bk","13895","LoadFromFile","","ContextList.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.CreateFormID_FormName","CB_IMGPSScanImp.pas.bk","13926","SaveToFile","","S.SaveToFile(Path + 'FormCode_Name.dat',TEnCoding.UTF8);"
[V],"TCB_IMGPSScanX.CreateDocNo_DocName","CB_IMGPSScanImp.pas.bk","13948","SaveToFile","","S.SaveToFile(Path+'DocNo_Name.dat',TEnCoding.UTF8);"
[V],"TCB_IMGPSScanX.CreateIn_WH","CB_IMGPSScanImp.pas.bk","13963","FileExists","","if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then"
[V],"TCB_IMGPSScanX.CreateIn_WH","CB_IMGPSScanImp.pas.bk","13964","LoadFromFile","","DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.CreateIn_WH","CB_IMGPSScanImp.pas.bk","13977","SaveToFile","","In_WH_List.SaveToFile(ImageSavePath+CaseID+'\In_Wh.dat');"
[V],"TCB_IMGPSScanX.CreateDocNo_Info","CB_IMGPSScanImp.pas.bk","14000","FileExists","","if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;"
[V],"TCB_IMGPSScanX.CreateDocNo_Info","CB_IMGPSScanImp.pas.bk","14002","LoadFromFile","","DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.CreateCustDocNo_Info","CB_IMGPSScanImp.pas.bk","14082","FileExists","","if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;"
[V],"TCB_IMGPSScanX.CreateCustDocNo_Info","CB_IMGPSScanImp.pas.bk","14083","LoadFromFile","","DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.CreateDocnoFrom_Info","CB_IMGPSScanImp.pas.bk","14137","FileExists","","if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;"
[V],"TCB_IMGPSScanX.CreateDocnoFrom_Info","CB_IMGPSScanImp.pas.bk","14138","LoadFromFile","","DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.CreateCustDocNoFrom_Info","CB_IMGPSScanImp.pas.bk","14201","FileExists","","if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;"
[V],"TCB_IMGPSScanX.CreateCustDocNoFrom_Info","CB_IMGPSScanImp.pas.bk","14202","LoadFromFile","","DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.GetDocNoEdit","CB_IMGPSScanImp.pas.bk","14263","FileExists","","if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then"
[V],"TCB_IMGPSScanX.GetDocNoEdit","CB_IMGPSScanImp.pas.bk","14264","LoadFromFile","","EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');"
[V],"TCB_IMGPSScanX.GetDocNo_Count","CB_IMGPSScanImp.pas.bk","14310","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.GetDocNo_Page","CB_IMGPSScanImp.pas.bk","14342","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.Case_DocNoExists","CB_IMGPSScanImp.pas.bk","14406","LoadFromFile","","S.LoadFromFile(ImageSavePath + CaseID+'\Context.dat');"
[V],"TCB_IMGPSScanX.ReSortFileName","CB_IMGPSScanImp.pas.bk","14427","ReSortFileName","","Procedure TCB_IMGPSScanX.ReSortFileName(Path:String); //檔名重新排序"
[V],"TCB_IMGPSScanX.ReSortFileName","CB_IMGPSScanImp.pas.bk","14435","FileExists","","if FileExists(Path+'Context.dat') then"
[V],"TCB_IMGPSScanX.ReSortFileName","CB_IMGPSScanImp.pas.bk","14437","LoadFromFile","","Filelist.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.ReSortFileName","CB_IMGPSScanImp.pas.bk","14444","RenameFile","","ReNameFile(Path+OldName,Path+NewName);"
[V],"TCB_IMGPSScanX.ReSortFileName","CB_IMGPSScanImp.pas.bk","14447","SaveToFile","","Filelist.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.ReSortFileName_New","CB_IMGPSScanImp.pas.bk","14455","ReSortFileName","","Procedure TCB_IMGPSScanX.ReSortFileName_New(Path:String); //檔名重新排序"
[V],"TCB_IMGPSScanX.ReSortFileName_New","CB_IMGPSScanImp.pas.bk","14463","FileExists","","if FileExists(Path+'Context.dat') then"
[V],"TCB_IMGPSScanX.ReSortFileName_New","CB_IMGPSScanImp.pas.bk","14465","LoadFromFile","","Filelist.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.ReSortFileName_New","CB_IMGPSScanImp.pas.bk","14471","RenameFile","","ReNameFile(Path+OldName,Path+NewName);"
[V],"TCB_IMGPSScanX.ReSortFileName_New","CB_IMGPSScanImp.pas.bk","14474","SaveToFile","","Filelist.SaveToFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.ReSortFileName2Scanlist","CB_IMGPSScanImp.pas.bk","14482","ReSortFileName","","Procedure TCB_IMGPSScanX.ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat"
[V],"TCB_IMGPSScanX.ReSortFileName2Scanlist","CB_IMGPSScanImp.pas.bk","14490","FileExists","","if FileExists(Path+'scanlist.dat') then"
[V],"TCB_IMGPSScanX.ReSortFileName2Scanlist","CB_IMGPSScanImp.pas.bk","14491","LoadFromFile","","S.LoadFromFile(Path+'scanlist.dat');"
[V],"TCB_IMGPSScanX.ReSortFileName2Scanlist","CB_IMGPSScanImp.pas.bk","14497","RenameFile","","//ReNameFile(Path+OldName,Path+NewName);"
[V],"TCB_IMGPSScanX.ReSortFileName2Scanlist","CB_IMGPSScanImp.pas.bk","14500","SaveToFile","","S.SaveToFile(Path+'scanlist.dat');"
[V],"TCB_IMGPSScanX.GetOMRCheckSet","CB_IMGPSScanImp.pas.bk","14516","FileExists","","if FileExists(CheckXmlPath+'OMRSet.zip') then"
[V],"TCB_IMGPSScanX.GetOMRCheckSet","CB_IMGPSScanImp.pas.bk","14522","LoadFromFile","","S.LoadFromFile(CheckXmlPath+'LastDateTime.dat');"
[V],"TCB_IMGPSScanX.GetOMRCheckSet","CB_IMGPSScanImp.pas.bk","14538","SaveToFile","","S.SaveToFile(CheckXmlPath+'LastDateTime.dat');"
[V],"TCB_IMGPSScanX.GetKeyinSet","CB_IMGPSScanImp.pas.bk","14575","FileExists","","if FileExists(SitePath+'KeyinSet.zip') then"
[V],"TCB_IMGPSScanX.GetKeyinSet","CB_IMGPSScanImp.pas.bk","14581","LoadFromFile","","S.LoadFromFile(SitePath+'LastDateTime.dat');"
[V],"TCB_IMGPSScanX.GetKeyinSet","CB_IMGPSScanImp.pas.bk","14596","SaveToFile","","S.SaveToFile(SitePath+'LastDateTime.dat');"
[V],"TCB_IMGPSScanX.CaseComplete","CB_IMGPSScanImp.pas.bk","14695","FileExists","","if FileExists(Path+'Context.dat') then    //掃描頁數"
[V],"TCB_IMGPSScanX.CaseComplete","CB_IMGPSScanImp.pas.bk","14697","LoadFromFile","","S.LoadFromFile(Path+'Context.dat');"
[V],"TCB_IMGPSScanX.Timer1Timer","CB_IMGPSScanImp.pas.bk","14991","GetLocalAppDir","","LngPath := GetLocalAppDir(Handle)+'MPS\CB_IMGPS\';"
[V],"TCB_IMGPSScanX.Timer1Timer","CB_IMGPSScanImp.pas.bk","14992","Str2Dir","","Str2Dir(LngPath);"
[V],"TCB_IMGPSScanX.Timer1Timer","CB_IMGPSScanImp.pas.bk","15202","_DelTree","","_Deltree(ImagePath);"
[V],"TCB_IMGPSScanX.Timer1Timer","CB_IMGPSScanImp.pas.bk","15234","FileExists","","//if not FileExists(ImageSavePath+FCaseID+'\CaseDocNo_Copies.dat') then   //這個會在Download2Case時一律產生所以不能有這行 20141013"
[V],"TCB_IMGPSScanX.TransBtnClick","CB_IMGPSScanImp.pas.bk","15415","LoadFromFile","","S.LoadFromFile(TransPath + 'Context.dat');"
[V],"TCB_IMGPSScanX.TreeView1Click","CB_IMGPSScanImp.pas.bk","15592","FileExists","","If FileExists(DisplayPath+'\upload\Checkerr.ini') and (not FileExists(DisplayPath+'\upload\OMRCheckOk.dat')) Then"
[V],"TCB_IMGPSScanX.TreeView1Click","CB_IMGPSScanImp.pas.bk","15596","LoadFromFile","","CaseDocNoList.LoadFromFile(DisplayPath+'CaseDocNo.dat');"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15806","RenameFile","","{ReNameFile(DisplayISB.FileName,NewPath+NewFileName);"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15869","CopyFile","","CopyFile(PWideChar(OldFileName),PwideChar(NewPath+NewFileName),False);"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15871","DeleteImageFile","","DeleteImageFile(ExtractFilePath(OldFileName),ExtractFileName(OldFileName),NowCaseNo);"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15881","LoadFromFile","","ContextList.LoadFromFile(DisplayPath+'Context.dat');"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15889","SaveToFile","","ContextList.SaveToFile(NewPath+'Context.dat');"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15901","_DelTree","","_DelTree(DisplayPath);"
[V],"TCB_IMGPSScanX.TreeView1DragDrop","CB_IMGPSScanImp.pas.bk","15910","ReSortFileName","","ReSortFileName(DisplayPath);"
[V],"TCB_IMGPSScanX.Set_language","CB_IMGPSScanImp.pas.bk","16085","FileExists","","if FileExists(LngPath+'Language.lng') then"
scripts/dist/CB_IMGPSScanImp.pas.bk.scan.csv
比對新檔案
@@ -0,0 +1,36 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"Global_Or_Interface","CB_IMGPSScanImp.pas.bk","8","Scanner","","EnScan,   { for Scanner }"
[V],"Button6Click","CB_IMGPSScanImp.pas.bk","466","Scanner","","ScannerReverse : Boolean; //是否需反相"
[V],"initkscan","CB_IMGPSScanImp.pas.bk","698","initkscan","","Procedure initkscan; //檢查掃描器的功能"
[V],"PageEnd","CB_IMGPSScanImp.pas.bk","873","PageEnd","","procedure PageEnd;   //掃描接收完成"
[V],"PageDone","CB_IMGPSScanImp.pas.bk","874","PageDone","","Procedure PageDone;  //掃描完成後顯示影像"
[V],"StatrTwainScan","CB_IMGPSScanImp.pas.bk","875","StatrTwainScan","","procedure StatrTwainScan;"
[V],"OnAcquire","CB_IMGPSScanImp.pas.bk","876","OnAcquire","","procedure OnAcquire( const DibHandle    : THandle;"
[V],"TCB_IMGPSScanX.NewScanBtnClick","CB_IMGPSScanImp.pas.bk","2416","StatrTwainScan","","StatrTwainScan;"
[V],"TCB_IMGPSScanX.OptionBtnClick","CB_IMGPSScanImp.pas.bk","2479","Scanner","","PatchDlg.ReverseCB.Checked := ScannerReverse;"
[V],"TCB_IMGPSScanX.PM505Click","CB_IMGPSScanImp.pas.bk","3538","StatrTwainScan","","StatrTwainScan;"
[V],"TCB_IMGPSScanX.SampleScanBtnClick","CB_IMGPSScanImp.pas.bk","4003","StatrTwainScan","","StatrTwainScan;"
[V],"TCB_IMGPSScanX.SelectScanBtnClick","CB_IMGPSScanImp.pas.bk","4096","SelectScanner","","scanner.SelectScanner;"
[V],"TCB_IMGPSScanX.SelectScanBtnClick","CB_IMGPSScanImp.pas.bk","4096","scanner.SelectScanner","","scanner.SelectScanner;"
[V],"TCB_IMGPSScanX.SelectScanBtnClick","CB_IMGPSScanImp.pas.bk","4096","Scanner","","scanner.SelectScanner;"
[V],"TCB_IMGPSScanX.AddScanBtnClick","CB_IMGPSScanImp.pas.bk","4230","StatrTwainScan","","StatrTwainScan;"
[V],"TCB_IMGPSScanX.Button3Click","CB_IMGPSScanImp.pas.bk","4293","initkscan","","//initkscan;"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4390","StatrTwainScan","","procedure TCB_IMGPSScanX.StatrTwainScan;"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4394","Scanner","","if not Scanner.IsConfigured then"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4412","Scanner.OpenSource","","Scanner.OpenSource;"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4426","Scanner.CloseSource","","Scanner.CloseSource;"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4431","OnAcquire","","Scanner.AcquireWithSourceOpen( OnAcquire, LongInt(@ScanInfo));"
[V],"TCB_IMGPSScanX.StatrTwainScan","CB_IMGPSScanImp.pas.bk","4431","Scanner.AcquireWithSourceOpen","","Scanner.AcquireWithSourceOpen( OnAcquire, LongInt(@ScanInfo));"
[V],"TCB_IMGPSScanX.OnAcquire","CB_IMGPSScanImp.pas.bk","4444","OnAcquire","","procedure TCB_IMGPSScanX.OnAcquire( const DibHandle    : THandle;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4505","Scanner","","IF ScannerReverse then"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4635","PageEnd","","PageEnd;"
[V],"Deletepage","CB_IMGPSScanImp.pas.bk","4667","PageDone","","PageDone;"
[V],"TCB_IMGPSScanX.PageDone","CB_IMGPSScanImp.pas.bk","4684","PageDone","","procedure TCB_IMGPSScanX.PageDone;"
[V],"TCB_IMGPSScanX.PageEnd","CB_IMGPSScanImp.pas.bk","4734","PageEnd","","procedure TCB_IMGPSScanX.PageEnd;"
[V],"TCB_IMGPSScanX.R_W_Scanini","CB_IMGPSScanImp.pas.bk","5264","Scanner","","ScannerReverse := ini.ReadBool('Scanner','Reverse',Def_ScannerReverse);"
[V],"TCB_IMGPSScanX.GetDefScanIni","CB_IMGPSScanImp.pas.bk","5303","Scanner","","Def_ScannerReverse := False;"
[V],"TCB_IMGPSScanX.initkscan","CB_IMGPSScanImp.pas.bk","9242","initkscan","","procedure TCB_IMGPSScanX.initkscan;"
[V],"TCB_IMGPSScanX.initkscan","CB_IMGPSScanImp.pas.bk","9245","Scanner","","if Scanner.IsConfigured then"
[V],"TCB_IMGPSScanX.initkscan","CB_IMGPSScanImp.pas.bk","9248","Scanner.OpenSource","","Scanner.OpenSource;"
[V],"TCB_IMGPSScanX.initkscan","CB_IMGPSScanImp.pas.bk","9259","Scanner.CloseSource","","Scanner.CloseSource;"
[V],"TCB_IMGPSScanX.Timer1Timer","CB_IMGPSScanImp.pas.bk","15146","initkscan","","initkscan;"
scripts/dist/CB_IMGPSScanImp.pas.bk.transp.csv
比對新檔案
@@ -0,0 +1,71 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"Global_Or_Interface","CB_IMGPSScanImp.pas.bk","25","IIS_Ftp","","SBSocket,IIS_Ftp, SBSimpleFTPS;"
[V],"Global_Or_Interface","CB_IMGPSScanImp.pas.bk","277","TElHTTPSClient","","HTTPSClient: TElHTTPSClient;"
[V],"Global_Or_Interface","CB_IMGPSScanImp.pas.bk","279","TElSimpleFTPSClient","","FTPSClient1: TElSimpleFTPSClient;"
[V],"HTTPSClientCertificateValidate","CB_IMGPSScanImp.pas.bk","348","HTTPSClientCertificateValidate","","procedure HTTPSClientCertificateValidate(Sender: TObject;"
[V],"SetFtpInfo","CB_IMGPSScanImp.pas.bk","635","SetFtpInfo","","Procedure SetFtpInfo;     //餵入FTP資訊"
[V],"FtpCaseComplete","CB_IMGPSScanImp.pas.bk","636","FtpCaseComplete","","Function FtpCaseComplete(SendData:String):Boolean;"
[V],"LoadFileGetMD5","CB_IMGPSScanImp.pas.bk","899","LoadFileGetMD5","","function LoadFileGetMD5(const filename:string):string; //20170809 å–的檔案的MD5"
[V],"TCB_IMGPSScanX.InitExistImgList","CB_IMGPSScanImp.pas.bk","1352","LoadFileGetMD5","","LogFile1.LogToFile(logTimeString+casepath+'Download\'+ST1.Strings[i]+',MD5='+LoadFileGetMD5(casepath+'Download\'+ST1.Strings[i]));"
[V],"TCB_IMGPSScanX.SampleScanBtnClick","CB_IMGPSScanImp.pas.bk","4021","upFile","","if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',SamplePath+SampleFormID+'.tif',FReWrite,Memo1,False) then"
[V],"TCB_IMGPSScanX.Button5Click","CB_IMGPSScanImp.pas.bk","4373","SetFtpInfo","","SetFtpInfo;"
[V],"TCB_IMGPSScanX.Button5Click","CB_IMGPSScanImp.pas.bk","4374","IIS_Ftp","","IIS_Ftp.FtpsConnect;"
[V],"TCB_IMGPSScanX.Button6Click","CB_IMGPSScanImp.pas.bk","4382","SetFtpInfo","","SetFtpInfo;"
[V],"TCB_IMGPSScanX.Button6Click","CB_IMGPSScanImp.pas.bk","4383","IIS_Ftp","","IIS_Ftp.FtpsConnect;"
[V],"TCB_IMGPSScanX.ExportBtClick","CB_IMGPSScanImp.pas.bk","4958","En_DecryptionStr_Base64","","SFileName := En_DecryptionStr_Base64('E','MPSLIC_SCAN.lic','9338430');"
[V],"TCB_IMGPSScanX.ExportBtClick","CB_IMGPSScanImp.pas.bk","4968","dnFile","","//if not dnFile(HTTPSClient,Furl,'servlet/CWC03',SendData,LngPath+SFileName,FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.ExportBtClick","CB_IMGPSScanImp.pas.bk","4970","dnFile_Get","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+SFileName,FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5045","En_DecryptionStr_Base64","","if (En_DecryptionStr_Base64('D',S.Strings[0],'9338430')<> ServerDate) then"
[V],"TCB_IMGPSScanX.ImportBtClick","CB_IMGPSScanImp.pas.bk","5058","upFile","","//if not upFile(HTTPSClient,FUrl,'servlet/CWC04','formid='+LicName+'@workno=CW@mode=sample','file',ZipPath+LicName,FReWrite,Memo1,False) then"
[V],"TCB_IMGPSScanX.HTTPSClientCertificateValidate","CB_IMGPSScanImp.pas.bk","5473","HTTPSClientCertificateValidate","","procedure TCB_IMGPSScanX.HTTPSClientCertificateValidate(Sender: TObject;"
[V],"TCB_IMGPSScanX.GetServerDate","CB_IMGPSScanImp.pas.bk","5603","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/servertimeforocx','',FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSampleInf","CB_IMGPSScanImp.pas.bk","5637","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/serversampleforocx','work_no='+FWork_no,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf1","CB_IMGPSScanImp.pas.bk","5674","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf1","CB_IMGPSScanImp.pas.bk","5679","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=1&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf2","CB_IMGPSScanImp.pas.bk","5716","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf2","CB_IMGPSScanImp.pas.bk","5719","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=2&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf3","CB_IMGPSScanImp.pas.bk","5755","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf3","CB_IMGPSScanImp.pas.bk","5759","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=3&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf4","CB_IMGPSScanImp.pas.bk","5796","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf4","CB_IMGPSScanImp.pas.bk","5799","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=4&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf5","CB_IMGPSScanImp.pas.bk","5836","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf5","CB_IMGPSScanImp.pas.bk","5839","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=5&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf6","CB_IMGPSScanImp.pas.bk","5876","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf6","CB_IMGPSScanImp.pas.bk","5879","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=6&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.GetSetInf7","CB_IMGPSScanImp.pas.bk","5916","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetSetInf7","CB_IMGPSScanImp.pas.bk","5919","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=7&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.ImageReSize_FormID","CB_IMGPSScanImp.pas.bk","6388","LoadFileGetMD5","","if (ISExistImg(ImageSavePath+CaseID+'\Upload\'+FileName)) and (reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\Upload\'+FileName))=-1) then"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6656","upFile","","if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/caseupload',SendData,'file',Path+'Img.zip',FReWrite,Memo1,False) then"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6680","SetFtpInfo","","SetFtpInfo;"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6682","IIS_Ftp","","if not IIS_Ftp.FtpsConnect then"
[V],"TCB_IMGPSScanX.TransCaseID","CB_IMGPSScanImp.pas.bk","6695","FtpCaseComplete","","if not FtpCaseComplete(SendData) then    //Ftp上傳後通知完成"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6838","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.GetNode2Name","CB_IMGPSScanImp.pas.bk","6840","dnFile","","if not dnFile(HTTPSClient,DownUrl,'','',DPath+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.DownLoadImage","CB_IMGPSScanImp.pas.bk","6959","SetFtpInfo","","SetFtpInfo;"
[V],"TCB_IMGPSScanX.DownLoadImage","CB_IMGPSScanImp.pas.bk","6961","IIS_Ftp","","if not IIS_Ftp.FtpsConnect then"
[V],"TCB_IMGPSScanX.Down_Img","CB_IMGPSScanImp.pas.bk","6987","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TCB_IMGPSScanX.Down_Img","CB_IMGPSScanImp.pas.bk","6991","dnFile_Get","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.Down_Img","CB_IMGPSScanImp.pas.bk","6991","dnFile","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.DistinctDocinCase","CB_IMGPSScanImp.pas.bk","7323","LoadFileGetMD5","","if (ISExistImg(Path+S.Strings[i])) or (reSizeExistImgList.IndexOf(LoadFileGetMD5(Path+S.Strings[i]))<>-1)  then"
[V],"TCB_IMGPSScanX.LoadFileGetMD5","CB_IMGPSScanImp.pas.bk","9551","LoadFileGetMD5","","function TCB_IMGPSScanX.LoadFileGetMD5(const filename: string): string;"
[V],"TCB_IMGPSScanX.LoadFileGetMD5","CB_IMGPSScanImp.pas.bk","9558","TIdHashMessageDigest5","","idmd5:TIdHashMessageDigest5;  //import IdHashMessageDigest, idHash"
[V],"TCB_IMGPSScanX.CheckAvailable","CB_IMGPSScanImp.pas.bk","9835","dnFile_Get","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.CheckAvailable","CB_IMGPSScanImp.pas.bk","9835","dnFile","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.CheckAvailable","CB_IMGPSScanImp.pas.bk","9891","upFile","","if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False) then"
[V],"TCB_IMGPSScanX.TransOldCaseFile","CB_IMGPSScanImp.pas.bk","10910","upFile","","if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/useOther',SendData,'file',OldCasePath+'UseCase.ini',FReWrite,Memo1,False) then"
[V],"DecodeFtpInfo","CB_IMGPSScanImp.pas.bk","10976","En_DecryptionStr_Base64","","FtpStr := En_DecryptionStr_Base64('D',EncryStr,MpsKey);"
[V],"DecodeFtpInfo","CB_IMGPSScanImp.pas.bk","10994","ProcessServlet_FormData","","If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/ftps',SendData,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.SetFtpInfo","CB_IMGPSScanImp.pas.bk","11042","SetFtpInfo","","Procedure TCB_IMGPSScanX.SetFtpInfo;     //餵入FTP資訊"
[V],"TCB_IMGPSScanX.SetFtpInfo","CB_IMGPSScanImp.pas.bk","11044","IIS_Ftp","","IIS_Ftp.Display1 := Display1;"
[V],"TCB_IMGPSScanX.FtpCaseComplete","CB_IMGPSScanImp.pas.bk","11072","FtpCaseComplete","","Function TCB_IMGPSScanX.FtpCaseComplete(SendData:String):Boolean;"
[V],"TCB_IMGPSScanX.FtpCaseComplete","CB_IMGPSScanImp.pas.bk","11075","ProcessServlet_FormData","","If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/caseupload',SendData,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.ISExistImg","CB_IMGPSScanImp.pas.bk","11359","LoadFileGetMD5","","if ExistImgList.IndexOf(LoadFileGetMD5(filename))<>-1 then"
[V],"TCB_IMGPSScanX.DistinctFormCode","CB_IMGPSScanImp.pas.bk","12222","LoadFileGetMD5","","LogFile1.LogToFile(logTimeString+S.Strings[i]+' reSizeExistImgList='+BoolToStr(reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))<>-1,true));"
[V],"TCB_IMGPSScanX.DownLanguage","CB_IMGPSScanImp.pas.bk","13062","dnFile","","//dnFile(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite.Text,Memo1,False,DownImgStatus)"
[V],"TCB_IMGPSScanX.DownLanguage","CB_IMGPSScanImp.pas.bk","13063","dnFile_Get","","If not dnFile_Get(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite,Memo1,False,DownImgStatus) Then"
[V],"TCB_IMGPSScanX.GetOMRCheckSet","CB_IMGPSScanImp.pas.bk","14527","dnFile_Get","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,CheckXmlPath+'OMRSet.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.GetOMRCheckSet","CB_IMGPSScanImp.pas.bk","14527","dnFile","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,CheckXmlPath+'OMRSet.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.GetKeyinSet","CB_IMGPSScanImp.pas.bk","14585","dnFile_Get","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,SitePath+'KeyinSet.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.GetKeyinSet","CB_IMGPSScanImp.pas.bk","14585","dnFile","","if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,SitePath+'KeyinSet.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TCB_IMGPSScanX.CaseAsk","CB_IMGPSScanImp.pas.bk","14634","ProcessServlet_Get","","If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC05/isnew',SendData,FReWrite,Memo1,False) Then"
[V],"TCB_IMGPSScanX.CaseComplete","CB_IMGPSScanImp.pas.bk","14689","En_DecryptionStr_Base64","","EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
scripts/dist/CB_IMGPSScanImp.remaining.txt
比對新檔案
@@ -0,0 +1,1051 @@
[1] unit CB_IMGPSScanImp;
[2] //TEST
[3] {$WARN SYMBOL_PLATFORM OFF}
[4]
[5] interface
[6]
[7] uses
[8]   EnScan,   { for Scanner }
[9]   EnDiGrph, { for TDibGraphic }
[10]   EnMisc,   { for MinFloat }
[11]   EnTifGr,  { for TTifGraphic }
[12]   {$IFDEF Production}
[13]   CB_IMGPSScan_TLB,
[14]   {$ENDIF}
[15]   {$IFDEF Test}
[16]   CB_IMGPSScan_test_TLB,
[17]   {$ENDIF}
[18]
[19]   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
[20]   ActiveX, AxCtrls, StdVcl, VCLUnZip, VCLZip, Encryp,
[21]   ExtCtrls, ComCtrls, Menus, StdCtrls, Gauges, EnImgScr, PJMenuSpeedButtons,
[22]   Buttons, ImgList, SBSimpleSSL, SBHTTPSClient, SBWinCertStorage, SBX509,
[23]   SBCustomCertStorage, SBUtils,mpsBarco,BarcodesFinder,HTTPApp,ErrList,
[24]   Xmltool,inifiles,printers,IdHashMessageDigest, idHash, LogFile,ShellApi,
[25]   SBSocket,IIS_Ftp, SBSimpleFTPS;
[26] Type
[27]   TTransMode =(tsHttp,tsFtp,tsNone);
[28]
[29] var
[30]   Ch_WriteNote : Boolean;
[31]   RejectCase : Boolean;
[32]   ErrIndex : Integer;
[33]
[34]   //*****預設區*****//
[35]     Def_DeviceDelete : Boolean;  //空白頁刪除啟動
[36]     Def_DeviceDeleteSize : Integer;  //空白頁Size
[37]     Def_ScannerReverse : Boolean; //是否需反相
[38]     Def_BoardClear : Boolean; //是否清黑邊
[39]     Def_ScanDpi : Integer;    //掃瞄DPI
[40]     Def_ScanDuplex : Boolean; //是否雙面掃瞄
[41]     Def_ScanRotate : Integer; //掃瞄時旋轉角度
[42]     Def_ScanDeskew : Boolean; //是否傾斜矯正
[43]     Def_ScanBright : Integer; //亮度
[44]     Def_ScanContrast : Integer; //對比
[45]     Def_ScanImgShowMode : Integer; //0:清楚影像 1:不清楚影像 2:不顯示
[46]     Def_ScanImgSetUse : Boolean; //是否使用亮度對比設定
[47]   //*****預設區*****//
[48]
[49] Const
[50]   ISBName = 'PreViewISB';
[51]
[52] {獲取自身版本號所需要 }
[53] type
[54]   TVersionLanguage = (vlArabic, vlBulgarian, vlCatalan, vlTraditionalChinese,
[55]      vlCzech, vlDanish, vlGerman, vlGreek, vlUSEnglish, vlCastilianSpanish,
[56]      vlFinnish, vlFrench, vlHebrew, vlHungarian, vlIcelandic, vlItalian,
[57]      vlJapanese, vlKorean, vlDutch, vlNorwegianBokmel, vlPolish,
[58]      vlBrazilianPortuguese, vlRhaetoRomanic, vlRomanian, vlRussian,
[59]      vlCroatoSerbian, vlSlovak, vlAlbanian, vlSwedish, vlThai, vlTurkish,
[60]      vlUrdu, vlBahasa, vlSimplifiedChinese, vlSwissGerman, vlUKEnglish,
[61]      vlMexicanSpanish, vlBelgianFrench, vlSwissItalian, vlBelgianDutch,
[62]      vlNorwegianNynorsk, vlPortuguese, vlSerboCroatian, vlCanadianFrench,
[63]      vlSwissFrench, vlUnknown);
[64]
[65] const LanguageValues: array[TVersionLanguage] of Word = ($0401, $0402, $0403,
[66]    $0404, $0405, $0406, $0407, $0408, $0409, $040A, $040B, $040C, $040D,
[67]    $040E, $040F, $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417,
[68]    $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F, $0420, $0421,
[69]    $0804, $0807, $0809, $080A, $080C, $0810, $0813, $0814, $0816, $081A,
[70]    $0C0C, $100C, $0000);
[71] {獲取自身版本號所需要 end}
[72]
[73]
[74] type
[75]   TScanMode = (smNew, smReplace, smInsert, smSample, smRTS);
[76]   TpScanInfo = ^TScanInfo;
[77]   TScanInfo = record
[78]     MultiPage  : Boolean;
[79]     { supplementary info when MultiPage is True }
[80]     Graphic    : TTiffGraphic;
[81]     Stream     : TFileStream;
[82]     ImageCount : LongInt;
[83]   end;
[84]   TOMRErrInfo = record
[85]     Display : Boolean;  //是否顯示
[86]     Ignore : Boolean; //可否刪除
[87]     Info : String;
[88]     Mode : String;
[89]   end;
[90]   TScrollRec = Record
[91]     HScroll : Integer;
[92]     VScroll : Integer;
[93]     Rate    : Single;
[94]   end;
[95]
[96] type
[97]   TCB_IMGPSScanX = class(TActiveForm, ICB_IMGPSScanX)
[98]     Panel1: TPanel;
[99]     TransBtn: TBitBtn;
[100]     Panel21: TPanel;
[101]     ViewModeBtn: TPJMenuSpeedButton;
[102]     Button2: TButton;
[103]     Button1: TButton;
[104]     OptionBtn: TBitBtn;
[105]     SelectScanBtn: TBitBtn;
[106]     NextPageBtn: TBitBtn;
[107]     PrePageBtn: TBitBtn;
[108]     FC6: TBitBtn;
[109]     FC5: TBitBtn;
[110]     FC4: TBitBtn;
[111]     FC3: TBitBtn;
[112]     FC2: TBitBtn;
[113]     FC1: TBitBtn;
[114]     FC0: TBitBtn;
[115]     Panel23: TPanel;
[116]     PJLinkedMenuSpeedButton2: TPJLinkedMenuSpeedButton;
[117]     NewScanBtn: TBitBtn;
[118]     AddScanBtn: TBitBtn;
[119]     Panel4: TPanel;
[120]     Panel2: TPanel;
[121]     Splitter1: TSplitter;
[122]     Panel3: TPanel;
[123]     Label7: TLabel;
[124]     Panel6: TPanel;
[125]     CB1: TCheckBox;
[126]     ScanDuplexCB: TCheckBox;
[127]     ScanFlatCB: TCheckBox;
[128]     Panel18: TPanel;
[129]     Panel12: TPanel;
[130]     Panel7: TPanel;
[131]     Panel9: TPanel;
[132]     Shape1: TShape;
[133]     ImageScrollBox1: TImageScrollBox;
[134]     imgp8: TPanel;
[135]     lb8: TLabel;
[136]     ISB8: TImageScrollBox;
[137]     imgp7: TPanel;
[138]     lb7: TLabel;
[139]     ISB7: TImageScrollBox;
[140]     imgp6: TPanel;
[141]     lb6: TLabel;
[142]     ISB6: TImageScrollBox;
[143]     imgp5: TPanel;
[144]     lb5: TLabel;
[145]     ISB5: TImageScrollBox;
[146]     imgp4: TPanel;
[147]     lb4: TLabel;
[148]     ISB4: TImageScrollBox;
[149]     imgp3: TPanel;
[150]     lb3: TLabel;
[151]     ISB3: TImageScrollBox;
[152]     imgp2: TPanel;
[153]     lb2: TLabel;
[154]     ISB2: TImageScrollBox;
[155]     imgp1: TPanel;
[156]     lb1: TLabel;
[157]     Memo1: TMemo;
[158]     Display1: TMemo;
[159]     Panel22: TPanel;
[160]     Panel8: TPanel;
[161]     Label2: TLabel;
[162]     Gauge1: TGauge;
[163]     ScrollBar1: TScrollBar;
[164]     Panel10: TPanel;
[165]     PageLV: TListView;
[166]     StatusBar1: TStatusBar;
[167]     ImageList4: TImageList;
[168]     ImageList3: TImageList;
[169]     ImageList1: TImageList;
[170]     PopupMenu2: TPopupMenu;
[171]     mode1: TMenuItem;
[172]     mode2: TMenuItem;
[173]     mode3: TMenuItem;
[174]     mode4: TMenuItem;
[175]     N51: TMenuItem;
[176]     ImageList2: TImageList;
[177]     OpenDialog1: TOpenDialog;
[178]     PopupMenu3: TPopupMenu;
[179]     PM301: TMenuItem;
[180]     PM302: TMenuItem;
[181]     PM303: TMenuItem;
[182]     Timer1: TTimer;
[183]     TomEncryption1: TTomEncryption;
[184]     SaveDialog1: TSaveDialog;
[185]     Timer2: TTimer;
[186]     VCLZip1: TVCLZip;
[187]     PopupMenu4: TPopupMenu;
[188]     PM401: TMenuItem;
[189]     PM402: TMenuItem;
[190]     PM403: TMenuItem;
[191]     PM404: TMenuItem;
[192]     ElWinCertStorage: TElWinCertStorage;
[193]     ElMemoryCertStorage: TElMemoryCertStorage;
[194]     Panel5: TPanel;
[195]     AddCredit1RG: TRadioGroup;
[196]     Panel11: TPanel;
[197]     SampleScanBtn: TBitBtn;
[198]     WNoteBtn: TBitBtn;
[199]     PopupMenu1: TPopupMenu;
[200]     PM101: TMenuItem;
[201]     N12: TMenuItem;
[202]     PM102: TMenuItem;
[203]     MenuItem1: TMenuItem;
[204]     PM103: TMenuItem;
[205]     PM104: TMenuItem;
[206]     N7: TMenuItem;
[207]     PM106: TMenuItem;
[208]     PM107: TMenuItem;
[209]     PM108: TMenuItem;
[210]     PM109: TMenuItem;
[211]     PopupMenu5: TPopupMenu;
[212]     PM501: TMenuItem;
[213]     PM502: TMenuItem;
[214]     PM503: TMenuItem;
[215]     PM504: TMenuItem;
[216]     N5: TMenuItem;
[217]     PM505: TMenuItem;
[218]     PM506: TMenuItem;
[219]     N29: TMenuItem;
[220]     PM510: TMenuItem;
[221]     PM509: TMenuItem;
[222]     PM507: TMenuItem;
[223]     N15: TMenuItem;
[224]     PM508: TMenuItem;
[225]     ExportBt: TButton;
[226]     ImportBt: TButton;
[227]     CheckCaseBtn: TBitBtn;
[228]     DenialTimeLb: TLabel;
[229]     Panel14: TPanel;
[230]     ScrollBox1: TScrollBox;
[231]     Label1: TLabel;
[232]     Button3: TButton;
[233]     Panel15: TPanel;
[234]     Button4: TButton;
[235]     PopupMenu6: TPopupMenu;
[236]     PM602: TMenuItem;
[237]     PM601: TMenuItem;
[238]     PM605: TMenuItem;
[239]     PM603: TMenuItem;
[240]     PM604: TMenuItem;
[241]     N8: TMenuItem;
[242]     Panel16: TPanel;
[243]     SpeedButton3: TSpeedButton;
[244]     SpeedButton14: TSpeedButton;
[245]     SpeedButton15: TSpeedButton;
[246]     SpeedButton16: TSpeedButton;
[247]     SpeedButton17: TSpeedButton;
[248]     SpeedButton18: TSpeedButton;
[249]     SpeedButton19: TSpeedButton;
[250]     SpeedButton20: TSpeedButton;
[251]     SpeedButton21: TSpeedButton;
[252]     SpeedButton22: TSpeedButton;
[253]     Edit1: TEdit;
[254]     PM110: TMenuItem;
[255]     Image1: TImage;
[256]     UseOldCaseLb: TLabel;
[257]     PM111: TMenuItem;
[258]     SmoothCB: TCheckBox;
[259]     ISB_BW: TImageScrollBox;
[260]     N1: TMenuItem;
[261]     N2: TMenuItem;
[262]     ISB1: TImageScrollBox;
[263]     Label3: TLabel;
[264]     LogFile1: TLogFile;
[265]     ScanGrayCB: TCheckBox;
[266]     AttFileGB: TGroupBox;
[267]     AttListBox: TListBox;
[268]     Panel20: TPanel;
[269]     AddAttFileLB: TLabel;
[270]     DelAttFileLB: TLabel;
[271]     Splitter2: TSplitter;
[272]     Panel17: TPanel;
[273]     TreeView1: TTreeView;
[274]     Panel13: TPanel;
[275]     PrtLb: TLabel;
[276]     CaseHelpBtn: TBitBtn;
[277]     HTTPSClient: TElHTTPSClient;
[278]     Button5: TButton;
[279]     FTPSClient1: TElSimpleFTPSClient;
[280]     Button6: TButton;
[281]     procedure ActiveFormCreate(Sender: TObject);
[282]     procedure Panel9Resize(Sender: TObject);
[283]     procedure ISB1Click(Sender: TObject);
[284]     procedure WNoteBtnClick(Sender: TObject);
[285]     procedure CaseHelpBtnClick(Sender: TObject);
[286]     procedure FC0Click(Sender: TObject);
[287]     procedure FC1Click(Sender: TObject);
[288]     procedure FC2Click(Sender: TObject);
[289]     procedure FC3Click(Sender: TObject);
[290]     procedure FC4Click(Sender: TObject);
[291]     procedure FC5Click(Sender: TObject);
[292]     procedure FC6Click(Sender: TObject);
[293]     procedure PrePageBtnClick(Sender: TObject);
[294]     procedure NextPageBtnClick(Sender: TObject);
[295]     procedure OptionBtnClick(Sender: TObject);
[296]     procedure SelectScanBtnClick(Sender: TObject);
[297]     procedure mode1Click(Sender: TObject);
[298]     procedure mode2Click(Sender: TObject);
[299]     procedure mode3Click(Sender: TObject);
[300]     procedure mode4Click(Sender: TObject);
[301]     procedure N51Click(Sender: TObject);
[302]     procedure ScrollBar1Change(Sender: TObject);
[303]     procedure ISB1EndScroll(Sender: TObject);
[304]     procedure ISB1ImageMouseDown(Sender: TObject; Button: TMouseButton;
[305]       Shift: TShiftState; X, Y: Integer);
[306]     procedure ISB1ImageMouseMove(Sender: TObject; Shift: TShiftState; X,
[307]       Y: Integer);
[308]     procedure ISB1ImageMouseUp(Sender: TObject; Button: TMouseButton;
[309]       Shift: TShiftState; X, Y: Integer);
[310]     procedure PM508Click(Sender: TObject);
[311]     procedure PM401Click(Sender: TObject);
[312]     procedure PM402Click(Sender: TObject);
[313]     procedure PM403Click(Sender: TObject);
[314]     procedure PM404Click(Sender: TObject);
[315]     procedure TreeView1Click(Sender: TObject);
[316]     procedure NewScanBtnClick(Sender: TObject);
[317]     procedure AddScanBtnClick(Sender: TObject);
[318]     procedure PageLVClick(Sender: TObject);
[319]     procedure PageLVKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
[320]     procedure PageLVMouseDown(Sender: TObject; Button: TMouseButton;
[321]       Shift: TShiftState; X, Y: Integer);
[322]     procedure PM101Click(Sender: TObject);
[323]     procedure PM104Click(Sender: TObject);
[324]     procedure PM102Click(Sender: TObject);
[325]     procedure PM103Click(Sender: TObject);
[326]     procedure PM106Click(Sender: TObject);
[327]     procedure PM107Click(Sender: TObject);
[328]     procedure PM108Click(Sender: TObject);
[329]     procedure PM109Click(Sender: TObject);
[330]     procedure PM301Click(Sender: TObject);
[331]     procedure PM302Click(Sender: TObject);
[332]     procedure PM303Click(Sender: TObject);
[333]     procedure PM501Click(Sender: TObject);
[334]     procedure PM502Click(Sender: TObject);
[335]     procedure PM503Click(Sender: TObject);
[336]     procedure PM504Click(Sender: TObject);
[337]     procedure PM505Click(Sender: TObject);
[338]     procedure PM510Click(Sender: TObject);
[339]     procedure PM509Click(Sender: TObject);
[340]     procedure PM507Click(Sender: TObject);
[341]     procedure PopupMenu1Popup(Sender: TObject);
[342]     procedure PopupMenu4Popup(Sender: TObject);
[343]     procedure PopupMenu5Popup(Sender: TObject);
[344]     procedure SampleScanBtnClick(Sender: TObject);
[345]     procedure StatusBar1DblClick(Sender: TObject);
[346]     procedure ExportBtClick(Sender: TObject);
[347]     procedure ImportBtClick(Sender: TObject);
[348]     procedure HTTPSClientCertificateValidate(Sender: TObject;
[349]       X509Certificate: TElX509Certificate; var Validate: Boolean);
[350]     procedure ScanDuplexCBClick(Sender: TObject);
[351]     procedure CheckCaseBtnClick(Sender: TObject);
[352]     procedure Timer1Timer(Sender: TObject);
[353]     procedure Timer2Timer(Sender: TObject);
[354]     procedure TransBtnClick(Sender: TObject);
[355]     procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
[356]     procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
[357]       State: TDragState; var Accept: Boolean);
[358]     procedure TreeView1KeyUp(Sender: TObject; var Key: Word;
[359]       Shift: TShiftState);
[360]     procedure TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
[361]       Shift: TShiftState; X, Y: Integer);
[362]     procedure ViewModeBtnMouseEnter(Sender: TObject);
[363]     procedure Button3Click(Sender: TObject);
[364]     procedure AddCredit1RGClick(Sender: TObject);
[365]     procedure CB1Click(Sender: TObject);
[366]     procedure Button4Click(Sender: TObject);
[367]     procedure ISB1Enter(Sender: TObject);
[368]     procedure TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,
[369]       Y: Integer);
[370]     procedure PM601Click(Sender: TObject);
[371]     procedure PopupMenu6Popup(Sender: TObject);
[372]     procedure PM604Click(Sender: TObject);
[373]     procedure PM605Click(Sender: TObject);
[374]     procedure SpeedButton3Click(Sender: TObject);
[375]     procedure SpeedButton14Click(Sender: TObject);
[376]     procedure SpeedButton15Click(Sender: TObject);
[377]     procedure SpeedButton16Click(Sender: TObject);
[378]     procedure SpeedButton17Click(Sender: TObject);
[379]     procedure SpeedButton18Click(Sender: TObject);
[380]     procedure SpeedButton19Click(Sender: TObject);
[381]     procedure SpeedButton20Click(Sender: TObject);
[382]     procedure SpeedButton21Click(Sender: TObject);
[383]     procedure SpeedButton22Click(Sender: TObject);
[384]     procedure ActiveFormKeyUp(Sender: TObject; var Key: Word;
[385]       Shift: TShiftState);
[386]     procedure PM110Click(Sender: TObject);
[387]     procedure PM602Click(Sender: TObject);
[388]     procedure PrtLbClick(Sender: TObject);
[389]     procedure Panel1DblClick(Sender: TObject);
[390]     procedure Panel11DblClick(Sender: TObject);
[391]     procedure UseOldCaseLbClick(Sender: TObject);
[392]     procedure PM111Click(Sender: TObject);
[393]     procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
[394]     procedure SmoothCBClick(Sender: TObject);
[395]     procedure N1Click(Sender: TObject);
[396]     procedure TreeView1MouseEnter(Sender: TObject);
[397]     procedure ScrollBox1MouseEnter(Sender: TObject);
[398]     procedure ScanGrayCBClick(Sender: TObject);
[399]     procedure AddAttFileLBClick(Sender: TObject);
[400]     procedure DelAttFileLBClick(Sender: TObject);
[401]     procedure AttListBoxDblClick(Sender: TObject);
[402]     procedure AttListBoxClick(Sender: TObject);
[403]     procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
[404]       Shift: TShiftState; X, Y: Integer);
[405]     procedure HTTPSClientRedirection(Sender: TObject; const OldURL: string;
[406]       var NewURL: string; var AllowRedirection: Boolean);
[407]     procedure Button5Click(Sender: TObject);
[408]     procedure Button6Click(Sender: TObject);
[409]   private
[410]     { Private declarations }
[411]     HotKeyId1,HotKeyId2,HotKeyId3,HotKeyId4 :Integer;
[412]
[413]     ////////傳入參數/////////
[414]     FUrl : String;
[415]     FCaseID : String;
[416]     FMode : String;        //NSCAN:新件;ESCAN:修改 20170306 DSCAN:被配合待掃瞄清單使用
[417]     FModeName : String;
[418]     FWork_no : String;
[419]     FUserID : String;
[420]     FUserName : String;
[421]     FUserUnit : String;
[422]     FData : String;
[423]     FVerify : String;
[424]     FReWrite : String;
[425]     FLanguage : String;
[426]     FLoanDoc_Value : String; //新增授信卷的值
[427]     FLoanDoc_Enable : String; //新增授信卷是否可異動
[428]     FUseProxy : String; //是否使用Proxy
[429]     FC_DocNoList : String; //外面傳來要新增的文件編號
[430]     FC_DocNameList : String; //外面傳來要新增的自訂文件
[431]     FFixFileList : String; //要鎖住的檔名
[432]     FIs_In_Wh : String; //是否只顯示入庫文件  (Y:只顯示入庫 N:只顯示非入庫 空白:都顯示)
[433]     FOldCaseInfo : String; //舊件資訊  CaseID_year[tab]CaseID_year
[434]     FPrintyn : String; //是否可列印
[435]     FIs_OldCase : String; //是否是舊案第一次進入
[436]     FCustDocYN : String; //是否可自訂文件
[437]     //20170222 新增
[438]     FImgDPI:integer;//DPI  依業務別決定 150~~1200  預設300
[439]     FScanColor:integer;///掃瞄色彩  依業務別決定   0 :黑白  1:灰階   2:彩色 預設黑白
[440]     FFileSizeLimit:integer;//匯入單一檔案大小限  依業務別決定  以KB為單位  預設5*1024kb
[441]     FCaseNoLength:integer;//案件編號長度檢查  依業務別決定   無預設  一定要傳入
[442]     FImgDelete:string; // Y/N  有權限可在補件時刪除影像
[443]     FIsExternal:string;//Y/N
[444]     FCheck_main_form:string; //Y/N
[445]     FWH_category:string;  //Y/N  Y是歸類時有區分入庫非入庫文件  N 是不區分
[446]     ////////傳入參數///////
[447]
[448]     TransMode : TTransMode;   //用何種方式上傳檔案
[449]     //********Http參數********
[450]     HttpErrStr : String; //錯誤訊息
[451]     //********Http參數********
[452]
[453]     //********Ftp參數*********
[454]     FFtpIP : String;
[455]     FFtpID : String;
[456]     FFtpPwd : String;
[457]     FFtpRootPath : String;
[458]     FFtpExtraPath : String;
[459]     FFtpPort : Integer;
[460]     FFtpProtocol : TFtpProtocol;
[461]     //********Ftp參數*********
[462]
[463]     //********ini參數********
[464]     DeviceDelete : Boolean;     //空白頁刪除啟動
[465]     DeviceDeleteSize : Integer;  //空白頁Size
[466]     ScannerReverse : Boolean; //是否需反相
[467]     BoardClear : Boolean; //是否清黑邊
[468]     ScanDpi : Integer;    //掃瞄DPI
[469]     ScanDuplex : Boolean; //是否雙面掃瞄
[470]     ScanRotate : Integer; //掃瞄時旋轉角度
[471]     ScanDeskew : Boolean; //是否傾斜矯正
[472]     ScanBright : Integer; //亮度
[473]     ScanContrast : Integer; //對比
[474]     ScanImgShowMode : Integer; //0:清楚影像 1:不清楚影像 2:不顯示
[475]     ScanImgSetUse : Boolean; //是否使用亮度對比設定
[476]
[477]     //********ini參數********
[478]     ScanColor : TImageFormat;
[479]
[480]     //********時間********
[481]     ServerDate : String;
[482]     ServerTime : String;
[483]     Balance : Longint; //local跟server的時間差
[484]     ScanDenialTime : String; //停止進件時間
[485]     //********時間********
[486]     ScanDenialHint : String; //掃描顯示提醒字串
[487]
[488]     //********路徑********
[489]     ScanPath : String;       // SpecifyDir\Workid\userunit\mode
[490]     ImagePath : String;      // SpecifyDir\Workid\userunit\mode
[491]     ImageSavePath : String;   // ImagePath\
[492]     ScaniniPath : String;    // SpecifyDir\Workid\userunit\
[493]     LngPath :String;         //多國語言檔目錄
[494]     CheckXmlPath : String;   //檢核用的Xml存放目錄
[495]     SitePath : String;      //登打位置(切簽名用)
[496]     SamplePath : String;     //範本目錄
[497]     TransPath : String;     //檔案上傳的路徑(補充件會多一層目錄)
[498]     //********路徑********
[499]     ScanSaveFilename : String; //掃瞄的檔名
[500]     ScanCaseno : String;  //掃瞄時的案號
[501]     ScanDocDir : String;  //掃描時的文件代號目錄
[502]     //********清單區********
[503]     Doc_Inf_List : TStringList;  //Doc_Inf 清單
[504]     DM_FORM_INF_List :TstringList;  //DM_FORM_INF 清單
[505]     FORM_INF_List : TStringList; //FORM_INF的清單
[506]     CHECK_RULE_INF_List : TStringList;  //CHECK_RULE_INF  清單
[507]     MEMO_INF_List : TStringList;  //MEMO_INF 清單
[508]     WORK_INF_List : TStringList;  //WORK_INF 清單
[509]     LASTEST_FORM_INF_List : TStringList;  // LASTEST_FORM_INF 清單
[510]
[511]     FindResult : TStringList;    //找SQLData的結果
[512]     CaseList : TStringList;    //記錄掃瞄案件的順序
[513]     Context_DocnoList : TStringlist; //案件裡的Docno清單
[514]     CaseDocNoList : TStringlist;  //案件裡的DocNo清單(不重複)
[515]     CaseDocNo_CopiesList : TStringlist; //案件裡的DocNo份數清單
[516]     ContextList : TStringlist; //案件裡的檔案清單
[517]     AttContextList : TStringlist; //案件裡的附加檔案清單
[518]     OMRFileList : TStringList; //要OMR檢核的文件(只檢查每種Form的第一頁)
[519]     Cust_DocNoList : TStringlist; //自行定義文件名稱
[520]     IN_WH_DocNoList : TStringlist; //入庫的文件清單
[521]
[522]     FormCode_PageSize : TStringList; //文件的預設大小  FormCode_Height_Width
[523]     DocNo_NeedDoc : TStringList; //有Docno時要相依的文件   DocNo_相依文件_相依文件
[524]     DocNo_NoDoc : TstringList; //有Docno時互斥的文件   DocNo_互斥文件_互斥文件
[525]     DocNo_VerinCase : TStringlist; //案件裡的DocNo+版本的清單
[526]
[527]     NoSaveBarCodeList : TStringlist; //不儲存的條碼清單
[528]     FormID_List : TStringlist;    //FormID 清單  20130403 因為原FormCode2Docno會很慢..把FormID抽出來
[529]     DocNo_List : TStringlist;     //DocNo 清單  20130403 因為原FormCode2Docno會很慢..把DocNo抽出來
[530]     NowShowFileList : TStringlist;  //目前顯示的影像清單
[531]     NowSelectFileList : TStringlist; //目前被點選的影像清單
[532]     GuideFormIDList : TStringlist; //要當導引頁表單清單
[533]     DivPageFormIDList:TStringlist; //要當分案頁表單清單
[534]     LastInitFormidList:TStringList;
[535]     LastAddFormidList:TstringList;
[536]     SampleFormIDList:TStringList; //20170627 已存在範本的formid
[537]     ExistImgList:TStringList;  //20170724  已經存在的影像list for ESCAN  //Img的完整路徑
[538]     reSizeExistImgList:TstringList; //20171012被縮放的舊圖MD5存入
[539]     //********清單區********
[540]
[541]     //********顯示區********
[542]     NowCaseno : String; //目前顯示的案件編號
[543]     NowDocNo : String;  //目前的文件編號
[544]     NowDocDir : String; //目前的文件目錄
[545]     NowFormCode : String; //目前顯示的表單編號
[546]     NowFormName : String; //目前顯示的表單名稱
[547]     NowPage : Integer;   //目前點選的頁碼
[548]     DisplayPath : String; //目前顯示的目錄
[549]     //********顯示區********
[550]
[551]     //******索引資料*********
[552]     Case_loandoc : String; //是否新增授信卷
[553]     //******索引資料*********
[554]
[555]     //********十字定位點資訊********
[556]     UpLPoint : Tpoint;  //左上方的十字點
[557]     UpRPoint : Tpoint;  //右上方的十字點
[558]     DownLPoint : Tpoint;  //左下方的十字點
[559]     DownRPoint : Tpoint;  //右下方的十字點
[560]     Point_Width : String;   //十字點的寬
[561]     Point_Height : String;   //十字點的高
[562]     //********十字定位點資訊********
[563]
[564]     CaseIDLength : Integer; //案件編號長度
[565]     FormIDLength : Integer; //FormID長度
[566]     DocNoLength : Integer;  //Docno長度
[567]
[568]     PEFileName : String; //掃描時的檔名
[569]     DownFileErrStr : String;  //下載影像時發生的錯誤
[570]
[571]     ISB : TImageScrollBox;
[572]     ScanInfo    : TScanInfo;
[573]     TwainShowUI : Boolean;
[574]     MpsBarcodeinf : TMpsBarcodeinf;
[575]     ScanMode : TScanMode;
[576]     Mpskey : String;
[577]     Seg : Integer; //顯示的邊界值
[578]     VMode : Integer; //顯示的index
[579]     NowClick : Integer;   //目前點到的按鈕功能Index
[580]     ScanIP : String;  //掃瞄端的IP
[581]     DisplayISB : TImageScrollBox; //被點到的影像
[582]     SelectISB : TImageScrollBox; //被點到的縮圖
[583]     SelectPage : Integer; //被點到的頁數
[584]     NewTreeNode,MyTreeNode1,MyTreeNode2,MyTreeNode3 : TTreenode;
[585]     InitialOk : Boolean; //資訊載入是否完成
[586]     ShowText : String; //DataLoading時要秀出的訊息
[587]     Ext : String; //附檔名  .tif .jpg
[588]     SafePixel : Integer;  //OMR容忍誤差值點數
[589]     OMRErrInfo : Array[1..11] of TOMRErrInfo;  //檢核的方式及訊息
[590]     ScrollRec : Array[1..8] of TScrollRec; //瀏覽窗的Scroll記錄
[591]     RecHozPos,RecVerPos : Integer;  //記錄MPSViewX1的ScrollBar位置
[592]     ReczoomPercent : Single;
[593]     SortMode : Boolean;
[594]     PreMytreeNode2Name:String;
[595]     HS,VS : Integer;
[596]     iRate : Single;
[597]     Bt : Integer; //去直線時橫線判斷的容忍值
[598]     BarCodeRotate : Integer; //條碼要轉的角度
[599]     HaveAppDoc : Boolean; //補全時是否有補入要保書
[600]     PageLVclear : Boolean;
[601]     CaseCount,PageCount : Integer; //總案件量及總頁數
[602]     Item : TMenuItem;
[603]     SampleAnchorMode : String; //範本掃瞄十字線的模式  NONE:無;ANCHOR:十字;FRAME:邊框
[604]     DownImgStatus : String;  //下載影像的狀態(NO_DATA:沒資料;NO_FILE:沒影像)
[605]     TransForm_Field : String; //要用OMR勾選確認是否轉換FORMID的欄位名稱
[606]     NowWork_No : String; //現在的作業別
[607]     CropBarcode : String; //要切影像的條碼
[608]     Has_Authorize :String; //是否有授權書影像
[609]     AttName : String; //未歸類目錄名稱
[610]     NowGuideFormID : String;
[611]     NowDivPageFormID:String;
[612]
[613]     FirstDocDir : String;
[614]     FMaxUploadSize:String;// 上傳zip大小限制
[615]     FJpgCompression:integer;// 20171211 jpg to tif 的壓縮率
[616]
[617]     Draging : Boolean;
[618]     MDown : Boolean;  //20181210 用來判斷滑鼠右鍵要Popupmenu是否有MouseDonw發生
[619]
[620]     FEvents: ICB_IMGPSScanXEvents;
[621]
[622]     procedure HotKeyDown (var Msg : TMessage);message WM_HOTKEY;
[623]     Procedure InitialLanguage(Sender: TObject);   //畫面載入多國語言
[624]     //Function _Msg(S:String):String;
[625]
[626]     //*********SQL相關************
[627]     Procedure SetSQLData(ColumeStr:String;FromList,ToList:TStringlist); //把SQL值塞入
[628]     Function GetSQLData(TableList:TStringlist;Colname:String;colNo:Integer):String; //依欄位及索引取值
[629]     Function FindSQLData(TableList:TStringlist;ColumeStr,KeyColumeStr,KeyStr:String;ColNo:Integer;Var ResultList:TStringlist):Boolean; //找指定的資料
[630]     Function GetFindResult(Col:String):String;
[631]     //*********SQL相關************
[632]
[633]     //*********FTP相關************
[634]     Function GetFtpinfo(CaseID,Action:String):Boolean;
[635]     Procedure SetFtpInfo;     //餵入FTP資訊
[636]     Function FtpCaseComplete(SendData:String):Boolean;
[637]     //*********FTP相關************
[638]
[639]     //*******轉換區*********
[640]     Function FindDivFormCode(FormCode:String):Boolean; //找有沒有分案的條碼
[641]     Function FormCode2FormName(CaseID,FormCode:String):String; //用FormCode轉成文件名稱
[642]     Function FormCode2FileName(FormCode:String;List:TStrings):String; //用FormCode找出檔名(第一頁)
[643]     Function FileName2FormCode(FileName:String):String; //從檔名取出FormCode
[644]     Function FileName2FormName(CaseID,FileName:String):String; //從檔名取出文件名稱
[645]     Function FileName2ScanPage(FileName:String):Integer; //從檔名取出掃瞄頁數
[646]     Function FileName2NoQuene_Filename(FileName:String):String; //取出沒有序號的檔名
[647]     Function FileName2Index(FileName:String):Integer; //從檔名取出在ContextList的序號
[648]     Function FileName2NowDcoNo(FileName:String;CtList,DNList:TStrings):String; //從檔名取出歸屬的文件代號
[649]     Function FormCode2DocNo(FormCode:String):String;   //FormCode轉Docno
[650]     Function FormCode2Version(FormCode:String):String; //FormCode轉版本
[651]     Function FormCode2Page(FormCode:String):String; //FormCode轉文件頁數
[652]     Function DocNo2DocName(CaseID,DocNo:String):String; //Docno轉Doc名稱
[653]     Function DocNo2FileName(DocNo:String;List:TStrings):String; //用DocNo找出檔名(第一頁)
[654]     Function FormCode2WorkNo(FormCode:String):String; //用FormCode取出作業別
[655]     Function DocNo2WorkNo(DocNo:String):String; //用DocNo取出作業別
[656]     Function DocNo2DocNoDir(Path,DocNo:String):String;    //DocNo轉成DocNo(份數)目錄
[657]     Function DocNoDir2DocNo(DocNoDir:String):String; //DocNo(份數)目錄轉成DocNo
[658]     Function DocNoDir2Index(Path,DocNoDir:String):Integer; //DocNo(份數)目錄轉成index
[659]
[660]     Function DocNoNeedDiv(DocNo:String):Boolean; //是否是需分份數的文件代號
[661]     //Function CaseNo2DocNo(CaseNo:String):TStringList;
[662]
[663]     Function CaseNode2Info(Node:TTreeNode;Mode:Char):String;   //案件Node取案件編號  Mode: I:Caseno;P:Page
[664]     Function DocNode2Info(Node:TTreeNode;Mode:Char):String;     //文件Node取文件代號 Mode: I:Docno;N:Docname;P:Page;G:Group
[665]     Function FormNode2Info(Node:TTreeNode;Mode:Char):String;   //表單Node取表單代號  Mode: I:FormID;N:FormName;P:Page
[666]     //*******轉換區*********
[667]
[668]     Procedure PriorPage(Page:Integer); //上一頁
[669]     Procedure NextPage(Page:Integer); //下一頁
[670]
[671]     Function DocNoExistsinTree(CaseNode:TTreeNode;DocNo:String):Boolean; //DocNo是否己存在樹裡
[672]     Function DocnoNeedGroup(DocNo:String):Boolean; //傳入的DocNo是否需分組
[673]
[674]     function GetSiteOMR(FileName, Site: String;bt: Integer): Integer;
[675]     Function FindISB2View(Vmode:Integer):TImageScrollBox; //找空的ISB來顯示
[676]     Procedure R_W_ScanIni(Mode:Char); //'R'讀取;'W'寫入
[677]     Procedure GetDefScanIni; //取得掃瞄的預設值
[678]     procedure DesableImage;
[679]     procedure EnableImage(v:integer;Sender : TObject);
[680]     Procedure ViewMouseMode(v:Integer);
[681]     Procedure GoViewMode;
[682]     Procedure DisplayMode(index,H_Count,W_Count:Integer;BasePanel:TPanel);
[683]     Function GetServerDate : Boolean; //取主機時間
[684]     Function GetSetInf1 : Boolean; //取系統設定資訊mode1  DOC_INF
[685]     Function GetSetInf2 : Boolean; //取系統設定資訊mode2  DM_FORM_INF
[686]     Function GetSetInf3 : Boolean; //取系統設定資訊mode3  FORM_INF
[687]     Function GetSetInf4 : Boolean; //取系統設定資訊mode4  CHECK_RULE_INF
[688]     Function GetSetInf5 : Boolean; //取系統設定資訊mode5  MEMO_INF
[689]     Function GetSetInf6 : Boolean; //取系統設定資訊mode6  WORK_INF
[690]     Function GetSetInf7 : Boolean; //取系統設定資訊mode7  LASTESTFORM_INF
[691]     Procedure SetFormID_DocNo; //將FormID及Docno抽出來另存入list裡
[692]     Procedure SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
[693]
[694]     Procedure DataLoading(Loading,UseTimer:Boolean);  //資料載入中要停止點選的動作
[695]     procedure ClearView(stkv:Integer); //清除瀏覽窗的影像
[696]     Function DrawDocItem2(CaseNode : TTreenode;Caseno:String):Boolean;  //畫出文件名稱的Tree
[697]
[698]     Procedure initkscan; //檢查掃描器的功能
[699]     procedure LoadImgFile; //載入案件
[700]     procedure LoadImgFile1; //載入案件
[701]     procedure LoadAttFile(CaseID:String); //載入附加檔案
[702]     Procedure DistinctFormCode(CaseID:String); //案件裡的FormCode取出第一頁
[703]     Function OMRCheckCase(CaseID:String):Boolean; //OMR檢核
[704]     Procedure OMRErr2ini(CaseID,Reason,FileName,Site,RelaFileName,RelaSite,Anchor,Anchor1:String;Del,Ingnore,Display:Boolean); //OMR檢核失敗寫入ini
[705]     Procedure OMRErrini2List(CaseID:String;ErrlistForm : TErrlistForm); //OMR檢核失敗從ini寫入ListView
[706]     Function DownLanguage:Boolean;  //下載多國語言檔
[707]     Function FindMpsView(Vmode:Integer):TImageScrollBox;
[708]     Function CaseAsk(CaseID:String):Integer;  //詢問是否可上傳  (-1:失敗;0:可以;1:不行;)
[709]     Function CaseComplete(Path,CaseID:String;MainCase:Boolean):Boolean;  //通知傳送完成
[710]     Function GetCaseFormID(Path:String):String;  //取案件的FormID
[711]     Procedure CreateFormID_FormName(Path,CaseID:String);  //產生FormID_FormName.dat
[712]     Procedure CreateDocNo_DocName(Path,CaseID:String);  //產生DocNo_DocName.dat
[713]     Procedure CreateIn_WH(CaseID:String);  //產生In_WH.dat
[714]     Function CreateDocNo_Info(CaseID:String):String; //產生保管袋文件 DocNo[tab]份數[tab]總頁數[tab]是否異動[換行]DocNo[tab]份數[tab]總頁數[tab]是否異動
[715]     Function CreateCustDocNo_Info(CaseID:String):String; //產生自訂文件 DocName[tab]份數[tab]總頁數[tab]是否異動[#13#10]DocName[tab]份數[tab]總頁數[tab]是否異動
[716]     //Function CreateCustDocNo_Info(path,CaseID:String):String; overload
[717]     Function CreateAttach_Info(CaseID:String):String; //產生是否有Attach Y:有 N:沒有
[718]     Function CreateDocnoFrom_Info(CaseID:String):String; //產生被引進的保管袋文件資訊  Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
[719]     Function CreateCustDocNoFrom_Info(CaseID:String):String; //產生被引進的自定文件資訊  Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
[720]
[721]     Function GetDocNoEdit(CaseID,DocNo,DocName:String):String; //取出DocNo是否被異動 (Y/N)
[722]     Function GetDocNo_Count(Path,DocNo:String):Integer;  //取出文件份數
[723]     Function GetDocNo_Page(Path,DocNo:String):Integer;  //取出文件總頁數
[724]     Function FormIDExists(FormCode:String;CheckDate:Boolean;index:Integer):Boolean;  //檢查FormID是否存在及是否要檢查啟用停用日期
[725]     Function Case_DocNoExists(CaseID,Docno:String):Boolean; //Docno是否存在案件裡
[726]     Procedure ReSortFileName_New(Path:String); //檔名重新排序
[727]     Procedure ReSortFileName(Path:String); //檔名重新排序
[728]     Procedure ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
[729]     Function GetOMRCheckSet:Boolean;  //下載OMR檢核XML檔
[730]     Function GetKeyinSet : Boolean; //取登打設定
[731]     Procedure CheckRule2OMRErrInfo;   //檢核規則填入OMRErrINFo Record
[732]     Procedure ReNameContext(Path,OldName,NewName:String);
[733]     Procedure DeleteImageFile(Path,FileName,CaseID:String); // 刪除檔案
[734]     Procedure DeleteFormCodeFile(CaseID,DocDir,FormID:String);  //刪除指定FormID文件
[735]     Function DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
[736]     Procedure DeleteShowFile(Path:String); //刪除顯示中的影像
[737]     Function GetDataDocNoPage(MainDocNo,MainVersion:String):Integer;  //取記錄的文件_版本頁數
[738]     Function CheckCaseDocNoPage(CaseID,DocNo,Version:String;Pages:Integer):Integer; //檢查案件裡的文件_版本頁數
[739]     Function FindFormCodePages(CaseID,FormCode:String):Integer;  //計算案件裡FormID的頁數
[740]     Function GetDataFormCodePages(FormCode:String):Integer;   //取記錄的FormcID的頁數
[741]     Procedure CaseReSize(CaseID:String); //案件的影像縮放
[742]     Procedure ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放
[743]     Procedure ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)
[744]     Function TransCaseID(Path,CaseID:String;MainCase:Boolean):Boolean; //傳送案件
[745]     Procedure NewTreeNodeRefresh;
[746]     Procedure MyTreeNode1Refresh;
[747]     Procedure MyTreeNode2ReFresh(CaseID:String);
[748]     Procedure MyTreeNode3ReFresh(CaseID:String);
[749]     Function Node2DocNo(Node2:TTreeNode):String;  //MyTreeNode2取DocNo出來
[750]     Function Node3DocNo(Node3:TTreeNode):String;  //MyTreeNode3取DocNo出來
[751]     Function Node3FormID(Node3:TTreeNode):String;  //MyTreeNode3取FormCode出來
[752]     Function GetNode2Name(Node2:TTreeNode):String;  //取MyTreeNode2的識別字出來(記之前點選用)
[753]     //Function Down_Replace_Img(SPAth,DPath,CaseID:String):Boolean;
[754]     Function DownLoadImage(Path,CaseID:String):Boolean;
[755]     Function Down_Img(Path,CaseID:String):Boolean;
[756]     Function GetNoNameCase(Path:string):String; //取未配號XXXX
[757]     Procedure CaseResort(Path:String); //案件的檔案重新排序(次文件依Docno挑)
[758]     Procedure CaseResort2Scanlist(Path:String); //案件的檔案重新排序給scanlist(次文件依FormID排)
[759]     Procedure DistinctDocinCase(Path:String); //列出案件裡的Docno_版本
[760]     Procedure DistinctDocNoinCase(Path:String); //列出案件裡的Docno
[761]     Procedure ClearErrini(CaseID:String;CaseNode:TTreeNode); //清掉檢核檔案
[762]     Procedure SetCaseList(Mode:Char;Index:Integer;text:String);  //'A:加入,I:插入,D:刪除,E:修改'
[763]     Procedure SetDocNoList(Mode:Char;Index:Integer;CaseNo,DocDir,Copies:String);  //'A:加入,I:插入,D:刪除,E:修改'
[764]     Procedure SetContextList(Mode:Char;Index:Integer;CaseNo,DocDir,FileName:String);  //'A:加入,I:插入,D:刪除,E:修改'
[765]     Procedure SetAttContextList(Mode:Char;Index:Integer;CaseNo,FileName:String);  //'A:加入,I:插入,D:刪除,E:修改'
[766]
[767]
[768]     Function checkCaseOMRDone:Boolean;  //檢查案件是否完成OMR檢核
[769]     Function CheckCaseID_OK:Boolean;  //檢查是否有未配號的案件
[770]     Procedure CreateEmptyCase(Path,CaseID:String);  //產生空白案號(重掃件用)
[771]     Procedure InitScrollRec; //初始化影像Scroll記錄
[772]     Procedure GetScrollData(ISB:TImageScrollBox;Var HS,VS:Integer;Var iRate:Single); //取影像Scroll記錄
[773]     Procedure SetScrollData(ISB:TImageScrollBox;HS,VS:Integer;iRate:Single); //寫影像Scroll記錄
[774]     Procedure FormIDReplace(CaseID,DocDir,OldFormID,NewFormID:String); //指定FormID更換成新的FormID
[775]     Procedure ShowFileReplace(Path,NewFormID:String);//顯示的影像換成新的FormID
[776]     Procedure PageReplaceFormID(Path,NowFormID,NewFormID:String); //選取頁更換FormID
[777]     Function ModeNeedCheck(OMRMode,ScanMode:String):Boolean; //掃瞄模式是否要做檢核
[778]     procedure WMMOUSEWHEEL(var message: TWMMouseWheel); message WM_MOUSEWHEEL;
[779]     Function GetCasePage(Path,CaseID:String):Integer;
[780]     Function GetFormIDPage(FileList:TStringlist;FormID:String):Integer;
[781]     Procedure SetFile2Case(CaseID,FileName:String);
[782]     Procedure WriteResize(ImgName,TxtName:String); //產生Resize.dat
[783]     Function GetCase_PageCount(var CaseCount,PageCount:Integer):Boolean; //取出案件的數量及頁數 ID為空值時為取所有的
[784]     Function BarCode2FormID : String; //Barcode依規則轉成FormID
[785]     Function BarCode2CaseID : String; //Barcode依規則轉成CaseID
[786]     Procedure WriteCaseIndex(Path:String);
[787]     Procedure ReadCaseIndex(Path:String);
[788]     Procedure ClearCaseIndex;
[789]     Procedure GetSelectImageFile;
[790]     Function GetDocNoDir(Path,DocNo:String):String; //取出目前DocNo的份數
[791]     Function CheckFormIDExists(DocNoNode:TTreeNode;FormID:String):Boolean; //檢查FormID是否存在文件裡
[792]
[793]     Procedure ZipMainFile(SoPath,DePath,ZipName:String); //壓縮影像檔
[794]     Procedure ZipMaskFile(SoPath,MarkPath,DePath,ZipName:String); //壓縮遮罩影像檔
[795]     Procedure ParserPoint(S:String); //解析十字點的字串
[796]     Function CheckScanDenialTime:Boolean;
[797]     Function FormID2Anchor(FormID:String):String;  //用FormID取出十字模式
[798]     Function Index2Anchor(Anchor:String):String;   //十字模式 0->NONE;1->ANCHOR;2->FRAME
[799]     Function MemoInfoTransfer(Mode,Str:String;ID_S,Name_S:TStringlist):String;  //註記代碼註記類別轉換  Mode 'ID':代碼轉名稱;'NAME':名稱轉代碼
[800]     Function GetFormatID(CaseID:String):String; //取出案件的FormatID
[801]     Function FindNoSaveBarCode : Boolean; //找是否有不要儲存影像的條碼
[802]     Function CheckAvailable:Boolean; //檢查是否可使用元件
[803]     Function Case2Mask(SoPath,DePath:String):Boolean;//產生遮罩影像
[804]     Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
[805]     Function GetNewCustomDocNo(Path,DocName:String):String; //取出未使用的自訂文件代號
[806]     Function GetCustomDocName(Path,DocNo:String):String; //取出自定文件名稱
[807]     Function GetCustomFormID(Path,DocNo:String):String; //取出自定文件FormID
[808]     Function GetCustomDocDir(Path,DocName:String):String; //取出自定文件DocDir
[809]     Function FindCustomDocName(Path,DocName:String):Boolean; //尋找自定文件名稱是否存在
[810]     Procedure DeleteCustomDocDir(Path,DocNo:String); //刪除自定文件DocNo
[811]     Function CheckFormID_Prt(FormID:String):Boolean; //傳入的FormID是否預設列印
[812]     procedure PrintImg(FileName, LoginID, Datetime,Path: WideString);
[813]     Function FindLastestDocDir(CaseID,DocNo:String):String; //找出最新的DocDir
[814]     Procedure Create_Cust_DocDir(CaseID:String); //產生外面傳入的文件代號及自定文件
[815]     Procedure OldCasetoNewCase(CaseID:String); //將舊案份數轉成新規則
[816]     Procedure ErrFormtoCurrentForm(CaseID,EFormID,CFormID:String);//將舊案的錯誤FormID改正確的FormID
[817]     Procedure SetRecordEditedDocDir(Mode:Char;CaseID,DocDir:String);  //記錄被異動的文件目錄  'A:加入D:刪掉'
[818]     Function GetDocDir_Page(CaseID,DocDir:String):Integer;  //取得DocDir的頁數
[819]     Function Path2DocDir(Path,CaseID:String):String;
[820]     Function GetDocNo_IS_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
[821]     Procedure SortDocDir_FormID(CaseID,DocDir:String); //將DocDir裡的文件編號排序
[822]     Procedure GotoAttach(OldLevel:Integer);
[823]     Function DocNoIs_In_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
[824]     Procedure CreateCaseNeedData(Path:String);  //先做影像截取會少二個文字檔,產生CaseDocNo.dat及DocDir.dat
[825]     Procedure SetDocDirtoSelected(CaseNode:TTreeNode;DocDir:String);
[826]     Function CheckSelectImg_UseCase(Path,CaseID:String):Boolean; //檢查選擇的影像是否有包含被引用的影像
[827]     Function TransOldCaseFile(Path:String):Boolean;  //上傳引用舊件的記錄檔
[828]     Function Writelog(CaseID:String):Boolean;
[829]     Function FormIDAppear(FormID:String):Boolean; //FormID是否可出現
[830]     Function DocNoAppear(DocNo:String):Boolean;   //DocNo是否可出現
[831]     Function GetDocNoCount(CaseID,DocNo:String):Integer; //取DocNo數量
[832]     Function GetDocDirCopies(CaseID,DocDir:String):Integer; //取DocDir份數
[833]     Procedure SetDocDirCopies(CaseID,DocDir:String;NewCopies:Integer); //修改DocDir份數
[834]     Function GetDocDirCopies_Rec(Path,CaseID,DocDir:String):Integer; //取記錄裡的DocDir份數
[835]     Function GetCustomNameCount(CustomName:String):Integer;   //取外傳的名稱數量
[836]     Function GetCustomDocNoCount(Docno:String):Integer;   //取外傳的DocNo數量
[837]     Function ISGuideFormID(FormID:String):Boolean;
[838]     Function CaseDelete_Enable(CaseID:String):Boolean;  //案件可否被刪除
[839]
[840]     Procedure MoveImage(Path:String;mp:Integer); //移動頁數
[841]     Procedure MoveImage_Drag(Path:String;fp,tp:Integer); //拖拉移動頁數
[842]
[843]
[844]     Procedure SetUseCase(Mode:Char;Path,DocDir,FormCaseID,ToCaseID:String);   //記錄引用其他案件 A:加入 D:刪掉
[845]     Function GetUseCase(Mode:Char;Path,DocDir:String):String;  //F:取被引用 To:引用
[846]
[847]     Procedure Case2upload(CaseID:String);
[848]     Procedure Download2Case(SoDir,DeDir:String);
[849]
[850]     procedure view_image_FormCode(Path,FormCode:String;stpage,stview:integer); //用FormCode來找影像
[851]     procedure view_image_DocNo(Path,DocNo,FormID:String;Pages:integer); //用DocNo來找影像
[852]
[853]     Function ShapeName2PreViewISBName(SP:TShape):String; //轉出指定PreViewISBName
[854]     Procedure CreatePreViewISB(Count:Integer);
[855]     Procedure FreePreViewISB;
[856]     Procedure FitPreViewISB;
[857]     Procedure PaintShape(FromImg,ToImg:TImageScrollBox); //畫有被選取的影像
[858]     Procedure FreeShapeobj(SelectISB : TImageScrollBox);
[859]     Procedure ISBClick(Sender : TObject);
[860]     Procedure ISBMouseMove(Sender: TObject; Shift: TShiftState;
[861]     X, Y: Integer);
[862]     procedure ISBImageMouseDown(Sender: TObject; Button: TMouseButton;
[863]       Shift: TShiftState; X, Y: Integer);
[864]     procedure ISBImageMouseUp(Sender: TObject; Button: TMouseButton;
[865]       Shift: TShiftState; X, Y: Integer);
[866]     procedure ISBEndDrag(Sender, Target: TObject; X, Y: Integer);
[867]     procedure ISBDragDrop(Sender, Source: TObject; X, Y: Integer);
[868]     procedure ISBDragOver(Sender, Source: TObject; X, Y: Integer;
[869]       State: TDragState; var Accept: Boolean);
[870]
[871]     procedure BtnMouseEnter(Sender: TObject);
[872]
[873]     procedure PageEnd;   //掃描接收完成
[874]     Procedure PageDone;  //掃描完成後顯示影像
[875]     procedure StatrTwainScan;
[876]     procedure OnAcquire( const DibHandle    : THandle;
[877]                          const XDpi         : Word;
[878]                          const YDpi         : Word;
[879]                          const CallBackData : LongInt );
[880]
[881]
[882]     procedure ActivateEvent(Sender: TObject);
[883]     procedure ClickEvent(Sender: TObject);
[884]     procedure CreateEvent(Sender: TObject);
[885]     procedure DblClickEvent(Sender: TObject);
[886]     procedure DeactivateEvent(Sender: TObject);
[887]     procedure DestroyEvent(Sender: TObject);
[888]     procedure KeyPressEvent(Sender: TObject; var Key: Char);
[889]     procedure MouseEnterEvent(Sender: TObject);
[890]     procedure MouseLeaveEvent(Sender: TObject);
[891]     procedure PaintEvent(Sender: TObject);
[892]     function GetCurrentVersionNo: String;
[893]     procedure initParameter;
[894]     procedure LastInitFormidListCreate(path:string);
[895]     function checkFormCodeIsCustom(path,formcode:string):boolean;
[896]     function ISDivPageFormID(FormID: String): Boolean;
[897]     function GetSampleInf: Boolean;
[898]     procedure InitExistImgList(casepath:String);
[899]     function LoadFileGetMD5(const filename:string):string; //20170809 取的檔案的MD5
[900]     function ISExistImg(const filename:string):boolean;  //20170809 確認是否存在原有影像
[901]     procedure _DelTreeForExistImg(ASourceDir:String);   //2017 刪除前確認 有舊影像嗎
[902]     function DocNoIsExistImg(DocNopath: String): boolean; //2017 刪除前確認 有舊影像嗎
[903]     function CheckCaseAttach_OK: Boolean;
[904]     function DeleteDocNoFileForESCAN(Path, DocNo: String): Boolean;     //2017 確認是否有未歸類文件
[905]     function CheckRequiredColumnValues(workno,caseno:String) :Boolean;  //20171003  此大類下此案是否檢核必填
[906]     function logTimeString :String;
[907]     procedure ReduceLogFile ;
[908]     function FindLastestDocDirForPage(CaseID, DocNo, formid: String): String;
[909]     function OMRErrini2ListForLog(CaseID: String):String;
[910]   protected
[911]     { Protected declarations }
[912]     procedure DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage); override;
[913]     procedure EventSinkChanged(const EventSink: IUnknown); override;
[914]     function Get_Active: WordBool; safecall;
[915]     function Get_AlignDisabled: WordBool; safecall;
[916]     function Get_AlignWithMargins: WordBool; safecall;
[917]     function Get_AutoScroll: WordBool; safecall;
[918]     function Get_AutoSize: WordBool; safecall;
[919]     function Get_AxBorderStyle: TxActiveFormBorderStyle; safecall;
[920]     function Get_Caption: WideString; safecall;
[921]     function Get_Color: OLE_COLOR; safecall;
[922]     function Get_DockSite: WordBool; safecall;
[923]     function Get_DoubleBuffered: WordBool; safecall;
[924]     function Get_DropTarget: WordBool; safecall;
[925]     function Get_Enabled: WordBool; safecall;
[926]     function Get_ExplicitHeight: Integer; safecall;
[927]     function Get_ExplicitLeft: Integer; safecall;
[928]     function Get_ExplicitTop: Integer; safecall;
[929]     function Get_ExplicitWidth: Integer; safecall;
[930]     function Get_Font: IFontDisp; safecall;
[931]     function Get_HelpFile: WideString; safecall;
[932]     function Get_KeyPreview: WordBool; safecall;
[933]     function Get_MouseInClient: WordBool; safecall;
[934]     function Get_ParentCustomHint: WordBool; safecall;
[935]     function Get_ParentDoubleBuffered: WordBool; safecall;
[936]     function Get_PixelsPerInch: Integer; safecall;
[937]     function Get_PopupMode: TxPopupMode; safecall;
[938]     function Get_PrintScale: TxPrintScale; safecall;
[939]     function Get_Scaled: WordBool; safecall;
[940]     function Get_ScreenSnap: WordBool; safecall;
[941]     function Get_SnapBuffer: Integer; safecall;
[942]     function Get_UseDockManager: WordBool; safecall;
[943]     function Get_Visible: WordBool; safecall;
[944]     function Get_VisibleDockClientCount: Integer; safecall;
[945]     procedure _Set_Font(var Value: IFontDisp); safecall;
[946]     procedure Set_AlignWithMargins(Value: WordBool); safecall;
[947]     procedure Set_AutoScroll(Value: WordBool); safecall;
[948]     procedure Set_AutoSize(Value: WordBool); safecall;
[949]     procedure Set_AxBorderStyle(Value: TxActiveFormBorderStyle); safecall;
[950]     procedure Set_Caption(const Value: WideString); safecall;
[951]     procedure Set_Color(Value: OLE_COLOR); safecall;
[952]     procedure Set_DockSite(Value: WordBool); safecall;
[953]     procedure Set_DoubleBuffered(Value: WordBool); safecall;
[954]     procedure Set_DropTarget(Value: WordBool); safecall;
[955]     procedure Set_Enabled(Value: WordBool); safecall;
[956]     procedure Set_Font(const Value: IFontDisp); safecall;
[957]     procedure Set_HelpFile(const Value: WideString); safecall;
[958]     procedure Set_KeyPreview(Value: WordBool); safecall;
[959]     procedure Set_ParentCustomHint(Value: WordBool); safecall;
[960]     procedure Set_ParentDoubleBuffered(Value: WordBool); safecall;
[961]     procedure Set_PixelsPerInch(Value: Integer); safecall;
[962]     procedure Set_PopupMode(Value: TxPopupMode); safecall;
[963]     procedure Set_PrintScale(Value: TxPrintScale); safecall;
[964]     procedure Set_Scaled(Value: WordBool); safecall;
[965]     procedure Set_ScreenSnap(Value: WordBool); safecall;
[966]     procedure Set_SnapBuffer(Value: Integer); safecall;
[967]     procedure Set_UseDockManager(Value: WordBool); safecall;
[968]     procedure Set_Visible(Value: WordBool); safecall;
[969]     procedure Set_caseid(const Value: WideString); safecall;
[970]     procedure Set_data(const Value: WideString); safecall;
[971]     procedure Set_mode(const Value: WideString); safecall;
[972]     procedure Set_rewrite(const Value: WideString); safecall;
[973]     procedure Set_url(const Value: WideString); safecall;
[974]     procedure Set_userid(const Value: WideString); safecall;
[975]     procedure Set_username(const Value: WideString); safecall;
[976]     procedure Set_verify(const Value: WideString); safecall;
[977]     procedure Set_language(const Value: WideString); safecall;
[978]     procedure Set_modename(const Value: WideString); safecall;
[979]     procedure Set_userunit(const Value: WideString); safecall;
[980]     procedure Set_work_no(const Value: WideString); safecall;
[981]     procedure Set_loandoc_enable(const Value: WideString); safecall;
[982]     procedure Set_loandoc_value(const Value: WideString); safecall;
[983]     procedure Set_useproxy(const Value: WideString); safecall;
[984]     procedure Set_c_docnamelist(const Value: WideString); safecall;
[985]     procedure Set_c_docnolist(const Value: WideString); safecall;
[986]     procedure Set_fixfilelist(const Value: WideString); safecall;
[987]     procedure Set_is_in_wh(const Value: WideString); safecall;
[988]     procedure Set_oldcaseinfo(const Value: WideString); safecall;
[989]     function Get_c_docnamelist: WideString; safecall;
[990]     function Get_c_docnolist: WideString; safecall;
[991]     function Get_caseid: WideString; safecall;
[992]     function Get_data: WideString; safecall;
[993]     function Get_fixfilelist: WideString; safecall;
[994]     function Get_is_in_wh: WideString; safecall;
[995]     function Get_language: WideString; safecall;
[996]     function Get_loandoc_enable: WideString; safecall;
[997]     function Get_loandoc_value: WideString; safecall;
[998]     function Get_mode: WideString; safecall;
[999]     function Get_modename: WideString; safecall;
[1000]     function Get_oldcaseinfo: WideString; safecall;
[1001]     function Get_rewrite: WideString; safecall;
[1002]     function Get_url: WideString; safecall;
[1003]     function Get_useproxy: WideString; safecall;
[1004]     function Get_userid: WideString; safecall;
[1005]     function Get_username: WideString; safecall;
[1006]     function Get_userunit: WideString; safecall;
[1007]     function Get_verify: WideString; safecall;
[1008]     function Get_work_no: WideString; safecall;
[1009]     function Get_printyn: WideString; safecall;
[1010]     procedure Set_printyn(const Value: WideString); safecall;
[1011]     function Get_is_oldcase: WideString; safecall;
[1012]     procedure Set_is_oldcase(const Value: WideString); safecall;
[1013]     function Get_custdocyn: WideString; safecall;
[1014]     procedure Set_custdocyn(const Value: WideString); safecall;
[1015]     function Get_casenolength: WideString; safecall;
[1016]     function Get_filesizelimit: WideString; safecall;
[1017]     function Get_imgdpi: WideString; safecall;
[1018]     function Get_scancolor: WideString; safecall;
[1019]     procedure Set_casenolength(const Value: WideString); safecall;
[1020]     procedure Set_filesizelimit(const Value: WideString); safecall;
[1021]     procedure Set_imgdpi(const Value: WideString); safecall;
[1022]     procedure Set_scancolor(const Value: WideString); safecall;
[1023]     function Get_imgdelete: WideString; safecall;
[1024]     procedure Set_imgdelete(const Value: WideString); safecall;
[1025]     function Get_check_main_form: WideString; safecall;
[1026]     function Get_isExternal: WideString; safecall;
[1027]     procedure Set_check_main_form(const Value: WideString); safecall;
[1028]     procedure Set_isExternal(const Value: WideString); safecall;
[1029]     function Get_WH_CATEGORY: WideString; safecall;
[1030]     procedure Set_WH_CATEGORY(const Value: WideString); safecall;
[1031]   public
[1032]     { Public declarations }
[1033]     procedure Initialize; override;
[1034]   end;
[1035]
[1036] implementation
[1037]
[1038] uses EnBarcode,
[1039]      EnTransf, { for TImageTransform }
[1040]      Enpnggr,  { for PNGGraphic }
[1041]      EnJpgGr,  { for JPGGraphic }
[1042]      EnReg,
[1043]      EnBmpGr,  { for TBitmapGraphic }
[1044]      EnPrint,  { for TEnvisionPrintMode, TDibGraphicPrinter }
[1045]      ComObj, ComServ,IISUnit,IIS_File2Web,IIS_ImageProcess,
[1046]      PatchFom,Doclist,ScanMemo,DocCopy,InputMask,SortMemo,DocPrt,OldCaseInfo;
[1047]
[1048] {$R *.DFM}
[1049]
[1050] { TCB_IMGPSScanX }
[1051]
scripts/dist/ErrList.pas.image.csv
比對新檔案
@@ -0,0 +1,5 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"ImageScrollBox1NewGraphic","ErrList.pas","109","TDibGraphic","","procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);"
[V],"TErrlistForm.GetOMRErrini","ErrList.pas","487","FindPoint","","//FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,'NONE');"
[V],"TErrlistForm.ImageScrollBox1NewGraphic","ErrList.pas","553","TDibGraphic","","procedure TErrlistForm.ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);"
[V],"TErrlistForm.ImageScrollBox1NewGraphic","ErrList.pas","559","ConvertToBW","","ConvertToBW(ISB_BW.Graphic);"
scripts/dist/ErrList.pas.io.csv
比對新檔案
@@ -0,0 +1,12 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"TErrlistForm.RejectBtClick","ErrList.pas","155","FileExists","","if FileExists(iniPath+'RemoveMemo.dat') then"
[V],"TErrlistForm.RejectBtClick","ErrList.pas","156","LoadFromFile","","S.LoadFromFile(iniPath+'RemoveMemo.dat');"
[V],"TErrlistForm.RejectBtClick","ErrList.pas","161","SaveToFile","","S.SaveToFile(iniPath+'RemoveMemo.dat');"
[V],"TErrlistForm.DeleteBtClick","ErrList.pas","189","FileExists","","if FileExists(iniPath+'RemoveMemo.dat') then"
[V],"TErrlistForm.DeleteBtClick","ErrList.pas","190","LoadFromFile","","S.LoadFromFile(iniPath+'RemoveMemo.dat');"
[V],"TErrlistForm.DeleteBtClick","ErrList.pas","197","SaveToFile","","S.SaveToFile(iniPath+'RemoveMemo.dat');"
[V],"TErrlistForm.EnforceBtClick","ErrList.pas","241","FileExists","","if FileExists(iniPath+'RemoveMemo.dat') then"
[V],"TErrlistForm.EnforceBtClick","ErrList.pas","242","LoadFromFile","","S.LoadFromFile(iniPath+'RemoveMemo.dat');"
[V],"TErrlistForm.EnforceBtClick","ErrList.pas","252","SaveToFile","","S.SaveToFile(iniPath+'RemoveMemo.dat');"
[V],"TErrlistForm.GetOMRErrini","ErrList.pas","485","LoadFromFile","","ImageScrollBox1.LoadFromFile(FileName,1);"
[V],"TErrlistForm.GetOMRErrini","ErrList.pas","504","FileExists","","if (RelaFileName <> '') and FileExists(RelaFileName) then //¦³Ãö«Y¼v¹³"
scripts/dist/OldCaseInfo.pas.image.csv
比對新檔案
@@ -0,0 +1,2 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"TOldCaseInfoForm.ShowImage","OldCaseInfo.pas","333","DpiResize","","DpiResize(ISB.Graphic,36,False);"
scripts/dist/OldCaseInfo.pas.io.csv
比對新檔案
@@ -0,0 +1,18 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"TOldCaseInfoForm.Down_Img","OldCaseInfo.pas","131","FileExists","","if FileExists(Path+CaseID+'.zip') then"
[V],"TOldCaseInfoForm.LoadImg","OldCaseInfo.pas","185","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\CaseDocNo.dat') then"
[V],"TOldCaseInfoForm.LoadImg","OldCaseInfo.pas","186","LoadFromFile","","DocDirList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\CaseDocNo.dat');"
[V],"TOldCaseInfoForm.DocNo2DocName","OldCaseInfo.pas","233","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\DocNo_Name.dat') then"
[V],"TOldCaseInfoForm.DocNo2DocName","OldCaseInfo.pas","234","LoadFromFile","","DocNo_DocNameList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\DocNo_Name.dat',TEnCoding.UTF8);"
[V],"TOldCaseInfoForm.Docdir2Pages","OldCaseInfo.pas","261","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat') then"
[V],"TOldCaseInfoForm.Docdir2Pages","OldCaseInfo.pas","262","LoadFromFile","","FileList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat');"
[V],"TOldCaseInfoForm.ShowImage","OldCaseInfo.pas","317","FileExists","","if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat') then"
[V],"TOldCaseInfoForm.ShowImage","OldCaseInfo.pas","318","LoadFromFile","","FileList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat');"
[V],"TOldCaseInfoForm.ErrFormtoCurrentForm","OldCaseInfo.pas","382","LoadFromFile","","DocNoList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\CaseDocNo.dat',Tencoding.UTF8);"
[V],"TOldCaseInfoForm.ErrFormtoCurrentForm","OldCaseInfo.pas","400","RenameFile","","RenameFile(iPath+OldFile,iPath+NewFile);"
[V],"TOldCaseInfoForm.ErrFormtoCurrentForm","OldCaseInfo.pas","401","SaveToFile","","FileList.SaveToFile(iPath+'Context.dat',Tencoding.UTF8);"
[V],"TOldCaseInfoForm.ErrFormtoCurrentForm","OldCaseInfo.pas","412","MoveFile","","//MoveFile(PWideChar(iPath),PWideChar(iiPath));"
[V],"TOldCaseInfoForm.ISBClick","OldCaseInfo.pas","595","LoadFromFile","","ISB1.LoadFromFile(SelectISB.FileName,1);"
[V],"TOldCaseInfoForm.LoadBtClick","OldCaseInfo.pas","812","FileExists","","if not FileExists(imageSavePath+CaseID+'\'+UseCaseID+'\Context.dat') then"
[V],"TOldCaseInfoForm.LoadBtClick","OldCaseInfo.pas","814","DirectoryExists","","if DirectoryExists(ImageSavePath+CaseID+'\'+UseCaseID) then"
[V],"TOldCaseInfoForm.LoadBtClick","OldCaseInfo.pas","815","_DelTree","","_Deltree(ImageSavePath+CaseID+'\'+UseCaseID);"
scripts/dist/OldCaseInfo.pas.transp.csv
比對新檔案
@@ -0,0 +1,7 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"Global_Or_Interface","OldCaseInfo.pas","40","TElHTTPSClient","","HTTPSClient: TElHTTPSClient;"
[V],"HTTPSClientCertificateValidate","OldCaseInfo.pas","46","HTTPSClientCertificateValidate","","procedure HTTPSClientCertificateValidate(Sender: TObject;"
[V],"TOldCaseInfoForm.Down_Img","OldCaseInfo.pas","108","En_DecryptionStr_Base64","","//EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);"
[V],"TOldCaseInfoForm.Down_Img","OldCaseInfo.pas","113","dnFile_Get","","if not dnFile_Get(HTTPSClient,Furl,'service/slic/SLIC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TOldCaseInfoForm.Down_Img","OldCaseInfo.pas","113","dnFile","","if not dnFile_Get(HTTPSClient,Furl,'service/slic/SLIC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then"
[V],"TOldCaseInfoForm.HTTPSClientCertificateValidate","OldCaseInfo.pas","710","HTTPSClientCertificateValidate","","procedure TOldCaseInfoForm.HTTPSClientCertificateValidate(Sender: TObject;"
scripts/dist/PatchFom.pas.image.csv
比對新檔案
@@ -0,0 +1,7 @@
方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
"Global_Or_Interface","PatchFom.pas","22","Rotate","","ScanRotateRG: TRadioGroup;"
"TPatchDlg.DefaultBtClick","PatchFom.pas","97","Rotate","","case Def_ScanRotate of"
"TPatchDlg.DefaultBtClick","PatchFom.pas","98","Rotate","","0  : ScanRotateRG.ItemIndex := 0;"
"TPatchDlg.DefaultBtClick","PatchFom.pas","99","Rotate","","270 : ScanRotateRG.ItemIndex := 1;"
"TPatchDlg.DefaultBtClick","PatchFom.pas","100","Rotate","","180 : ScanRotateRG.ItemIndex := 2;"
"TPatchDlg.DefaultBtClick","PatchFom.pas","101","Rotate","","90 : PatchDlg.ScanRotateRG.ItemIndex := 3;"
scripts/dist/PatchFom.pas.scan.csv
比對新檔案
@@ -0,0 +1,3 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],"Global_Or_Interface","PatchFom.pas","18","Scanner","","ScannerGB: TGroupBox;"
[V],"TPatchDlg.DefaultBtClick","PatchFom.pas","91","Scanner","","ReverseCB.Checked := Def_ScannerReverse;"
scripts/dist/deps.all.csv
比對新檔案
@@ -0,0 +1,607 @@
[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段
[V],Global_Or_Interface,CB_IMGPSScanImp.pas.bk,9,TDibGraphic,,EnDiGrph, { for TDibGraphic }
[V],Global_Or_Interface,CB_IMGPSScanImp.pas.bk,80,TTiffGraphic,,Graphic    : TTiffGraphic;
[V],ImageScrollBox1NewGraphic,CB_IMGPSScanImp.pas.bk,393,TDibGraphic,,procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
[V],Button6Click,CB_IMGPSScanImp.pas.bk,598,Rotate,,BarCodeRotate : Integer; //條碼要轉的角度
[V],Button6Click,CB_IMGPSScanImp.pas.bk,615,FJpgCompression,,FJpgCompression:integer;// 20171211 jpg to tif çš„壓縮率
[V],GetSiteOMR,CB_IMGPSScanImp.pas.bk,674,GetSiteOMR,,function GetSiteOMR(FileName, Site: String;bt: Integer): Integer;
[V],ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,742,ImageReSize_FormID,,Procedure ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放
[V],ImageReSize_tmp,CB_IMGPSScanImp.pas.bk,743,ImageReSize_tmp,,Procedure ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)
[V],CheckNeedCrop,CB_IMGPSScanImp.pas.bk,804,TDibGraphic,,Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
[V],CheckNeedCrop,CB_IMGPSScanImp.pas.bk,804,CheckNeedCrop,,Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
[V],Initialize,CB_IMGPSScanImp.pas.bk,1044,TDibGraphic,,EnPrint,  { for TEnvisionPrintMode, TDibGraphicPrinter }
[V],TCB_IMGPSScanX.ISB1ImageMouseUp,CB_IMGPSScanImp.pas.bk,1505,TJpegGraphic,,TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.ISB1ImageMouseUp,CB_IMGPSScanImp.pas.bk,1505,SaveQuality,,TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.PM604Click,CB_IMGPSScanImp.pas.bk,2315,DeskewImg,,DeskewImg(iISB.Graphic);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2799,TTiffGraphic,,iGraphic, iGraphic_First, iGraphic_sec: TTiffGraphic;
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2801,TJpegGraphic,,JpgGr : TJpegGraphic;
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2838,FJpgCompression,,cooom:=FJpgCompression;//20171211彩色tif採jpg壓縮的比例
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2850,DeskewImg,,DeskewImg(ISB.Graphic);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2856,ConvertToBW,,ConvertToBW(ISB_BW.Graphic);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2866,MpsGetBarcode,,MpsGetBarcode(ISB_BW.Graphic, MpsBarcodeinf); //判斷A3 æœ‰ç”¨FormID æ‰€ä»¥è¦å…ˆè¾¨æ¢ç¢¼
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2871,Rotate,,Rotate(ISB.Graphic, MpsBarcodeinf.r180[n]);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2879,CheckNeedCrop,,If CheckNeedCrop(iGraphic_First) Then
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2886,CropImg,,CropImg(iGraphic_First, iRect);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3000,ifBlackWhite,,if iGraphic.ImageFormat = ifBlackWhite then   //20200806 å‡ºç¾ç„¡æ³•匯入,是因color256無法壓JPEG,待報會後再開啟
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3003,tcGroup4,,iGraphic.Compression:=tcGroup4;
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3005,ifColor25,,else if iGraphic.ImageFormat= ifColor256 then
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3008,ConvertToGray,,ConverttoGray(iGraphic);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3009,tcJpeg,,iGraphic.Compression:=tcJPEG;
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3012,ifTrueColor,,else if (iGraphic.ImageFormat = ifTrueColor) or (iGraphic.ImageFormat = ifGray256) then
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3012,ifGray256,,else if (iGraphic.ImageFormat = ifTrueColor) or (iGraphic.ImageFormat = ifGray256) then
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,3050,SaveQuality,,JpgGr.SaveQuality := 30;
[V],TCB_IMGPSScanX.PM301Click,CB_IMGPSScanImp.pas.bk,3475,ifBlackWhite,,ScanColor := ifBlackWhite;
[V],TCB_IMGPSScanX.PM302Click,CB_IMGPSScanImp.pas.bk,3483,ifGray256,,ScanColor := ifGray256;
[V],TCB_IMGPSScanX.PM303Click,CB_IMGPSScanImp.pas.bk,3492,ifTrueColor,,ScanColor := ifTrueColor;
[V],TCB_IMGPSScanX.PM510Click,CB_IMGPSScanImp.pas.bk,3664,DeskewImg,,DeskewImg(DisplayISB.Graphic);
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4402,TTiffGraphic,,ScanInfo.Graphic := TTiffGraphic.Create;
[V],TCB_IMGPSScanX.OnAcquire,CB_IMGPSScanImp.pas.bk,4455,TTiffGraphic,,iGraphic,iGraphic_First,iGraphic_sec : TTiffGraphic;
[V],TCB_IMGPSScanX.OnAcquire,CB_IMGPSScanImp.pas.bk,4457,TJpegGraphic,,JpgGr : TJpegGraphic;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4460,TDibGraphic,,function Deletepage(Graphic:TDibGraphic;BlankSize:Integer):Boolean;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4487,ifBlackWhite,,if pScanInfo^.Graphic.ImageFormat = ifBlackWhite then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4492,tcGroup4,,pScanInfo^.Graphic.Compression := tcGroup4;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4493,MpsGetBarcode,,MpsGetBarcode(pScanInfo^.Graphic,MpsBarcodeinf);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4498,Rotate,,Rotate(pScanInfo^.Graphic,MpsBarcodeinf.r180[i]);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4506,NegativeImg,,NegativeImg(pScanInfo^.Graphic);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4509,DeskewImg,,DeskewImg(pScanInfo^.Graphic);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4512,CleanupBorder,,CleanupBorder(pScanInfo^.Graphic);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4514,ifTrueColor,,else if pScanInfo^.Graphic.ImageFormat = ifTrueColor then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4529,tcJpeg,,pScanInfo^.Graphic.Compression := tcJpeg;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4530,FJpgCompression,,pScanInfo^.Graphic.JpegQuality := FJpgCompression;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4532,ifColor25,,else if pScanInfo^.Graphic.ImageFormat = ifColor256 Then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4535,ConvertToGray,,ConvertToGray(pScanInfo^.Graphic);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4539,ifGray256,,else if pScanInfo^.Graphic.ImageFormat = ifGray256 Then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4566,tcPackBits,,pScanInfo^.Graphic.Compression := tcPackBits;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4571,TTiffGraphic,,iGraphic_First := TTiffGraphic.Create;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4577,CheckNeedCrop,,if CheckNeedCrop(iGraphic_First) Then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4583,CropImg,,CropImg(iGraphic_First,iRect);
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4656,TJpegGraphic,,JpgGr := TJpegGraphic.Create;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4659,SaveQuality,,JpgGr.SaveQuality := FJpgCompression;
[V],TCB_IMGPSScanX.GetSiteOMR,CB_IMGPSScanImp.pas.bk,5173,GetSiteOMR,,function TCB_IMGPSScanX.GetSiteOMR(FileName,Site:String;bt: Integer): Integer;
[V],TCB_IMGPSScanX.GetSiteOMR,CB_IMGPSScanImp.pas.bk,5191,FindPoint,,FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,'');
[V],TCB_IMGPSScanX.GetSiteOMR,CB_IMGPSScanImp.pas.bk,5222,Get_OMR,,result := Get_OMR(ISB_BW.Graphic,OMRRect);
[V],TCB_IMGPSScanX.GetDefScanIni,CB_IMGPSScanImp.pas.bk,5366,Rotate,,Else if GetSQLData(WORK_INF_List,'PARA_NO',i) = 'SCAN_ROTATE_MODE' Then //掃瞄時旋轉角度
[V],TCB_IMGPSScanX.GetDefScanIni,CB_IMGPSScanImp.pas.bk,5462,FJpgCompression,,FJpgCompression := StrToInt(PARA_CONTENT);
[V],TCB_IMGPSScanX.CaseReSize,CB_IMGPSScanImp.pas.bk,6336,ImageReSize_FormID,,ImageReSize_FormID(CaseID,FileName);  //依十字定位點做縮放
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6343,ImageReSize_FormID,,Procedure TCB_IMGPSScanX.ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6376,FindPoint,,//FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,NowW,NowH);
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6379,CheckSize,,SizeStr := CheckSize(ISB_BW,UpLPoint,UpRPoint,DownLPoint,DW,DH);
[V],TCB_IMGPSScanX.ImageReSize_tmp,CB_IMGPSScanImp.pas.bk,6421,ImageReSize_tmp,,Procedure TCB_IMGPSScanX.ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)
[V],TCB_IMGPSScanX.ImageReSize_tmp,CB_IMGPSScanImp.pas.bk,6437,CheckSize,,SizeStr := CheckSize(ImageScrollBox1,UpLPoint,UpRPoint,DownLPoint,DW,DH);
[V],TCB_IMGPSScanX.ImageScrollBox1NewGraphic,CB_IMGPSScanImp.pas.bk,6447,TDibGraphic,,procedure TCB_IMGPSScanX.ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
[V],TCB_IMGPSScanX.ImageScrollBox1NewGraphic,CB_IMGPSScanImp.pas.bk,6453,ConvertToBW,,ConvertToBW(ISB_BW.Graphic);
[V],TCB_IMGPSScanX.ScanGrayCBClick,CB_IMGPSScanImp.pas.bk,8573,ifGray256,,ScanColor:=ifGray256;
[V],TCB_IMGPSScanX.ScanGrayCBClick,CB_IMGPSScanImp.pas.bk,8579,ifBlackWhite,,ScanColor := ifBlackWhite;
[V],TCB_IMGPSScanX.ScanGrayCBClick,CB_IMGPSScanImp.pas.bk,8591,ifTrueColor,,ScanColor := ifTrueColor ;
[V],TCB_IMGPSScanX.initParameter,CB_IMGPSScanImp.pas.bk,9290,ifBlackWhite,,ScanColor := ifBlackWhite;
[V],TCB_IMGPSScanX.initParameter,CB_IMGPSScanImp.pas.bk,9295,ifGray256,,ScanColor := ifGray256 ;
[V],TCB_IMGPSScanX.initParameter,CB_IMGPSScanImp.pas.bk,9301,ifTrueColor,,ScanColor := ifTrueColor ;
[V],TCB_IMGPSScanX.SmoothCBClick,CB_IMGPSScanImp.pas.bk,9927,Image_Smooth,,Image_Smooth(ISB1.Graphic);
[V],TCB_IMGPSScanX.Case2Mask,CB_IMGPSScanImp.pas.bk,9962,FindPoint,,//ParserPoint(CropMpsV.FindPoint(Anchor));
[V],TCB_IMGPSScanX.CheckNeedCrop,CB_IMGPSScanImp.pas.bk,9996,TDibGraphic,,Function TCB_IMGPSScanX.CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
[V],TCB_IMGPSScanX.CheckNeedCrop,CB_IMGPSScanImp.pas.bk,9996,CheckNeedCrop,,Function TCB_IMGPSScanX.CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
[V],TCB_IMGPSScanX.PrintImg,CB_IMGPSScanImp.pas.bk,10223,TDibGraphic,,GraphicPrinter : TDibGraphicPrinter;
[V],PrintWithManualPrintJob,CB_IMGPSScanImp.pas.bk,10241,TDibGraphic,,property of the TDibGraphicPrinter object is used to specify the
[V],PrintWithAutoPrintJob,CB_IMGPSScanImp.pas.bk,10274,TDibGraphic,,GraphicPrinter := TDibGraphicPrinter.Create;
[V],TCB_IMGPSScanX.OMRCheckCase,CB_IMGPSScanImp.pas.bk,12510,ImageReSize_FormID,,ImageReSize_FormID(CaseID,OMRFile);
[V],TCB_IMGPSScanX.OMRCheckCase,CB_IMGPSScanImp.pas.bk,12545,GetSiteOMR,,//Showmessage(ColCName +','+ inttostr(OMRMpsV1.GetSiteOMR(ImageSavePath+CaseID+'\upload\'+OMRFile,Site))+','+inttostr(Pixel + SafePixel));
[V],TCB_IMGPSScanX.OMRCheckCase,CB_IMGPSScanImp.pas.bk,12548,FindPoint,,//FindPoint(ISB_BW.Graphic,UpLPoint,UpRPoint,DownLPoint,ANCHOR);
[V],TCB_IMGPSScanX.view_image_DocNo,CB_IMGPSScanImp.pas.bk,13278,DpiResize,,DpiResize(ISB.Graphic,36,False);
[V],TCB_IMGPSScanX.SpeedButton14Click,CB_IMGPSScanImp.pas.bk,13407,Rotate,,Rotate(ISB1.Graphic,270);
[V],TCB_IMGPSScanX.SpeedButton14Click,CB_IMGPSScanImp.pas.bk,13410,TJpegGraphic,,TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.SpeedButton14Click,CB_IMGPSScanImp.pas.bk,13410,SaveQuality,,TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.SpeedButton15Click,CB_IMGPSScanImp.pas.bk,13428,Rotate,,Rotate(ISB1.Graphic,180);
[V],TCB_IMGPSScanX.SpeedButton15Click,CB_IMGPSScanImp.pas.bk,13431,TJpegGraphic,,TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.SpeedButton15Click,CB_IMGPSScanImp.pas.bk,13431,SaveQuality,,TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.SpeedButton16Click,CB_IMGPSScanImp.pas.bk,13449,Rotate,,Rotate(ISB1.Graphic,90);
[V],TCB_IMGPSScanX.SpeedButton16Click,CB_IMGPSScanImp.pas.bk,13452,TJpegGraphic,,TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.SpeedButton16Click,CB_IMGPSScanImp.pas.bk,13452,SaveQuality,,TJpegGraphic(ISB1.Graphic).SaveQuality := 30;
[V],TCB_IMGPSScanX.ISBClick,CB_IMGPSScanImp.pas.bk,13729,Image_Smooth,,Image_Smooth(ISB1.Graphic);
[V],TCB_IMGPSScanX.Timer1Timer,CB_IMGPSScanImp.pas.bk,14919,FJpgCompression,,FJpgCompression:=50;
[V],TCB_IMGPSScanX.Set_scancolor,CB_IMGPSScanImp.pas.bk,16357,ifBlackWhite,,ScanColor := ifBlackWhite;
[V],TCB_IMGPSScanX.Set_scancolor,CB_IMGPSScanImp.pas.bk,16367,ifGray256,,ScanColor := ifGray256 ;
[V],TCB_IMGPSScanX.Set_scancolor,CB_IMGPSScanImp.pas.bk,16372,ifTrueColor,,ScanColor := ifTrueColor ;
[V],ImageScrollBox1NewGraphic,ErrList.pas,109,TDibGraphic,,procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
[V],TErrlistForm.GetOMRErrini,ErrList.pas,487,FindPoint,,//FindPoint(ImageScrollBox1.Graphic,UpLPoint,UpRPoint,DownLPoint,'NONE');
[V],TErrlistForm.ImageScrollBox1NewGraphic,ErrList.pas,553,TDibGraphic,,procedure TErrlistForm.ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
[V],TErrlistForm.ImageScrollBox1NewGraphic,ErrList.pas,559,ConvertToBW,,ConvertToBW(ISB_BW.Graphic);
[V],TOldCaseInfoForm.ShowImage,OldCaseInfo.pas,333,DpiResize,,DpiResize(ISB.Graphic,36,False);
[V],ReSortFileName_New,CB_IMGPSScanImp.pas.bk,726,ReSortFileName,,Procedure ReSortFileName_New(Path:String); //檔名重新排序
[V],ReSortFileName,CB_IMGPSScanImp.pas.bk,727,ReSortFileName,,Procedure ReSortFileName(Path:String); //檔名重新排序
[V],ReSortFileName2Scanlist,CB_IMGPSScanImp.pas.bk,728,ReSortFileName,,Procedure ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
[V],DeleteImageFile,CB_IMGPSScanImp.pas.bk,733,DeleteImageFile,,Procedure DeleteImageFile(Path,FileName,CaseID:String); // åˆªé™¤æª”案
[V],DeleteDocNoFile,CB_IMGPSScanImp.pas.bk,735,DeleteDocNoFile,,Function DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
[V],DeleteShowFile,CB_IMGPSScanImp.pas.bk,736,DeleteShowFile,,Procedure DeleteShowFile(Path:String); //刪除顯示中的影像
[V],GetNoNameCase,CB_IMGPSScanImp.pas.bk,756,GetNoNameCase,,Function GetNoNameCase(Path:string):String; //取未配號XXXX
[V],_DelTreeForExistImg,CB_IMGPSScanImp.pas.bk,901,_DelTree,,procedure _DelTreeForExistImg(ASourceDir:String);   //2017 åˆªé™¤å‰ç¢ºèª æœ‰èˆŠå½±åƒå—Ž
[V],DeleteDocNoFileForESCAN,CB_IMGPSScanImp.pas.bk,904,DeleteDocNoFile,,function DeleteDocNoFileForESCAN(Path, DocNo: String): Boolean;     //2017 ç¢ºèªæ˜¯å¦æœ‰æœªæ­¸é¡žæ–‡ä»¶
[V],TCB_IMGPSScanX.WNoteBtnClick,CB_IMGPSScanImp.pas.bk,1200,FileExists,,if FileExists(DisplayPath+'Scan_Memo.dat') then
[V],TCB_IMGPSScanX.WNoteBtnClick,CB_IMGPSScanImp.pas.bk,1202,LoadFromFile,,S.LoadFromFile(DisplayPath+'Scan_Memo.dat');
[V],TCB_IMGPSScanX.WNoteBtnClick,CB_IMGPSScanImp.pas.bk,1229,SaveToFile,,S.SaveToFile(DisplayPath+'Scan_Memo.dat');
[V],TCB_IMGPSScanX.InitExistImgList,CB_IMGPSScanImp.pas.bk,1349,LoadFromFile,,ST1.LoadFromFile(casepath+'Download\Context.dat');
[V],TCB_IMGPSScanX.ISB1ImageMouseDown,CB_IMGPSScanImp.pas.bk,1458,LoadFromFile,,TImageScrollBox(Sender).LoadFromFile(TImageScrollBox(Sender).FileName,1);
[V],TCB_IMGPSScanX.ISB1ImageMouseUp,CB_IMGPSScanImp.pas.bk,1506,SaveToFile,,TJpegGraphic(TImageScrollBox(Sender).Graphic).SaveToFile(TImageScrollBox(Sender).FileName);
[V],TCB_IMGPSScanX.DestroyEvent,CB_IMGPSScanImp.pas.bk,1750,_DelTree,,_Deltree(ImagePath);
[V],TCB_IMGPSScanX.PM401Click,CB_IMGPSScanImp.pas.bk,1945,GetNoNameCase,,CaseID := GetNoNameCase(ImageSavePath);
[V],TCB_IMGPSScanX.PM401Click,CB_IMGPSScanImp.pas.bk,1947,Str2Dir,,Str2Dir(NewPath);
[V],TCB_IMGPSScanX.PM401Click,CB_IMGPSScanImp.pas.bk,1954,RenameFile,,ReNameFile(DisplayPath+OldName,NewPath+NewName);
[V],TCB_IMGPSScanX.PM401Click,CB_IMGPSScanImp.pas.bk,1956,SaveToFile,,S.SaveToFile(NewPath+'Context.dat');
[V],TCB_IMGPSScanX.PM401Click,CB_IMGPSScanImp.pas.bk,1964,FileExists,,if FileExists(DisplayPath+'CaseIndex.dat') then  //把原經辦代號取出來再寫入新件裡
[V],TCB_IMGPSScanX.PM401Click,CB_IMGPSScanImp.pas.bk,1966,LoadFromFile,,S.LoadFromFile(DisplayPath+'CaseIndex.dat');
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2159,FileExists,,if FileExists(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat') then
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2161,LoadFromFile,,ST1.LoadFromFile(ImageSavePath + NowCaseno+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2176,DirectoryExists,,if (not DirectoryExists(ImageSavePath + NowCaseno+'\'+DocDir+'\')) and (DocDir <> AttName) then
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2193,CopyFile,,CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2195,SaveToFile,,ContextList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat'); }
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2197,DeleteImageFile,,DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2198,RenameFile,,//RenameFile(iISB.FileName,ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName);
[V],TCB_IMGPSScanX.PM601Click,CB_IMGPSScanImp.pas.bk,2203,ReSortFileName,,ReSortFileName(ExtractFilePath(iISB.FileName));
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2259,Str2Dir,,Str2Dir(SavePath);
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2264,FileExists,,if FileExists(SavePath+'Context.dat') then
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2265,LoadFromFile,,FileList.LoadFromFile(SavePath+'Context.dat');
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2278,CopyFile,,CopyFile(PWideChar(iISB.FileName),PwideChar(ImageSavePath+NowCaseno+'\'+DocDir+'\'+NewName),False);
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2282,SaveToFile,,FileList.SaveToFile(ImageSavePath+NowCaseno+'\'+DocDir+'\Context.dat');}
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2283,DeleteImageFile,,DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
[V],TCB_IMGPSScanX.PM602Click,CB_IMGPSScanImp.pas.bk,2289,ReSortFileName,,ReSortFileName(ExtractFilePath(iISB.FileName));
[V],TCB_IMGPSScanX.PM604Click,CB_IMGPSScanImp.pas.bk,2317,SaveToFile,,iISB.SaveToFile(iISB.FileName);
[V],TCB_IMGPSScanX.PM604Click,CB_IMGPSScanImp.pas.bk,2318,LoadFromFile,,DisplayISB.LoadFromFile(DisplayISB.FileName,1);
[V],TCB_IMGPSScanX.PM605Click,CB_IMGPSScanImp.pas.bk,2350,DeleteImageFile,,DeleteImageFile(ExtractFilePath(iISB.FileName),ExtractFileName(iISB.FileName),NowCaseNo);
[V],TCB_IMGPSScanX.PM605Click,CB_IMGPSScanImp.pas.bk,2354,ReSortFileName,,ReSortFileName(ExtractFilePath(iISB.FileName));
[V],TCB_IMGPSScanX.PM101Click,CB_IMGPSScanImp.pas.bk,2585,_DelTree,,_DelTree(ImageSavePath);
[V],TCB_IMGPSScanX.PM101Click,CB_IMGPSScanImp.pas.bk,2628,DirectoryExists,,if not DirectoryExists(ImageSavePath+FCaseID) then
[V],TCB_IMGPSScanX.PM101Click,CB_IMGPSScanImp.pas.bk,2645,DeleteDocNoFile,,//ShowMessage('DeleteDocNoFileForESCAN');
[V],TCB_IMGPSScanX.DocNoIsExistImg,CB_IMGPSScanImp.pas.bk,2685,FileExists,,if FileExists(DocNopath+'\Context.dat') then   /////20190319 Hong ç•¶æœ‰ç©ºçš„Docno目錄時會掛掉,增加這行
[V],TCB_IMGPSScanX.DocNoIsExistImg,CB_IMGPSScanImp.pas.bk,2686,LoadFromFile,,ST.loadFromfile(DocNopath+'\Context.dat');
[V],TCB_IMGPSScanX._DelTreeForExistImg,CB_IMGPSScanImp.pas.bk,2702,_DelTree,,procedure TCB_IMGPSScanX._DelTreeForExistImg(ASourceDir:String);
[V],TCB_IMGPSScanX.PM102Click,CB_IMGPSScanImp.pas.bk,2732,DirectoryExists,,if DirectoryExists(ImageSavePath+NewCaseID) then
[V],TCB_IMGPSScanX.PM102Click,CB_IMGPSScanImp.pas.bk,2741,RenameFile,,RenameFile(ImageSavePath+NowCaseno,ImageSavePath+NewCaseID);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2819,FindFirst,,FindFirst(FName, faAnyfile, FileRec);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2849,LoadFromFile,,ISB.LoadFromFile(FName, i);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2858,SaveToFile,,///ISB_BW.SaveToFile('KKKKKKKK.tif');
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2934,DirectoryExists,,If DirectoryExists(ImageSavePath + CaseID + '\') Then
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2936,_DelTree,,_DelTree(ImageSavePath + CaseID + '\');
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2942,GetNoNameCase,,CaseID := GetNoNameCase(ImageSavePath);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2947,Str2Dir,,Str2Dir(SavePath);
[V],TCB_IMGPSScanX.PM104Click,CB_IMGPSScanImp.pas.bk,2979,FileExists,,If FileExists(SavePath + 'Context.dat') Then
[V],TCB_IMGPSScanX.PM106Click,CB_IMGPSScanImp.pas.bk,3190,CopyFile,,CopyFormID,Copy2Caseno,CopyFileName : String;
[V],TCB_IMGPSScanX.PM106Click,CB_IMGPSScanImp.pas.bk,3238,LoadFromFile,,S.LoadFromFile(ImageSavePath + Copy2Caseno +'\Context.dat');
[V],TCB_IMGPSScanX.PM106Click,CB_IMGPSScanImp.pas.bk,3260,SaveToFile,,S.SaveToFile(ImageSavePath + Copy2Caseno +'\Context.dat');
[V],TCB_IMGPSScanX.PM109Click,CB_IMGPSScanImp.pas.bk,3400,SaveToFile,,S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
[V],TCB_IMGPSScanX.PM110Click,CB_IMGPSScanImp.pas.bk,3433,Str2Dir,,Str2Dir(SavePath);
[V],TCB_IMGPSScanX.PM507Click,CB_IMGPSScanImp.pas.bk,3588,RenameFile,,RenameFile(DisplayPath+OldName,DisplayPath+NewName);
[V],TCB_IMGPSScanX.PM508Click,CB_IMGPSScanImp.pas.bk,3625,_DelTree,,_DelTree(DisplayPath);
[V],TCB_IMGPSScanX.PM508Click,CB_IMGPSScanImp.pas.bk,3634,SaveToFile,,ContextList.SaveToFile(ImageSavePath + NowCaseno+'\Context.dat');
[V],TCB_IMGPSScanX.PM508Click,CB_IMGPSScanImp.pas.bk,3638,ReSortFileName,,ReSortFileName(DisplayPath);
[V],TCB_IMGPSScanX.PM508Click,CB_IMGPSScanImp.pas.bk,3639,LoadFromFile,,ContextList.LoadFromFile(ImageSavePath + NowCaseno+'\Context.dat');
[V],TCB_IMGPSScanX.PM508Click,CB_IMGPSScanImp.pas.bk,3641,FileExists,,if FileExists(ImageSavePath + NowCaseno+'\CustomDocNo.dat') then
[V],TCB_IMGPSScanX.PM510Click,CB_IMGPSScanImp.pas.bk,3665,SaveToFile,,DisplayISB.SaveToFile(DisplayISB.FileName);
[V],TCB_IMGPSScanX.SampleScanBtnClick,CB_IMGPSScanImp.pas.bk,4009,FileExists,,if (ISB1.FileName <> '') and FileExists(SamplePath+SampleFormID+'.tif') then
[V],TCB_IMGPSScanX.SampleScanBtnClick,CB_IMGPSScanImp.pas.bk,4014,LoadFromFile,,ImageScrollBox1.LoadFromFile(SamplePath+SampleFormID+'.tif',1);
[V],TCB_IMGPSScanX.SampleScanBtnClick,CB_IMGPSScanImp.pas.bk,4016,SaveToFile,,ImageScrollBox1.SaveToFile(SamplePath+SampleFormID+'.jpg');
[V],TCB_IMGPSScanX.AddAttFileLBClick,CB_IMGPSScanImp.pas.bk,4179,FileExists,,if FileExists(ImageSavePath+NowCaseno+'\'+AddFile) then
[V],TCB_IMGPSScanX.AddAttFileLBClick,CB_IMGPSScanImp.pas.bk,4187,CopyFile,,CopyFile(Pchar(OpenDialog1.Files.Strings[i]),Pchar(ImageSavePath+NowCaseno+'\'+AddFile),False);
[V],TCB_IMGPSScanX.AttListBoxDblClick,CB_IMGPSScanImp.pas.bk,4264,FileExists,,if FileExists(DisplayPath+AttFile) then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4466,LoadFromFile,,//DeleteStm.LoadFromFile(Path+'temp.tif');
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4640,FileExists,,if FileExists( PEFileName ) then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4661,SaveToFile,,JpgGr.SaveToFile(PEFileName);
[V],TCB_IMGPSScanX.PageDone,CB_IMGPSScanImp.pas.bk,4697,LoadFromFile,,ISB.LoadFromFile(PEFileName,1);
[V],TCB_IMGPSScanX.PageEnd,CB_IMGPSScanImp.pas.bk,4788,GetNoNameCase,,ScanCaseno := GetNoNameCase(ImageSavePath);
[V],TCB_IMGPSScanX.PageEnd,CB_IMGPSScanImp.pas.bk,4793,DirectoryExists,,if DirectoryExists(ImageSavePath + ScanCaseno+'\') then
[V],TCB_IMGPSScanX.PageEnd,CB_IMGPSScanImp.pas.bk,4795,_DelTree,,_DelTree(ImageSavePath + ScanCaseno+'\');
[V],TCB_IMGPSScanX.PageEnd,CB_IMGPSScanImp.pas.bk,4801,Str2Dir,,Str2Dir(ScanPath);
[V],TCB_IMGPSScanX.PageEnd,CB_IMGPSScanImp.pas.bk,4859,SaveToFile,,//ContextList.SaveToFile(ScanPath+'Context.dat');
[V],TCB_IMGPSScanX.ExportBtClick,CB_IMGPSScanImp.pas.bk,4995,SaveToFile,,S.SaveToFile(LngPath+'mps.dat');
[V],TCB_IMGPSScanX.ExportBtClick,CB_IMGPSScanImp.pas.bk,5000,FileExists,,if FileExists(LngPath+'mps.zip') then
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5036,Str2Dir,,str2dir(ZipPath);
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5039,FileExists,,if not FileExists(ZipPath+'mps.dat') then
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5044,LoadFromFile,,S.LoadFromFile(ZipPath+'mps.dat');
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5054,RenameFile,,RenameFile(ZipPath+S.Strings[i],ZipPath+LicName);
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5085,_DelTree,,_DelTree(ZipPath);
[V],TCB_IMGPSScanX.GetSiteOMR,CB_IMGPSScanImp.pas.bk,5185,LoadFromFile,,ImageScrollBox1.LoadFromFile(FileName,1);
[V],TCB_IMGPSScanX.ReNameContext,CB_IMGPSScanImp.pas.bk,6020,SaveToFile,,ContextList.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DeleteImageFile,CB_IMGPSScanImp.pas.bk,6028,DeleteImageFile,,Procedure TCB_IMGPSScanX.DeleteImageFile(Path,FileName,CaseID:String); // åˆªé™¤æª”案  (無法得到DocDir用)
[V],TCB_IMGPSScanX.DeleteImageFile,CB_IMGPSScanImp.pas.bk,6042,FileExists,,if FileExists(Path+'Context.dat') then
[V],TCB_IMGPSScanX.DeleteImageFile,CB_IMGPSScanImp.pas.bk,6043,LoadFromFile,,FileList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DeleteImageFile,CB_IMGPSScanImp.pas.bk,6049,SaveToFile,,FileList.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DeleteFormCodeFile,CB_IMGPSScanImp.pas.bk,6068,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
[V],TCB_IMGPSScanX.DeleteFormCodeFile,CB_IMGPSScanImp.pas.bk,6069,LoadFromFile,,FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.DeleteFormCodeFile,CB_IMGPSScanImp.pas.bk,6084,DeleteImageFile,,DeleteImageFile(ImageSavePath+CaseID+'\'+DocDir+'\',FileList.Strings[i],CaseID);
[V],TCB_IMGPSScanX.DeleteFormCodeFile,CB_IMGPSScanImp.pas.bk,6090,ReSortFileName,,ReSortFileName(ImageSavePath+CaseID+'\'+DocDir+'\');
[V],TCB_IMGPSScanX.DeleteFormCodeFile,CB_IMGPSScanImp.pas.bk,6111,SaveToFile,,ContextList.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DeleteDocNoFile,CB_IMGPSScanImp.pas.bk,6115,DeleteDocNoFile,,Function TCB_IMGPSScanX.DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
[V],TCB_IMGPSScanX.DeleteDocNoFile,CB_IMGPSScanImp.pas.bk,6132,SaveToFile,,ContextList.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DeleteDocNoFile,CB_IMGPSScanImp.pas.bk,6134,ReSortFileName,,ReSortFileName(Path);
[V],TCB_IMGPSScanX.DeleteDocNoFile,CB_IMGPSScanImp.pas.bk,6135,LoadFromFile,,ContextList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DeleteDocNoFile,CB_IMGPSScanImp.pas.bk,6137,FileExists,,if FileExists(Path+'CustomDocNo.dat') then
[V],TCB_IMGPSScanX.DeleteDocNoFileForESCAN,CB_IMGPSScanImp.pas.bk,6141,DeleteDocNoFile,,Function TCB_IMGPSScanX.DeleteDocNoFileForESCAN(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
[V],TCB_IMGPSScanX.DeleteDocNoFileForESCAN,CB_IMGPSScanImp.pas.bk,6164,SaveToFile,,ContextList.SaveToFile(Path+'\Context.dat');
[V],TCB_IMGPSScanX.DeleteDocNoFileForESCAN,CB_IMGPSScanImp.pas.bk,6165,LoadFromFile,,ContextList.LoadFromFile(Path+'\Context.dat');
[V],TCB_IMGPSScanX.DeleteDocNoFileForESCAN,CB_IMGPSScanImp.pas.bk,6169,_DelTree,,_DelTree(Path);
[V],TCB_IMGPSScanX.DeleteShowFile,CB_IMGPSScanImp.pas.bk,6175,DeleteShowFile,,Procedure TCB_IMGPSScanX.DeleteShowFile(Path:String); //刪除顯示中的影像
[V],TCB_IMGPSScanX.CheckCaseDocNoPage,CB_IMGPSScanImp.pas.bk,6219,LoadFromFile,,S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
[V],TCB_IMGPSScanX.FindFormCodePages,CB_IMGPSScanImp.pas.bk,6287,LoadFromFile,,S.LoadFromFile(ImageSavePath+CaseID+'\upload\Context.dat');
[V],TCB_IMGPSScanX.CaseReSize,CB_IMGPSScanImp.pas.bk,6326,FileExists,,{if FileExists(ImageSavePath+CaseID+'\ReSize.dat') then
[V],TCB_IMGPSScanX.CaseReSize,CB_IMGPSScanImp.pas.bk,6332,LoadFromFile,,S.LoadFromFile(ImageSavePath+CaseID+'\Upload\Context.dat');
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6369,LoadFromFile,,ImageScrollBox1.LoadFromFile(ImageSavePath+CaseID+'\Upload\'+FileName,1);
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6392,SaveToFile,,ImageScrollBox1.SaveToFile(ImageSavePath+CaseID+'\Upload\'+FileName);
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6399,FileExists,,if FileExists(ImageSavePath+CaseID+'\Upload\ReSize.dat') then
[V],TCB_IMGPSScanX.ImageReSize_tmp,CB_IMGPSScanImp.pas.bk,6436,LoadFromFile,,ImageScrollBox1.LoadFromFile(FileName,1);
[V],TCB_IMGPSScanX.ImageReSize_tmp,CB_IMGPSScanImp.pas.bk,6440,SaveToFile,,ImageScrollBox1.SaveToFile(FileName);
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6486,FileExists,,if fileExists(Path+'Context.dat') then
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6488,LoadFromFile,,ContextList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6588,CopyFile,,CopyFile(PWChar(casepath+'Download\FirstImg.zip'),PWChar(path+'FirstImg.zip'),false);
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6609,FindFirst,,FindFirst(FName, faAnyfile, FileRec);
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6728,_DelTree,,//_DelTree(Path);  //會只刪TransPath
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6859,FileExists,,if FileExists(DPath+CaseID+'.zip') then
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6868,Str2Dir,,Str2Dir(AttPath);
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6877,SaveToFile,,SC.SaveToFile(DPath+'Context.dat');
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6889,LoadFromFile,,SC.LoadFromFile(SPath+'Context.dat');
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6901,DeleteDocNoFile,,DeleteDocNoFile(DPath,DocNo);
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6916,CopyFile,,CopyFile(PWideChar(SPath+OldFName),PWideChar(DPath+NewMainFName),False);
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6930,DirectoryExists,,if DirectoryExists(SPath+'AttFile\') then
[V],TCB_IMGPSScanX.Down_Img,CB_IMGPSScanImp.pas.bk,7011,FileExists,,if FileExists(Path+CaseID+'.zip') then
[V],TCB_IMGPSScanX.Down_Img,CB_IMGPSScanImp.pas.bk,7020,Str2Dir,,Str2Dir(AttPath);
[V],TCB_IMGPSScanX.GetNoNameCase,CB_IMGPSScanImp.pas.bk,7033,GetNoNameCase,,Function TCB_IMGPSScanX.GetNoNameCase(Path:String):String; //取未配號XXXX
[V],TCB_IMGPSScanX.GetNoNameCase,CB_IMGPSScanImp.pas.bk,7039,DirectoryExists,,if Not DirectoryExists(Path+_Msg('未配號')+Add_Zoo(i,4)) then
[V],TCB_IMGPSScanX.CaseResort,CB_IMGPSScanImp.pas.bk,7057,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.CaseResort,CB_IMGPSScanImp.pas.bk,7171,FileExists,,if FileExists(Path+OldName) then
[V],TCB_IMGPSScanX.CaseResort,CB_IMGPSScanImp.pas.bk,7173,RenameFile,,ReNameFile(Path+OldName,Path+NewName);
[V],TCB_IMGPSScanX.CaseResort,CB_IMGPSScanImp.pas.bk,7175,SaveToFile,,S.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.CaseResort,CB_IMGPSScanImp.pas.bk,7178,ReSortFileName,,ReSortFileName(Path);
[V],TCB_IMGPSScanX.CaseResort2Scanlist,CB_IMGPSScanImp.pas.bk,7195,FileExists,,if FileExists(Path+'Context.dat') then
[V],TCB_IMGPSScanX.CaseResort2Scanlist,CB_IMGPSScanImp.pas.bk,7196,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.CaseResort2Scanlist,CB_IMGPSScanImp.pas.bk,7294,RenameFile,,//ReNameFile(Path+OldName,Path+NewName);
[V],TCB_IMGPSScanX.CaseResort2Scanlist,CB_IMGPSScanImp.pas.bk,7296,SaveToFile,,S.SaveToFile(Path+'scanlist.dat');
[V],TCB_IMGPSScanX.CaseResort2Scanlist,CB_IMGPSScanImp.pas.bk,7299,ReSortFileName,,ReSortFileName2Scanlist(Path);
[V],TCB_IMGPSScanX.DistinctDocinCase,CB_IMGPSScanImp.pas.bk,7318,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.DistinctDocNoinCase,CB_IMGPSScanImp.pas.bk,7362,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.ClearErrini,CB_IMGPSScanImp.pas.bk,7392,FileExists,,if FileExists(ImageSavePath+CaseID+'\Checkerr.ini') then
[V],TCB_IMGPSScanX.SetCaseList,CB_IMGPSScanImp.pas.bk,7412,FileExists,,if FileExists(ImageSavePath + 'CaseList.dat') then
[V],TCB_IMGPSScanX.SetCaseList,CB_IMGPSScanImp.pas.bk,7413,LoadFromFile,,CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
[V],TCB_IMGPSScanX.SetCaseList,CB_IMGPSScanImp.pas.bk,7443,SaveToFile,,CaseList.SaveToFile(ImageSavePath+'CaseList.dat');
[V],TCB_IMGPSScanX.SetDocNoList,CB_IMGPSScanImp.pas.bk,7456,FileExists,,if FileExists(ImageSavePath+CaseNo+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.SetDocNoList,CB_IMGPSScanImp.pas.bk,7457,LoadFromFile,,CaseDocNoList.LoadFromFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.SetDocNoList,CB_IMGPSScanImp.pas.bk,7507,SaveToFile,,CaseDocNoList.SaveToFile(ImageSavePath+CaseNo+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.SetContextList,CB_IMGPSScanImp.pas.bk,7527,FileExists,,if FileExists(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat') then
[V],TCB_IMGPSScanX.SetContextList,CB_IMGPSScanImp.pas.bk,7528,LoadFromFile,,ContextList.LoadFromFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.SetContextList,CB_IMGPSScanImp.pas.bk,7562,SaveToFile,,ContextList.SaveToFile(ImageSavePath+CaseNo+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.SetAttContextList,CB_IMGPSScanImp.pas.bk,7571,FileExists,,if FileExists(ImageSavePath+CaseNo+'\AttContext.dat') then
[V],TCB_IMGPSScanX.SetAttContextList,CB_IMGPSScanImp.pas.bk,7572,LoadFromFile,,AttContextList.LoadFromFile(ImageSavePath+CaseNo+'\AttContext.dat');
[V],TCB_IMGPSScanX.SetAttContextList,CB_IMGPSScanImp.pas.bk,7605,SaveToFile,,AttContextList.SaveToFile(ImageSavePath+CaseNo+'\AttContext.dat');
[V],TCB_IMGPSScanX.CreateEmptyCase,CB_IMGPSScanImp.pas.bk,7684,SaveToFile,,S.SaveToFile(Path+CaseID+'\Context.dat');
[V],TCB_IMGPSScanX.FormIDReplace,CB_IMGPSScanImp.pas.bk,7749,FileExists,,if FileExists(ImageSavePath + CaseID+'\'+NewDocDir+'\Context.dat') then
[V],TCB_IMGPSScanX.FormIDReplace,CB_IMGPSScanImp.pas.bk,7751,LoadFromFile,,ST1.LoadFromFile(ImageSavePath + CaseID+'\'+NewDocDir+'\Context.dat');
[V],TCB_IMGPSScanX.FormIDReplace,CB_IMGPSScanImp.pas.bk,7795,DirectoryExists,,if Not DirectoryExists(ImageSavePath+CaseID+'\'+NewDocDir) then
[V],TCB_IMGPSScanX.FormIDReplace,CB_IMGPSScanImp.pas.bk,7811,CopyFile,,CopyFile(PWideChar(ImageSavePath+CaseID+'\'+DocDir+'\'+OldFile),PWideChar(ImageSavePath+CaseID+'\'+NewDocDir+'\'+NewFile),False);
[V],TCB_IMGPSScanX.FormIDReplace,CB_IMGPSScanImp.pas.bk,7827,RenameFile,,ReNameFile(Path+OldFile,Path+NewFile);
[V],TCB_IMGPSScanX.FormIDReplace,CB_IMGPSScanImp.pas.bk,7831,SaveToFile,,S.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.ShowFileReplace,CB_IMGPSScanImp.pas.bk,7852,RenameFile,,ReNameFile(Path+OldFile,Path+NewFile);
[V],TCB_IMGPSScanX.PageReplaceFormID,CB_IMGPSScanImp.pas.bk,7867,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.PageReplaceFormID,CB_IMGPSScanImp.pas.bk,7891,RenameFile,,ReNameFile(Path+OldFile,Path+NewFile);
[V],TCB_IMGPSScanX.PageReplaceFormID,CB_IMGPSScanImp.pas.bk,7899,SaveToFile,,S.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.GetCasePage,CB_IMGPSScanImp.pas.bk,7925,FileExists,,if FileExists(Path+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.GetCasePage,CB_IMGPSScanImp.pas.bk,7926,LoadFromFile,,DocDirList.LoadFromFile(Path+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.SetFile2Case,CB_IMGPSScanImp.pas.bk,8006,LoadFromFile,,S.LoadFromFile(ImageSavePath+CaseID+'\Context.dat');
[V],TCB_IMGPSScanX.SetFile2Case,CB_IMGPSScanImp.pas.bk,8008,SaveToFile,,S.SaveToFile(ImageSavePath+CaseID+'\Context.dat');
[V],TCB_IMGPSScanX.WriteResize,CB_IMGPSScanImp.pas.bk,8022,LoadFromFile,,ImageScrollBox1.LoadFromFile(ImgName,1);
[V],TCB_IMGPSScanX.WriteResize,CB_IMGPSScanImp.pas.bk,8045,FileExists,,if FileExists(TxtName) then
[V],TCB_IMGPSScanX.WriteResize,CB_IMGPSScanImp.pas.bk,8049,SaveToFile,,S.SaveToFile(TxtName);
[V],TCB_IMGPSScanX.GetCase_PageCount,CB_IMGPSScanImp.pas.bk,8072,FileExists,,if FileExists(ImageSavePath + 'CaseList.dat') then
[V],TCB_IMGPSScanX.GetCase_PageCount,CB_IMGPSScanImp.pas.bk,8073,LoadFromFile,,CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
[V],TCB_IMGPSScanX.WriteCaseIndex,CB_IMGPSScanImp.pas.bk,8205,SaveToFile,,S.SaveToFile(Path+'CaseIndex.dat');
[V],TCB_IMGPSScanX.ReadCaseIndex,CB_IMGPSScanImp.pas.bk,8221,FileExists,,if FileExists(Path+'CaseIndex.dat') then
[V],TCB_IMGPSScanX.ReadCaseIndex,CB_IMGPSScanImp.pas.bk,8223,LoadFromFile,,S.LoadFromFile(Path+'CaseIndex.dat');
[V],TCB_IMGPSScanX.ReduceLogFile,CB_IMGPSScanImp.pas.bk,8249,FileExists,,if FileExists(LngPath+'IMGPSCheck.log') then
[V],TCB_IMGPSScanX.ReduceLogFile,CB_IMGPSScanImp.pas.bk,8251,LoadFromFile,,ST1.LoadFromFile(LngPath+'IMGPSCheck.log');
[V],TCB_IMGPSScanX.ReduceLogFile,CB_IMGPSScanImp.pas.bk,8258,SaveToFile,,ST1.SaveToFile(LngPath+'IMGPSCheck.log');
[V],TCB_IMGPSScanX.GetDocNoDir,CB_IMGPSScanImp.pas.bk,8304,DirectoryExists,,until not DirectoryExists(Path+iDocNo);
[V],TCB_IMGPSScanX.DocNo2DocNoDir,CB_IMGPSScanImp.pas.bk,8341,DirectoryExists,,until not DirectoryExists(Path+iDocNo);
[V],TCB_IMGPSScanX.DocNoDir2Index,CB_IMGPSScanImp.pas.bk,8374,LoadFromFile,,CaseNo_List.LoadFromFile(Path+'CaseDocNo.dat');
[V],TCB_IMGPSScanX.ZipMainFile,CB_IMGPSScanImp.pas.bk,8395,FileExists,,if fileExists(DePath+ZipName) then
[V],TCB_IMGPSScanX.ZipMainFile,CB_IMGPSScanImp.pas.bk,8412,LoadFromFile,,AttContextList.LoadFromFile(SoPath+'ATTContext.dat');
[V],TCB_IMGPSScanX.ZipMaskFile,CB_IMGPSScanImp.pas.bk,8468,FileExists,,if fileExists(DePath+ZipName) then
[V],TCB_IMGPSScanX.GetFormatID,CB_IMGPSScanImp.pas.bk,8605,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseIndex.dat') then
[V],TCB_IMGPSScanX.GetFormatID,CB_IMGPSScanImp.pas.bk,8607,LoadFromFile,,S.LoadFromFile(ImageSavePath+CaseID+'\CaseIndex.dat');
[V],TCB_IMGPSScanX.CheckCaseBtnClick,CB_IMGPSScanImp.pas.bk,8952,SaveToFile,,S.SaveToFile(ImageSavePath+CaseID+'\OMRCheckOk.dat');
[V],TCB_IMGPSScanX.DrawDocItem2,CB_IMGPSScanImp.pas.bk,9012,FileExists,,if FileExists(ImageSavePath+Caseno+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.DrawDocItem2,CB_IMGPSScanImp.pas.bk,9013,LoadFromFile,,CaseDocNoList.LoadFromFile(ImageSavePath+Caseno+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.DrawDocItem2,CB_IMGPSScanImp.pas.bk,9162,DirectoryExists,,if DirectoryExists(ImageSavePath+Caseno+'\'+AttName) then
[V],TCB_IMGPSScanX.PrtLbClick,CB_IMGPSScanImp.pas.bk,9320,LoadFromFile,,//ontextList.LoadFromFile(ImageSavePath+NowCaseNo+'\Upload\Context.dat');
[V],TCB_IMGPSScanX.UseOldCaseLbClick,CB_IMGPSScanImp.pas.bk,9441,FileExists,,if FileExists(NewPath+'CaseDocNo.dat') then
[V],TCB_IMGPSScanX.UseOldCaseLbClick,CB_IMGPSScanImp.pas.bk,9442,LoadFromFile,,iDocNoList.LoadFromFile(NewPath+'CaseDocNo.dat');
[V],TCB_IMGPSScanX.UseOldCaseLbClick,CB_IMGPSScanImp.pas.bk,9471,DirectoryExists,,if Not DirectoryExists(NewPath+NewDocDir) then
[V],TCB_IMGPSScanX.UseOldCaseLbClick,CB_IMGPSScanImp.pas.bk,9501,CopyFile,,CopyFile(PwideChar(OldPath+OldFile),Pwidechar(NewPath+NewDocDir+'\'+NewFile),False);
[V],TCB_IMGPSScanX.UseOldCaseLbClick,CB_IMGPSScanImp.pas.bk,9504,SaveToFile,,iFileList.SaveToFile(NewPath+NewDocDir+'\Context.dat');
[V],TCB_IMGPSScanX.LastInitFormidListCreate,CB_IMGPSScanImp.pas.bk,9538,LoadFromFile,,ST1.LoadFromFile(path+'FormCode_Name.dat');
[V],TCB_IMGPSScanX.LoadImgFile,CB_IMGPSScanImp.pas.bk,9604,FileExists,,if FileExists(ImageSavePath + 'CaseList.dat') then
[V],TCB_IMGPSScanX.LoadImgFile,CB_IMGPSScanImp.pas.bk,9605,LoadFromFile,,CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
[V],TCB_IMGPSScanX.LoadImgFile,CB_IMGPSScanImp.pas.bk,9617,SaveToFile,,CaseDocNo_CopiesList.SaveToFile(ImageSavePath+CaseList.Strings[i]+'\CaseDocNo_Copies.dat');
[V],TCB_IMGPSScanX.LoadImgFile1,CB_IMGPSScanImp.pas.bk,9689,FileExists,,if FileExists(ImageSavePath + 'CaseList.dat') then
[V],TCB_IMGPSScanX.LoadImgFile1,CB_IMGPSScanImp.pas.bk,9690,LoadFromFile,,CaseList.LoadFromFile(ImageSavePath + 'CaseList.dat');
[V],TCB_IMGPSScanX.LoadImgFile1,CB_IMGPSScanImp.pas.bk,9720,SaveToFile,,Context_DocnoList.SaveToFile(ImageSavePath+CaseList.Strings[n]+'\Context_DocNo.dat');
[V],TCB_IMGPSScanX.LoadAttFile,CB_IMGPSScanImp.pas.bk,9779,FileExists,,if FileExists(ImageSavePath+CaseID+'\AttContext.dat') then
[V],TCB_IMGPSScanX.LoadAttFile,CB_IMGPSScanImp.pas.bk,9781,LoadFromFile,,AttContextList.LoadFromFile(ImageSavePath+CaseID+'\AttContext.dat');
[V],TCB_IMGPSScanX.CheckAvailable,CB_IMGPSScanImp.pas.bk,9915,FileExists,,if FileExists(LngPath+'MPSLIC_SCAN.lic') then
[V],TCB_IMGPSScanX.Case2Mask,CB_IMGPSScanImp.pas.bk,9946,DirectoryExists,,if DirectoryExists(DePath) then
[V],TCB_IMGPSScanX.Case2Mask,CB_IMGPSScanImp.pas.bk,9947,_DelTree,,_DelTree(DePath);
[V],TCB_IMGPSScanX.Case2Mask,CB_IMGPSScanImp.pas.bk,9948,Str2Dir,,Str2Dir(DePath);
[V],TCB_IMGPSScanX.Case2Mask,CB_IMGPSScanImp.pas.bk,9954,LoadFromFile,,S.LoadFromFile(SoPath+'Context.dat');
[V],TCB_IMGPSScanX.Case2Mask,CB_IMGPSScanImp.pas.bk,9964,FileExists,,if FileExists(CheckXmlPath+FWork_no+'\'+FormID+'.xml') then  //沒有Xml就不用遮罩
[V],TCB_IMGPSScanX.GetNewCustomDocNo,CB_IMGPSScanImp.pas.bk,10059,FileExists,,if FileExists(Path+'CustomDocNo.dat') then
[V],TCB_IMGPSScanX.GetNewCustomDocNo,CB_IMGPSScanImp.pas.bk,10062,LoadFromFile,,S.LoadFromFile(Path+'CustomDocNo.dat');
[V],TCB_IMGPSScanX.GetNewCustomDocNo,CB_IMGPSScanImp.pas.bk,10080,SaveToFile,,S.SaveToFile(Path+'CustomDocNo.dat');
[V],PrintWithAutoPrintJob,CB_IMGPSScanImp.pas.bk,10285,LoadFromFile,,ImageScrollBox1.LoadFromFile(Path+S.Strings[i],1);
[V],TCB_IMGPSScanX.FindLastestDocDir,CB_IMGPSScanImp.pas.bk,10307,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.FindLastestDocDir,CB_IMGPSScanImp.pas.bk,10308,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.FindLastestDocDirForPage,CB_IMGPSScanImp.pas.bk,10335,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.FindLastestDocDirForPage,CB_IMGPSScanImp.pas.bk,10336,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.Create_Cust_DocDir,CB_IMGPSScanImp.pas.bk,10401,DirectoryExists,,if DirectoryExists(ImageSavePath+CaseID+'\'+DocNo+'('+inttostr(DocNo_Ct)+')') then  //存在了
[V],TCB_IMGPSScanX.OldCasetoNewCase,CB_IMGPSScanImp.pas.bk,10469,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.OldCasetoNewCase,CB_IMGPSScanImp.pas.bk,10494,SaveToFile,,DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
[V],TCB_IMGPSScanX.ErrFormtoCurrentForm,CB_IMGPSScanImp.pas.bk,10539,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.ErrFormtoCurrentForm,CB_IMGPSScanImp.pas.bk,10545,FileExists,,if FileExists(iPath+'Context.dat') then  //20140909漏加這個判斷造成自訂文件但沒影像會出錯誤訊息
[V],TCB_IMGPSScanX.ErrFormtoCurrentForm,CB_IMGPSScanImp.pas.bk,10555,RenameFile,,RenameFile(iPath+OldFile,iPath+NewFile);
[V],TCB_IMGPSScanX.ErrFormtoCurrentForm,CB_IMGPSScanImp.pas.bk,10556,SaveToFile,,FileList.SaveToFile(iPath+'Context.dat');
[V],TCB_IMGPSScanX.ErrFormtoCurrentForm,CB_IMGPSScanImp.pas.bk,10563,MoveFile,,MoveFile(PWideChar(iPath),PWideChar(iiPath));
[V],TCB_IMGPSScanX.SetRecordEditedDocDir,CB_IMGPSScanImp.pas.bk,10583,FileExists,,if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then
[V],TCB_IMGPSScanX.SetRecordEditedDocDir,CB_IMGPSScanImp.pas.bk,10584,LoadFromFile,,EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
[V],TCB_IMGPSScanX.SetRecordEditedDocDir,CB_IMGPSScanImp.pas.bk,10599,SaveToFile,,EditedDocDirList.SaveToFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
[V],TCB_IMGPSScanX.GetDocDir_Page,CB_IMGPSScanImp.pas.bk,10630,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
[V],TCB_IMGPSScanX.GetDocDir_Page,CB_IMGPSScanImp.pas.bk,10632,LoadFromFile,,FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.Path2DocDir,CB_IMGPSScanImp.pas.bk,10648,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.Path2DocDir,CB_IMGPSScanImp.pas.bk,10649,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.SortDocDir_FormID,CB_IMGPSScanImp.pas.bk,10692,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat') then
[V],TCB_IMGPSScanX.SortDocDir_FormID,CB_IMGPSScanImp.pas.bk,10694,LoadFromFile,,FileList.LoadFromFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.SortDocDir_FormID,CB_IMGPSScanImp.pas.bk,10733,RenameFile,,RenameFile(ImageSavePath+CaseID+'\'+DocDir+'\'+OldName,ImageSavePath+CaseID+'\'+DocDir+'\'+NewName);
[V],TCB_IMGPSScanX.SortDocDir_FormID,CB_IMGPSScanImp.pas.bk,10744,SaveToFile,,FileList.SaveToFile(ImageSavePath+CaseID+'\'+DocDir+'\Context.dat');
[V],TCB_IMGPSScanX.CreateCaseNeedData,CB_IMGPSScanImp.pas.bk,10807,FileExists,,if FileExists(Path+'Context.dat') then
[V],TCB_IMGPSScanX.CreateCaseNeedData,CB_IMGPSScanImp.pas.bk,10809,LoadFromFile,,FileList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.CreateCaseNeedData,CB_IMGPSScanImp.pas.bk,10828,SaveToFile,,DocNoList.SaveToFile(Path+'DocDir.dat');
[V],TCB_IMGPSScanX.TransOldCaseFile,CB_IMGPSScanImp.pas.bk,10902,FileExists,,if FileExists(OldCasePath+'UseCase.dat') and FileExists(OldCasePath+'UseCase.ini') then
[V],TCB_IMGPSScanX.GetDocNoCount,CB_IMGPSScanImp.pas.bk,11148,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.GetDocNoCount,CB_IMGPSScanImp.pas.bk,11150,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.GetDocDirCopies,CB_IMGPSScanImp.pas.bk,11177,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.GetDocDirCopies,CB_IMGPSScanImp.pas.bk,11178,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.SetDocDirCopies,CB_IMGPSScanImp.pas.bk,11206,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.SetDocDirCopies,CB_IMGPSScanImp.pas.bk,11208,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.SetDocDirCopies,CB_IMGPSScanImp.pas.bk,11216,SaveToFile,,DocNo_CopiesList.SaveToFile(ImageSavePath+CaseID+'\CaseDocNo_Copies.dat');
[V],TCB_IMGPSScanX.CaseDelete_Enable,CB_IMGPSScanImp.pas.bk,11377,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.CaseDelete_Enable,CB_IMGPSScanImp.pas.bk,11378,LoadFromFile,,CaseDocNoList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.MoveImage,CB_IMGPSScanImp.pas.bk,11398,LoadFromFile,,FList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.MoveImage,CB_IMGPSScanImp.pas.bk,11403,RenameFile,,Renamefile(Path+Flist.Strings[i],path+'@'+Flist.Strings[i]);
[V],TCB_IMGPSScanX.MoveImage,CB_IMGPSScanImp.pas.bk,11435,SaveToFile,,Flist.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.MoveImage,CB_IMGPSScanImp.pas.bk,11438,ReSortFileName,,ReSortFileName(Path);
[V],TCB_IMGPSScanX.MoveImage_Drag,CB_IMGPSScanImp.pas.bk,11456,LoadFromFile,,FList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.MoveImage_Drag,CB_IMGPSScanImp.pas.bk,11459,RenameFile,,Renamefile(Path+Flist.Strings[i],path+'@'+Flist.Strings[i]);
[V],TCB_IMGPSScanX.MoveImage_Drag,CB_IMGPSScanImp.pas.bk,11493,SaveToFile,,Flist.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.MoveImage_Drag,CB_IMGPSScanImp.pas.bk,11496,ReSortFileName,,ReSortFileName(Path);
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11566,DirectoryExists,,if DirectoryExists(NewPath) then
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11567,_DelTree,,_DelTree(NewPath);
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11568,Str2Dir,,str2dir(NewPath);
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11569,CopyFile,,CopyFile(PWideChar(OldPath+'CaseDocNo.dat'),PWideChar(NewPath+'CaseDocNo.dat'),False);
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11576,FileExists,,if FileExists(OldPath+'CaseDocNo.dat') then
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11578,LoadFromFile,,DocNoList.LoadFromFile(OldPath+'CaseDocNo.dat');
[V],TCB_IMGPSScanX.Case2upload,CB_IMGPSScanImp.pas.bk,11582,SaveToFile,,DocNoList.SaveToFile(OldPath+'CaseDocNo.dat');
[V],TCB_IMGPSScanX.Download2Case,CB_IMGPSScanImp.pas.bk,11684,FileExists,,if (not FileExists(SoDir+'CaseDocNo.dat')) or (not FileExists(SoDir+'DocDir.dat')) then   //截畫面會沒這些檔
[V],TCB_IMGPSScanX.Download2Case,CB_IMGPSScanImp.pas.bk,11690,CopyFile,,AA:=CopyFile(PWideChar(SoDir+'CaseDocNo.dat'),PWideChar(DeDir+'CaseDocNo.dat'),False);
[V],TCB_IMGPSScanX.Download2Case,CB_IMGPSScanImp.pas.bk,11708,LoadFromFile,,//iFileList.LoadFromFile(SoDir+'Context.dat');
[V],TCB_IMGPSScanX.Download2Case,CB_IMGPSScanImp.pas.bk,11738,DirectoryExists,,if not DirectoryExists(DeDir+DocDir) then
[V],TCB_IMGPSScanX.Download2Case,CB_IMGPSScanImp.pas.bk,11748,SaveToFile,,DocNoList.SaveToFile(DeDir+'CaseDocNo.dat');
[V],TCB_IMGPSScanX.DistinctFormCode,CB_IMGPSScanImp.pas.bk,12218,LoadFromFile,,S.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');
[V],TCB_IMGPSScanX.OMRCheckCase,CB_IMGPSScanImp.pas.bk,12420,LoadFromFile,,List.LoadFromFile(ImageSavePath + CaseID+'\upload\Context.dat');
[V],TCB_IMGPSScanX.OMRCheckCase,CB_IMGPSScanImp.pas.bk,12515,FileExists,,if not FileExists(CheckXmlPath+FWork_no+'\'+OMRFormCode+'.xml') then  //沒有Xml就不用檢核
[V],TCB_IMGPSScanX.OMRCheckCase,CB_IMGPSScanImp.pas.bk,12937,SaveToFile,,ValueXT.SaveToFile(ImageSavePath+CaseID+'/GetValue.xml');
[V],TCB_IMGPSScanX.OMRErr2ini,CB_IMGPSScanImp.pas.bk,12981,FileExists,,if FileExists(ImageSavePath + CaseID+'\CheckMemo.dat') then
[V],TCB_IMGPSScanX.OMRErr2ini,CB_IMGPSScanImp.pas.bk,12982,LoadFromFile,,S.LoadFromFile(ImageSavePath + CaseID+'\CheckMemo.dat');
[V],TCB_IMGPSScanX.OMRErr2ini,CB_IMGPSScanImp.pas.bk,12984,SaveToFile,,S.SaveToFile(ImageSavePath + CaseID+'\CheckMemo.dat');
[V],TCB_IMGPSScanX.OMRErrini2ListForLog,CB_IMGPSScanImp.pas.bk,13034,LoadFromFile,,CaseList.LoadFromFile(ImageSavePath+'CaseList.dat');
[V],TCB_IMGPSScanX.view_image_FormCode,CB_IMGPSScanImp.pas.bk,13106,LoadFromFile,,ISB.LoadFromFile(Path+ContextList.Strings[i],1);
[V],TCB_IMGPSScanX.view_image_DocNo,CB_IMGPSScanImp.pas.bk,13230,FileExists,,if FileExists(ImageSavePath+NowCaseno+'\EditedDocDir.dat') then
[V],TCB_IMGPSScanX.view_image_DocNo,CB_IMGPSScanImp.pas.bk,13232,LoadFromFile,,ST1.LoadFromFile(ImageSavePath+NowCaseno+'\EditedDocDir.dat');
[V],TCB_IMGPSScanX.view_image_DocNo,CB_IMGPSScanImp.pas.bk,13284,DirectoryExists,,//if DirectoryExists(Path+'Attach') then
[V],TCB_IMGPSScanX.SpeedButton14Click,CB_IMGPSScanImp.pas.bk,13406,LoadFromFile,,ISB1.LoadFromFile(ISB1.FileName,1);
[V],TCB_IMGPSScanX.SpeedButton14Click,CB_IMGPSScanImp.pas.bk,13411,SaveToFile,,TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
[V],TCB_IMGPSScanX.SpeedButton15Click,CB_IMGPSScanImp.pas.bk,13427,LoadFromFile,,ISB1.LoadFromFile(ISB1.FileName,1);
[V],TCB_IMGPSScanX.SpeedButton15Click,CB_IMGPSScanImp.pas.bk,13432,SaveToFile,,TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
[V],TCB_IMGPSScanX.SpeedButton16Click,CB_IMGPSScanImp.pas.bk,13448,LoadFromFile,,ISB1.LoadFromFile(ISB1.FileName,1);
[V],TCB_IMGPSScanX.SpeedButton16Click,CB_IMGPSScanImp.pas.bk,13453,SaveToFile,,TJpegGraphic(ISB1.Graphic).SaveToFile(ISB1.FileName);
[V],TCB_IMGPSScanX.ISBClick,CB_IMGPSScanImp.pas.bk,13727,LoadFromFile,,ISB1.LoadFromFile(SelectISB.FileName,1);
[V],TCB_IMGPSScanX.ISBImageMouseDown,CB_IMGPSScanImp.pas.bk,13802,LoadFromFile,,ISB1.LoadFromFile(SelectISB.FileName,1);
[V],TCB_IMGPSScanX.GetCaseFormID,CB_IMGPSScanImp.pas.bk,13895,LoadFromFile,,ContextList.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.CreateFormID_FormName,CB_IMGPSScanImp.pas.bk,13926,SaveToFile,,S.SaveToFile(Path + 'FormCode_Name.dat',TEnCoding.UTF8);
[V],TCB_IMGPSScanX.CreateDocNo_DocName,CB_IMGPSScanImp.pas.bk,13948,SaveToFile,,S.SaveToFile(Path+'DocNo_Name.dat',TEnCoding.UTF8);
[V],TCB_IMGPSScanX.CreateIn_WH,CB_IMGPSScanImp.pas.bk,13963,FileExists,,if FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then
[V],TCB_IMGPSScanX.CreateIn_WH,CB_IMGPSScanImp.pas.bk,13964,LoadFromFile,,DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.CreateIn_WH,CB_IMGPSScanImp.pas.bk,13977,SaveToFile,,In_WH_List.SaveToFile(ImageSavePath+CaseID+'\In_Wh.dat');
[V],TCB_IMGPSScanX.CreateDocNo_Info,CB_IMGPSScanImp.pas.bk,14000,FileExists,,if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
[V],TCB_IMGPSScanX.CreateDocNo_Info,CB_IMGPSScanImp.pas.bk,14002,LoadFromFile,,DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.CreateCustDocNo_Info,CB_IMGPSScanImp.pas.bk,14082,FileExists,,if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
[V],TCB_IMGPSScanX.CreateCustDocNo_Info,CB_IMGPSScanImp.pas.bk,14083,LoadFromFile,,DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.CreateDocnoFrom_Info,CB_IMGPSScanImp.pas.bk,14137,FileExists,,if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
[V],TCB_IMGPSScanX.CreateDocnoFrom_Info,CB_IMGPSScanImp.pas.bk,14138,LoadFromFile,,DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.CreateCustDocNoFrom_Info,CB_IMGPSScanImp.pas.bk,14201,FileExists,,if Not FileExists(ImageSavePath+CaseID+'\CaseDocNo.dat') then Exit;
[V],TCB_IMGPSScanX.CreateCustDocNoFrom_Info,CB_IMGPSScanImp.pas.bk,14202,LoadFromFile,,DocDirList.LoadFromFile(ImageSavePath+CaseID+'\CaseDocNo.dat');
[V],TCB_IMGPSScanX.GetDocNoEdit,CB_IMGPSScanImp.pas.bk,14263,FileExists,,if FileExists(ImageSavePath+CaseID+'\EditedDocDir.dat') then
[V],TCB_IMGPSScanX.GetDocNoEdit,CB_IMGPSScanImp.pas.bk,14264,LoadFromFile,,EditedDocDirList.LoadFromFile(ImageSavePath+CaseID+'\EditedDocDir.dat');
[V],TCB_IMGPSScanX.GetDocNo_Count,CB_IMGPSScanImp.pas.bk,14310,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.GetDocNo_Page,CB_IMGPSScanImp.pas.bk,14342,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.Case_DocNoExists,CB_IMGPSScanImp.pas.bk,14406,LoadFromFile,,S.LoadFromFile(ImageSavePath + CaseID+'\Context.dat');
[V],TCB_IMGPSScanX.ReSortFileName,CB_IMGPSScanImp.pas.bk,14427,ReSortFileName,,Procedure TCB_IMGPSScanX.ReSortFileName(Path:String); //檔名重新排序
[V],TCB_IMGPSScanX.ReSortFileName,CB_IMGPSScanImp.pas.bk,14435,FileExists,,if FileExists(Path+'Context.dat') then
[V],TCB_IMGPSScanX.ReSortFileName,CB_IMGPSScanImp.pas.bk,14437,LoadFromFile,,Filelist.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.ReSortFileName,CB_IMGPSScanImp.pas.bk,14444,RenameFile,,ReNameFile(Path+OldName,Path+NewName);
[V],TCB_IMGPSScanX.ReSortFileName,CB_IMGPSScanImp.pas.bk,14447,SaveToFile,,Filelist.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.ReSortFileName_New,CB_IMGPSScanImp.pas.bk,14455,ReSortFileName,,Procedure TCB_IMGPSScanX.ReSortFileName_New(Path:String); //檔名重新排序
[V],TCB_IMGPSScanX.ReSortFileName_New,CB_IMGPSScanImp.pas.bk,14463,FileExists,,if FileExists(Path+'Context.dat') then
[V],TCB_IMGPSScanX.ReSortFileName_New,CB_IMGPSScanImp.pas.bk,14465,LoadFromFile,,Filelist.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.ReSortFileName_New,CB_IMGPSScanImp.pas.bk,14471,RenameFile,,ReNameFile(Path+OldName,Path+NewName);
[V],TCB_IMGPSScanX.ReSortFileName_New,CB_IMGPSScanImp.pas.bk,14474,SaveToFile,,Filelist.SaveToFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.ReSortFileName2Scanlist,CB_IMGPSScanImp.pas.bk,14482,ReSortFileName,,Procedure TCB_IMGPSScanX.ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
[V],TCB_IMGPSScanX.ReSortFileName2Scanlist,CB_IMGPSScanImp.pas.bk,14490,FileExists,,if FileExists(Path+'scanlist.dat') then
[V],TCB_IMGPSScanX.ReSortFileName2Scanlist,CB_IMGPSScanImp.pas.bk,14491,LoadFromFile,,S.LoadFromFile(Path+'scanlist.dat');
[V],TCB_IMGPSScanX.ReSortFileName2Scanlist,CB_IMGPSScanImp.pas.bk,14497,RenameFile,,//ReNameFile(Path+OldName,Path+NewName);
[V],TCB_IMGPSScanX.ReSortFileName2Scanlist,CB_IMGPSScanImp.pas.bk,14500,SaveToFile,,S.SaveToFile(Path+'scanlist.dat');
[V],TCB_IMGPSScanX.GetOMRCheckSet,CB_IMGPSScanImp.pas.bk,14516,FileExists,,if FileExists(CheckXmlPath+'OMRSet.zip') then
[V],TCB_IMGPSScanX.GetOMRCheckSet,CB_IMGPSScanImp.pas.bk,14522,LoadFromFile,,S.LoadFromFile(CheckXmlPath+'LastDateTime.dat');
[V],TCB_IMGPSScanX.GetOMRCheckSet,CB_IMGPSScanImp.pas.bk,14538,SaveToFile,,S.SaveToFile(CheckXmlPath+'LastDateTime.dat');
[V],TCB_IMGPSScanX.GetKeyinSet,CB_IMGPSScanImp.pas.bk,14575,FileExists,,if FileExists(SitePath+'KeyinSet.zip') then
[V],TCB_IMGPSScanX.GetKeyinSet,CB_IMGPSScanImp.pas.bk,14581,LoadFromFile,,S.LoadFromFile(SitePath+'LastDateTime.dat');
[V],TCB_IMGPSScanX.GetKeyinSet,CB_IMGPSScanImp.pas.bk,14596,SaveToFile,,S.SaveToFile(SitePath+'LastDateTime.dat');
[V],TCB_IMGPSScanX.CaseComplete,CB_IMGPSScanImp.pas.bk,14695,FileExists,,if FileExists(Path+'Context.dat') then    //掃描頁數
[V],TCB_IMGPSScanX.CaseComplete,CB_IMGPSScanImp.pas.bk,14697,LoadFromFile,,S.LoadFromFile(Path+'Context.dat');
[V],TCB_IMGPSScanX.Timer1Timer,CB_IMGPSScanImp.pas.bk,14991,GetLocalAppDir,,LngPath := GetLocalAppDir(Handle)+'MPS\CB_IMGPS\';
[V],TCB_IMGPSScanX.Timer1Timer,CB_IMGPSScanImp.pas.bk,14992,Str2Dir,,Str2Dir(LngPath);
[V],TCB_IMGPSScanX.Timer1Timer,CB_IMGPSScanImp.pas.bk,15202,_DelTree,,_Deltree(ImagePath);
[V],TCB_IMGPSScanX.Timer1Timer,CB_IMGPSScanImp.pas.bk,15234,FileExists,,//if not FileExists(ImageSavePath+FCaseID+'\CaseDocNo_Copies.dat') then   //這個會在Download2Case時一律產生所以不能有這行 20141013
[V],TCB_IMGPSScanX.TransBtnClick,CB_IMGPSScanImp.pas.bk,15415,LoadFromFile,,S.LoadFromFile(TransPath + 'Context.dat');
[V],TCB_IMGPSScanX.TreeView1Click,CB_IMGPSScanImp.pas.bk,15592,FileExists,,If FileExists(DisplayPath+'\upload\Checkerr.ini') and (not FileExists(DisplayPath+'\upload\OMRCheckOk.dat')) Then
[V],TCB_IMGPSScanX.TreeView1Click,CB_IMGPSScanImp.pas.bk,15596,LoadFromFile,,CaseDocNoList.LoadFromFile(DisplayPath+'CaseDocNo.dat');
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15806,RenameFile,,{ReNameFile(DisplayISB.FileName,NewPath+NewFileName);
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15869,CopyFile,,CopyFile(PWideChar(OldFileName),PwideChar(NewPath+NewFileName),False);
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15871,DeleteImageFile,,DeleteImageFile(ExtractFilePath(OldFileName),ExtractFileName(OldFileName),NowCaseNo);
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15881,LoadFromFile,,ContextList.LoadFromFile(DisplayPath+'Context.dat');
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15889,SaveToFile,,ContextList.SaveToFile(NewPath+'Context.dat');
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15901,_DelTree,,_DelTree(DisplayPath);
[V],TCB_IMGPSScanX.TreeView1DragDrop,CB_IMGPSScanImp.pas.bk,15910,ReSortFileName,,ReSortFileName(DisplayPath);
[V],TCB_IMGPSScanX.Set_language,CB_IMGPSScanImp.pas.bk,16085,FileExists,,if FileExists(LngPath+'Language.lng') then
[V],TErrlistForm.RejectBtClick,ErrList.pas,155,FileExists,,if FileExists(iniPath+'RemoveMemo.dat') then
[V],TErrlistForm.RejectBtClick,ErrList.pas,156,LoadFromFile,,S.LoadFromFile(iniPath+'RemoveMemo.dat');
[V],TErrlistForm.RejectBtClick,ErrList.pas,161,SaveToFile,,S.SaveToFile(iniPath+'RemoveMemo.dat');
[V],TErrlistForm.DeleteBtClick,ErrList.pas,189,FileExists,,if FileExists(iniPath+'RemoveMemo.dat') then
[V],TErrlistForm.DeleteBtClick,ErrList.pas,190,LoadFromFile,,S.LoadFromFile(iniPath+'RemoveMemo.dat');
[V],TErrlistForm.DeleteBtClick,ErrList.pas,197,SaveToFile,,S.SaveToFile(iniPath+'RemoveMemo.dat');
[V],TErrlistForm.EnforceBtClick,ErrList.pas,241,FileExists,,if FileExists(iniPath+'RemoveMemo.dat') then
[V],TErrlistForm.EnforceBtClick,ErrList.pas,242,LoadFromFile,,S.LoadFromFile(iniPath+'RemoveMemo.dat');
[V],TErrlistForm.EnforceBtClick,ErrList.pas,252,SaveToFile,,S.SaveToFile(iniPath+'RemoveMemo.dat');
[V],TErrlistForm.GetOMRErrini,ErrList.pas,485,LoadFromFile,,ImageScrollBox1.LoadFromFile(FileName,1);
[V],TErrlistForm.GetOMRErrini,ErrList.pas,504,FileExists,,if (RelaFileName <> '') and FileExists(RelaFileName) then //¦³Ãö«Y¼v¹³
[V],TOldCaseInfoForm.Down_Img,OldCaseInfo.pas,131,FileExists,,if FileExists(Path+CaseID+'.zip') then
[V],TOldCaseInfoForm.LoadImg,OldCaseInfo.pas,185,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\CaseDocNo.dat') then
[V],TOldCaseInfoForm.LoadImg,OldCaseInfo.pas,186,LoadFromFile,,DocDirList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\CaseDocNo.dat');
[V],TOldCaseInfoForm.DocNo2DocName,OldCaseInfo.pas,233,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\DocNo_Name.dat') then
[V],TOldCaseInfoForm.DocNo2DocName,OldCaseInfo.pas,234,LoadFromFile,,DocNo_DocNameList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\DocNo_Name.dat',TEnCoding.UTF8);
[V],TOldCaseInfoForm.Docdir2Pages,OldCaseInfo.pas,261,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat') then
[V],TOldCaseInfoForm.Docdir2Pages,OldCaseInfo.pas,262,LoadFromFile,,FileList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat');
[V],TOldCaseInfoForm.ShowImage,OldCaseInfo.pas,317,FileExists,,if FileExists(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat') then
[V],TOldCaseInfoForm.ShowImage,OldCaseInfo.pas,318,LoadFromFile,,FileList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\Context.dat');
[V],TOldCaseInfoForm.ErrFormtoCurrentForm,OldCaseInfo.pas,382,LoadFromFile,,DocNoList.LoadFromFile(ImageSavePath+CaseID+'\'+UseCaseID+'\CaseDocNo.dat',Tencoding.UTF8);
[V],TOldCaseInfoForm.ErrFormtoCurrentForm,OldCaseInfo.pas,400,RenameFile,,RenameFile(iPath+OldFile,iPath+NewFile);
[V],TOldCaseInfoForm.ErrFormtoCurrentForm,OldCaseInfo.pas,401,SaveToFile,,FileList.SaveToFile(iPath+'Context.dat',Tencoding.UTF8);
[V],TOldCaseInfoForm.ErrFormtoCurrentForm,OldCaseInfo.pas,412,MoveFile,,//MoveFile(PWideChar(iPath),PWideChar(iiPath));
[V],TOldCaseInfoForm.ISBClick,OldCaseInfo.pas,595,LoadFromFile,,ISB1.LoadFromFile(SelectISB.FileName,1);
[V],TOldCaseInfoForm.LoadBtClick,OldCaseInfo.pas,812,FileExists,,if not FileExists(imageSavePath+CaseID+'\'+UseCaseID+'\Context.dat') then
[V],TOldCaseInfoForm.LoadBtClick,OldCaseInfo.pas,814,DirectoryExists,,if DirectoryExists(ImageSavePath+CaseID+'\'+UseCaseID) then
[V],TOldCaseInfoForm.LoadBtClick,OldCaseInfo.pas,815,_DelTree,,_Deltree(ImageSavePath+CaseID+'\'+UseCaseID);
[V],Global_Or_Interface,CB_IMGPSScanImp.pas.bk,8,Scanner,,EnScan,   { for Scanner }
[V],Button6Click,CB_IMGPSScanImp.pas.bk,466,Scanner,,ScannerReverse : Boolean; //是否需反相
[V],initkscan,CB_IMGPSScanImp.pas.bk,698,initkscan,,Procedure initkscan; //檢查掃描器的功能
[V],PageEnd,CB_IMGPSScanImp.pas.bk,873,PageEnd,,procedure PageEnd;   //掃描接收完成
[V],PageDone,CB_IMGPSScanImp.pas.bk,874,PageDone,,Procedure PageDone;  //掃描完成後顯示影像
[V],StatrTwainScan,CB_IMGPSScanImp.pas.bk,875,StatrTwainScan,,procedure StatrTwainScan;
[V],OnAcquire,CB_IMGPSScanImp.pas.bk,876,OnAcquire,,procedure OnAcquire( const DibHandle    : THandle;
[V],TCB_IMGPSScanX.NewScanBtnClick,CB_IMGPSScanImp.pas.bk,2416,StatrTwainScan,,StatrTwainScan;
[V],TCB_IMGPSScanX.OptionBtnClick,CB_IMGPSScanImp.pas.bk,2479,Scanner,,PatchDlg.ReverseCB.Checked := ScannerReverse;
[V],TCB_IMGPSScanX.PM505Click,CB_IMGPSScanImp.pas.bk,3538,StatrTwainScan,,StatrTwainScan;
[V],TCB_IMGPSScanX.SampleScanBtnClick,CB_IMGPSScanImp.pas.bk,4003,StatrTwainScan,,StatrTwainScan;
[V],TCB_IMGPSScanX.SelectScanBtnClick,CB_IMGPSScanImp.pas.bk,4096,SelectScanner,,scanner.SelectScanner;
[V],TCB_IMGPSScanX.SelectScanBtnClick,CB_IMGPSScanImp.pas.bk,4096,scanner.SelectScanner,,scanner.SelectScanner;
[V],TCB_IMGPSScanX.SelectScanBtnClick,CB_IMGPSScanImp.pas.bk,4096,Scanner,,scanner.SelectScanner;
[V],TCB_IMGPSScanX.AddScanBtnClick,CB_IMGPSScanImp.pas.bk,4230,StatrTwainScan,,StatrTwainScan;
[V],TCB_IMGPSScanX.Button3Click,CB_IMGPSScanImp.pas.bk,4293,initkscan,,//initkscan;
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4390,StatrTwainScan,,procedure TCB_IMGPSScanX.StatrTwainScan;
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4394,Scanner,,if not Scanner.IsConfigured then
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4412,Scanner.OpenSource,,Scanner.OpenSource;
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4426,Scanner.CloseSource,,Scanner.CloseSource;
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4431,OnAcquire,,Scanner.AcquireWithSourceOpen( OnAcquire, LongInt(@ScanInfo));
[V],TCB_IMGPSScanX.StatrTwainScan,CB_IMGPSScanImp.pas.bk,4431,Scanner.AcquireWithSourceOpen,,Scanner.AcquireWithSourceOpen( OnAcquire, LongInt(@ScanInfo));
[V],TCB_IMGPSScanX.OnAcquire,CB_IMGPSScanImp.pas.bk,4444,OnAcquire,,procedure TCB_IMGPSScanX.OnAcquire( const DibHandle    : THandle;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4505,Scanner,,IF ScannerReverse then
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4635,PageEnd,,PageEnd;
[V],Deletepage,CB_IMGPSScanImp.pas.bk,4667,PageDone,,PageDone;
[V],TCB_IMGPSScanX.PageDone,CB_IMGPSScanImp.pas.bk,4684,PageDone,,procedure TCB_IMGPSScanX.PageDone;
[V],TCB_IMGPSScanX.PageEnd,CB_IMGPSScanImp.pas.bk,4734,PageEnd,,procedure TCB_IMGPSScanX.PageEnd;
[V],TCB_IMGPSScanX.R_W_Scanini,CB_IMGPSScanImp.pas.bk,5264,Scanner,,ScannerReverse := ini.ReadBool('Scanner','Reverse',Def_ScannerReverse);
[V],TCB_IMGPSScanX.GetDefScanIni,CB_IMGPSScanImp.pas.bk,5303,Scanner,,Def_ScannerReverse := False;
[V],TCB_IMGPSScanX.initkscan,CB_IMGPSScanImp.pas.bk,9242,initkscan,,procedure TCB_IMGPSScanX.initkscan;
[V],TCB_IMGPSScanX.initkscan,CB_IMGPSScanImp.pas.bk,9245,Scanner,,if Scanner.IsConfigured then
[V],TCB_IMGPSScanX.initkscan,CB_IMGPSScanImp.pas.bk,9248,Scanner.OpenSource,,Scanner.OpenSource;
[V],TCB_IMGPSScanX.initkscan,CB_IMGPSScanImp.pas.bk,9259,Scanner.CloseSource,,Scanner.CloseSource;
[V],TCB_IMGPSScanX.Timer1Timer,CB_IMGPSScanImp.pas.bk,15146,initkscan,,initkscan;
[V],Global_Or_Interface,PatchFom.pas,18,Scanner,,ScannerGB: TGroupBox;
[V],TPatchDlg.DefaultBtClick,PatchFom.pas,91,Scanner,,ReverseCB.Checked := Def_ScannerReverse;
[V],Global_Or_Interface,CB_IMGPSScanImp.pas.bk,25,IIS_Ftp,,SBSocket,IIS_Ftp, SBSimpleFTPS;
[V],Global_Or_Interface,CB_IMGPSScanImp.pas.bk,277,TElHTTPSClient,,HTTPSClient: TElHTTPSClient;
[V],Global_Or_Interface,CB_IMGPSScanImp.pas.bk,279,TElSimpleFTPSClient,,FTPSClient1: TElSimpleFTPSClient;
[V],HTTPSClientCertificateValidate,CB_IMGPSScanImp.pas.bk,348,HTTPSClientCertificateValidate,,procedure HTTPSClientCertificateValidate(Sender: TObject;
[V],SetFtpInfo,CB_IMGPSScanImp.pas.bk,635,SetFtpInfo,,Procedure SetFtpInfo;     //餵入FTP資訊
[V],FtpCaseComplete,CB_IMGPSScanImp.pas.bk,636,FtpCaseComplete,,Function FtpCaseComplete(SendData:String):Boolean;
[V],LoadFileGetMD5,CB_IMGPSScanImp.pas.bk,899,LoadFileGetMD5,,function LoadFileGetMD5(const filename:string):string; //20170809 å–的檔案的MD5
[V],TCB_IMGPSScanX.InitExistImgList,CB_IMGPSScanImp.pas.bk,1352,LoadFileGetMD5,,LogFile1.LogToFile(logTimeString+casepath+'Download\'+ST1.Strings[i]+',MD5='+LoadFileGetMD5(casepath+'Download\'+ST1.Strings[i]));
[V],TCB_IMGPSScanX.SampleScanBtnClick,CB_IMGPSScanImp.pas.bk,4021,upFile,,if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',SamplePath+SampleFormID+'.tif',FReWrite,Memo1,False) then
[V],TCB_IMGPSScanX.Button5Click,CB_IMGPSScanImp.pas.bk,4373,SetFtpInfo,,SetFtpInfo;
[V],TCB_IMGPSScanX.Button5Click,CB_IMGPSScanImp.pas.bk,4374,IIS_Ftp,,IIS_Ftp.FtpsConnect;
[V],TCB_IMGPSScanX.Button6Click,CB_IMGPSScanImp.pas.bk,4382,SetFtpInfo,,SetFtpInfo;
[V],TCB_IMGPSScanX.Button6Click,CB_IMGPSScanImp.pas.bk,4383,IIS_Ftp,,IIS_Ftp.FtpsConnect;
[V],TCB_IMGPSScanX.ExportBtClick,CB_IMGPSScanImp.pas.bk,4958,En_DecryptionStr_Base64,,SFileName := En_DecryptionStr_Base64('E','MPSLIC_SCAN.lic','9338430');
[V],TCB_IMGPSScanX.ExportBtClick,CB_IMGPSScanImp.pas.bk,4968,dnFile,,//if not dnFile(HTTPSClient,Furl,'servlet/CWC03',SendData,LngPath+SFileName,FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.ExportBtClick,CB_IMGPSScanImp.pas.bk,4970,dnFile_Get,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+SFileName,FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5045,En_DecryptionStr_Base64,,if (En_DecryptionStr_Base64('D',S.Strings[0],'9338430')<> ServerDate) then
[V],TCB_IMGPSScanX.ImportBtClick,CB_IMGPSScanImp.pas.bk,5058,upFile,,//if not upFile(HTTPSClient,FUrl,'servlet/CWC04','formid='+LicName+'@workno=CW@mode=sample','file',ZipPath+LicName,FReWrite,Memo1,False) then
[V],TCB_IMGPSScanX.HTTPSClientCertificateValidate,CB_IMGPSScanImp.pas.bk,5473,HTTPSClientCertificateValidate,,procedure TCB_IMGPSScanX.HTTPSClientCertificateValidate(Sender: TObject;
[V],TCB_IMGPSScanX.GetServerDate,CB_IMGPSScanImp.pas.bk,5603,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/servertimeforocx','',FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSampleInf,CB_IMGPSScanImp.pas.bk,5637,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/serversampleforocx','work_no='+FWork_no,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf1,CB_IMGPSScanImp.pas.bk,5674,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf1,CB_IMGPSScanImp.pas.bk,5679,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=1&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf2,CB_IMGPSScanImp.pas.bk,5716,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf2,CB_IMGPSScanImp.pas.bk,5719,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=2&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf3,CB_IMGPSScanImp.pas.bk,5755,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf3,CB_IMGPSScanImp.pas.bk,5759,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=3&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf4,CB_IMGPSScanImp.pas.bk,5796,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf4,CB_IMGPSScanImp.pas.bk,5799,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=4&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf5,CB_IMGPSScanImp.pas.bk,5836,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf5,CB_IMGPSScanImp.pas.bk,5839,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=5&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf6,CB_IMGPSScanImp.pas.bk,5876,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf6,CB_IMGPSScanImp.pas.bk,5879,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=6&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.GetSetInf7,CB_IMGPSScanImp.pas.bk,5916,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetSetInf7,CB_IMGPSScanImp.pas.bk,5919,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC01/tables','checktime='+EnCodeDateTime+'&mode=7&col='+En_DecryptionStr_Base64('E',ColumeStr,Mpskey)+'&work_no='+FWork_No,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.ImageReSize_FormID,CB_IMGPSScanImp.pas.bk,6388,LoadFileGetMD5,,if (ISExistImg(ImageSavePath+CaseID+'\Upload\'+FileName)) and (reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\Upload\'+FileName))=-1) then
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6656,upFile,,if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/caseupload',SendData,'file',Path+'Img.zip',FReWrite,Memo1,False) then
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6680,SetFtpInfo,,SetFtpInfo;
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6682,IIS_Ftp,,if not IIS_Ftp.FtpsConnect then
[V],TCB_IMGPSScanX.TransCaseID,CB_IMGPSScanImp.pas.bk,6695,FtpCaseComplete,,if not FtpCaseComplete(SendData) then    //Ftp上傳後通知完成
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6838,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.GetNode2Name,CB_IMGPSScanImp.pas.bk,6840,dnFile,,if not dnFile(HTTPSClient,DownUrl,'','',DPath+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.DownLoadImage,CB_IMGPSScanImp.pas.bk,6959,SetFtpInfo,,SetFtpInfo;
[V],TCB_IMGPSScanX.DownLoadImage,CB_IMGPSScanImp.pas.bk,6961,IIS_Ftp,,if not IIS_Ftp.FtpsConnect then
[V],TCB_IMGPSScanX.Down_Img,CB_IMGPSScanImp.pas.bk,6987,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TCB_IMGPSScanX.Down_Img,CB_IMGPSScanImp.pas.bk,6991,dnFile_Get,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.Down_Img,CB_IMGPSScanImp.pas.bk,6991,dnFile,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.DistinctDocinCase,CB_IMGPSScanImp.pas.bk,7323,LoadFileGetMD5,,if (ISExistImg(Path+S.Strings[i])) or (reSizeExistImgList.IndexOf(LoadFileGetMD5(Path+S.Strings[i]))<>-1)  then
[V],TCB_IMGPSScanX.LoadFileGetMD5,CB_IMGPSScanImp.pas.bk,9551,LoadFileGetMD5,,function TCB_IMGPSScanX.LoadFileGetMD5(const filename: string): string;
[V],TCB_IMGPSScanX.LoadFileGetMD5,CB_IMGPSScanImp.pas.bk,9558,TIdHashMessageDigest5,,idmd5:TIdHashMessageDigest5;  //import IdHashMessageDigest, idHash
[V],TCB_IMGPSScanX.CheckAvailable,CB_IMGPSScanImp.pas.bk,9835,dnFile_Get,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.CheckAvailable,CB_IMGPSScanImp.pas.bk,9835,dnFile,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC04/sample',SendData,LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.CheckAvailable,CB_IMGPSScanImp.pas.bk,9891,upFile,,if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/sample',SendData,'file',LngPath+'MPSLIC_SCAN.lic',FReWrite,Memo1,False) then
[V],TCB_IMGPSScanX.TransOldCaseFile,CB_IMGPSScanImp.pas.bk,10910,upFile,,if not upFile(HTTPSClient,FUrl,'service/imgpsc/IMGPSC02/useOther',SendData,'file',OldCasePath+'UseCase.ini',FReWrite,Memo1,False) then
[V],DecodeFtpInfo,CB_IMGPSScanImp.pas.bk,10976,En_DecryptionStr_Base64,,FtpStr := En_DecryptionStr_Base64('D',EncryStr,MpsKey);
[V],DecodeFtpInfo,CB_IMGPSScanImp.pas.bk,10994,ProcessServlet_FormData,,If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/ftps',SendData,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.SetFtpInfo,CB_IMGPSScanImp.pas.bk,11042,SetFtpInfo,,Procedure TCB_IMGPSScanX.SetFtpInfo;     //餵入FTP資訊
[V],TCB_IMGPSScanX.SetFtpInfo,CB_IMGPSScanImp.pas.bk,11044,IIS_Ftp,,IIS_Ftp.Display1 := Display1;
[V],TCB_IMGPSScanX.FtpCaseComplete,CB_IMGPSScanImp.pas.bk,11072,FtpCaseComplete,,Function TCB_IMGPSScanX.FtpCaseComplete(SendData:String):Boolean;
[V],TCB_IMGPSScanX.FtpCaseComplete,CB_IMGPSScanImp.pas.bk,11075,ProcessServlet_FormData,,If not ProcessServlet_FormData(HTTPSClient,FURL+'service/imgpsc/IMGPSC02/caseupload',SendData,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.ISExistImg,CB_IMGPSScanImp.pas.bk,11359,LoadFileGetMD5,,if ExistImgList.IndexOf(LoadFileGetMD5(filename))<>-1 then
[V],TCB_IMGPSScanX.DistinctFormCode,CB_IMGPSScanImp.pas.bk,12222,LoadFileGetMD5,,LogFile1.LogToFile(logTimeString+S.Strings[i]+' reSizeExistImgList='+BoolToStr(reSizeExistImgList.IndexOf(LoadFileGetMD5(ImageSavePath+CaseID+'\upload\'+S.Strings[i]))<>-1,true));
[V],TCB_IMGPSScanX.DownLanguage,CB_IMGPSScanImp.pas.bk,13062,dnFile,,//dnFile(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite.Text,Memo1,False,DownImgStatus)
[V],TCB_IMGPSScanX.DownLanguage,CB_IMGPSScanImp.pas.bk,13063,dnFile_Get,,If not dnFile_Get(HTTPSClient,FUrl+'Language.Lng','','',LngPath+'Language.Lng',FReWrite,Memo1,False,DownImgStatus) Then
[V],TCB_IMGPSScanX.GetOMRCheckSet,CB_IMGPSScanImp.pas.bk,14527,dnFile_Get,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,CheckXmlPath+'OMRSet.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.GetOMRCheckSet,CB_IMGPSScanImp.pas.bk,14527,dnFile,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,CheckXmlPath+'OMRSet.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.GetKeyinSet,CB_IMGPSScanImp.pas.bk,14585,dnFile_Get,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,SitePath+'KeyinSet.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.GetKeyinSet,CB_IMGPSScanImp.pas.bk,14585,dnFile,,if not dnFile_Get(HTTPSClient,Furl,'service/imgpsc/IMGPSC01/settings',SendData,SitePath+'KeyinSet.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TCB_IMGPSScanX.CaseAsk,CB_IMGPSScanImp.pas.bk,14634,ProcessServlet_Get,,If not ProcessServlet_Get(HTTPSClient,FURL+'service/imgpsc/IMGPSC05/isnew',SendData,FReWrite,Memo1,False) Then
[V],TCB_IMGPSScanX.CaseComplete,CB_IMGPSScanImp.pas.bk,14689,En_DecryptionStr_Base64,,EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],Global_Or_Interface,OldCaseInfo.pas,40,TElHTTPSClient,,HTTPSClient: TElHTTPSClient;
[V],HTTPSClientCertificateValidate,OldCaseInfo.pas,46,HTTPSClientCertificateValidate,,procedure HTTPSClientCertificateValidate(Sender: TObject;
[V],TOldCaseInfoForm.Down_Img,OldCaseInfo.pas,108,En_DecryptionStr_Base64,,//EnCodeDateTime := En_DecryptionStr_Base64('E',ServerDate+GetBalance2Time(Balance),Mpskey);
[V],TOldCaseInfoForm.Down_Img,OldCaseInfo.pas,113,dnFile_Get,,if not dnFile_Get(HTTPSClient,Furl,'service/slic/SLIC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TOldCaseInfoForm.Down_Img,OldCaseInfo.pas,113,dnFile,,if not dnFile_Get(HTTPSClient,Furl,'service/slic/SLIC04/case',SendData,Path+CaseID+'.zip',FReWrite,Memo1,False,DownImgStatus) then
[V],TOldCaseInfoForm.HTTPSClientCertificateValidate,OldCaseInfo.pas,710,HTTPSClientCertificateValidate,,procedure TOldCaseInfoForm.HTTPSClientCertificateValidate(Sender: TObject;
scripts/dist/readme.md
比對新檔案
@@ -0,0 +1,18 @@
### 模組引用相依分析
.image, .io, .scan, .transp, 分別代表 影像, IO, 掃描, Transportation
- [deps.all.csv](deps.all.csv)(合併以下所有)
- [CB_IMGPSScanImp.pas.bk.image.csv](CB_IMGPSScanImp.pas.bk.image.csv)
- [CB_IMGPSScanImp.pas.bk.io.csv](CB_IMGPSScanImp.pas.bk.io.csv)
- [CB_IMGPSScanImp.pas.bk.scan.csv](CB_IMGPSScanImp.pas.bk.scan.csv)
- [CB_IMGPSScanImp.pas.bk.transp.csv](CB_IMGPSScanImp.pas.bk.transp.csv)
- [ErrList.pas.image.csv](ErrList.pas.image.csv)
- [ErrList.pas.io.csv](ErrList.pas.io.csv)
- [OldCaseInfo.pas.image.csv](OldCaseInfo.pas.image.csv)
- [OldCaseInfo.pas.io.csv](OldCaseInfo.pas.io.csv)
- [OldCaseInfo.pas.transp.csv](OldCaseInfo.pas.transp.csv)
- [PatchFom.pas.image.csv](PatchFom.pas.image.csv)
- [PatchFom.pas.scan.csv](PatchFom.pas.scan.csv)
scripts/dist/scanimpl_annalysis.remainings.txt
比對新檔案
@@ -0,0 +1,1050 @@
unit CB_IMGPSScanImp;
//TEST
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
  EnScan,   { for Scanner }
  EnDiGrph, { for TDibGraphic }
  EnMisc,   { for MinFloat }
  EnTifGr,  { for TTifGraphic }
  {$IFDEF Production}
  CB_IMGPSScan_TLB,
  {$ENDIF}
  {$IFDEF Test}
  CB_IMGPSScan_test_TLB,
  {$ENDIF}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ActiveX, AxCtrls, StdVcl, VCLUnZip, VCLZip, Encryp,
  ExtCtrls, ComCtrls, Menus, StdCtrls, Gauges, EnImgScr, PJMenuSpeedButtons,
  Buttons, ImgList, SBSimpleSSL, SBHTTPSClient, SBWinCertStorage, SBX509,
  SBCustomCertStorage, SBUtils,mpsBarco,BarcodesFinder,HTTPApp,ErrList,
  Xmltool,inifiles,printers,IdHashMessageDigest, idHash, LogFile,ShellApi,
  SBSocket,IIS_Ftp, SBSimpleFTPS;
Type
  TTransMode =(tsHttp,tsFtp,tsNone);
var
  Ch_WriteNote : Boolean;
  RejectCase : Boolean;
  ErrIndex : Integer;
  //*****預設區*****//
    Def_DeviceDelete : Boolean;  //空白頁刪除啟動
    Def_DeviceDeleteSize : Integer;  //空白頁Size
    Def_ScannerReverse : Boolean; //是否需反相
    Def_BoardClear : Boolean; //是否清黑邊
    Def_ScanDpi : Integer;    //掃瞄DPI
    Def_ScanDuplex : Boolean; //是否雙面掃瞄
    Def_ScanRotate : Integer; //掃瞄時旋轉角度
    Def_ScanDeskew : Boolean; //是否傾斜矯正
    Def_ScanBright : Integer; //亮度
    Def_ScanContrast : Integer; //對比
    Def_ScanImgShowMode : Integer; //0:清楚影像 1:不清楚影像 2:不顯示
    Def_ScanImgSetUse : Boolean; //是否使用亮度對比設定
  //*****預設區*****//
Const
  ISBName = 'PreViewISB';
{獲取自身版本號所需要 }
type
  TVersionLanguage = (vlArabic, vlBulgarian, vlCatalan, vlTraditionalChinese,
     vlCzech, vlDanish, vlGerman, vlGreek, vlUSEnglish, vlCastilianSpanish,
     vlFinnish, vlFrench, vlHebrew, vlHungarian, vlIcelandic, vlItalian,
     vlJapanese, vlKorean, vlDutch, vlNorwegianBokmel, vlPolish,
     vlBrazilianPortuguese, vlRhaetoRomanic, vlRomanian, vlRussian,
     vlCroatoSerbian, vlSlovak, vlAlbanian, vlSwedish, vlThai, vlTurkish,
     vlUrdu, vlBahasa, vlSimplifiedChinese, vlSwissGerman, vlUKEnglish,
     vlMexicanSpanish, vlBelgianFrench, vlSwissItalian, vlBelgianDutch,
     vlNorwegianNynorsk, vlPortuguese, vlSerboCroatian, vlCanadianFrench,
     vlSwissFrench, vlUnknown);
const LanguageValues: array[TVersionLanguage] of Word = ($0401, $0402, $0403,
   $0404, $0405, $0406, $0407, $0408, $0409, $040A, $040B, $040C, $040D,
   $040E, $040F, $0410, $0411, $0412, $0413, $0414, $0415, $0416, $0417,
   $0418, $0419, $041A, $041B, $041C, $041D, $041E, $041F, $0420, $0421,
   $0804, $0807, $0809, $080A, $080C, $0810, $0813, $0814, $0816, $081A,
   $0C0C, $100C, $0000);
{獲取自身版本號所需要 end}
type
  TScanMode = (smNew, smReplace, smInsert, smSample, smRTS);
  TpScanInfo = ^TScanInfo;
  TScanInfo = record
    MultiPage  : Boolean;
    { supplementary info when MultiPage is True }
    Graphic    : TTiffGraphic;
    Stream     : TFileStream;
    ImageCount : LongInt;
  end;
  TOMRErrInfo = record
    Display : Boolean;  //是否顯示
    Ignore : Boolean; //可否刪除
    Info : String;
    Mode : String;
  end;
  TScrollRec = Record
    HScroll : Integer;
    VScroll : Integer;
    Rate    : Single;
  end;
type
  TCB_IMGPSScanX = class(TActiveForm, ICB_IMGPSScanX)
    Panel1: TPanel;
    TransBtn: TBitBtn;
    Panel21: TPanel;
    ViewModeBtn: TPJMenuSpeedButton;
    Button2: TButton;
    Button1: TButton;
    OptionBtn: TBitBtn;
    SelectScanBtn: TBitBtn;
    NextPageBtn: TBitBtn;
    PrePageBtn: TBitBtn;
    FC6: TBitBtn;
    FC5: TBitBtn;
    FC4: TBitBtn;
    FC3: TBitBtn;
    FC2: TBitBtn;
    FC1: TBitBtn;
    FC0: TBitBtn;
    Panel23: TPanel;
    PJLinkedMenuSpeedButton2: TPJLinkedMenuSpeedButton;
    NewScanBtn: TBitBtn;
    AddScanBtn: TBitBtn;
    Panel4: TPanel;
    Panel2: TPanel;
    Splitter1: TSplitter;
    Panel3: TPanel;
    Label7: TLabel;
    Panel6: TPanel;
    CB1: TCheckBox;
    ScanDuplexCB: TCheckBox;
    ScanFlatCB: TCheckBox;
    Panel18: TPanel;
    Panel12: TPanel;
    Panel7: TPanel;
    Panel9: TPanel;
    Shape1: TShape;
    ImageScrollBox1: TImageScrollBox;
    imgp8: TPanel;
    lb8: TLabel;
    ISB8: TImageScrollBox;
    imgp7: TPanel;
    lb7: TLabel;
    ISB7: TImageScrollBox;
    imgp6: TPanel;
    lb6: TLabel;
    ISB6: TImageScrollBox;
    imgp5: TPanel;
    lb5: TLabel;
    ISB5: TImageScrollBox;
    imgp4: TPanel;
    lb4: TLabel;
    ISB4: TImageScrollBox;
    imgp3: TPanel;
    lb3: TLabel;
    ISB3: TImageScrollBox;
    imgp2: TPanel;
    lb2: TLabel;
    ISB2: TImageScrollBox;
    imgp1: TPanel;
    lb1: TLabel;
    Memo1: TMemo;
    Display1: TMemo;
    Panel22: TPanel;
    Panel8: TPanel;
    Label2: TLabel;
    Gauge1: TGauge;
    ScrollBar1: TScrollBar;
    Panel10: TPanel;
    PageLV: TListView;
    StatusBar1: TStatusBar;
    ImageList4: TImageList;
    ImageList3: TImageList;
    ImageList1: TImageList;
    PopupMenu2: TPopupMenu;
    mode1: TMenuItem;
    mode2: TMenuItem;
    mode3: TMenuItem;
    mode4: TMenuItem;
    N51: TMenuItem;
    ImageList2: TImageList;
    OpenDialog1: TOpenDialog;
    PopupMenu3: TPopupMenu;
    PM301: TMenuItem;
    PM302: TMenuItem;
    PM303: TMenuItem;
    Timer1: TTimer;
    TomEncryption1: TTomEncryption;
    SaveDialog1: TSaveDialog;
    Timer2: TTimer;
    VCLZip1: TVCLZip;
    PopupMenu4: TPopupMenu;
    PM401: TMenuItem;
    PM402: TMenuItem;
    PM403: TMenuItem;
    PM404: TMenuItem;
    ElWinCertStorage: TElWinCertStorage;
    ElMemoryCertStorage: TElMemoryCertStorage;
    Panel5: TPanel;
    AddCredit1RG: TRadioGroup;
    Panel11: TPanel;
    SampleScanBtn: TBitBtn;
    WNoteBtn: TBitBtn;
    PopupMenu1: TPopupMenu;
    PM101: TMenuItem;
    N12: TMenuItem;
    PM102: TMenuItem;
    MenuItem1: TMenuItem;
    PM103: TMenuItem;
    PM104: TMenuItem;
    N7: TMenuItem;
    PM106: TMenuItem;
    PM107: TMenuItem;
    PM108: TMenuItem;
    PM109: TMenuItem;
    PopupMenu5: TPopupMenu;
    PM501: TMenuItem;
    PM502: TMenuItem;
    PM503: TMenuItem;
    PM504: TMenuItem;
    N5: TMenuItem;
    PM505: TMenuItem;
    PM506: TMenuItem;
    N29: TMenuItem;
    PM510: TMenuItem;
    PM509: TMenuItem;
    PM507: TMenuItem;
    N15: TMenuItem;
    PM508: TMenuItem;
    ExportBt: TButton;
    ImportBt: TButton;
    CheckCaseBtn: TBitBtn;
    DenialTimeLb: TLabel;
    Panel14: TPanel;
    ScrollBox1: TScrollBox;
    Label1: TLabel;
    Button3: TButton;
    Panel15: TPanel;
    Button4: TButton;
    PopupMenu6: TPopupMenu;
    PM602: TMenuItem;
    PM601: TMenuItem;
    PM605: TMenuItem;
    PM603: TMenuItem;
    PM604: TMenuItem;
    N8: TMenuItem;
    Panel16: TPanel;
    SpeedButton3: TSpeedButton;
    SpeedButton14: TSpeedButton;
    SpeedButton15: TSpeedButton;
    SpeedButton16: TSpeedButton;
    SpeedButton17: TSpeedButton;
    SpeedButton18: TSpeedButton;
    SpeedButton19: TSpeedButton;
    SpeedButton20: TSpeedButton;
    SpeedButton21: TSpeedButton;
    SpeedButton22: TSpeedButton;
    Edit1: TEdit;
    PM110: TMenuItem;
    Image1: TImage;
    UseOldCaseLb: TLabel;
    PM111: TMenuItem;
    SmoothCB: TCheckBox;
    ISB_BW: TImageScrollBox;
    N1: TMenuItem;
    N2: TMenuItem;
    ISB1: TImageScrollBox;
    Label3: TLabel;
    LogFile1: TLogFile;
    ScanGrayCB: TCheckBox;
    AttFileGB: TGroupBox;
    AttListBox: TListBox;
    Panel20: TPanel;
    AddAttFileLB: TLabel;
    DelAttFileLB: TLabel;
    Splitter2: TSplitter;
    Panel17: TPanel;
    TreeView1: TTreeView;
    Panel13: TPanel;
    PrtLb: TLabel;
    CaseHelpBtn: TBitBtn;
    HTTPSClient: TElHTTPSClient;
    Button5: TButton;
    FTPSClient1: TElSimpleFTPSClient;
    Button6: TButton;
    procedure ActiveFormCreate(Sender: TObject);
    procedure Panel9Resize(Sender: TObject);
    procedure ISB1Click(Sender: TObject);
    procedure WNoteBtnClick(Sender: TObject);
    procedure CaseHelpBtnClick(Sender: TObject);
    procedure FC0Click(Sender: TObject);
    procedure FC1Click(Sender: TObject);
    procedure FC2Click(Sender: TObject);
    procedure FC3Click(Sender: TObject);
    procedure FC4Click(Sender: TObject);
    procedure FC5Click(Sender: TObject);
    procedure FC6Click(Sender: TObject);
    procedure PrePageBtnClick(Sender: TObject);
    procedure NextPageBtnClick(Sender: TObject);
    procedure OptionBtnClick(Sender: TObject);
    procedure SelectScanBtnClick(Sender: TObject);
    procedure mode1Click(Sender: TObject);
    procedure mode2Click(Sender: TObject);
    procedure mode3Click(Sender: TObject);
    procedure mode4Click(Sender: TObject);
    procedure N51Click(Sender: TObject);
    procedure ScrollBar1Change(Sender: TObject);
    procedure ISB1EndScroll(Sender: TObject);
    procedure ISB1ImageMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ISB1ImageMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ISB1ImageMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PM508Click(Sender: TObject);
    procedure PM401Click(Sender: TObject);
    procedure PM402Click(Sender: TObject);
    procedure PM403Click(Sender: TObject);
    procedure PM404Click(Sender: TObject);
    procedure TreeView1Click(Sender: TObject);
    procedure NewScanBtnClick(Sender: TObject);
    procedure AddScanBtnClick(Sender: TObject);
    procedure PageLVClick(Sender: TObject);
    procedure PageLVKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure PageLVMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PM101Click(Sender: TObject);
    procedure PM104Click(Sender: TObject);
    procedure PM102Click(Sender: TObject);
    procedure PM103Click(Sender: TObject);
    procedure PM106Click(Sender: TObject);
    procedure PM107Click(Sender: TObject);
    procedure PM108Click(Sender: TObject);
    procedure PM109Click(Sender: TObject);
    procedure PM301Click(Sender: TObject);
    procedure PM302Click(Sender: TObject);
    procedure PM303Click(Sender: TObject);
    procedure PM501Click(Sender: TObject);
    procedure PM502Click(Sender: TObject);
    procedure PM503Click(Sender: TObject);
    procedure PM504Click(Sender: TObject);
    procedure PM505Click(Sender: TObject);
    procedure PM510Click(Sender: TObject);
    procedure PM509Click(Sender: TObject);
    procedure PM507Click(Sender: TObject);
    procedure PopupMenu1Popup(Sender: TObject);
    procedure PopupMenu4Popup(Sender: TObject);
    procedure PopupMenu5Popup(Sender: TObject);
    procedure SampleScanBtnClick(Sender: TObject);
    procedure StatusBar1DblClick(Sender: TObject);
    procedure ExportBtClick(Sender: TObject);
    procedure ImportBtClick(Sender: TObject);
    procedure HTTPSClientCertificateValidate(Sender: TObject;
      X509Certificate: TElX509Certificate; var Validate: Boolean);
    procedure ScanDuplexCBClick(Sender: TObject);
    procedure CheckCaseBtnClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
    procedure TransBtnClick(Sender: TObject);
    procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure TreeView1KeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ViewModeBtnMouseEnter(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure AddCredit1RGClick(Sender: TObject);
    procedure CB1Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure ISB1Enter(Sender: TObject);
    procedure TreeView1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PM601Click(Sender: TObject);
    procedure PopupMenu6Popup(Sender: TObject);
    procedure PM604Click(Sender: TObject);
    procedure PM605Click(Sender: TObject);
    procedure SpeedButton3Click(Sender: TObject);
    procedure SpeedButton14Click(Sender: TObject);
    procedure SpeedButton15Click(Sender: TObject);
    procedure SpeedButton16Click(Sender: TObject);
    procedure SpeedButton17Click(Sender: TObject);
    procedure SpeedButton18Click(Sender: TObject);
    procedure SpeedButton19Click(Sender: TObject);
    procedure SpeedButton20Click(Sender: TObject);
    procedure SpeedButton21Click(Sender: TObject);
    procedure SpeedButton22Click(Sender: TObject);
    procedure ActiveFormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure PM110Click(Sender: TObject);
    procedure PM602Click(Sender: TObject);
    procedure PrtLbClick(Sender: TObject);
    procedure Panel1DblClick(Sender: TObject);
    procedure Panel11DblClick(Sender: TObject);
    procedure UseOldCaseLbClick(Sender: TObject);
    procedure PM111Click(Sender: TObject);
    procedure ImageScrollBox1NewGraphic(const Graphic: TDibGraphic);
    procedure SmoothCBClick(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure TreeView1MouseEnter(Sender: TObject);
    procedure ScrollBox1MouseEnter(Sender: TObject);
    procedure ScanGrayCBClick(Sender: TObject);
    procedure AddAttFileLBClick(Sender: TObject);
    procedure DelAttFileLBClick(Sender: TObject);
    procedure AttListBoxDblClick(Sender: TObject);
    procedure AttListBoxClick(Sender: TObject);
    procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure HTTPSClientRedirection(Sender: TObject; const OldURL: string;
      var NewURL: string; var AllowRedirection: Boolean);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
  private
    { Private declarations }
    HotKeyId1,HotKeyId2,HotKeyId3,HotKeyId4 :Integer;
    ////////傳入參數/////////
    FUrl : String;
    FCaseID : String;
    FMode : String;        //NSCAN:新件;ESCAN:修改 20170306 DSCAN:被配合待掃瞄清單使用
    FModeName : String;
    FWork_no : String;
    FUserID : String;
    FUserName : String;
    FUserUnit : String;
    FData : String;
    FVerify : String;
    FReWrite : String;
    FLanguage : String;
    FLoanDoc_Value : String; //新增授信卷的值
    FLoanDoc_Enable : String; //新增授信卷是否可異動
    FUseProxy : String; //是否使用Proxy
    FC_DocNoList : String; //外面傳來要新增的文件編號
    FC_DocNameList : String; //外面傳來要新增的自訂文件
    FFixFileList : String; //要鎖住的檔名
    FIs_In_Wh : String; //是否只顯示入庫文件  (Y:只顯示入庫 N:只顯示非入庫 空白:都顯示)
    FOldCaseInfo : String; //舊件資訊  CaseID_year[tab]CaseID_year
    FPrintyn : String; //是否可列印
    FIs_OldCase : String; //是否是舊案第一次進入
    FCustDocYN : String; //是否可自訂文件
    //20170222 新增
    FImgDPI:integer;//DPI  依業務別決定 150~~1200  預設300
    FScanColor:integer;///掃瞄色彩  依業務別決定   0 :黑白  1:灰階   2:彩色 預設黑白
    FFileSizeLimit:integer;//匯入單一檔案大小限  依業務別決定  以KB為單位  預設5*1024kb
    FCaseNoLength:integer;//案件編號長度檢查  依業務別決定   無預設  一定要傳入
    FImgDelete:string; // Y/N  有權限可在補件時刪除影像
    FIsExternal:string;//Y/N
    FCheck_main_form:string; //Y/N
    FWH_category:string;  //Y/N  Y是歸類時有區分入庫非入庫文件  N 是不區分
    ////////傳入參數///////
    TransMode : TTransMode;   //用何種方式上傳檔案
    //********Http參數********
    HttpErrStr : String; //錯誤訊息
    //********Http參數********
    //********Ftp參數*********
    FFtpIP : String;
    FFtpID : String;
    FFtpPwd : String;
    FFtpRootPath : String;
    FFtpExtraPath : String;
    FFtpPort : Integer;
    FFtpProtocol : TFtpProtocol;
    //********Ftp參數*********
    //********ini參數********
    DeviceDelete : Boolean;     //空白頁刪除啟動
    DeviceDeleteSize : Integer;  //空白頁Size
    ScannerReverse : Boolean; //是否需反相
    BoardClear : Boolean; //是否清黑邊
    ScanDpi : Integer;    //掃瞄DPI
    ScanDuplex : Boolean; //是否雙面掃瞄
    ScanRotate : Integer; //掃瞄時旋轉角度
    ScanDeskew : Boolean; //是否傾斜矯正
    ScanBright : Integer; //亮度
    ScanContrast : Integer; //對比
    ScanImgShowMode : Integer; //0:清楚影像 1:不清楚影像 2:不顯示
    ScanImgSetUse : Boolean; //是否使用亮度對比設定
    //********ini參數********
    ScanColor : TImageFormat;
    //********時間********
    ServerDate : String;
    ServerTime : String;
    Balance : Longint; //local跟server的時間差
    ScanDenialTime : String; //停止進件時間
    //********時間********
    ScanDenialHint : String; //掃描顯示提醒字串
    //********路徑********
    ScanPath : String;       // SpecifyDir\Workid\userunit\mode
    ImagePath : String;      // SpecifyDir\Workid\userunit\mode
    ImageSavePath : String;   // ImagePath\
    ScaniniPath : String;    // SpecifyDir\Workid\userunit\
    LngPath :String;         //多國語言檔目錄
    CheckXmlPath : String;   //檢核用的Xml存放目錄
    SitePath : String;      //登打位置(切簽名用)
    SamplePath : String;     //範本目錄
    TransPath : String;     //檔案上傳的路徑(補充件會多一層目錄)
    //********路徑********
    ScanSaveFilename : String; //掃瞄的檔名
    ScanCaseno : String;  //掃瞄時的案號
    ScanDocDir : String;  //掃描時的文件代號目錄
    //********清單區********
    Doc_Inf_List : TStringList;  //Doc_Inf 清單
    DM_FORM_INF_List :TstringList;  //DM_FORM_INF 清單
    FORM_INF_List : TStringList; //FORM_INF的清單
    CHECK_RULE_INF_List : TStringList;  //CHECK_RULE_INF  清單
    MEMO_INF_List : TStringList;  //MEMO_INF 清單
    WORK_INF_List : TStringList;  //WORK_INF 清單
    LASTEST_FORM_INF_List : TStringList;  // LASTEST_FORM_INF 清單
    FindResult : TStringList;    //找SQLData的結果
    CaseList : TStringList;    //記錄掃瞄案件的順序
    Context_DocnoList : TStringlist; //案件裡的Docno清單
    CaseDocNoList : TStringlist;  //案件裡的DocNo清單(不重複)
    CaseDocNo_CopiesList : TStringlist; //案件裡的DocNo份數清單
    ContextList : TStringlist; //案件裡的檔案清單
    AttContextList : TStringlist; //案件裡的附加檔案清單
    OMRFileList : TStringList; //要OMR檢核的文件(只檢查每種Form的第一頁)
    Cust_DocNoList : TStringlist; //自行定義文件名稱
    IN_WH_DocNoList : TStringlist; //入庫的文件清單
    FormCode_PageSize : TStringList; //文件的預設大小  FormCode_Height_Width
    DocNo_NeedDoc : TStringList; //有Docno時要相依的文件   DocNo_相依文件_相依文件
    DocNo_NoDoc : TstringList; //有Docno時互斥的文件   DocNo_互斥文件_互斥文件
    DocNo_VerinCase : TStringlist; //案件裡的DocNo+版本的清單
    NoSaveBarCodeList : TStringlist; //不儲存的條碼清單
    FormID_List : TStringlist;    //FormID 清單  20130403 因為原FormCode2Docno會很慢..把FormID抽出來
    DocNo_List : TStringlist;     //DocNo 清單  20130403 因為原FormCode2Docno會很慢..把DocNo抽出來
    NowShowFileList : TStringlist;  //目前顯示的影像清單
    NowSelectFileList : TStringlist; //目前被點選的影像清單
    GuideFormIDList : TStringlist; //要當導引頁表單清單
    DivPageFormIDList:TStringlist; //要當分案頁表單清單
    LastInitFormidList:TStringList;
    LastAddFormidList:TstringList;
    SampleFormIDList:TStringList; //20170627 已存在範本的formid
    ExistImgList:TStringList;  //20170724  已經存在的影像list for ESCAN  //Img的完整路徑
    reSizeExistImgList:TstringList; //20171012被縮放的舊圖MD5存入
    //********清單區********
    //********顯示區********
    NowCaseno : String; //目前顯示的案件編號
    NowDocNo : String;  //目前的文件編號
    NowDocDir : String; //目前的文件目錄
    NowFormCode : String; //目前顯示的表單編號
    NowFormName : String; //目前顯示的表單名稱
    NowPage : Integer;   //目前點選的頁碼
    DisplayPath : String; //目前顯示的目錄
    //********顯示區********
    //******索引資料*********
    Case_loandoc : String; //是否新增授信卷
    //******索引資料*********
    //********十字定位點資訊********
    UpLPoint : Tpoint;  //左上方的十字點
    UpRPoint : Tpoint;  //右上方的十字點
    DownLPoint : Tpoint;  //左下方的十字點
    DownRPoint : Tpoint;  //右下方的十字點
    Point_Width : String;   //十字點的寬
    Point_Height : String;   //十字點的高
    //********十字定位點資訊********
    CaseIDLength : Integer; //案件編號長度
    FormIDLength : Integer; //FormID長度
    DocNoLength : Integer;  //Docno長度
    PEFileName : String; //掃描時的檔名
    DownFileErrStr : String;  //下載影像時發生的錯誤
    ISB : TImageScrollBox;
    ScanInfo    : TScanInfo;
    TwainShowUI : Boolean;
    MpsBarcodeinf : TMpsBarcodeinf;
    ScanMode : TScanMode;
    Mpskey : String;
    Seg : Integer; //顯示的邊界值
    VMode : Integer; //顯示的index
    NowClick : Integer;   //目前點到的按鈕功能Index
    ScanIP : String;  //掃瞄端的IP
    DisplayISB : TImageScrollBox; //被點到的影像
    SelectISB : TImageScrollBox; //被點到的縮圖
    SelectPage : Integer; //被點到的頁數
    NewTreeNode,MyTreeNode1,MyTreeNode2,MyTreeNode3 : TTreenode;
    InitialOk : Boolean; //資訊載入是否完成
    ShowText : String; //DataLoading時要秀出的訊息
    Ext : String; //附檔名  .tif .jpg
    SafePixel : Integer;  //OMR容忍誤差值點數
    OMRErrInfo : Array[1..11] of TOMRErrInfo;  //檢核的方式及訊息
    ScrollRec : Array[1..8] of TScrollRec; //瀏覽窗的Scroll記錄
    RecHozPos,RecVerPos : Integer;  //記錄MPSViewX1的ScrollBar位置
    ReczoomPercent : Single;
    SortMode : Boolean;
    PreMytreeNode2Name:String;
    HS,VS : Integer;
    iRate : Single;
    Bt : Integer; //去直線時橫線判斷的容忍值
    BarCodeRotate : Integer; //條碼要轉的角度
    HaveAppDoc : Boolean; //補全時是否有補入要保書
    PageLVclear : Boolean;
    CaseCount,PageCount : Integer; //總案件量及總頁數
    Item : TMenuItem;
    SampleAnchorMode : String; //範本掃瞄十字線的模式  NONE:無;ANCHOR:十字;FRAME:邊框
    DownImgStatus : String;  //下載影像的狀態(NO_DATA:沒資料;NO_FILE:沒影像)
    TransForm_Field : String; //要用OMR勾選確認是否轉換FORMID的欄位名稱
    NowWork_No : String; //現在的作業別
    CropBarcode : String; //要切影像的條碼
    Has_Authorize :String; //是否有授權書影像
    AttName : String; //未歸類目錄名稱
    NowGuideFormID : String;
    NowDivPageFormID:String;
    FirstDocDir : String;
    FMaxUploadSize:String;// 上傳zip大小限制
    FJpgCompression:integer;// 20171211 jpg to tif 的壓縮率
    Draging : Boolean;
    MDown : Boolean;  //20181210 用來判斷滑鼠右鍵要Popupmenu是否有MouseDonw發生
    FEvents: ICB_IMGPSScanXEvents;
    procedure HotKeyDown (var Msg : TMessage);message WM_HOTKEY;
    Procedure InitialLanguage(Sender: TObject);   //畫面載入多國語言
    //Function _Msg(S:String):String;
    //*********SQL相關************
    Procedure SetSQLData(ColumeStr:String;FromList,ToList:TStringlist); //把SQL值塞入
    Function GetSQLData(TableList:TStringlist;Colname:String;colNo:Integer):String; //依欄位及索引取值
    Function FindSQLData(TableList:TStringlist;ColumeStr,KeyColumeStr,KeyStr:String;ColNo:Integer;Var ResultList:TStringlist):Boolean; //找指定的資料
    Function GetFindResult(Col:String):String;
    //*********SQL相關************
    //*********FTP相關************
    Function GetFtpinfo(CaseID,Action:String):Boolean;
    Procedure SetFtpInfo;     //餵入FTP資訊
    Function FtpCaseComplete(SendData:String):Boolean;
    //*********FTP相關************
    //*******轉換區*********
    Function FindDivFormCode(FormCode:String):Boolean; //找有沒有分案的條碼
    Function FormCode2FormName(CaseID,FormCode:String):String; //用FormCode轉成文件名稱
    Function FormCode2FileName(FormCode:String;List:TStrings):String; //用FormCode找出檔名(第一頁)
    Function FileName2FormCode(FileName:String):String; //從檔名取出FormCode
    Function FileName2FormName(CaseID,FileName:String):String; //從檔名取出文件名稱
    Function FileName2ScanPage(FileName:String):Integer; //從檔名取出掃瞄頁數
    Function FileName2NoQuene_Filename(FileName:String):String; //取出沒有序號的檔名
    Function FileName2Index(FileName:String):Integer; //從檔名取出在ContextList的序號
    Function FileName2NowDcoNo(FileName:String;CtList,DNList:TStrings):String; //從檔名取出歸屬的文件代號
    Function FormCode2DocNo(FormCode:String):String;   //FormCode轉Docno
    Function FormCode2Version(FormCode:String):String; //FormCode轉版本
    Function FormCode2Page(FormCode:String):String; //FormCode轉文件頁數
    Function DocNo2DocName(CaseID,DocNo:String):String; //Docno轉Doc名稱
    Function DocNo2FileName(DocNo:String;List:TStrings):String; //用DocNo找出檔名(第一頁)
    Function FormCode2WorkNo(FormCode:String):String; //用FormCode取出作業別
    Function DocNo2WorkNo(DocNo:String):String; //用DocNo取出作業別
    Function DocNo2DocNoDir(Path,DocNo:String):String;    //DocNo轉成DocNo(份數)目錄
    Function DocNoDir2DocNo(DocNoDir:String):String; //DocNo(份數)目錄轉成DocNo
    Function DocNoDir2Index(Path,DocNoDir:String):Integer; //DocNo(份數)目錄轉成index
    Function DocNoNeedDiv(DocNo:String):Boolean; //是否是需分份數的文件代號
    //Function CaseNo2DocNo(CaseNo:String):TStringList;
    Function CaseNode2Info(Node:TTreeNode;Mode:Char):String;   //案件Node取案件編號  Mode: I:Caseno;P:Page
    Function DocNode2Info(Node:TTreeNode;Mode:Char):String;     //文件Node取文件代號 Mode: I:Docno;N:Docname;P:Page;G:Group
    Function FormNode2Info(Node:TTreeNode;Mode:Char):String;   //表單Node取表單代號  Mode: I:FormID;N:FormName;P:Page
    //*******轉換區*********
    Procedure PriorPage(Page:Integer); //上一頁
    Procedure NextPage(Page:Integer); //下一頁
    Function DocNoExistsinTree(CaseNode:TTreeNode;DocNo:String):Boolean; //DocNo是否己存在樹裡
    Function DocnoNeedGroup(DocNo:String):Boolean; //傳入的DocNo是否需分組
    function GetSiteOMR(FileName, Site: String;bt: Integer): Integer;
    Function FindISB2View(Vmode:Integer):TImageScrollBox; //找空的ISB來顯示
    Procedure R_W_ScanIni(Mode:Char); //'R'讀取;'W'寫入
    Procedure GetDefScanIni; //取得掃瞄的預設值
    procedure DesableImage;
    procedure EnableImage(v:integer;Sender : TObject);
    Procedure ViewMouseMode(v:Integer);
    Procedure GoViewMode;
    Procedure DisplayMode(index,H_Count,W_Count:Integer;BasePanel:TPanel);
    Function GetServerDate : Boolean; //取主機時間
    Function GetSetInf1 : Boolean; //取系統設定資訊mode1  DOC_INF
    Function GetSetInf2 : Boolean; //取系統設定資訊mode2  DM_FORM_INF
    Function GetSetInf3 : Boolean; //取系統設定資訊mode3  FORM_INF
    Function GetSetInf4 : Boolean; //取系統設定資訊mode4  CHECK_RULE_INF
    Function GetSetInf5 : Boolean; //取系統設定資訊mode5  MEMO_INF
    Function GetSetInf6 : Boolean; //取系統設定資訊mode6  WORK_INF
    Function GetSetInf7 : Boolean; //取系統設定資訊mode7  LASTESTFORM_INF
    Procedure SetFormID_DocNo; //將FormID及Docno抽出來另存入list裡
    Procedure SetIn_WH_DocNo; //將要入庫的DocNo抽出來另存入list裡
    Procedure DataLoading(Loading,UseTimer:Boolean);  //資料載入中要停止點選的動作
    procedure ClearView(stkv:Integer); //清除瀏覽窗的影像
    Function DrawDocItem2(CaseNode : TTreenode;Caseno:String):Boolean;  //畫出文件名稱的Tree
    Procedure initkscan; //檢查掃描器的功能
    procedure LoadImgFile; //載入案件
    procedure LoadImgFile1; //載入案件
    procedure LoadAttFile(CaseID:String); //載入附加檔案
    Procedure DistinctFormCode(CaseID:String); //案件裡的FormCode取出第一頁
    Function OMRCheckCase(CaseID:String):Boolean; //OMR檢核
    Procedure OMRErr2ini(CaseID,Reason,FileName,Site,RelaFileName,RelaSite,Anchor,Anchor1:String;Del,Ingnore,Display:Boolean); //OMR檢核失敗寫入ini
    Procedure OMRErrini2List(CaseID:String;ErrlistForm : TErrlistForm); //OMR檢核失敗從ini寫入ListView
    Function DownLanguage:Boolean;  //下載多國語言檔
    Function FindMpsView(Vmode:Integer):TImageScrollBox;
    Function CaseAsk(CaseID:String):Integer;  //詢問是否可上傳  (-1:失敗;0:可以;1:不行;)
    Function CaseComplete(Path,CaseID:String;MainCase:Boolean):Boolean;  //通知傳送完成
    Function GetCaseFormID(Path:String):String;  //取案件的FormID
    Procedure CreateFormID_FormName(Path,CaseID:String);  //產生FormID_FormName.dat
    Procedure CreateDocNo_DocName(Path,CaseID:String);  //產生DocNo_DocName.dat
    Procedure CreateIn_WH(CaseID:String);  //產生In_WH.dat
    Function CreateDocNo_Info(CaseID:String):String; //產生保管袋文件 DocNo[tab]份數[tab]總頁數[tab]是否異動[換行]DocNo[tab]份數[tab]總頁數[tab]是否異動
    Function CreateCustDocNo_Info(CaseID:String):String; //產生自訂文件 DocName[tab]份數[tab]總頁數[tab]是否異動[#13#10]DocName[tab]份數[tab]總頁數[tab]是否異動
    //Function CreateCustDocNo_Info(path,CaseID:String):String; overload
    Function CreateAttach_Info(CaseID:String):String; //產生是否有Attach Y:有 N:沒有
    Function CreateDocnoFrom_Info(CaseID:String):String; //產生被引進的保管袋文件資訊  Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
    Function CreateCustDocNoFrom_Info(CaseID:String):String; //產生被引進的自定文件資訊  Docno[tab]份數[tab]案件編號#13#10Docno[tab]份數[tab]案件編號
    Function GetDocNoEdit(CaseID,DocNo,DocName:String):String; //取出DocNo是否被異動 (Y/N)
    Function GetDocNo_Count(Path,DocNo:String):Integer;  //取出文件份數
    Function GetDocNo_Page(Path,DocNo:String):Integer;  //取出文件總頁數
    Function FormIDExists(FormCode:String;CheckDate:Boolean;index:Integer):Boolean;  //檢查FormID是否存在及是否要檢查啟用停用日期
    Function Case_DocNoExists(CaseID,Docno:String):Boolean; //Docno是否存在案件裡
    Procedure ReSortFileName_New(Path:String); //檔名重新排序
    Procedure ReSortFileName(Path:String); //檔名重新排序
    Procedure ReSortFileName2Scanlist(Path:String); //檔名重新排序給Scanlist.dat
    Function GetOMRCheckSet:Boolean;  //下載OMR檢核XML檔
    Function GetKeyinSet : Boolean; //取登打設定
    Procedure CheckRule2OMRErrInfo;   //檢核規則填入OMRErrINFo Record
    Procedure ReNameContext(Path,OldName,NewName:String);
    Procedure DeleteImageFile(Path,FileName,CaseID:String); // 刪除檔案
    Procedure DeleteFormCodeFile(CaseID,DocDir,FormID:String);  //刪除指定FormID文件
    Function DeleteDocNoFile(Path,DocNo:String):Boolean;  //刪除指定DocNo文件
    Procedure DeleteShowFile(Path:String); //刪除顯示中的影像
    Function GetDataDocNoPage(MainDocNo,MainVersion:String):Integer;  //取記錄的文件_版本頁數
    Function CheckCaseDocNoPage(CaseID,DocNo,Version:String;Pages:Integer):Integer; //檢查案件裡的文件_版本頁數
    Function FindFormCodePages(CaseID,FormCode:String):Integer;  //計算案件裡FormID的頁數
    Function GetDataFormCodePages(FormCode:String):Integer;   //取記錄的FormcID的頁數
    Procedure CaseReSize(CaseID:String); //案件的影像縮放
    Procedure ImageReSize_FormID(CaseID,FileName:String);  //依十字定位點做縮放
    Procedure ImageReSize_tmp(FormID,FileName:String);  //依十字定位點做縮放(暫存檔)
    Function TransCaseID(Path,CaseID:String;MainCase:Boolean):Boolean; //傳送案件
    Procedure NewTreeNodeRefresh;
    Procedure MyTreeNode1Refresh;
    Procedure MyTreeNode2ReFresh(CaseID:String);
    Procedure MyTreeNode3ReFresh(CaseID:String);
    Function Node2DocNo(Node2:TTreeNode):String;  //MyTreeNode2取DocNo出來
    Function Node3DocNo(Node3:TTreeNode):String;  //MyTreeNode3取DocNo出來
    Function Node3FormID(Node3:TTreeNode):String;  //MyTreeNode3取FormCode出來
    Function GetNode2Name(Node2:TTreeNode):String;  //取MyTreeNode2的識別字出來(記之前點選用)
    //Function Down_Replace_Img(SPAth,DPath,CaseID:String):Boolean;
    Function DownLoadImage(Path,CaseID:String):Boolean;
    Function Down_Img(Path,CaseID:String):Boolean;
    Function GetNoNameCase(Path:string):String; //取未配號XXXX
    Procedure CaseResort(Path:String); //案件的檔案重新排序(次文件依Docno挑)
    Procedure CaseResort2Scanlist(Path:String); //案件的檔案重新排序給scanlist(次文件依FormID排)
    Procedure DistinctDocinCase(Path:String); //列出案件裡的Docno_版本
    Procedure DistinctDocNoinCase(Path:String); //列出案件裡的Docno
    Procedure ClearErrini(CaseID:String;CaseNode:TTreeNode); //清掉檢核檔案
    Procedure SetCaseList(Mode:Char;Index:Integer;text:String);  //'A:加入,I:插入,D:刪除,E:修改'
    Procedure SetDocNoList(Mode:Char;Index:Integer;CaseNo,DocDir,Copies:String);  //'A:加入,I:插入,D:刪除,E:修改'
    Procedure SetContextList(Mode:Char;Index:Integer;CaseNo,DocDir,FileName:String);  //'A:加入,I:插入,D:刪除,E:修改'
    Procedure SetAttContextList(Mode:Char;Index:Integer;CaseNo,FileName:String);  //'A:加入,I:插入,D:刪除,E:修改'
    Function checkCaseOMRDone:Boolean;  //檢查案件是否完成OMR檢核
    Function CheckCaseID_OK:Boolean;  //檢查是否有未配號的案件
    Procedure CreateEmptyCase(Path,CaseID:String);  //產生空白案號(重掃件用)
    Procedure InitScrollRec; //初始化影像Scroll記錄
    Procedure GetScrollData(ISB:TImageScrollBox;Var HS,VS:Integer;Var iRate:Single); //取影像Scroll記錄
    Procedure SetScrollData(ISB:TImageScrollBox;HS,VS:Integer;iRate:Single); //寫影像Scroll記錄
    Procedure FormIDReplace(CaseID,DocDir,OldFormID,NewFormID:String); //指定FormID更換成新的FormID
    Procedure ShowFileReplace(Path,NewFormID:String);//顯示的影像換成新的FormID
    Procedure PageReplaceFormID(Path,NowFormID,NewFormID:String); //選取頁更換FormID
    Function ModeNeedCheck(OMRMode,ScanMode:String):Boolean; //掃瞄模式是否要做檢核
    procedure WMMOUSEWHEEL(var message: TWMMouseWheel); message WM_MOUSEWHEEL;
    Function GetCasePage(Path,CaseID:String):Integer;
    Function GetFormIDPage(FileList:TStringlist;FormID:String):Integer;
    Procedure SetFile2Case(CaseID,FileName:String);
    Procedure WriteResize(ImgName,TxtName:String); //產生Resize.dat
    Function GetCase_PageCount(var CaseCount,PageCount:Integer):Boolean; //取出案件的數量及頁數 ID為空值時為取所有的
    Function BarCode2FormID : String; //Barcode依規則轉成FormID
    Function BarCode2CaseID : String; //Barcode依規則轉成CaseID
    Procedure WriteCaseIndex(Path:String);
    Procedure ReadCaseIndex(Path:String);
    Procedure ClearCaseIndex;
    Procedure GetSelectImageFile;
    Function GetDocNoDir(Path,DocNo:String):String; //取出目前DocNo的份數
    Function CheckFormIDExists(DocNoNode:TTreeNode;FormID:String):Boolean; //檢查FormID是否存在文件裡
    Procedure ZipMainFile(SoPath,DePath,ZipName:String); //壓縮影像檔
    Procedure ZipMaskFile(SoPath,MarkPath,DePath,ZipName:String); //壓縮遮罩影像檔
    Procedure ParserPoint(S:String); //解析十字點的字串
    Function CheckScanDenialTime:Boolean;
    Function FormID2Anchor(FormID:String):String;  //用FormID取出十字模式
    Function Index2Anchor(Anchor:String):String;   //十字模式 0->NONE;1->ANCHOR;2->FRAME
    Function MemoInfoTransfer(Mode,Str:String;ID_S,Name_S:TStringlist):String;  //註記代碼註記類別轉換  Mode 'ID':代碼轉名稱;'NAME':名稱轉代碼
    Function GetFormatID(CaseID:String):String; //取出案件的FormatID
    Function FindNoSaveBarCode : Boolean; //找是否有不要儲存影像的條碼
    Function CheckAvailable:Boolean; //檢查是否可使用元件
    Function Case2Mask(SoPath,DePath:String):Boolean;//產生遮罩影像
    Function CheckNeedCrop(Graphic:TDibGraphic):Boolean; //是否是A3要切影像
    Function GetNewCustomDocNo(Path,DocName:String):String; //取出未使用的自訂文件代號
    Function GetCustomDocName(Path,DocNo:String):String; //取出自定文件名稱
    Function GetCustomFormID(Path,DocNo:String):String; //取出自定文件FormID
    Function GetCustomDocDir(Path,DocName:String):String; //取出自定文件DocDir
    Function FindCustomDocName(Path,DocName:String):Boolean; //尋找自定文件名稱是否存在
    Procedure DeleteCustomDocDir(Path,DocNo:String); //刪除自定文件DocNo
    Function CheckFormID_Prt(FormID:String):Boolean; //傳入的FormID是否預設列印
    procedure PrintImg(FileName, LoginID, Datetime,Path: WideString);
    Function FindLastestDocDir(CaseID,DocNo:String):String; //找出最新的DocDir
    Procedure Create_Cust_DocDir(CaseID:String); //產生外面傳入的文件代號及自定文件
    Procedure OldCasetoNewCase(CaseID:String); //將舊案份數轉成新規則
    Procedure ErrFormtoCurrentForm(CaseID,EFormID,CFormID:String);//將舊案的錯誤FormID改正確的FormID
    Procedure SetRecordEditedDocDir(Mode:Char;CaseID,DocDir:String);  //記錄被異動的文件目錄  'A:加入D:刪掉'
    Function GetDocDir_Page(CaseID,DocDir:String):Integer;  //取得DocDir的頁數
    Function Path2DocDir(Path,CaseID:String):String;
    Function GetDocNo_IS_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
    Procedure SortDocDir_FormID(CaseID,DocDir:String); //將DocDir裡的文件編號排序
    Procedure GotoAttach(OldLevel:Integer);
    Function DocNoIs_In_WH(DocNo:String):Boolean; //DocNo是否為入庫文件
    Procedure CreateCaseNeedData(Path:String);  //先做影像截取會少二個文字檔,產生CaseDocNo.dat及DocDir.dat
    Procedure SetDocDirtoSelected(CaseNode:TTreeNode;DocDir:String);
    Function CheckSelectImg_UseCase(Path,CaseID:String):Boolean; //檢查選擇的影像是否有包含被引用的影像
    Function TransOldCaseFile(Path:String):Boolean;  //上傳引用舊件的記錄檔
    Function Writelog(CaseID:String):Boolean;
    Function FormIDAppear(FormID:String):Boolean; //FormID是否可出現
    Function DocNoAppear(DocNo:String):Boolean;   //DocNo是否可出現
    Function GetDocNoCount(CaseID,DocNo:String):Integer; //取DocNo數量
    Function GetDocDirCopies(CaseID,DocDir:String):Integer; //取DocDir份數
    Procedure SetDocDirCopies(CaseID,DocDir:String;NewCopies:Integer); //修改DocDir份數
    Function GetDocDirCopies_Rec(Path,CaseID,DocDir:String):Integer; //取記錄裡的DocDir份數
    Function GetCustomNameCount(CustomName:String):Integer;   //取外傳的名稱數量
    Function GetCustomDocNoCount(Docno:String):Integer;   //取外傳的DocNo數量
    Function ISGuideFormID(FormID:String):Boolean;
    Function CaseDelete_Enable(CaseID:String):Boolean;  //案件可否被刪除
    Procedure MoveImage(Path:String;mp:Integer); //移動頁數
    Procedure MoveImage_Drag(Path:String;fp,tp:Integer); //拖拉移動頁數
    Procedure SetUseCase(Mode:Char;Path,DocDir,FormCaseID,ToCaseID:String);   //記錄引用其他案件 A:加入 D:刪掉
    Function GetUseCase(Mode:Char;Path,DocDir:String):String;  //F:取被引用 To:引用
    Procedure Case2upload(CaseID:String);
    Procedure Download2Case(SoDir,DeDir:String);
    procedure view_image_FormCode(Path,FormCode:String;stpage,stview:integer); //用FormCode來找影像
    procedure view_image_DocNo(Path,DocNo,FormID:String;Pages:integer); //用DocNo來找影像
    Function ShapeName2PreViewISBName(SP:TShape):String; //轉出指定PreViewISBName
    Procedure CreatePreViewISB(Count:Integer);
    Procedure FreePreViewISB;
    Procedure FitPreViewISB;
    Procedure PaintShape(FromImg,ToImg:TImageScrollBox); //畫有被選取的影像
    Procedure FreeShapeobj(SelectISB : TImageScrollBox);
    Procedure ISBClick(Sender : TObject);
    Procedure ISBMouseMove(Sender: TObject; Shift: TShiftState;
    X, Y: Integer);
    procedure ISBImageMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ISBImageMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ISBEndDrag(Sender, Target: TObject; X, Y: Integer);
    procedure ISBDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure ISBDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure BtnMouseEnter(Sender: TObject);
    procedure PageEnd;   //掃描接收完成
    Procedure PageDone;  //掃描完成後顯示影像
    procedure StatrTwainScan;
    procedure OnAcquire( const DibHandle    : THandle;
                         const XDpi         : Word;
                         const YDpi         : Word;
                         const CallBackData : LongInt );
    procedure ActivateEvent(Sender: TObject);
    procedure ClickEvent(Sender: TObject);
    procedure CreateEvent(Sender: TObject);
    procedure DblClickEvent(Sender: TObject);
    procedure DeactivateEvent(Sender: TObject);
    procedure DestroyEvent(Sender: TObject);
    procedure KeyPressEvent(Sender: TObject; var Key: Char);
    procedure MouseEnterEvent(Sender: TObject);
    procedure MouseLeaveEvent(Sender: TObject);
    procedure PaintEvent(Sender: TObject);
    function GetCurrentVersionNo: String;
    procedure initParameter;
    procedure LastInitFormidListCreate(path:string);
    function checkFormCodeIsCustom(path,formcode:string):boolean;
    function ISDivPageFormID(FormID: String): Boolean;
    function GetSampleInf: Boolean;
    procedure InitExistImgList(casepath:String);
    function LoadFileGetMD5(const filename:string):string; //20170809 取的檔案的MD5
    function ISExistImg(const filename:string):boolean;  //20170809 確認是否存在原有影像
    procedure _DelTreeForExistImg(ASourceDir:String);   //2017 刪除前確認 有舊影像嗎
    function DocNoIsExistImg(DocNopath: String): boolean; //2017 刪除前確認 有舊影像嗎
    function CheckCaseAttach_OK: Boolean;
    function DeleteDocNoFileForESCAN(Path, DocNo: String): Boolean;     //2017 確認是否有未歸類文件
    function CheckRequiredColumnValues(workno,caseno:String) :Boolean;  //20171003  此大類下此案是否檢核必填
    function logTimeString :String;
    procedure ReduceLogFile ;
    function FindLastestDocDirForPage(CaseID, DocNo, formid: String): String;
    function OMRErrini2ListForLog(CaseID: String):String;
  protected
    { Protected declarations }
    procedure DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage); override;
    procedure EventSinkChanged(const EventSink: IUnknown); override;
    function Get_Active: WordBool; safecall;
    function Get_AlignDisabled: WordBool; safecall;
    function Get_AlignWithMargins: WordBool; safecall;
    function Get_AutoScroll: WordBool; safecall;
    function Get_AutoSize: WordBool; safecall;
    function Get_AxBorderStyle: TxActiveFormBorderStyle; safecall;
    function Get_Caption: WideString; safecall;
    function Get_Color: OLE_COLOR; safecall;
    function Get_DockSite: WordBool; safecall;
    function Get_DoubleBuffered: WordBool; safecall;
    function Get_DropTarget: WordBool; safecall;
    function Get_Enabled: WordBool; safecall;
    function Get_ExplicitHeight: Integer; safecall;
    function Get_ExplicitLeft: Integer; safecall;
    function Get_ExplicitTop: Integer; safecall;
    function Get_ExplicitWidth: Integer; safecall;
    function Get_Font: IFontDisp; safecall;
    function Get_HelpFile: WideString; safecall;
    function Get_KeyPreview: WordBool; safecall;
    function Get_MouseInClient: WordBool; safecall;
    function Get_ParentCustomHint: WordBool; safecall;
    function Get_ParentDoubleBuffered: WordBool; safecall;
    function Get_PixelsPerInch: Integer; safecall;
    function Get_PopupMode: TxPopupMode; safecall;
    function Get_PrintScale: TxPrintScale; safecall;
    function Get_Scaled: WordBool; safecall;
    function Get_ScreenSnap: WordBool; safecall;
    function Get_SnapBuffer: Integer; safecall;
    function Get_UseDockManager: WordBool; safecall;
    function Get_Visible: WordBool; safecall;
    function Get_VisibleDockClientCount: Integer; safecall;
    procedure _Set_Font(var Value: IFontDisp); safecall;
    procedure Set_AlignWithMargins(Value: WordBool); safecall;
    procedure Set_AutoScroll(Value: WordBool); safecall;
    procedure Set_AutoSize(Value: WordBool); safecall;
    procedure Set_AxBorderStyle(Value: TxActiveFormBorderStyle); safecall;
    procedure Set_Caption(const Value: WideString); safecall;
    procedure Set_Color(Value: OLE_COLOR); safecall;
    procedure Set_DockSite(Value: WordBool); safecall;
    procedure Set_DoubleBuffered(Value: WordBool); safecall;
    procedure Set_DropTarget(Value: WordBool); safecall;
    procedure Set_Enabled(Value: WordBool); safecall;
    procedure Set_Font(const Value: IFontDisp); safecall;
    procedure Set_HelpFile(const Value: WideString); safecall;
    procedure Set_KeyPreview(Value: WordBool); safecall;
    procedure Set_ParentCustomHint(Value: WordBool); safecall;
    procedure Set_ParentDoubleBuffered(Value: WordBool); safecall;
    procedure Set_PixelsPerInch(Value: Integer); safecall;
    procedure Set_PopupMode(Value: TxPopupMode); safecall;
    procedure Set_PrintScale(Value: TxPrintScale); safecall;
    procedure Set_Scaled(Value: WordBool); safecall;
    procedure Set_ScreenSnap(Value: WordBool); safecall;
    procedure Set_SnapBuffer(Value: Integer); safecall;
    procedure Set_UseDockManager(Value: WordBool); safecall;
    procedure Set_Visible(Value: WordBool); safecall;
    procedure Set_caseid(const Value: WideString); safecall;
    procedure Set_data(const Value: WideString); safecall;
    procedure Set_mode(const Value: WideString); safecall;
    procedure Set_rewrite(const Value: WideString); safecall;
    procedure Set_url(const Value: WideString); safecall;
    procedure Set_userid(const Value: WideString); safecall;
    procedure Set_username(const Value: WideString); safecall;
    procedure Set_verify(const Value: WideString); safecall;
    procedure Set_language(const Value: WideString); safecall;
    procedure Set_modename(const Value: WideString); safecall;
    procedure Set_userunit(const Value: WideString); safecall;
    procedure Set_work_no(const Value: WideString); safecall;
    procedure Set_loandoc_enable(const Value: WideString); safecall;
    procedure Set_loandoc_value(const Value: WideString); safecall;
    procedure Set_useproxy(const Value: WideString); safecall;
    procedure Set_c_docnamelist(const Value: WideString); safecall;
    procedure Set_c_docnolist(const Value: WideString); safecall;
    procedure Set_fixfilelist(const Value: WideString); safecall;
    procedure Set_is_in_wh(const Value: WideString); safecall;
    procedure Set_oldcaseinfo(const Value: WideString); safecall;
    function Get_c_docnamelist: WideString; safecall;
    function Get_c_docnolist: WideString; safecall;
    function Get_caseid: WideString; safecall;
    function Get_data: WideString; safecall;
    function Get_fixfilelist: WideString; safecall;
    function Get_is_in_wh: WideString; safecall;
    function Get_language: WideString; safecall;
    function Get_loandoc_enable: WideString; safecall;
    function Get_loandoc_value: WideString; safecall;
    function Get_mode: WideString; safecall;
    function Get_modename: WideString; safecall;
    function Get_oldcaseinfo: WideString; safecall;
    function Get_rewrite: WideString; safecall;
    function Get_url: WideString; safecall;
    function Get_useproxy: WideString; safecall;
    function Get_userid: WideString; safecall;
    function Get_username: WideString; safecall;
    function Get_userunit: WideString; safecall;
    function Get_verify: WideString; safecall;
    function Get_work_no: WideString; safecall;
    function Get_printyn: WideString; safecall;
    procedure Set_printyn(const Value: WideString); safecall;
    function Get_is_oldcase: WideString; safecall;
    procedure Set_is_oldcase(const Value: WideString); safecall;
    function Get_custdocyn: WideString; safecall;
    procedure Set_custdocyn(const Value: WideString); safecall;
    function Get_casenolength: WideString; safecall;
    function Get_filesizelimit: WideString; safecall;
    function Get_imgdpi: WideString; safecall;
    function Get_scancolor: WideString; safecall;
    procedure Set_casenolength(const Value: WideString); safecall;
    procedure Set_filesizelimit(const Value: WideString); safecall;
    procedure Set_imgdpi(const Value: WideString); safecall;
    procedure Set_scancolor(const Value: WideString); safecall;
    function Get_imgdelete: WideString; safecall;
    procedure Set_imgdelete(const Value: WideString); safecall;
    function Get_check_main_form: WideString; safecall;
    function Get_isExternal: WideString; safecall;
    procedure Set_check_main_form(const Value: WideString); safecall;
    procedure Set_isExternal(const Value: WideString); safecall;
    function Get_WH_CATEGORY: WideString; safecall;
    procedure Set_WH_CATEGORY(const Value: WideString); safecall;
  public
    { Public declarations }
    procedure Initialize; override;
  end;
implementation
uses EnBarcode,
     EnTransf, { for TImageTransform }
     Enpnggr,  { for PNGGraphic }
     EnJpgGr,  { for JPGGraphic }
     EnReg,
     EnBmpGr,  { for TBitmapGraphic }
     EnPrint,  { for TEnvisionPrintMode, TDibGraphicPrinter }
     ComObj, ComServ,IISUnit,IIS_File2Web,IIS_ImageProcess,
     PatchFom,Doclist,ScanMemo,DocCopy,InputMask,SortMemo,DocPrt,OldCaseInfo;
{$R *.DFM}
{ TCB_IMGPSScanX }
scripts/final_classify_scanImp_pas.js
比對新檔案
@@ -0,0 +1,264 @@
const fs = require('fs');
const path = require('path');
const JSON_FILES = [
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.BusinessLogic.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.ImageProcessor.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.ScannerController.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.TransportManager.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.UIView.json'
];
// 1.優先
// team_task_classification 團隊分工覆寫
const PRIM_TAGS_TO_FIE = {
  // // ScannerController
  // 'ScannerController.acquisitionHandler': 'scan/acquisition.pas',
  // 'ScannerController.twainWrapper': 'scan/twain.pas',
  //
  // // ImageProcessor
  // 'ImageProcessor.transformer': 'img/transformer.pas',
  // 'ImageProcessor.converter': 'img/converter.pas',
  // 'ImageProcessor.anchorAnalyzer': 'img/anchor.pas',
  // 'ImageProcessor.payloadArchiver': 'img/imgArchiver.pas',
  '初始化與生命週期': 'CB_IMGPSScanImp.lfcycle.pas',
  'API 呼叫相關': 'CB_IMGPSScanImp.api.pas',
  '轉換區(名稱/格式轉換)': 'CB_IMGPSScanImp.convert.pas',
  '案件管理(TreeView / 案件操作)': 'CB_IMGPSScanImp.caseMgr.pas',
  '清單管理': 'CB_IMGPSScanImp.listMgr.pas',
  '檔案操作': 'CB_IMGPSScanImp.fileOp.pas',
  '上傳前置資料產生': 'CB_IMGPSScanImp.prUpload.pas',
  '文件份數/頁數/查詢': 'CB_IMGPSScanImp.docq.pas',
  '自訂文件': 'CB_IMGPSScanImp.custdoc.pas',
  '舊案/異動件處理': 'CB_IMGPSScanImp.docmod.pas',
  '入庫文件/可見性': 'CB_IMGPSScanImp.inbound.pas',
  // '影像瀏覽/顯示': 'CB_IMGPSScanImp.image.pas',
  'OMR 檢核': 'CB_IMGPSScanImp.omr.pas',
  '縮圖預覽(PreViewISB)': 'CB_IMGPSScanImp.preview.pas',
  '其他內部': 'CB_IMGPSScanImp.misc.pas',
}
// 2.若 1未定義到, 則從這裡分類
const TAGS_TO_FILE = {
  // ScannerController
  'ScannerController.acquisitionHandler': 'scan/acquisition.pas',
  'ScannerController.twainWrapper': 'scan/twain.pas',
  // ImageProcessor
  'ImageProcessor.transformer': 'img/transformer.pas',
  'ImageProcessor.converter': 'img/converter.pas',
  'ImageProcessor.anchorAnalyzer': 'img/anchor.pas',
  'ImageProcessor.payloadArchiver': 'img/imgArchiver.pas',
  // TransportManager
  'TransportManager.apiClient': 'transp/apiClient.pas',
  'TransportManager.fileTransfer': 'transp/fileClient.pas',
  'TransportManager.certificateManager': 'transp/certManager.pas',
  'TransportManager.payloadArchiver': 'transp/payloadArchiver.pas',
  // BusinessLogic
  'BusinessLogic.systemInternal': 'bloc/sys.pas',
  'BusinessLogic.configRepository': 'bloc/cfg.pas',
  'BusinessLogic.ormRuleEngine': 'bloc/ormRuleEngine.pas',
  'BusinessLogic.entityMapping': 'bloc/entityMapping.pas',
  'BusinessLogic.fileManager': 'bloc/fileManager.pas',
  'BusinessLogic.caseManager': 'bloc/caseManager.pas',
  'BusinessLogic.entityModel': 'bloc/entityModel.pas',
  'BusinessLogic.activeXWrapper': 'bloc/ocx.pas',
  // UIView
  'UIView.statusMessenger': 'view/msger.pas',
  'UIView.events': 'view/events.pas',
  'UIView.i18n': 'view/i18n.pas',
  'UIView.inputHandler': 'view/input.pas',
  'UIView.configRepository': 'view/cfg.pas',
  'UIView.treeView': 'view/treeView.pas',
  'UIView.toolBar': 'view/toolBar.pas',
  'UIView.imageScrollBox': 'view/isb.pas',
  'UIView.popupMenu': 'view/popupMenu.pas',
  'UIView.listView': 'view/listView.pas',
  'UIView.scrollView': 'view/scrollView.pas',
  'UIView.misc': 'view/misc.pas'
};
const SRC_FILE = 'CB_IMGPSScanImp.pas.bk';
const DEST_FILE = 'CB_IMGPSScanImp.pas';
const OUTPUT_DEST = 'reassemble';
const REMAININGS_FILE = 'scripts/dist/scanimpl_annalysis.remainings.txt';
function getVisualWidth(str) {
  let width = 0;
  for (let i = 0; i < str.length; i++) {
    const code = str.charCodeAt(i);
    if (code >= 0x4e00 && code <= 0x9fff) {
      width += 2;
    } else {
      width += 1;
    }
  }
  return width;
}
function wrapText(text, limit, wrapIndent) {
  if (!text) return "";
  // 處理 1. 2. 3. 這種標示點,先進行初步換行
  // 尋找符合 "數字." 的模式,並在其前面加上換行符(如果不是在開頭的話)
  let formattedText = text.replace(/(\d+\.)/g, (match, p1, offset) => {
    return offset === 0 ? match : "\n" + match;
  });
  const segments = formattedText.split('\n');
  let resultLines = [];
  segments.forEach(segment => {
    let currentLine = "";
    let currentLineWidth = 0;
    // 將 segment 依字元處理
    for (let i = 0; i < segment.length; i++) {
      const char = segment[i];
      const charWidth = getVisualWidth(char);
      if (currentLineWidth + charWidth > limit) {
        resultLines.push(currentLine);
        currentLine = char;
        currentLineWidth = charWidth;
      } else {
        currentLine += char;
        currentLineWidth += charWidth;
      }
    }
    if (currentLine) resultLines.push(currentLine);
  });
  return resultLines.join("\n" + wrapIndent);
}
function getDocString(m) {
  const methodName = m.matcher.match(/^(procedure|function)\s+TCB_IMGPSScanX\.([\w\.]+)/i)?.[2] || m.matcher;
  const deps = (m.deps || []).join(', ');
  const wrappedDeps = wrapText(deps, 68, "            ");
  const desc = m.description || '';
  const wrappedDesc = wrapText(desc, 68, "            ");
  return `{ ==============================================================================
  方法名稱:${methodName}
  引用相依:${wrappedDeps}
  方法描述:${wrappedDesc}
============================================================================== }\n`;
}
function main() {
  console.log('Copying ' + SRC_FILE + ' to ' + DEST_FILE);
  fs.copyFileSync(SRC_FILE, DEST_FILE);
  const originalContent = fs.readFileSync(DEST_FILE, 'utf8');
  const lines = originalContent.split(/\r?\n/);
  const allMethods = [];
  JSON_FILES.forEach(jsonFile => {
    if (!fs.existsSync(jsonFile)) return;
    const data = JSON.parse(fs.readFileSync(jsonFile, 'utf8'));
    data.forEach(m => {
      const lIndex = parseInt(m.lIndex);
      const rIndex = parseInt(m.rIndex);
      if (lIndex > 0 && rIndex > 0) {
        allMethods.push({
          ...m,
          lIndex,
          rIndex
        });
      }
    });
  });
  const lineToTargetFile = new Array(lines.length + 1).fill(null);
  const fileToMethods = {};
  allMethods.forEach(m => {
    let targetFile = null;
    // team_task_classification 團隊分工覆寫
    if (!targetFile) {
      for (const tag of m.tags) {
        if (PRIM_TAGS_TO_FIE[tag]) {
          targetFile = PRIM_TAGS_TO_FIE[tag];
          break;
        }
      }
    }
    if (!targetFile) {
      for (const tag of m.tags) {
        if (TAGS_TO_FILE[tag]) {
          targetFile = TAGS_TO_FILE[tag];
          break;
        }
      }
    }
    if (!targetFile) targetFile = 'view/misc.pas';
    if (!fileToMethods[targetFile]) {
      fileToMethods[targetFile] = [];
    }
    fileToMethods[targetFile].push(m);
    for (let i = m.lIndex; i <= m.rIndex; i++) {
      if (i <= lines.length) {
        lineToTargetFile[i] = targetFile;
      }
    }
  });
  // Create sub-files
  for (const targetFile in fileToMethods) {
    const methods = fileToMethods[targetFile];
    methods.sort((a, b) => a.lIndex - b.lIndex);
    let subFileContent = '';
    methods.forEach(m => {
      const methodLines = lines.slice(m.lIndex - 1, m.rIndex);
      subFileContent += getDocString(m) + methodLines.join('\n') + '\n\n';
    });
    const fullPath = path.join(OUTPUT_DEST, targetFile);
    fs.mkdirSync(path.dirname(fullPath), { recursive: true });
    fs.writeFileSync(fullPath, subFileContent);
    console.log(`Saved ${methods.length} methods to ${fullPath}`);
  }
  // Rewrite main file and generate remainings
  const newMainLines = [];
  const remainingsLines = [];
  const includedFiles = new Set();
  for (let i = 1; i <= lines.length; i++) {
    const targetFile = lineToTargetFile[i];
    if (targetFile) {
      if (!includedFiles.has(targetFile)) {
        newMainLines.push(`{$I ${OUTPUT_DEST}/${targetFile}}`);
        includedFiles.add(targetFile);
      }
    } else {
      newMainLines.push(lines[i - 1]);
      remainingsLines.push(lines[i - 1]);
    }
  }
  const finalContent = newMainLines.join('\n');
  fs.writeFileSync(DEST_FILE, finalContent);
  if (!fs.existsSync(path.dirname(REMAININGS_FILE))) {
    fs.mkdirSync(path.dirname(REMAININGS_FILE), { recursive: true });
  }
  fs.writeFileSync(REMAININGS_FILE, remainingsLines.join('\n'));
  console.log('\n--- Content of ' + DEST_FILE + ' after disaggregation ---\n');
  console.log(finalContent.substring(0, 1000) + '\n...');
  console.log('\n--- End of Preview ---\n');
  console.log('Remainings saved to: ' + REMAININGS_FILE);
  console.log('Done.');
}
main();
scripts/final_classify_scanImp_pas.test.js
比對新檔案
@@ -0,0 +1,115 @@
const fs = require('fs');
const path = require('path');
const JSON_FILES = [
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.BusinessLogic.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.ImageProcessor.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.ScannerController.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.TransportManager.json',
  'doc/curtis/prompt/scanimpl_analysis/scanimpl_annalysis.UIView.json'
];
const TAGS_TO_FILE = {
  // ScannerController
  'ScannerController.acquisitionHandler': 'CB_IMGPSScanImp.scan.ac.pas',
  'ScannerController.twainWrapper': 'CB_IMGPSScanImp.scan.twain.pas',
  // TransportManager
  'TransportManager.apiClient': 'CB_IMGPSScanImp.apiClient.pas',
  'TransportManager.fileTransfer': 'CB_IMGPSScanImp.fileClient.pas',
  'TransportManager.certificateManager': 'CB_IMGPSScanImp.cert.pas',
  'TransportManager.payloadArchiver': 'CB_IMGPSScanImp.archiver.pas',
  // ImageProcessor
  'ImageProcessor.transformer': 'CB_IMGPSScanImp.img.trans.pas',
  'ImageProcessor.converter': 'CB_IMGPSScanImp.img.cnv.pas',
  'ImageProcessor.anchorAnalyzer': 'CB_IMGPSScanImp.img.anchor.pas',
  'ImageProcessor.payloadArchiver': 'CB_IMGPSScanImp.archiver.pas',
  // BusinessLogic
  'BusinessLogic.systemInternal': 'CB_IMGPSScanImp.bloc.sys.pas',
  'BusinessLogic.configRepository': 'CB_IMGPSScanImp.bloc.cfg.pas',
  'BusinessLogic.ruleEngine': 'CB_IMGPSScanImp.bloc.rule.pas',
  'BusinessLogic.entityMapping': 'CB_IMGPSScanImp.bloc.map.pas',
  'BusinessLogic.fileManager': 'CB_IMGPSScanImp.bloc.file.pas',
  'BusinessLogic.caseManager': 'CB_IMGPSScanImp.bloc.case.pas',
  'BusinessLogic.entityModel': 'CB_IMGPSScanImp.bloc.model.pas',
  'BusinessLogic.activeXWrapper': 'CB_IMGPSScanImp.bloc.ocx.pas',
  // UIView
  '初始化與生命週期': 'CB_IMGPSScanImp.view.lfcycle.pas',
  'UIView.events': 'CB_IMGPSScanImp.view.evt.pas',
  'UIView.inputHandler': 'CB_IMGPSScanImp.view.evt.pas',
  'UIView.configRepository': 'CB_IMGPSScanImp.view.cfg.pas',
  'UIView.ruleEngine': 'CB_IMGPSScanImp.view.rule.pas',
  'UIView.entityMapping': 'CB_IMGPSScanImp.view.map.pas',
  'UIView.fileManager': 'CB_IMGPSScanImp.view.file.pas',
  'UIView.caseManager': 'CB_IMGPSScanImp.view.case.pas',
  'UIView.entityModel': 'CB_IMGPSScanImp.view.model.pas',
  'UIView.activeXWrapper': 'CB_IMGPSScanImp.view.ocx.pas',
  'UIView.treeView': 'CB_IMGPSScanImp.view.tree.pas',
  'UIView.toolBar': 'CB_IMGPSScanImp.view.toolbar.pas',
  'UIView.imageScrollBox': 'CB_IMGPSScanImp.view.isb.pas',
  'UIView.popupMenu': 'CB_IMGPSScanImp.view.menu.pas',
  'UIView.listView': 'CB_IMGPSScanImp.view.list.pas',
};
const SRC_FILE = 'CB_IMGPSScanImp.pas.bk';
function main() {
  const originalContent = fs.readFileSync(SRC_FILE, 'utf8');
  const lines = originalContent.split(/\r?\n/);
  let successCount = 0;
  let failCount = 0;
  JSON_FILES.forEach(jsonFile => {
    console.log(`Checking ${jsonFile}...`);
    const data = JSON.parse(fs.readFileSync(jsonFile, 'utf8'));
    data.forEach(m => {
      const lIndex = parseInt(m.lIndex);
      const rIndex = parseInt(m.rIndex);
      if (lIndex <= 0 || rIndex <= 0) return;
      // Find the target file
      let targetFile = null;
      for (const tag of m.tags) {
        if (TAGS_TO_FILE[tag]) {
          targetFile = TAGS_TO_FILE[tag];
          break;
        }
      }
      if (targetFile) {
        if (!fs.existsSync(targetFile)) {
          console.error(`Error: Target file ${targetFile} does not exist.`);
          failCount++;
          return;
        }
        const subFileContent = fs.readFileSync(targetFile, 'utf8');
        const expectedCodeLines = lines.slice(lIndex - 1, rIndex);
        const expectedCode = expectedCodeLines.join('\n');
        // Check if expectedCode exists in subFileContent
        // Note: the subFileContent has an extra \n between methods
        if (subFileContent.includes(expectedCode)) {
          successCount++;
        } else {
          console.error(`Error: Code for ${m.matcher} (line ${lIndex}-${rIndex}) not found in ${targetFile}`);
          failCount++;
        }
      }
    });
  });
  console.log(`\nVerification Results:`);
  console.log(`  Success: ${successCount}`);
  console.log(`  Fail: ${failCount}`);
  if (failCount > 0) {
    process.exit(1);
  }
}
main();
scripts/list_dependencies.js
比對新檔案
@@ -0,0 +1,110 @@
const fs = require('fs');
const readline = require('readline');
const path = require('path');
/**
 * 尋找 Pascal 檔案中的影像處理相關關鍵字,並生成 CSV 輸出。
 * @param {string} filePath - Pascal 檔案路徑
 * @param {string} outputCsv - 輸出的 CSV 檔案名稱
 */
async function findImageKeywords(filePath, keywordsStr, exclusionStr, outputCsv) {
  const keeper = {}
  // 拆分並使用 Set 移除重複的關鍵字
  const keywords = [...new Set(keywordsStr.split('|'))];
  const exclusion = exclusionStr ? [...new Set(exclusionStr.split('|'))] : [];
  // 用於匹配 Delphi procedure 或 function 的正規表達式
  const methodPattern = /^\s*(?:procedure|function)\s+([a-zA-Z0-9_\.]+)/i;
  const results = [];
  let currentMethod = "Global_Or_Interface"; // 預設狀態 (尚未進入任何方法)
  if (!fs.existsSync(filePath)) {
    console.error(`❌ 錯誤: 找不到指定的檔案 '${filePath}'`);
    console.log("請確保檔案名稱正確,並與此腳本放在同一目錄下。");
    return;
  }
  console.log(`🔍 開始掃描檔案: ${filePath} ...\n`);
  const fileName = path.basename(filePath);
  // 建立逐行讀取流 (使用 latin1 讀取以避免 Big5 中文字元在原生 Node 環境報錯)
  // 由於我們只比對英文關鍵字,編碼不會影響比對結果
  const fileStream = fs.createReadStream(filePath, {encoding: 'latin1'});
  const rl = readline.createInterface({
    input: fileStream,
    crlfDelay: Infinity
  });
  let lineNum = 0;
  for await (const line of rl) {
    lineNum++;
    // 檢查是否進入了新的方法實作區塊
    const methodMatch = line.match(methodPattern);
    if (methodMatch) {
      currentMethod = methodMatch[1];
    }
    const lineLower = line.toLowerCase();
    // 檢查該行是否包含我們關注的關鍵字
    for (const kw of keywords) {
      if (lineLower.includes(kw.toLowerCase()) && !exclusion.some((_)=>lineLower.includes(_.toLowerCase()))) {
        keeper[currentMethod] ??= new Set([])
        if (keeper[currentMethod].has(kw))
          continue
        keeper[currentMethod].add(kw)
        results.push({
          MethodName: currentMethod,
          FileName: fileName,
          LineNumber: lineNum,
          Dependency: kw,
          CodeSnippet: line.trim().replace(/"/g, '""') // 處理 CSV 雙引號跳脫
        });
      }
    }
  }
  // 1. 輸出至 Console
  console.log("-".repeat(90));
  // 為了讓 Console 顯示更乾淨,我們按方法名稱進行分組顯示
  const groupedResults = results.reduce((acc, curr) => {
    if (!acc[curr.MethodName]) acc[curr.MethodName] = [];
    acc[curr.MethodName].push(curr);
    return acc;
  }, {});
  for (const [method, items] of Object.entries(groupedResults)) {
    // 收集該方法內找到的所有相依關鍵字 (去重複)
    const deps = [...new Set(items.map(i => i.Dependency))].join(', ');
    const lines = [...new Set(items.map(i => i.LineNumber))].join(', ');
    console.log(`${method.padEnd(30)} | ${fileName.padEnd(20)} | ${lines.padEnd(5)} | ${deps}`);
  }
  console.log(`\n✅ 掃描成功!共找到 ${results.length} 次相依引用。`);
  // 2. 輸出至 CSV 檔案
  // 加入 BOM 以確保 Excel 能正確解析 UTF-8 中文
  const csvHeader = '\uFEFF[ ],方法名,所在檔名,行號,引用了什麼相依,方法描述(請手動填寫),原始程式碼片段\n';
  const csvContent = results.map(r =>
    `[V],"${r.MethodName}","${r.FileName}","${r.LineNumber}","${r.Dependency}","","${r.CodeSnippet}"`
  ).join('\n');
  if (results.length) {
    fs.writeFileSync(outputCsv, csvHeader + csvContent, 'utf8');
  }
  console.log(`📁 詳細結果已匯出至: ${outputCsv} (可直接用 Excel 打開)`);
  return {
    csvHeader,
    csvContent
  }
}
module.exports = {
  findImageKeywords
}
scripts/list_dependencies_run.js
比對新檔案
@@ -0,0 +1,99 @@
const img = require('./list_image_dependencies')
const io = require('./list_io_dependencies')
const scan = require('./list_scan_dependencies')
const transp = require('./list_transport_dependencies')
const fs = require("fs");
const path = require("path");
const baseDir = path.join(process.cwd(), 'scripts/dist');
const IMG_DEPS = img.listDependencies()
const IO_DEPS = io.listDependencies()
const SCAN_DEPS = scan.listDependencies()
const TRANS_DEPS = transp.listDependencies()
/**
 * 解析單行 CSV 字串,能正確處理被引號包覆且內部含有逗號的欄位。
 * @param {string} line - 要解析的單行 CSV 字串。
 * @returns {string[]} 解析後的欄位陣列。
 */
function parseCsvLine(line) {
  const fields = [];
  let currentField = '';
  let inQuotes = false;
  for (let i = 0; i < line.length; i++) {
    const char = line[i];
    if (char === '"') {
      // 處理 CSV 中用兩個雙引號來代表一個雙引號的轉義規則
      if (inQuotes && line[i + 1] === '"') {
        currentField += '"';
        i++; // 跳過下一個引號
      } else {
        inQuotes = !inQuotes; // 進入或離開引號模式
      }
    } else if (char === ',' && !inQuotes) {
      // 當不在引號內且遇到逗號時,才視為一個欄位的結束
      fields.push(currentField);
      currentField = '';
    } else {
      // 一般字元,直接附加到當前欄位
      currentField += char;
    }
  }
  // 將最後一個欄位加入陣列
  fields.push(currentField);
  return fields;
}
// 您可以這樣使用它:
// const [pick, methodName, fileName, lineno, deps, desc, source] = parseCsvLine(line);
function flatten(arrOStr) {
  if (Array.isArray(arrOStr)) {
    return arrOStr.reduce((acc, cur)=>{
      if (typeof cur === 'string') acc.push(cur)
      else acc.push(...flatten(cur))
      return acc
    }, [])
  }
  return arrOStr
}
async function main() {
  const imgDeps = (await IMG_DEPS).filter((_) => _.csvContent).map((_) => _.csvContent.split('\n'))
  const ioDeps = (await IO_DEPS).filter((_) => _.csvContent).map((_) => _.csvContent.split('\n'))
  const scanDeps = (await SCAN_DEPS).filter((_) => _.csvContent).map((_) => _.csvContent.split('\n'))
  const transDeps = (await TRANS_DEPS).filter((_) => _.csvContent).map((_) => _.csvContent.split('\n'))
  const csvHeader = (await IMG_DEPS)[0].csvHeader
  const allCsvContent = flatten([
    ...imgDeps,
    ...ioDeps,
    ...scanDeps,
    ...transDeps
  ])
  const keep = {}
  const results = []
  allCsvContent.forEach((line)=>{
    const [pick, methodName, fileName, lineno, deps, desc, source] = parseCsvLine(line)
    const ident = `${fileName}-${methodName}`
    keep[ident] ??= {}
    if (keep[ident][deps])
      return
    keep[ident][deps] ??= {
      source, lineno, desc
    }
    results.push({
      pick, methodName, fileName, lineno, deps, desc, source
    })
  })
  const csvContent = results.map(r =>
    `${r.pick},${r.methodName},${r.fileName},${r.lineno},${r.deps},${r.desc},${r.source}`
  ).join('\n');
  const outputCsv = path.join(baseDir, `deps.all.csv`)
  fs.writeFileSync(outputCsv, csvHeader + csvContent, 'utf8');
}
main()
scripts/list_image_dependencies.js
比對新檔案
@@ -0,0 +1,82 @@
/**
 *
 *  IMAGE 模組列表輸出至 CSV  scripts/dist/*.image.csv
 *
 *
 * */
const fs = require('fs');
const readline = require('readline');
const path = require('path');
const {findImageKeywords} = require('./list_dependencies')
const baseDir = path.join(process.cwd(), 'scripts/dist');
const exclusions = Array.from(new Set([
  'ScanRotate',
  'ImageFormat <> ifBlackWhite',
])).join('|')
// 您提供的關鍵字 (以 | 分隔)
const keywordsStr = Array.from(new Set([
  'TTiffGraphic',
  'TDibGraphic',
  'DeskewImg',
  'Rotate',
  'CropImg',
  'ImageReSize_FormID',
  'ImageReSize_tmp',
  'CheckNeedCrop',
  'ImageProcessor.transformer',
  'ConvertToBW',
  'ConvertToGray',
  'Image_Smooth',
  'NegativeImg',
  'CleanupBorder',
  'ImageProcessor.converter',
  'MpsGetBarcode',
  'Get_OMR',
  'ImageProcessor.barcodeRecognizer',
  'FindPoint',
  'CheckSize',
  'GetSiteOMR',
  'ImageProcessor.anchorAnalyzer',
  'TJpegGraphic',
  'DpiResize',
  // 以下可省
  'SaveQuality',
  'FJpgCompression',
  'ifTrueColor',
  'ifGray256',
  'ConvertToBW',
  'ConvertToGray',
  'Image_Smooth',
  'NegativeImg',
  'CleanupBorder',
  'ifBlackWhite',
  'tcGroup4',
  'tcPackBits',
  'tcJpeg',
  'ifColor25'
])).join('|')
// 執行腳本 (請確認您的目標檔案名稱,預設為 CB_IMGPSScanImp.pas)
const targetFiles = [
  'CB_IMGPSScanImp.pas.bk',
  'DocCopy.pas',
  'DocList.pas',
  'DocPrt.pas',
  'ErrList.pas',
  'InputMask.pas',
  'OldCaseImg.pas',
  'OldCaseInfo.pas',
  'PatchFom.pas',
  'ScanMemo.pas'
]
async function listDependencies() {
  console.log(`${'方法名'.padEnd(30)} | ${'所在檔名'.padEnd(20)} | ${'行號'.padEnd(5)} | ${'引用了什麼相依 (關鍵字)'}`);
  console.log(`--- | --- | --- | --- |`);
  return await Promise.all(targetFiles.map((_) => findImageKeywords(_, keywordsStr, exclusions, path.join(baseDir, `${_}.image.csv`))))
}
module.exports = {
  listDependencies
}
scripts/list_io_dependencies.js
比對新檔案
@@ -0,0 +1,61 @@
/**
 *
 *  SCAN 模組列表輸出至 CSV  scripts/dist/*.scan.csv
 *
 *
 * */
const fs = require('fs');
const readline = require('readline');
const path = require('path');
const { findImageKeywords } = require('./list_dependencies')
const baseDir = path.join(process.cwd(), 'scripts/dist');
const exclusions = Array.from(new Set([])).join('|')
// 您提供的關鍵字 (以 | 分隔)
const keywordsStr = Array.from(new Set([
  'SaveToFile',
  'LoadFromFile',
  'ReSortFileName',
  'DeleteImageFile',
  'DeleteDocNoFile',
  'DeleteShowFile',
  'RenameFile',
  'MoveFile',
  'CopyFile',
  'FileExists',
  'DirectoryExists',
  'FindFirst',
  'FindNext',
  '_DelTree',
  'Str2Dir',
  'ForceDirectories',
  'GetNoNameCase',
  'GetLocalAppDir'
])).join('|')
// 執行腳本 (請確認您的目標檔案名稱,預設為 CB_IMGPSScanImp.pas)
const targetFiles = [
  'CB_IMGPSScanImp.pas.bk',
  'DocCopy.pas',
  'DocList.pas',
  'DocPrt.pas',
  'ErrList.pas',
  'InputMask.pas',
  'OldCaseImg.pas',
  'OldCaseInfo.pas',
  'PatchFom.pas',
  'ScanMemo.pas'
]
async function listDependencies() {
  console.log(`${'方法名'.padEnd(30)} | ${'所在檔名'.padEnd(20)} | ${'行號'.padEnd(5)} | ${'引用了什麼相依 (關鍵字)'}`);
  console.log(`--- | --- | --- | --- |`);
  return await Promise.all(targetFiles.map((_) => findImageKeywords(_, keywordsStr, exclusions, path.join(baseDir, `${_}.io.csv`))))
}
module.exports = {
  listDependencies
}
scripts/list_scan_dependencies.js
比對新檔案
@@ -0,0 +1,53 @@
/**
 *
 *  SCAN 模組列表輸出至 CSV  scripts/dist/*.scan.csv
 *
 *
 * */
const fs = require('fs');
const readline = require('readline');
const path = require('path');
const { findImageKeywords } = require('./list_dependencies')
const baseDir = path.join(process.cwd(), 'scripts/dist');
const exclusions = Array.from(new Set([])).join('|')
// 您提供的關鍵字 (以 | 分隔)
const keywordsStr = Array.from(new Set([
  'OnAcquire',
  'SelectScanner',
  'scanner.SelectScanner',
  'initkscan',
  'CheckScannerConfig',
  'PageEnd',
  'PageDone',
  'ScannerControl.twainWrapper',
  'StatrTwainScan',
  'Scanner.OpenSource',
  'Scanner.AcquireWithSourceOpen',
  'Scanner.CloseSource',
  'Scanner'
])).join('|')
// 執行腳本 (請確認您的目標檔案名稱,預設為 CB_IMGPSScanImp.pas)
const targetFiles = [
  'CB_IMGPSScanImp.pas.bk',
  'DocCopy.pas',
  'DocList.pas',
  'DocPrt.pas',
  'ErrList.pas',
  'InputMask.pas',
  'OldCaseImg.pas',
  'OldCaseInfo.pas',
  'PatchFom.pas',
  'ScanMemo.pas'
]
async function listDependencies() {
  console.log(`${'方法名'.padEnd(30)} | ${'所在檔名'.padEnd(20)} | ${'行號'.padEnd(5)} | ${'引用了什麼相依 (關鍵字)'}`);
  console.log(`--- | --- | --- | --- |`);
  return await Promise.all(targetFiles.map((_) => findImageKeywords(_, keywordsStr, exclusions, path.join(baseDir, `${_}.scan.csv`))))
}
module.exports = {
  listDependencies
}
scripts/list_transport_dependencies.js
比對新檔案
@@ -0,0 +1,56 @@
/**
 *
 *  SCAN 模組列表輸出至 CSV  scripts/dist/*.scan.csv
 *
 *
 * */
const fs = require('fs');
const readline = require('readline');
const path = require('path');
const { findImageKeywords } = require('./list_dependencies')
const baseDir = path.join(process.cwd(), 'scripts/dist');
const exclusions = Array.from(new Set([])).join('|')
// 您提供的關鍵字 (以 | 分隔)
const keywordsStr = Array.from(new Set([
  'TElHTTPSClient',
  'ProcessServlet_Get',
  'ProcessServlet_FormData',
  'upFile',
  'dnFile_Get',
  'dnFile',
  'TElSimpleFTPSClient',
  'SetFtpInfo',
  'IIS_Ftp',
  'FtpCaseComplete',
  'En_DecryptionStr_Base64',
  'TIdHashMessageDigest5',
  'LoadFileGetMD5',
  'HTTPSClientCertificateValidate',
  'HttpClient'
])).join('|')
// 執行腳本 (請確認您的目標檔案名稱,預設為 CB_IMGPSScanImp.pas)
const targetFiles = [
  'CB_IMGPSScanImp.pas.bk',
  'DocCopy.pas',
  'DocList.pas',
  'DocPrt.pas',
  'ErrList.pas',
  'InputMask.pas',
  'OldCaseImg.pas',
  'OldCaseInfo.pas',
  'PatchFom.pas',
  'ScanMemo.pas'
]
async function listDependencies() {
  console.log(`${'方法名'.padEnd(30)} | ${'所在檔名'.padEnd(20)} | ${'行號'.padEnd(5)} | ${'引用了什麼相依 (關鍵字)'}`);
  console.log(`--- | --- | --- | --- |`);
  return await Promise.all(targetFiles.map((_) => findImageKeywords(_, keywordsStr, exclusions, path.join(baseDir, `${_}.transp.csv`))))
}
module.exports = {
  listDependencies
}
scripts/readme.md
比對新檔案
@@ -0,0 +1,30 @@
## 分析/產出/驗證-模組分類
### 粗拆分(.json)
[scanimpl_annalysis_classify.js](scanimpl_annalysis_classify.js)
[scanimpl_annalysis_disaggregate.js](scanimpl_annalysis_disaggregate.js)
[scanimpl_annalysis_extract_methods.js](scanimpl_annalysis_extract_methods.js)
[scanimpl_annalysis_validate.js](scanimpl_annalysis_validate.js)
### 最終拆分(.pascal)
[classify_scanImp_pas.js](classify_scanImp_pas.js)
[classify_scanImp_pas.test.js](classify_scanImp_pas.test.js)
## 生成模組引用 CSV
[list_dependencies.js](list_dependencies.js)
[list_dependencies_run.js](list_dependencies_run.js)
[list_image_dependencies.js](list_image_dependencies.js)
[list_io_dependencies.js](list_io_dependencies.js)
[list_scan_dependencies.js](list_scan_dependencies.js)
[list_transport_dependencies.js](list_transport_dependencies.js)
## 模組額外分類腳本(e.g.: excel 定義)
[gen_scanimpl_annalysis_json.test.js](gen_scanimpl_annalysis_json.test.js)
[scanimpl_annalysis_addon_json.js](scanimpl_annalysis_addon_json.js)
## dfm to web - spec template 生成
[batch_dfm_to_web.js](batch_dfm_to_web.js)
scripts/scanimpl_annalysis_addon_json.js
比對新檔案
@@ -0,0 +1,125 @@
/**
 * 需求 0.3.1 生成處理額外分類腳本
 * * 執行方式:
 * node scripts/scanimpl_annalysis_addon_json.js
 */
const fs = require('fs');
const path = require('path');
// 尋找目標檔案的遞迴函數
function findTargetJsonFiles(dir, fileList = []) {
  if (!fs.existsSync(dir)) return fileList;
  const files = fs.readdirSync(dir);
  for (const file of files) {
    const filePath = path.join(dir, file);
    const stat = fs.statSync(filePath);
    // 略過不需要掃描的系統或依賴目錄
    if (stat.isDirectory() && !['node_modules', '.git', 'scripts'].includes(file)) {
      findTargetJsonFiles(filePath, fileList);
    } else if (file.startsWith('scanimpl_annalysis.') && file.endsWith('.json')) {
      fileList.push(filePath);
    }
  }
  return fileList;
}
function main() {
  // 設定路徑參數 (以執行時的目錄為基準)
  const baseDir = path.join(process.cwd(), 'doc/curtis/prompt/scanimpl_analysis');
  const classificationFilePath = path.join(baseDir, '02', 'team_tasks_classification.json');
  console.log('=============================================');
  console.log('開始執行額外分類整合...');
  console.log(`讀取額外分類檔: ${classificationFilePath}`);
  if (!fs.existsSync(classificationFilePath)) {
    console.error(`[錯誤] 找不到額外分類檔: ${classificationFilePath}`);
    console.log('請確認是否在專案根目錄下執行此腳本。');
    return;
  }
  // 1. 讀取並解析 team_tasks_classification.json
  const classificationData = JSON.parse(fs.readFileSync(classificationFilePath, 'utf8'));
  // 建立 lineno 到 tags 的 Mapping 字典
  // 這麼做可以處理同一個 lineno 同時要新增多個不同 tag 的情況
  const addonMap = new Map();
  classificationData.forEach(item => {
    if (!item.lineno || !item.tag) return;
    // 將 lineno 轉為字串以確保後續比對型別一致
    const linenoStr = String(item.lineno);
    if (!addonMap.has(linenoStr)) {
      addonMap.set(linenoStr, new Set());
    }
    addonMap.get(linenoStr).add(item.tag);
  });
  console.log(`成功載入 ${addonMap.size} 筆需要更新的行號設定。`);
  // 2. 找出專案內所有的 scanimpl_annalysis.*.json 檔案
  const targetFiles = findTargetJsonFiles(baseDir);
  if (targetFiles.length === 0) {
    console.warn(`[警告] 在專案中找不到任何 scanimpl_annalysis.*.json 檔案`);
    return;
  }
  let totalUpdatedFiles = 0;
  let totalAddedTags = 0;
  // 3. 處理每一個目標 JSON 檔
  targetFiles.forEach(filePath => {
    const fileName = path.basename(filePath);
    let isModified = false;
    let fileContent;
    try {
      fileContent = JSON.parse(fs.readFileSync(filePath, 'utf8'));
    } catch (e) {
      console.error(`[錯誤] 解析檔案 ${fileName} 失敗:`, e.message);
      return;
    }
    // 0.3.1.1 步驟1 變更資料
    if (Array.isArray(fileContent)) {
      fileContent.forEach(methodDef => {
        const currentLIndex = String(methodDef.lIndex);
        // 檢查該方法的 lIndex 是否存在於我們要添加的對映表中
        if (addonMap.has(currentLIndex)) {
          const newTags = Array.from(addonMap.get(currentLIndex));
          if (!methodDef.tags) {
            methodDef.tags = [];
          }
          newTags.forEach(newTag => {
            // 避免重複添加相同的 tag
            if (!methodDef.tags.includes(newTag)) {
              methodDef.tags.push(newTag);
              isModified = true;
              totalAddedTags++;
              console.log(`  [新增] 檔案: ${fileName} | 行號: ${currentLIndex} | 新增 Tag: "${newTag}"`);
            }
          });
        }
      });
    }
    // 0.3.1.2 步驟2 寫入資料
    if (isModified) {
      fs.writeFileSync(filePath, JSON.stringify(fileContent, null, 2), 'utf8');
      totalUpdatedFiles++;
    }
  });
  console.log('=============================================');
  console.log(`執行完畢!`);
  console.log(`共更新了 ${totalUpdatedFiles} 個檔案,累計新增了 ${totalAddedTags} 個標籤。`);
}
main();
scripts/scanimpl_annalysis_addon_json.test.js
比對新檔案
@@ -0,0 +1,183 @@
const fs = require('fs');
const path = require('path');
const PROJECT_ROOT = path.resolve(__dirname, '..');
const SOURCE_FILE = path.join(PROJECT_ROOT, 'CB_IMGPSScanImp.pas.bk');
const JSON_DIR = path.join(PROJECT_ROOT, 'doc', 'curtis', 'prompt', 'scanimpl_analysis');
const REVIEW_FILE = path.join(PROJECT_ROOT, 'CB_IMGPSScanImp_Remain_Review.pas');
// --- 動態 Delphi 語法解析器 ---
function findDelphiMethodBounds(lines, matcher, startIndexHint = 0) {
    // 取得函式宣告的前半段特徵,並統一轉換為小寫比對 (避免 Delphi 的大小寫差異)
    // 例如: "procedure TCB_IMGPSScanX.initkscan"
    const rawSignature = matcher.split('(')[0].trim().toLowerCase().replace(';', '');
    // 針對有參數跟沒參數的,進一步過濾乾淨
    const signature = rawSignature.split(':')[0].trim();
    let startIdx = -1;
    let endIdx = -1;
    // 1. 找尋起點 (從 startIndexHint 開始找,支援屬性 getter/setter 重名問題)
    for (let i = startIndexHint; i < lines.length; i++) {
        const line = lines[i].toLowerCase();
        // 確保是宣告實作區段,而非 interface 宣告
        if (line.includes(signature) &&
           (line.startsWith('procedure ') || line.startsWith('function ') || line.includes(' procedure ') || line.includes(' function '))) {
            // 避免找到 interface 區段的宣告 (通常以分號結尾且無 begin)
            // 簡單判斷:如果是實作區,往下找幾行應該會有 begin, var, const 等宣告
            let isImpl = false;
            for(let scan = i; scan < Math.min(i + 20, lines.length); scan++) {
                if (lines[scan].toLowerCase().match(/\b(begin|var|const|type)\b/)) {
                    isImpl = true;
                    break;
                }
            }
            if (isImpl) {
                startIdx = i;
                break;
            }
        }
    }
    if (startIdx === -1) return null;
    // 2. 透過括號與 Begin/End 深度計算法找尋終點 end;
    let openCount = 0;
    let foundBegin = false;
    let inAsm = false;
    for (let i = startIdx; i < lines.length; i++) {
        let line = lines[i].toLowerCase();
        // 剃除字串與註解,避免干擾括號計算
        line = line.replace(/'[^']*'/g, '').replace(/\/\/.*$/, '').replace(/\{[^}]*\}/g, '').replace(/\(\*.*?\*\)/g, '');
        // 分割出乾淨的字詞
        const words = line.split(/[\s;()\[\]=]+/g).filter(Boolean);
        for (const word of words) {
            if (word === 'asm') inAsm = true;
            if (word === 'begin' || word === 'case' || word === 'try' || word === 'asm') {
                openCount++;
                foundBegin = true;
            }
            if (word === 'end') {
                openCount--;
                if (inAsm && openCount === 0) inAsm = false;
            }
        }
        // 當發現了 begin 且深度歸零,代表這個方法完全結束了
        if (foundBegin && openCount === 0) {
            endIdx = i;
            break;
        }
    }
    return { lIndex: startIdx + 1, rIndex: endIdx + 1 };
}
function runTest() {
    console.log("==================================================");
    console.log("  CB_IMGPSScanImp 動態全域解析與拆解測試腳本 (自動校正行號)");
    console.log("==================================================\n");
    if (!fs.existsSync(SOURCE_FILE)) {
        console.error(`[錯誤] 找不到來源備份檔: ${SOURCE_FILE}`);
        return;
    }
    let sourceLines = fs.readFileSync(SOURCE_FILE, 'utf-8').split(/\r?\n/);
    let parsedTargets = [];
    let totalUpdated = 0;
    let missingCount = 0;
    if (!fs.existsSync(JSON_DIR)) {
        console.error(`[錯誤] 找不到 JSON 目錄: ${JSON_DIR}`);
        return;
    }
    const files = fs.readdirSync(JSON_DIR).filter(f => f.endsWith('.json'));
    console.log(`>> 找到 ${files.length} 個 JSON 分類檔,開始進行語法比對與深度解析...`);
    // 略過 interface 區段,避免把 interface 的宣告誤當作實作
    let implementationStartLine = 0;
    for(let i=0; i<sourceLines.length; i++){
        if(sourceLines[i].toLowerCase().trim() === 'implementation') {
            implementationStartLine = i;
            break;
        }
    }
    // --- 0.2.2.1: 測試與動態驗證 (Verification & Correction Phase) ---
    for (const file of files) {
        const filePath = path.join(JSON_DIR, file);
        let hasChanges = false;
        try {
            const content = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
            const items = Array.isArray(content) ? content : [content];
            for (let item of items) {
                // 呼叫 AST 語法掃描器動態找尋真實行號 (從 implementation 之後開始找)
                const actualBounds = findDelphiMethodBounds(sourceLines, item.matcher, implementationStartLine);
                if (actualBounds && actualBounds.lIndex > 0 && actualBounds.rIndex >= actualBounds.lIndex) {
                    // 若偵測到的與原本不同的,自動更新並標記變更
                    if (item.lIndex != actualBounds.lIndex || item.rIndex != actualBounds.rIndex) {
                        item.lIndex = actualBounds.lIndex.toString();
                        item.rIndex = actualBounds.rIndex.toString();
                        hasChanges = true;
                        totalUpdated++;
                    }
                    // 轉換為 0-based index 加入待刪除清單
                    parsedTargets.push({
                        ...item,
                        startIdx: actualBounds.lIndex - 1,
                        endIdx: actualBounds.rIndex - 1
                    });
                } else {
                    console.warn(`[警告] 無法在原始碼中定位 Matcher 或其包含無效範圍: ${item.matcher}`);
                    missingCount++;
                }
            }
            // 若有修正,回寫覆蓋原本的 JSON 檔
            if (hasChanges) {
                fs.writeFileSync(filePath, JSON.stringify(items, null, 2), 'utf-8');
            }
        } catch (e) {
            console.error(`[錯誤] 解析 JSON 檔案 ${file} 失敗:`, e.message);
        }
    }
    console.log(`\n>> 驗證完成。`);
    console.log(`   成功動態定位: ${parsedTargets.length} 個區段。`);
    console.log(`   自動校正誤差: ${totalUpdated} 個。`);
    console.log(`   無法定位遺漏: ${missingCount} 個。\n`);
    // --- 0.2.2.2: 執行區段移除並審核 (Removal Phase) ---
    console.log("[階段 2] 執行區段移除...");
    // 依照 startIdx 由大到小排序 (由尾部往上刪),保證刪除時上方行號不會產生位移跑版
    parsedTargets.sort((a, b) => b.startIdx - a.startIdx);
    let removedCount = 0;
    for (const target of parsedTargets) {
        const deleteCount = target.endIdx - target.startIdx + 1;
        if (deleteCount > 0) {
            sourceLines.splice(target.startIdx, deleteCount);
            removedCount++;
        }
    }
    // 寫入完整剩餘結果至實體檔案
    fs.writeFileSync(REVIEW_FILE, sourceLines.join('\n'), 'utf-8');
    console.log(`✅ 成功移除 ${removedCount} 個方法區段。`);
    console.log(`✅ 移除後的剩餘程式碼已儲存至: \n   ${REVIEW_FILE}`);
    console.log(`   您可以開啟該檔案進行人工審核 (裡面應該只剩下全域變數與宣告區段)。`);
}
runTest();
scripts/scanimpl_annalysis_classify.js
比對新檔案
@@ -0,0 +1,115 @@
const fs = require('fs');
const path = require('path');
const base_path = 'doc/curtis/prompt/scanimpl_analysis';
const inputFile = path.join(base_path, 'step1_raw_methods.json');
const outputFile = path.join(base_path, 'step2_classified_methods.json');
const rules = [
  {
    tag: 'ScannerController',
    subs: [
      {
        sub: 'twainWrapper',
        keywords: ['StatrTwainScan', 'OnAcquire', 'initkscan', 'CheckScannerConfig', 'PageEnd', 'PageDone', 'R_W_Scanini', 'GetDefScanIni']
      }
    ]
  },
  {
    tag: 'ImageProcessor',
    subs: [
      {
        sub: 'transformer',
        keywords: ['DeskewImg', 'Rotate', 'CropImg', 'ImageReSize_FormID', 'ImageReSize_tmp', 'CheckNeedCrop']
      },
      {sub: 'converter', keywords: ['ConvertToBW', 'ConvertToGray', 'Image_Smooth', 'NegativeImg', 'CleanupBorder']},
      {sub: 'barcodeRecognizer', keywords: ['MpsGetBarcode', 'Get_OMR']},
      {sub: 'anchorAnalyzer', keywords: ['FindPoint', 'CheckSize', 'GetSiteOMR']}
    ]
  },
  {
    tag: 'TransportManager',
    subs: [
      {sub: 'requestWrapper', keywords: ['ProcessServlet', 'ProcessServlet_Get', 'ProcessServlet_FormData']},
      {
        sub: 'fileTransfer',
        keywords: ['upFile', 'dnFile', 'dnFile_Get', 'GetftpInfo', 'SetFtpInfo', 'FtpCaseComplete']
      },
      {sub: 'utilities', keywords: ['En_DecryptionStr_Base64', 'LoadFileGetMD5', 'HTTPSClientCertificateValidate']},
      {sub: 'payloadArchiver', keywords: ['ZipMainFile', 'ZipMaskFile', 'ExecuteUnZip']}
    ]
  },
  {
    tag: 'BusinessLogic',
    subs: [
      {
        sub: 'paramState',
        keywords: ['SetSQLData', 'GetSQLData', 'FindSQLData', 'GetSetInf1', 'GetSetInf2', 'GetSetInf3', 'GetSetInf4', 'GetSetInf5', 'GetSetInf6', 'GetSetInf7']
      },
      {
        sub: 'entityMapping',
        keywords: ['BarCode2FormID', 'BarCode2CaseID', 'FormCode2DocNo', 'DocNo2DocName', 'DocNoNeedDiv', 'CreateDocNo_Info', 'CreateCustDocNo_Info']
      },
      {sub: 'ormRuleEngine', keywords: ['OMRCheckCase', 'OMRErr2ini', 'OMRErrini2List']},
      {
        sub: 'caseModification',
        keywords: ['SetUseCase', 'GetUseCase', 'OldCasetoNewCase', 'ErrFormtoCurrentForm', 'DeleteDocNoFileForESCAN']
      }
    ]
  },
  {
    tag: 'UIView',
    subs: [
      {sub: 'treeView', keywords: ['TreeView', 'DrawDocItem2']},
      {sub: 'scrollView', keywords: ['ISB', 'ImageScrollBox', 'ScrollBox']},
      {sub: 'i18n', keywords: ['InitialLanguage', 'DownLanguage']},
      {sub: 'layouts', keywords: ['DisplayMode', 'GoViewMode']},
      {sub: 'statusMessenger', keywords: ['DataLoading', 'Timer2Timer', 'StatusBar1DblClick', 'Timer', 'StatusBar']},
      {sub: 'listView', keywords: ['PageLV', 'AttListBox', 'ListView', 'ListBox']},
      {sub: 'toolBar', keywords: ['BtnClick', 'FC', 'BitBtn', 'SpeedButton']},
      {sub: 'popupMenu', keywords: ['PM', 'PopupMenu', 'MenuItem']}
    ]
  }
];
function classify() {
  const rawMethods = JSON.parse(fs.readFileSync(inputFile, 'utf8'));
  const classified = rawMethods.map(method => {
    const tags = new Set();
    const lowerMatcher = method.matcher.toLowerCase();
    for (const rule of rules) {
      for (const subRule of rule.subs) {
        const matched = subRule.keywords.some(k => {
          if (k === 'PM') return method.matcher.includes('.PM');
          if (k === 'FC') return method.matcher.includes('.FC');
          return lowerMatcher.includes(k.toLowerCase());
        });
        if (matched) {
          tags.add(rule.tag);
          tags.add(`${rule.tag}.${subRule.sub}`);
        }
      }
    }
    if (tags.size === 0) {
      tags.add('UIView');
      tags.add('UIView.misc');
    }
    return {
      matcher: method.matcher,
      tags: Array.from(tags),
      deps: [],
      lIndex: method.lIndex.toString(),
      rIndex: method.rIndex.toString(),
      description: ""
    };
  });
  fs.writeFileSync(outputFile, JSON.stringify(classified, null, 2), 'utf8');
  console.log(`Classified ${classified.length} methods to ${outputFile}`);
}
classify();
scripts/scanimpl_annalysis_disaggregate.js
比對新檔案
@@ -0,0 +1,27 @@
const fs = require('fs');
const path = require('path');
const base_path = 'doc/curtis/prompt/scanimpl_analysis';
const inputFile = path.join(base_path, 'step2_classified_methods.json');
const modules = [
  'ScannerController',
  'BusinessLogic',
  'ImageProcessor',
  'TransportManager',
  'UIView'
];
function disaggregate() {
  const classifiedMethods = JSON.parse(fs.readFileSync(inputFile, 'utf8'));
  modules.forEach(mod => {
    // If any of the tags is the module name, it belongs to this module
    const filtered = classifiedMethods.filter(m => m.tags && m.tags.includes(mod));
    const outputFile = path.join(base_path, `scanimpl_annalysis.${mod}.json`);
    fs.writeFileSync(outputFile, JSON.stringify(filtered, null, 2), 'utf8');
    console.log(`Saved ${filtered.length} methods to ${outputFile}`);
  });
}
disaggregate();
scripts/scanimpl_annalysis_extract_methods.js
比對新檔案
@@ -0,0 +1,40 @@
const fs = require('fs');
const path = require('path');
const sourceFile = 'CB_IMGPSScanImp.pas.bk';
const base_path = 'doc/curtis/prompt/scanimpl_analysis';
const outputFile = path.join(base_path, 'step1_raw_methods.json');
function extract() {
  const lines = fs.readFileSync(sourceFile, 'utf8').split('\n');
  const totalLines = lines.length;
  const methods = [];
  const regex = /^(procedure|function)\s+TCB_IMGPSScanX\./i;
  for (let i = 0; i < totalLines; i++) {
    const line = lines[i];
    if (regex.test(line)) {
      methods.push({
        matcher: line.trim(),
        lIndex: i + 1,
        rIndex: -1 // To be filled
      });
    }
  }
  for (let i = 0; i < methods.length; i++) {
    if (i < methods.length - 1) {
      methods[i].rIndex = methods[i + 1].lIndex - 1;
    } else {
      methods[i].rIndex = totalLines;
    }
  }
  if (!fs.existsSync(base_path)) {
    fs.mkdirSync(base_path, {recursive: true});
  }
  fs.writeFileSync(outputFile, JSON.stringify(methods, null, 2), 'utf8');
  console.log(`Extracted ${methods.length} methods to ${outputFile}`);
}
extract();
scripts/scanimpl_annalysis_validate.js
比對新檔案
@@ -0,0 +1,65 @@
const fs = require('fs');
const path = require('path');
const sourceFile = 'CB_IMGPSScanImp.pas.bk';
const base_path = 'doc/curtis/prompt/scanimpl_analysis';
const remainingsFile = path.join(base_path, 'scanimpl_annalysis.remainings.txt');
const modules = [
  'ScannerController',
  'BusinessLogic',
  'ImageProcessor',
  'TransportManager',
  'UIView'
];
function validate() {
  const lines = fs.readFileSync(sourceFile, 'utf8').split('\n');
  const totalLines = lines.length;
  const allCapturedMethods = [];
  modules.forEach(mod => {
    const filePath = path.join(base_path, `scanimpl_annalysis.${mod}.json`);
    if (fs.existsSync(filePath)) {
      const methods = JSON.parse(fs.readFileSync(filePath, 'utf8'));
      allCapturedMethods.push(...methods);
    }
  });
  const coveredLines = new Uint8Array(totalLines + 1);
  allCapturedMethods.forEach(m => {
    const sourceLine = lines[m.lIndex - 1].trim();
    if (sourceLine !== m.matcher) {
      console.error(`Mismatch at line ${m.lIndex}: Expected "${m.matcher}", got "${sourceLine}"`);
    }
    for (let i = m.lIndex; i <= m.rIndex; i++) {
      coveredLines[i] = 1;
    }
  });
  let remainings = [];
  let start = -1;
  for (let i = 1; i <= totalLines; i++) {
    if (!coveredLines[i]) {
      if (start === -1) start = i;
    } else {
      if (start !== -1) {
        remainings.push({lIndex: start, rIndex: i - 1});
        start = -1;
      }
    }
  }
  if (start !== -1) remainings.push({lIndex: start, rIndex: totalLines});
  const remainingsText = remainings.map(r => {
    const content = lines.slice(r.lIndex - 1, r.rIndex).join('\n');
    return `[Lines ${r.lIndex} - ${r.rIndex}]\n${content}\n----------------------------------------\n`;
  }).join('\n');
  fs.writeFileSync(remainingsFile, remainingsText, 'utf8');
  console.log(`Validation complete. Remainings saved to ${remainingsFile}`);
}
validate();
separate/scanImp/CB_IMGPSScanImp_Data.pas
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_Data.ts
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_Main.ts
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_Scan.pas
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_Scan.ts
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_UI.pas
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_UI.ts
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_Utils.pas
檔案已刪除
separate/scanImp/CB_IMGPSScanImp_Utils.ts
檔案已刪除
split_pascal.js
檔案已刪除
uiOutput/CB_IMGPSScanImp/CB_IMGPSScanImp.ts
比對新檔案
@@ -0,0 +1,216 @@
import { ref, onMounted, onUnmounted } from 'vue';
// Mock Interfaces mapped from Delphi types
interface TTreeNode {
  text: string;
  expanded?: boolean;
  children?: TTreeNode[];
}
export function useCBIMGPSScanImpLogic() {
  // State
  const scanDuplex = ref<boolean>(false);
  const scanGray = ref<boolean>(false);
  const cb1 = ref<boolean>(false);
  const smoothView = ref<boolean>(false);
  const edit1 = ref<string>('');
  const showDenialTimeLb = ref<boolean>(false);
  const showAttFileGB = ref<boolean>(false);
  const showPageList = ref<boolean>(false);
  const showLoadingPanel = ref<boolean>(false);
  const showProgressPanel = ref<boolean>(false);
  const label7Text = ref<string>('Label7');
  const progressLabel = ref<string>('Label2');
  const progressValue = ref<number>(0);
  const scrollValue = ref<number>(1);
  const panel3Width = ref<number>(291);
  const statusPanels = ref<string[]>(['', '', '', '', '']);
  // Mock Data
  const treeNodes = ref<TTreeNode[]>([
    { text: '案件 1', children: [{ text: '文件 1-1' }] },
    { text: '案件 2' }
  ]);
  const selectedNodeIndex = ref<number>(-1);
  const attFiles = ref<string[]>(['file1.pdf', 'file2.pdf']);
  const pageList = ref<string[]>(['1', '2', '3']);
  const selectedPageIndex = ref<number>(-1);
  // Splitter logic
  const startResize = (e: MouseEvent) => {
    console.log('Splitter resize logic to adjust panel3Width');
  };
  // UI Event Handlers
  const ActiveFormCreate = () => { console.log('ActiveFormCreate'); };
  const ActiveFormKeyUp = () => { console.log('ActiveFormKeyUp'); };
  const TransBtnClick = () => { console.log('TransBtnClick'); };
  const NewScanBtnClick = () => { console.log('NewScanBtnClick'); };
  const AddScanBtnClick = () => { console.log('AddScanBtnClick'); };
  const FC0Click = () => { console.log('FC0Click'); };
  const FC1Click = () => { console.log('FC1Click'); };
  const FC2Click = () => { console.log('FC2Click'); };
  const FC3Click = () => { console.log('FC3Click'); };
  const FC4Click = () => { console.log('FC4Click'); };
  const FC5Click = () => { console.log('FC5Click'); };
  const FC6Click = () => { console.log('FC6Click'); };
  const ViewModeBtnMouseEnter = () => { console.log('ViewModeBtnMouseEnter'); };
  const PrePageBtnClick = () => { console.log('PrePageBtnClick'); };
  const NextPageBtnClick = () => { console.log('NextPageBtnClick'); };
  const OptionBtnClick = () => { console.log('OptionBtnClick'); };
  const SelectScanBtnClick = () => { console.log('SelectScanBtnClick'); };
  const ScanGrayCBClick = () => { console.log('ScanGrayCBClick:', scanGray.value); };
  const ScanDuplexCBClick = () => { console.log('ScanDuplexCBClick:', scanDuplex.value); };
  const CB1Click = () => { console.log('CB1Click:', cb1.value); };
  const SmoothCBClick = () => { console.log('SmoothCBClick:', smoothView.value); };
  const SampleScanBtnClick = () => { console.log('SampleScanBtnClick'); };
  const WNoteBtnClick = () => { console.log('WNoteBtnClick'); };
  const CheckCaseBtnClick = () => { console.log('CheckCaseBtnClick'); };
  const UseOldCaseLbClick = () => { console.log('UseOldCaseLbClick'); };
  const TreeView1Click = () => { console.log('TreeView1Click'); };
  const TreeView1KeyUp = () => { console.log('TreeView1KeyUp'); };
  const TreeView1MouseDown = () => { console.log('TreeView1MouseDown'); };
  const TreeView1MouseEnter = () => { console.log('TreeView1MouseEnter'); };
  const TreeView1MouseMove = () => { console.log('TreeView1MouseMove'); };
  const TreeView1MouseUp = () => { console.log('TreeView1MouseUp'); };
  const selectTreeNode = (idx: number) => { selectedNodeIndex.value = idx; console.log('Node selected', idx); };
  const PrtLbClick = () => { console.log('PrtLbClick'); };
  const CaseHelpBtnClick = () => { console.log('CaseHelpBtnClick'); };
  const AddAttFileLBClick = () => { console.log('AddAttFileLBClick'); };
  const DelAttFileLBClick = () => { console.log('DelAttFileLBClick'); };
  const AttListBoxClick = () => { console.log('AttListBoxClick'); };
  const AttListBoxDblClick = () => { console.log('AttListBoxDblClick'); };
  const Panel11DblClick = () => { console.log('Panel11DblClick'); };
  const ScrollBox1MouseEnter = () => { console.log('ScrollBox1MouseEnter'); };
  const Panel9Resize = () => { console.log('Panel9Resize'); };
  const ScrollBar1Change = () => { console.log('ScrollBar1Change:', scrollValue.value); };
  const SpeedButton3Click = () => { console.log('SpeedButton3Click'); };
  const SpeedButton14Click = () => { console.log('SpeedButton14Click'); };
  const SpeedButton15Click = () => { console.log('SpeedButton15Click'); };
  const SpeedButton16Click = () => { console.log('SpeedButton16Click'); };
  const SpeedButton17Click = () => { console.log('SpeedButton17Click'); };
  const SpeedButton18Click = () => { console.log('SpeedButton18Click'); };
  const SpeedButton19Click = () => { console.log('SpeedButton19Click'); };
  const SpeedButton20Click = () => { console.log('SpeedButton20Click'); };
  const SpeedButton21Click = () => { console.log('SpeedButton21Click'); };
  const SpeedButton22Click = () => { console.log('SpeedButton22Click'); };
  const PageLVClick = (idx: number) => { selectedPageIndex.value = idx; console.log('PageLVClick', idx); };
  const StatusBar1DblClick = () => { console.log('StatusBar1DblClick'); };
  const ExportBtClick = () => { console.log('ExportBtClick'); };
  const ImportBtClick = () => { console.log('ImportBtClick'); };
  const Button3Click = () => { console.log('Button3Click'); };
  const Button4Click = () => { console.log('Button4Click'); };
  const Button5Click = () => { console.log('Button5Click'); };
  const Button6Click = () => { console.log('Button6Click'); };
  // Placeholder for internal methods not directly exposed to UI but existing in pas
  const initParameter = () => {};
  const initkscan = () => {};
  onMounted(() => {
    ActiveFormCreate();
    initParameter();
  });
  return {
    scanDuplex,
    scanGray,
    cb1,
    smoothView,
    edit1,
    showDenialTimeLb,
    showAttFileGB,
    showPageList,
    showLoadingPanel,
    showProgressPanel,
    label7Text,
    progressLabel,
    progressValue,
    scrollValue,
    panel3Width,
    statusPanels,
    treeNodes,
    selectedNodeIndex,
    attFiles,
    pageList,
    selectedPageIndex,
    startResize,
    TransBtnClick,
    NewScanBtnClick,
    AddScanBtnClick,
    FC0Click,
    FC1Click,
    FC2Click,
    FC3Click,
    FC4Click,
    FC5Click,
    FC6Click,
    ViewModeBtnMouseEnter,
    PrePageBtnClick,
    NextPageBtnClick,
    OptionBtnClick,
    SelectScanBtnClick,
    ScanGrayCBClick,
    ScanDuplexCBClick,
    CB1Click,
    SmoothCBClick,
    SampleScanBtnClick,
    WNoteBtnClick,
    CheckCaseBtnClick,
    UseOldCaseLbClick,
    TreeView1Click,
    TreeView1KeyUp,
    TreeView1MouseDown,
    TreeView1MouseEnter,
    TreeView1MouseMove,
    TreeView1MouseUp,
    selectTreeNode,
    PrtLbClick,
    CaseHelpBtnClick,
    AddAttFileLBClick,
    DelAttFileLBClick,
    AttListBoxClick,
    AttListBoxDblClick,
    Panel11DblClick,
    ScrollBox1MouseEnter,
    Panel9Resize,
    ScrollBar1Change,
    SpeedButton3Click,
    SpeedButton14Click,
    SpeedButton15Click,
    SpeedButton16Click,
    SpeedButton17Click,
    SpeedButton18Click,
    SpeedButton19Click,
    SpeedButton20Click,
    SpeedButton21Click,
    SpeedButton22Click,
    PageLVClick,
    StatusBar1DblClick,
    ExportBtClick,
    ImportBtClick,
    Button3Click,
    Button4Click,
    Button5Click,
    Button6Click,
    ActiveFormKeyUp
  };
}
uiOutput/CB_IMGPSScanImp/CB_IMGPSScanImp.vue
比對新檔案
@@ -0,0 +1,264 @@
<template>
  <div class="cb-imgpsscanimp-form flex flex-col bg-gray-100 font-sans w-[950px] h-[618px]">
    <!-- Top Toolbar Panel1 -->
    <div class="panel-1 border-b border-gray-300 flex items-center h-[52px] flex-none px-2 space-x-2 bg-gray-100">
      <!-- Panel23 (Leftmost tools) -->
      <div class="panel-23 flex items-center h-full space-x-1" style="width: 56px;">
        <button class="new-scan-btn w-[42px] h-[50px] border border-gray-400 bg-gray-200 hover:bg-gray-300 flex items-center justify-center" @click="NewScanBtnClick">
           <img src="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'><path fill='none' stroke='black' stroke-width='2' d='M12 4v16m-8-8h16'/></svg>" alt="New" class="w-6 h-6"/>
        </button>
        <button v-show="false" class="add-scan-btn w-[42px] h-[50px] border border-gray-400 bg-gray-200" @click="AddScanBtnClick">Add</button>
      </div>
      <!-- TransBtn -->
      <button class="trans-btn w-[42px] h-[50px] border border-gray-400 bg-gray-200 hover:bg-gray-300 flex items-center justify-center" @click="TransBtnClick">
        <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"></path></svg>
      </button>
      <!-- Panel21 (Main Toolbar) -->
      <div class="panel-21 flex items-center h-full space-x-1" style="width: 545px;">
        <button class="fc0-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="FC0Click">FC0</button>
        <button class="fc1-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="FC1Click">FC1</button>
        <button class="fc2-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="FC2Click">FC2</button>
        <button class="fc3-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="FC3Click">FC3</button>
        <button class="fc4-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="FC4Click">FC4</button>
        <button class="fc5-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="FC5Click">FC5</button>
        <button v-show="false" class="fc6-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200" @click="FC6Click">FC6</button>
        <div class="w-2"></div> <!-- Spacer -->
        <button class="view-mode-btn w-[41px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @mouseenter="ViewModeBtnMouseEnter">VM</button>
        <button class="pre-page-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="PrePageBtnClick">&lt;</button>
        <button class="next-page-btn w-[42px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="NextPageBtnClick">&gt;</button>
        <button class="option-btn w-[41px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="OptionBtnClick">Opt</button>
        <button class="select-scan-btn w-[41px] h-[49px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="SelectScanBtnClick">Sel</button>
        <!-- Hidden Edit -->
        <input type="text" class="hidden" v-model="edit1" />
      </div>
      <!-- Right align stuff -->
      <div class="flex-grow"></div>
      <label v-show="showDenialTimeLb" class="text-red-500 font-bold w-[305px] truncate">可掃描上傳時間:</label>
      <!-- Hidden buttons in Top Panel -->
      <button v-show="false" @click="Button3Click">Btn3</button>
      <button v-show="false" @click="Button4Click">Btn4</button>
      <button v-show="false" @click="Button5Click">Btn5</button>
      <button v-show="false" @click="Button6Click">Btn6</button>
      <button v-show="false" @click="ExportBtClick">Export</button>
      <button v-show="false" @click="ImportBtClick">Import</button>
      <label class="scan-gray-cb flex items-center space-x-1 absolute right-[20px] top-[15px]">
          <input type="checkbox" v-model="scanGray" @change="ScanGrayCBClick" />
          <span>灰階掃描</span>
      </label>
    </div>
    <!-- Main Workspace Panel4 -->
    <div class="panel-4 flex flex-1 overflow-hidden relative">
      <!-- Left Tree/Settings Panel3 -->
      <div class="panel-3 flex flex-col w-[291px] border-r border-gray-300 bg-gray-100 flex-none z-10" :style="{ width: panel3Width + 'px' }">
        <!-- Scan Options Panel6 -->
        <div class="panel-6 h-[50px] border-b border-gray-300 flex items-center px-2 flex-none relative">
          <button v-show="false" class="sample-scan-btn w-[27px] h-[28px] border border-gray-400 mr-1" @click="SampleScanBtnClick">S</button>
          <button v-show="false" class="w-note-btn w-[27px] h-[28px] border border-gray-400 mr-1" @click="WNoteBtnClick">N</button>
          <div class="flex flex-col ml-2 text-sm space-y-1">
             <label class="flex items-center space-x-1">
               <input type="checkbox" v-model="scanDuplex" @change="ScanDuplexCBClick" />
               <span>雙面掃描</span>
             </label>
             <label class="flex items-center space-x-1">
               <input type="checkbox" v-model="cb1" @change="CB1Click" />
               <span>掃描對話窗</span>
             </label>
          </div>
          <button v-show="false" class="check-case-btn absolute right-2 top-2 border border-gray-400 px-2" @click="CheckCaseBtnClick">Chk</button>
        </div>
        <div v-show="false" class="panel-18 h-[32px] border-b border-gray-300 p-1 flex-none">
          <span class="text-blue-600 underline cursor-pointer" @click="UseOldCaseLbClick">舊案引入</span>
        </div>
        <!-- TreeView Area Panel17 -->
        <div class="panel-17 flex-1 flex flex-col min-h-0 bg-white border-b border-gray-300">
           <div class="tree-view-1 flex-1 overflow-auto p-1 border border-gray-300 m-1"
                @click="TreeView1Click" @keyup="TreeView1KeyUp" @mousedown="TreeView1MouseDown"
                @mouseenter="TreeView1MouseEnter" @mousemove="TreeView1MouseMove" @mouseup="TreeView1MouseUp">
               <!-- Mock TreeView -->
               <ul class="text-sm list-none p-0">
                  <li v-for="(node, idx) in treeNodes" :key="idx" class="cursor-pointer hover:bg-blue-100 p-1 rounded"
                      :class="{'bg-blue-500 text-white': selectedNodeIndex === idx}"
                      @click.stop="selectTreeNode(idx)">
                      <span v-if="node.children && node.children.length" class="mr-1 inline-block w-3">{{ node.expanded ? '-' : '+' }}</span>
                      <span v-else class="mr-1 inline-block w-3"></span>
                      {{ node.text }}
                  </li>
               </ul>
           </div>
           <!-- Bottom of TreeView (PrtLb, CaseHelpBtn) -->
           <div class="panel-13 h-[40px] flex items-center justify-between px-2 bg-gray-100 flex-none">
              <span v-show="false" class="text-blue-600 underline cursor-pointer" @click="PrtLbClick">列印</span>
              <button v-show="false" class="case-help-btn border border-gray-400 px-3 py-1" @click="CaseHelpBtnClick">Help</button>
           </div>
        </div>
        <!-- Attachment List (Hidden by default) -->
        <div v-show="showAttFileGB" class="att-file-gb h-[160px] border-t border-gray-300 bg-gray-100 flex-none p-1 flex flex-col">
           <div class="text-xs font-bold mb-1">PDF檔</div>
           <div class="panel-20 flex space-x-2 text-blue-600 underline text-sm mb-1 px-1 flex-none">
              <span class="cursor-pointer opacity-50">加入</span>
              <span class="cursor-pointer opacity-50">移除</span>
           </div>
           <select multiple class="att-list-box flex-1 border border-gray-300 w-full" @click="AttListBoxClick" @dblclick="AttListBoxDblClick">
              <option v-for="(att, idx) in attFiles" :key="idx">{{ att }}</option>
           </select>
        </div>
        <!-- Label7 from dfm -->
        <span class="absolute bottom-2 left-2 text-xs text-gray-500">{{ label7Text }}</span>
      </div>
      <!-- Splitter 1 -->
      <div class="splitter-1 w-[4px] bg-gray-300 cursor-col-resize flex-none hover:bg-gray-400 z-20" @mousedown="startResize"></div>
      <!-- Right Workspace Panel12 -->
      <div class="panel-12 flex-1 flex flex-col relative bg-gray-200">
        <!-- Top Info Panel5 -->
        <div class="panel-5 h-[52px] border-b border-gray-300 bg-gray-100 flex flex-none">
           <!-- AddCredit1RG -->
           <fieldset class="border border-gray-400 m-1 p-1 w-[161px] text-xs">
              <legend>是否新增授信檔</legend>
              <div class="flex space-x-2 justify-center mt-1">
                 <label><input type="radio" name="addCredit" disabled> 是</label>
                 <label><input type="radio" name="addCredit" disabled> 否</label>
              </div>
           </fieldset>
           <!-- Panel11 -->
           <div class="panel-11 flex-1 flex items-center p-2" @dblclick="Panel11DblClick">
              <span v-show="false" class="text-sm">oooo</span>
           </div>
        </div>
        <!-- Work Area Container -->
        <div class="flex flex-1 overflow-hidden relative">
           <!-- Panel14 (Thumbnails) -->
           <div class="panel-14 w-[185px] border-r border-gray-300 flex flex-col bg-white flex-none">
              <div class="bg-blue-600 text-white text-center text-sm font-bold py-1">1</div>
              <div class="panel-15 flex-1 overflow-auto relative">
                 <div class="scroll-box-1 absolute inset-0" @mouseenter="ScrollBox1MouseEnter">
                    <!-- Thumbnails go here -->
                 </div>
              </div>
           </div>
           <!-- Main Image Area Panel7 -->
           <div class="panel-7 flex-1 flex flex-col relative bg-gray-300">
              <!-- Image Tools Panel16 -->
              <div class="panel-16 h-[39px] border-b border-gray-300 bg-gray-100 flex items-center px-1 space-x-1 flex-none">
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="全部恢復全圖" @click="SpeedButton3Click">R</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="左轉90度" @click="SpeedButton14Click">L</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="轉180度" @click="SpeedButton15Click">U</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="右轉90度" @click="SpeedButton16Click">R</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="畫面同高" @click="SpeedButton17Click">H</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="畫面同寬" @click="SpeedButton18Click">W</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs font-bold" title="原圖" @click="SpeedButton19Click">1:1</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs" title="適窗" @click="SpeedButton20Click">F</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs font-bold" title="縮小50%" @click="SpeedButton21Click">50%</button>
                 <button class="w-[29px] h-[35px] border border-gray-400 bg-white hover:bg-gray-200 text-xs font-bold" title="縮小25%" @click="SpeedButton22Click">25%</button>
                 <label class="flex items-center space-x-1 text-xs ml-2">
                    <input type="checkbox" v-model="smoothView" @change="SmoothCBClick">
                    <span>灰階平滑顯示</span>
                 </label>
              </div>
              <!-- Main Viewport Panel9 -->
              <div class="panel-9 flex-1 relative bg-white overflow-hidden" @resize="Panel9Resize">
                 <!-- Main Image Scrollbox -->
                 <div class="isb-1 absolute top-1 left-1 w-[80px] h-[75px] border border-gray-400 z-10 hidden">ISB1</div>
                 <!-- Dynamic multi-image placeholders from dfm imgp1~imgp8 -->
                 <!-- Loading Panel -->
                 <div v-show="showLoadingPanel" class="panel-22 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white border-2 border-blue-500 w-[387px] h-[41px] flex items-center justify-center font-bold text-blue-800 z-50 shadow-lg">
                    資料載入中,請稍候
                 </div>
                 <!-- Progress Panel -->
                 <div v-show="showProgressPanel" class="panel-8 absolute bottom-10 left-10 w-[233px] bg-white border border-gray-400 p-1 z-50">
                    <div class="text-blue-600 text-sm mb-1 truncate">{{ progressLabel }}</div>
                    <div class="w-full bg-gray-200 h-4 relative">
                       <div class="bg-blue-500 h-full" :style="{ width: progressValue + '%' }"></div>
                    </div>
                 </div>
              </div>
              <!-- Bottom Scrollbar for Panel7 -->
              <input type="range" min="1" max="100" v-model="scrollValue" class="w-full h-[22px] flex-none m-0 p-0" @change="ScrollBar1Change">
           </div>
           <!-- Rightmost Page List Panel10 -->
           <div v-show="showPageList" class="panel-10 w-[69px] border-l border-gray-300 bg-white flex-none flex flex-col">
              <div class="bg-gray-200 border-b border-gray-300 px-1 py-0.5 text-xs text-center font-bold">頁數</div>
              <ul class="flex-1 overflow-auto list-none p-0 m-0 text-sm text-center">
                 <li v-for="(page, idx) in pageList" :key="idx" class="cursor-pointer hover:bg-blue-100 py-1"
                     :class="{'bg-blue-500 text-white': selectedPageIndex === idx}"
                     @click="PageLVClick(idx)">{{ page }}</li>
              </ul>
           </div>
        </div>
      </div>
    </div>
    <!-- StatusBar -->
    <div class="status-bar-1 h-[24px] border-t border-gray-400 bg-gray-200 flex text-xs flex-none" @dblclick="StatusBar1DblClick">
       <div class="border-r border-gray-400 w-[120px] px-2 flex items-center shadow-inner">{{ statusPanels[0] }}</div>
       <div class="border-r border-gray-400 w-[180px] px-2 flex items-center shadow-inner">{{ statusPanels[1] }}</div>
       <div class="border-r border-gray-400 w-[180px] px-2 flex items-center shadow-inner">{{ statusPanels[2] }}</div>
       <div class="border-r border-gray-400 w-[180px] px-2 flex items-center shadow-inner">{{ statusPanels[3] }}</div>
       <div class="w-[50px] px-2 flex items-center shadow-inner">{{ statusPanels[4] }}</div>
    </div>
  </div>
  <div class="cb-imgpsscanimp-form-layout flex flex-col bg-gray-100 font-sans w-[950px] h-[618px]">
    <img src="assets/CB_IMGPSScanImp.png"/>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useCBIMGPSScanImpLogic } from './CB_IMGPSScanImp.ts';
export default defineComponent({
  name: 'CB_IMGPSScanX',
  setup() {
    const logic = useCBIMGPSScanImpLogic();
    return { ...logic };
  }
});
</script>
<style scoped>
/* TreeView Custom Scrollbar */
.tree-view-1::-webkit-scrollbar { width: 12px; }
.tree-view-1::-webkit-scrollbar-track { background: #f1f1f1; border-left: 1px solid #ccc; }
.tree-view-1::-webkit-scrollbar-thumb { background: #c1c1c1; border: 1px solid #f1f1f1; }
.tree-view-1::-webkit-scrollbar-thumb:hover { background: #a8a8a8; }
.cb-imgpsscanimp-form-layout {
  opacity: 0.2;
  position: absolute;
  left: auto;
  right: auto;
  top: 203px;
}
</style>
uiOutput/ErrList/ErrList.ts
比對新檔案
@@ -0,0 +1,314 @@
import { ref, onMounted, onUnmounted } from 'vue';
// Interfaces mapping from Delphi structures
interface TPoint {
  X: number;
  Y: number;
}
interface TErrListItem {
  content: string;
  index: string;
}
export function useErrListLogic() {
  // State from Delphi variables
  const errListItems = ref<TErrListItem[]>([
    // Mock data for display
    { content: '測試錯誤原因1', index: 'Item_1' },
    { content: '測試錯誤原因2', index: 'Item_2' }
  ]);
  const selectedItemIndex = ref<number>(-1);
  const isDeleteEnabled = ref<boolean>(false);
  const siteIndex = ref<number>(0);
  const siteTotal = ref<number>(0);
  const isSitePreEnabled = ref<boolean>(false);
  const isSiteNextEnabled = ref<boolean>(false);
  const SiteList = ref<string[]>([]); // TStringlist
  const relaSiteIndex = ref<number>(0);
  const relaSiteTotal = ref<number>(0);
  const isRelaPreEnabled = ref<boolean>(false);
  const isRelaNextEnabled = ref<boolean>(false);
  const RelaSiteList = ref<string[]>([]); // TStringlist
  const showPanel6 = ref<boolean>(true); // Splitter visibility for related images
  const showNoteBtn = ref<boolean>(false);
  const showRejectBtn = ref<boolean>(false);
  const Ingnore = ref<boolean>(false);
  const NowIndex = ref<string>('');
  const iniPath = ref<string>(''); // Should be injected or configured
  const MyHotkeyid1 = ref<number>(0);
  // Point structures
  const UpLPoint = ref<TPoint>({ X: 0, Y: 0 });
  const UpRPoint = ref<TPoint>({ X: 0, Y: 0 });
  const DownLPoint = ref<TPoint>({ X: 0, Y: 0 });
  const DownRPoint = ref<TPoint>({ X: 0, Y: 0 });
  const UpLPoint_Rela = ref<TPoint>({ X: 0, Y: 0 });
  const UpRPoint_Rela = ref<TPoint>({ X: 0, Y: 0 });
  const DownLPoint_Rela = ref<TPoint>({ X: 0, Y: 0 });
  const DownRPoint_Rela = ref<TPoint>({ X: 0, Y: 0 });
  // Hotkey simulation mapped from WMHotKey
  const WMHotKey = (e: KeyboardEvent) => {
    if (e.ctrlKey && e.key.toLowerCase() === 'd' && isDeleteEnabled.value) {
      e.preventDefault();
      DeleteBtClick();
    }
  };
  onMounted(() => {
    window.addEventListener('keydown', WMHotKey);
    InitialData();
  });
  onUnmounted(() => {
    window.removeEventListener('keydown', WMHotKey);
  });
  const selectItem = (index: number) => {
    selectedItemIndex.value = index;
    ErrListLVClick();
  };
  // Delphi Methods
  const InitialData = () => {
    isSitePreEnabled.value = false;
    isSiteNextEnabled.value = false;
    isRelaPreEnabled.value = false;
    isRelaNextEnabled.value = false;
    SiteList.value = [];
    RelaSiteList.value = [];
    siteIndex.value = 1;
    siteTotal.value = 0;
    relaSiteIndex.value = 1;
    relaSiteTotal.value = 0;
    isDeleteEnabled.value = false;
  };
  const GetOMRErrini = (Index: string) => {
    console.log(`Getting OMR Err INI for index: ${Index}`);
    // Mock data population based on index
    SiteList.value = ['Site1', 'Site2'];
    RelaSiteList.value = ['Rela1'];
    Ingnore.value = true;
    siteTotal.value = SiteList.value.length;
    relaSiteTotal.value = RelaSiteList.value.length;
    if (RelaSiteList.value.length > 0) {
      showPanel6.value = true;
    } else {
      showPanel6.value = false;
    }
    if (SiteList.value.length > 1) isSiteNextEnabled.value = true;
    if (RelaSiteList.value.length > 1) isRelaNextEnabled.value = true;
    isDeleteEnabled.value = Ingnore.value;
    // Mock showing first errors
    if (SiteList.value.length > 0) ShowOMRErr(siteIndex.value);
    if (RelaSiteList.value.length > 0) ShowRelaOMRErr(relaSiteIndex.value);
  };
  const ErrListLVClick = () => {
    InitialData();
    if (selectedItemIndex.value === -1 || !errListItems.value[selectedItemIndex.value]) return;
    NowIndex.value = errListItems.value[selectedItemIndex.value].index;
    GetOMRErrini(NowIndex.value);
  };
  const ErrListLVKeyUp = (e: KeyboardEvent) => {
    if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
      ErrListLVClick();
    }
  };
  const ErrListLVMouseDown = (e: MouseEvent) => {
    // Right click
    if (e.button === 2) {
      ErrListLVClick();
    }
  };
  const DeleteBtClick = () => {
    InitialData();
    if (Ingnore.value) {
      console.log(`Writing Del=True to INI for ${NowIndex.value}`);
      const idx = selectedItemIndex.value;
      if (idx !== -1) {
        errListItems.value.splice(idx, 1);
        if (errListItems.value.length === 0) {
          console.log('All errors deleted, enabling Immediate button and writing OMRCheckOk.dat');
        } else {
          selectedItemIndex.value = Math.min(idx, errListItems.value.length - 1);
          ErrListLVClick();
        }
      }
    } else {
      alert('此項目不可刪除或已無可刪除項目');
    }
  };
  const EnforceBtClick = () => {
    InitialData();
    let deletedAny = false;
    for (let i = errListItems.value.length - 1; i >= 0; i--) {
      const itemIgnorable = true;
      if (itemIgnorable) {
        console.log(`Writing Del=True for ${errListItems.value[i].index}`);
        errListItems.value.splice(i, 1);
        deletedAny = true;
      }
    }
    if (errListItems.value.length === 0 && deletedAny) {
      console.log('All errors enforced, enabling Immediate button and writing OMRCheckOk.dat');
    }
  };
  const ImmediateBtClick = () => {
    console.log('ImmediateBtClick: ' + logTimeString() + ' 立即傳送');
    closeForm('ok');
  };
  const ExitBtClick = () => {
    closeForm('cancel');
  };
  const NoteBtClick = () => {
    console.log('Ch_WriteNote = True');
    closeForm('note');
  };
  const RejectBtClick = () => {
    if (confirm('是否確定退件??')) {
      console.log('RejectCase = True');
      closeForm('reject');
    }
  };
  const Button1Click = () => {
    alert(`UpLPoint=${UpLPoint.value.X},${UpLPoint.value.Y}\n` +
          `UpRPoint=${UpRPoint.value.X},${UpRPoint.value.Y}\n` +
          `DownLPoint=${DownLPoint.value.X},${DownLPoint.value.Y}\n` +
          `DownRPoint=${DownRPoint.value.X},${DownRPoint.value.Y}`);
  };
  const SiteNextBtClick = () => {
    siteIndex.value++;
    ShowOMRErr(siteIndex.value);
    isSitePreEnabled.value = false;
    isSiteNextEnabled.value = false;
    if (siteIndex.value > 1) isSitePreEnabled.value = true;
    if (siteIndex.value < siteTotal.value) isSiteNextEnabled.value = true;
  };
  const SitePreBtClick = () => {
    siteIndex.value--;
    ShowOMRErr(siteIndex.value);
    isSitePreEnabled.value = false;
    isSiteNextEnabled.value = false;
    if (siteIndex.value > 1) isSitePreEnabled.value = true;
    if (siteIndex.value < siteTotal.value) isSiteNextEnabled.value = true;
  };
  const RelaNextBtClick = () => {
    relaSiteIndex.value++;
    ShowRelaOMRErr(relaSiteIndex.value);
    isRelaPreEnabled.value = false;
    isRelaNextEnabled.value = false;
    if (relaSiteIndex.value > 1) isRelaPreEnabled.value = true;
    if (relaSiteIndex.value < relaSiteTotal.value) isRelaNextEnabled.value = true;
  };
  const RelaPreBtClick = () => {
    relaSiteIndex.value--;
    ShowRelaOMRErr(relaSiteIndex.value);
    isRelaPreEnabled.value = false;
    isRelaNextEnabled.value = false;
    if (relaSiteIndex.value > 1) isRelaPreEnabled.value = true;
    if (relaSiteIndex.value < relaSiteTotal.value) isRelaNextEnabled.value = true;
  };
  const ShowOMRErr = (Idx: number) => {
    if (Idx > SiteList.value.length) return;
    console.log(`Showing OMR Error shape for index ${Idx}`);
  };
  const ShowRelaOMRErr = (RelaIdx: number) => {
    if (RelaIdx > RelaSiteList.value.length) return;
    console.log(`Showing Related OMR Error shape for index ${RelaIdx}`);
  };
  // Missing or external methods mapped
  const logTimeString = (): string => {
    const now = new Date();
    const pad = (n: number) => (n < 10 ? '0' + n : n);
    return `${now.getFullYear()}${pad(now.getMonth()+1)}${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}  `;
  };
  const closeForm = (result: string) => {
    console.log(`Form closing with result: ${result}`);
  };
  const startResize = (e: MouseEvent) => {
    console.log('Splitter moving started');
  };
  return {
    errListItems,
    selectedItemIndex,
    isDeleteEnabled,
    siteIndex,
    siteTotal,
    isSitePreEnabled,
    isSiteNextEnabled,
    relaSiteIndex,
    relaSiteTotal,
    isRelaPreEnabled,
    isRelaNextEnabled,
    showPanel6,
    showNoteBtn,
    showRejectBtn,
    selectItem,
    ErrListLVClick,
    ErrListLVKeyUp,
    ErrListLVMouseDown,
    DeleteBtClick,
    EnforceBtClick,
    ImmediateBtClick,
    ExitBtClick,
    SitePreBtClick,
    SiteNextBtClick,
    RelaPreBtClick,
    RelaNextBtClick,
    NoteBtClick,
    RejectBtClick,
    Button1Click,
    startResize
  };
}
uiOutput/ErrList/ErrList.vue
比對新檔案
@@ -0,0 +1,200 @@
<template>
  <div class="err-list-form flex flex-col bg-gray-100 font-sans" style="width: 841px; height: 636px;">
    <!-- Top Panel: Error Reason & Details -->
    <div class="panel-3 border border-gray-300 flex-none" style="height: 212px;">
      <fieldset class="err-reason-gb m-2 border border-gray-400 p-2 h-[calc(100%-16px)]">
        <legend class="text-black text-base px-1">錯誤原因</legend>
        <div class="relative h-full">
          <!-- ListView for Error Items -->
          <div class="err-list-lv bg-white border border-gray-300 w-full h-[calc(100%-20px)] overflow-auto cursor-pointer"
               @click="errListLVClick" @keyup="errListLVKeyUp" @mousedown="errListLVMouseDown">
            <table class="w-full text-left text-base border-collapse">
              <thead>
                <tr class="bg-gray-200">
                  <th class="p-1 border border-gray-300 font-normal" style="width: 550px;">內容</th>
                  <th class="p-1 border border-gray-300 font-normal" style="width: 80px;">index</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(item, index) in errListItems" :key="index"
                    @click="selectItem(index)"
                    :class="{'bg-blue-600 text-white': selectedItemIndex === index, 'hover:bg-gray-100': selectedItemIndex !== index}">
                  <td class="p-1 border border-gray-300">{{ item.content }}</td>
                  <td class="p-1 border border-gray-300">{{ item.index }}</td>
                </tr>
              </tbody>
            </table>
          </div>
          <!-- Hidden ImageScrollBox3 -->
          <div v-show="false" class="image-scroll-box-3 absolute top-[94px] left-[720px] w-[100px] h-[100px] border"></div>
        </div>
      </fieldset>
    </div>
    <!-- Splitter 3 -->
    <div class="splitter-3 h-[5px] w-full bg-gray-300 cursor-row-resize flex-none"></div>
    <!-- Action Buttons Panel -->
    <div class="panel-1 border border-gray-300 bg-gray-100 flex items-center px-4 space-x-2 flex-none" style="height: 41px;">
      <button class="delete-bt px-4 py-1.5 border border-gray-400 bg-gray-200 hover:bg-gray-300 text-sm disabled:opacity-50"
              :disabled="!isDeleteEnabled" @click="DeleteBtClick">忽略</button>
      <button class="enforce-bt px-4 py-1.5 border border-gray-400 bg-gray-200 hover:bg-gray-300 text-sm"
              @click="EnforceBtClick">強制傳送</button>
      <button class="immediate-bt px-4 py-1.5 border border-gray-400 bg-gray-200 hover:bg-gray-300 text-sm"
              @click="ImmediateBtClick">立即傳送</button>
      <!-- Hidden buttons -->
      <button v-show="showNoteBtn" class="note-bt px-4 py-1.5 border border-gray-400 bg-gray-200" @click="NoteBtClick">備註</button>
      <button v-show="showRejectBtn" class="reject-bt px-4 py-1.5 border border-gray-400 bg-gray-200" @click="RejectBtClick">退件</button>
      <button v-show="false" class="button-1 px-4 py-1.5 border border-gray-400 bg-gray-200" @click="Button1Click">Button1</button>
      <div class="flex-grow"></div> <!-- Spacer -->
      <button class="exit-bt px-4 py-1.5 border border-gray-400 bg-gray-200 hover:bg-gray-300 text-sm"
              @click="ExitBtClick">離開</button>
    </div>
    <!-- Bottom Panel: Image Viewers -->
    <div class="panel-4 flex flex-1 overflow-hidden border border-gray-300">
      <!-- Left Image Viewer Panel -->
      <div class="panel-5 flex flex-col h-full w-[407px]">
        <div class="panel-8 flex items-center bg-gray-200 border-b border-gray-300 px-2 h-[28px] flex-none">
          <button class="site-pre-bt p-0.5 border border-gray-400 bg-gray-100 disabled:opacity-50 mr-1"
                  :disabled="!isSitePreEnabled" @click="SitePreBtClick">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
          </button>
          <span class="label-3 text-sm ml-2">{{ siteIndex }}/{{ siteTotal }}</span>
          <button class="site-next-bt p-0.5 border border-gray-400 bg-gray-100 disabled:opacity-50 ml-1"
                  :disabled="!isSiteNextEnabled" @click="SiteNextBtClick">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
          </button>
        </div>
        <div class="image-scroll-box-1 flex-1 bg-white border border-gray-300 overflow-auto relative">
           <!-- Placeholder for Main Image -->
           <div class="text-gray-400 absolute inset-0 flex items-center justify-center">Image 1</div>
        </div>
      </div>
      <!-- Splitter 1 -->
      <div class="splitter-1 w-[5px] h-full bg-gray-300 cursor-col-resize flex-none hover:bg-gray-400" @mousedown="startResize"></div>
      <!-- Right Image Viewer Panel (Conditional Visibility in original code based on RelaSite) -->
      <div class="panel-6 flex flex-col h-full flex-1" v-show="showPanel6">
        <div class="panel-9 flex items-center bg-gray-200 border-b border-gray-300 px-2 h-[28px] flex-none">
          <button class="rela-pre-bt p-0.5 border border-gray-400 bg-gray-100 disabled:opacity-50 mr-1"
                  :disabled="!isRelaPreEnabled" @click="RelaPreBtClick">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path></svg>
          </button>
          <span class="label-4 text-sm ml-2">{{ relaSiteIndex }}/{{ relaSiteTotal }}</span>
          <button class="rela-next-bt p-0.5 border border-gray-400 bg-gray-100 disabled:opacity-50 ml-1"
                  :disabled="!isRelaNextEnabled" @click="RelaNextBtClick">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path></svg>
          </button>
        </div>
        <div class="image-scroll-box-2 flex-1 bg-white border border-gray-300 overflow-auto relative">
           <!-- Placeholder for Related Image -->
           <div class="text-gray-400 absolute inset-0 flex items-center justify-center">Image 2 (Related)</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { useErrListLogic } from './ErrList.ts';
export default defineComponent({
  name: 'ErrlistForm',
  setup() {
    const {
      // State
      errListItems,
      selectedItemIndex,
      isDeleteEnabled,
      siteIndex,
      siteTotal,
      isSitePreEnabled,
      isSiteNextEnabled,
      relaSiteIndex,
      relaSiteTotal,
      isRelaPreEnabled,
      isRelaNextEnabled,
      showPanel6,
      showNoteBtn,
      showRejectBtn,
      // Actions
      selectItem,
      ErrListLVClick,
      ErrListLVKeyUp,
      ErrListLVMouseDown,
      DeleteBtClick,
      EnforceBtClick,
      ImmediateBtClick,
      ExitBtClick,
      SitePreBtClick,
      SiteNextBtClick,
      RelaPreBtClick,
      RelaNextBtClick,
      NoteBtClick,
      RejectBtClick,
      Button1Click,
      startResize
    } = useErrListLogic();
    return {
      errListItems,
      selectedItemIndex,
      isDeleteEnabled,
      siteIndex,
      siteTotal,
      isSitePreEnabled,
      isSiteNextEnabled,
      relaSiteIndex,
      relaSiteTotal,
      isRelaPreEnabled,
      isRelaNextEnabled,
      showPanel6,
      showNoteBtn,
      showRejectBtn,
      selectItem,
      ErrListLVClick,
      ErrListLVKeyUp,
      ErrListLVMouseDown,
      DeleteBtClick,
      EnforceBtClick,
      ImmediateBtClick,
      ExitBtClick,
      SitePreBtClick,
      SiteNextBtClick,
      RelaPreBtClick,
      RelaNextBtClick,
      NoteBtClick,
      RejectBtClick,
      Button1Click,
      startResize
    };
  }
});
</script>
<style scoped>
/* Optional: Add custom scrollbar styling to match Delphi look if desired */
.err-list-lv::-webkit-scrollbar {
  width: 16px;
}
.err-list-lv::-webkit-scrollbar-track {
  background: #f1f1f1;
}
.err-list-lv::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border: 1px solid #f1f1f1;
}
.err-list-lv::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}
</style>
uiOutput/PatchFom/PatchFom.ts
比對新檔案
@@ -0,0 +1,155 @@
import { ref, onMounted } from 'vue';
export function usePatchFomLogic() {
  // --- State Mapped from Delphi UI Components ---
  // ScannerGB
  const isDpiEnabled = ref<boolean>(false); // Enabled = False in DFM
  const dpi = ref<string>('240');
  const borderClear = ref<boolean>(false);
  const deskew = ref<boolean>(false);
  const reverse = ref<boolean>(false);
  const duplex = ref<boolean>(false); // Enabled = False in DFM
  // ImgSetGB
  const imgSetUse = ref<boolean>(false);
  const bright = ref<number>(0);
  const contrast = ref<number>(0);
  // ScanShowRG (0 = 清楚影像, 1 = 模糊影像, 2 = 無影像)
  const scanShowMode = ref<string>('0');
  // ScanRotateRG (0 = 無, 1 = 左轉90度, 2 = 轉180度, 3 = 右轉90度)
  const scanRotate = ref<string>('0');
  // BlankGB
  const blankUse = ref<boolean>(false);
  const blankSize = ref<number>(0);
  // Public property equivalent
  const SelectOk = ref<boolean>(false);
  // --- Mock external Global Variables from CB_IMGPSScanImp ---
  // In a real application, these would be imported from a store or context
  const mockGlobalState = {
    Def_DeviceDelete: false,
    Def_DeviceDeleteSize: 1024,
    Def_ScanDpi: 240,
    Def_ScanDuplex: true,
    Def_ScannerReverse: false,
    Def_BoardClear: true,
    Def_ScanDeskew: true,
    Def_ScanImgSetUse: false,
    Def_ScanBright: 10,
    Def_ScanContrast: 20,
    Def_ScanRotate: 90, // Mapped to 3 (右轉90度) in switch statement
    Def_ScanImgShowMode: 1 // Mapped to 1 (模糊影像)
  };
  // --- Methods ---
  const FormCreate = () => {
    // Equivalent to PostMessage(Handle,WM_ACTIVATE,WA_CLICKACTIVE,0);
    console.log('FormCreate: PatchDlg activated');
  };
  const BlankuseCBClick = () => {
    // If BlankuseCB.Checked Then SpinEdit5.Enabled := True Else SpinEdit5.Enabled := False;
    // handled via Vue binding `:disabled="!blankUse"` in template,
    // but kept here for logical representation
    console.log('BlankuseCBClick triggered, blankUse:', blankUse.value);
  };
  const DefaultBtClick = () => {
    // Reset to defaults
    blankUse.value = mockGlobalState.Def_DeviceDelete;
    blankSize.value = mockGlobalState.Def_DeviceDeleteSize;
    dpi.value = mockGlobalState.Def_ScanDpi.toString();
    duplex.value = mockGlobalState.Def_ScanDuplex;
    reverse.value = mockGlobalState.Def_ScannerReverse;
    borderClear.value = mockGlobalState.Def_BoardClear;
    deskew.value = mockGlobalState.Def_ScanDeskew;
    imgSetUse.value = mockGlobalState.Def_ScanImgSetUse;
    bright.value = mockGlobalState.Def_ScanBright;
    contrast.value = mockGlobalState.Def_ScanContrast;
    switch (mockGlobalState.Def_ScanRotate) {
      case 0: scanRotate.value = '0'; break;
      case 270: scanRotate.value = '1'; break;
      case 180: scanRotate.value = '2'; break;
      case 90: scanRotate.value = '3'; break;
      default: scanRotate.value = '0'; break;
    }
    switch (mockGlobalState.Def_ScanImgShowMode) {
      case 0: scanShowMode.value = '0'; break;
      case 1: scanShowMode.value = '1'; break;
      case 2: scanShowMode.value = '2'; break;
      default: scanShowMode.value = '0'; break;
    }
    console.log('Default values loaded');
  };
  const OkBtClick = () => {
    SelectOk.value = true;
    closeForm('ok');
  };
  const CancelBtClick = () => {
    SelectOk.value = false;
    closeForm('cancel');
  };
  const ComboBox1KeyPress = (e: KeyboardEvent) => {
    // IF ((Ord(Key) < 48) or (ord(Key) > 57)) and (ord(key) <> 8) Then key := Chr(0);
    const charCode = e.charCode;
    if ((charCode < 48 || charCode > 57) && e.key !== 'Backspace') {
      e.preventDefault();
    }
  };
  const ComboBox1Exit = () => {
    // IF ComboBox1.Text = '' Then ComBoBox1.Text := '240';
    if (!dpi.value) {
      dpi.value = '240';
    }
  };
  // Helper function to simulate modal close
  const closeForm = (result: string) => {
    console.log(`PatchDlg closing with result: ${result}`);
  };
  onMounted(() => {
    FormCreate();
    // Usually you'd call DefaultBtClick() here or in the parent before opening
  });
  return {
    // State
    isDpiEnabled,
    dpi,
    borderClear,
    deskew,
    reverse,
    duplex,
    imgSetUse,
    bright,
    contrast,
    scanShowMode,
    scanRotate,
    blankUse,
    blankSize,
    // Actions
    BlankuseCBClick,
    DefaultBtClick,
    OkBtClick,
    CancelBtClick,
    ComboBox1KeyPress,
    ComboBox1Exit
  };
}
uiOutput/PatchFom/PatchFom.vue
比對新檔案
@@ -0,0 +1,144 @@
<template>
  <div class="patch-dlg flex flex-col bg-gray-100 font-sans w-[434px] h-[389px] border border-gray-400">
    <!-- Scanner Settings GroupBox -->
    <fieldset class="scanner-gb border border-gray-400 m-2 p-2 relative h-[216px]">
      <legend class="text-black text-base px-1">掃描器設定</legend>
      <div class="relative h-full">
        <!-- DPI Setting -->
        <label class="absolute left-[19px] top-[7px] text-base">DPI</label>
        <select class="absolute left-[57px] top-[4px] w-[120px] h-[24px] border border-gray-400 bg-white"
                v-model="dpi" :disabled="!isDpiEnabled" @keypress="ComboBox1KeyPress" @blur="ComboBox1Exit">
          <option value="75">75</option>
          <option value="100">100</option>
          <option value="150">150</option>
          <option value="180">180</option>
          <option value="200">200</option>
          <option value="240">240</option>
          <option value="300">300</option>
          <option value="360">360</option>
          <option value="400">400</option>
          <option value="600">600</option>
          <option value="720">720</option>
        </select>
        <!-- Checkboxes -->
        <label class="absolute left-[16px] top-[60px] flex items-center space-x-1">
          <input type="checkbox" v-model="borderClear" />
          <span>清黑邊</span>
        </label>
        <label class="absolute left-[161px] top-[37px] flex items-center space-x-1">
          <input type="checkbox" v-model="deskew" />
          <span>傾斜校正</span>
        </label>
        <label class="absolute left-[161px] top-[60px] flex items-center space-x-1">
          <input type="checkbox" v-model="reverse" />
          <span>影像是否需反相</span>
        </label>
        <label class="absolute left-[16px] top-[37px] flex items-center space-x-1">
          <input type="checkbox" v-model="duplex" disabled />
          <span class="text-gray-500">雙面掃描</span>
        </label>
        <!-- Image Adjustment GroupBox -->
        <fieldset class="absolute bottom-[47px] left-0 w-full h-[64px] border border-gray-400 p-1">
          <legend class="text-black text-sm px-1">掃描器亮度對比調整</legend>
          <div class="flex items-center space-x-4 h-full px-2">
            <label class="flex items-center space-x-1">
              <input type="checkbox" v-model="imgSetUse" />
              <span>啟用</span>
            </label>
            <div class="flex items-center space-x-1">
              <label>亮度</label>
              <input type="number" v-model.number="bright" min="-127" max="127" class="w-[60px] border border-gray-400 p-1" />
            </div>
            <div class="flex items-center space-x-1">
              <label>對比</label>
              <input type="number" v-model.number="contrast" min="-127" max="127" class="w-[65px] border border-gray-400 p-1" />
            </div>
          </div>
        </fieldset>
        <!-- Scan Show Mode RadioGroup -->
        <fieldset class="absolute bottom-0 left-0 w-full h-[47px] border border-gray-400 p-1">
          <legend class="text-black text-sm px-1">掃描時影像顯示</legend>
          <div class="flex items-center justify-around h-full">
            <label><input type="radio" v-model="scanShowMode" value="0" /> 清楚影像(慢)</label>
            <label><input type="radio" v-model="scanShowMode" value="1" /> 模糊影像(普通)</label>
            <label><input type="radio" v-model="scanShowMode" value="2" /> 無影像(超快)</label>
          </div>
        </fieldset>
      </div>
    </fieldset>
    <!-- Scan Rotate RadioGroup -->
    <fieldset class="border border-gray-400 mx-2 mb-2 p-1 h-[56px] flex-none">
      <legend class="text-black text-base px-1">掃描時旋轉</legend>
      <div class="flex items-center justify-around h-full pt-1">
        <label><input type="radio" v-model="scanRotate" value="0" /> 無</label>
        <label><input type="radio" v-model="scanRotate" value="1" /> 左轉90度</label>
        <label><input type="radio" v-model="scanRotate" value="2" /> 轉180度</label>
        <label><input type="radio" v-model="scanRotate" value="3" /> 右轉90度</label>
      </div>
    </fieldset>
    <!-- Blank Page Deletion GroupBox -->
    <fieldset class="border border-gray-400 mx-2 mb-2 p-2 flex-1 relative">
      <legend class="text-black text-base px-1">空白頁刪除</legend>
      <div class="relative w-full h-full">
        <label class="absolute left-[16px] top-[12px] flex items-center space-x-1">
          <input type="checkbox" v-model="blankUse" @change="BlankuseCBClick" />
          <span>啟用</span>
        </label>
        <input type="number" v-model.number="blankSize" :disabled="!blankUse" min="0"
               class="absolute left-[95px] top-[11px] w-[78px] h-[26px] border border-gray-400 p-1 disabled:bg-gray-200" />
        <label class="absolute left-[177px] top-[16px] text-base">Bytes</label>
        <!-- Buttons -->
        <div class="absolute bottom-2 left-0 w-full flex justify-between px-2">
          <button class="w-[75px] h-[25px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="DefaultBtClick">預設值</button>
          <div class="space-x-2">
            <button class="w-[61px] h-[25px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="OkBtClick">確定</button>
            <button class="w-[64px] h-[25px] border border-gray-400 bg-gray-200 hover:bg-gray-300" @click="CancelBtClick">取消</button>
          </div>
        </div>
      </div>
    </fieldset>
  </div>
  <div class="patch-dlg-layout flex flex-col bg-gray-100 font-sans w-[434px] h-[389px] border border-gray-400">
    <img src="assets/CB_PatchFom.png"/>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { usePatchFomLogic } from './PatchFom.ts';
export default defineComponent({
  name: 'PatchDlg',
  setup() {
    const logic = usePatchFomLogic();
    return { ...logic };
  }
});
</script>
<style scoped>
/* Scoped styles if needed */
.patch-dlg-layout {
  opacity: 0.2;
  position: absolute;
  left: auto;
  right: auto;
  top: 314px;
}
</style>
uiOutput/assets/CB_ErrList.png
uiOutput/assets/CB_IMGPSScanImp.png
uiOutput/assets/CB_PatchFom.png
uiOutput/index.html
比對新檔案
@@ -0,0 +1,387 @@
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DFM to Vue Preview</title>
    <!-- 引入 Vue 3 -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <!-- 引入 Tailwind CSS 用於即時預覽 -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 使用 vue3-sfc-loader 來動態編譯 .vue 檔案 -->
    <script src="https://cdn.jsdelivr.net/npm/vue3-sfc-loader@0.8.4/dist/vue3-sfc-loader.js"></script>
    <!-- 加入 TypeScript 的 Babel transpiler 用於即時編譯 .ts -->
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            height: 100%;
            background-color: #f3f4f6; /* Tailwind gray-100 */
            font-family: sans-serif;
        }
        #app {
            display: flex;
            flex-direction: column;
            height: 100vh;
        }
        /* 上方清單區塊 (1.4.1.1) */
        .list-section {
            background-color: #ffffff;
            border-bottom: 1px solid #d1d5db; /* gray-300 */
            padding: 16px;
            box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
            z-index: 10;
        }
        .component-btn {
            background-color: #3b82f6; /* blue-500 */
            color: white;
            padding: 8px 16px;
            border-radius: 4px;
            border: none;
            cursor: pointer;
            font-size: 14px;
            margin-right: 8px;
            transition: background-color 0.2s;
        }
        .component-btn:hover {
            background-color: #2563eb; /* blue-600 */
        }
        .component-btn.active {
            background-color: #1e40af; /* blue-800 */
            box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2);
        }
        /* 下方預覽區塊 (1.4.1.2) */
        .preview-section {
            flex: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 24px;
            overflow: auto;
            background-color: #e5e7eb; /* Tailwind gray-200 */
        }
        /* 模擬 Windows 視窗外框 */
        .preview-container {
            background-color: white;
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
            border: 1px solid #9ca3af;
            border-radius: 4px;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            /* 讓內部的子元件決定自己的寬高,但不能超過螢幕 */
            max-width: 100%;
            max-height: 100%;
        }
        .window-title {
            background-color: #0058b0;
            color: white;
            padding: 6px 10px;
            font-size: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            user-select: none;
        }
        .window-controls span {
            display: inline-block;
            width: 16px;
            height: 16px;
            background-color: #ccc;
            margin-left: 4px;
            border-radius: 2px;
            text-align: center;
            line-height: 14px;
            color: black;
            cursor: pointer;
            font-size: 10px;
            font-weight: bold;
        }
        .window-controls span:hover {
            background-color: #e81123;
            color: white;
        }
        /* 載入中動畫 */
        .loader {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #3b82f6;
            border-radius: 50%;
            width: 30px;
            height: 30px;
            animation: spin 1s linear infinite;
        }
        @keyframes spin {
            0% {
                transform: rotate(0deg);
            }
            100% {
                transform: rotate(360deg);
            }
        }
    </style>
</head>
<body>
<div id="app">
    <!-- 1.4.1.1: List button 區塊 -->
    <div class="list-section">
        <h2 class="text-lg font-bold text-gray-700 mb-3">Converted Vue Components</h2>
        <div class="flex flex-wrap gap-2">
            <button
                    v-for="comp in availableComponents"
                    :key="comp.id"
                    @click="loadComponent(comp)"
                    :class="['component-btn', { active: currentComponent && currentComponent.id === comp.id }]"
            >
                {{ comp.name }}
            </button>
        </div>
    </div>
    <!-- 1.4.1.2: Preview viewer 區塊 -->
    <div class="preview-section relative">
        <div v-if="isLoading"
             class="absolute inset-0 flex flex-col items-center justify-center bg-gray-200 bg-opacity-75 z-20">
            <div class="loader mb-4"></div>
            <div class="text-gray-600 font-medium">Loading component...</div>
        </div>
        <div v-else-if="!currentComponent" class="text-gray-500 text-lg">
            Please select a component from the top menu to preview.
        </div>
        <div v-else class="preview-container">
            <!-- 模擬 Windows 視窗標題列 -->
            <div class="window-title">
                <span>{{ currentComponent.windowTitle }}</span>
                <div class="window-controls">
                    <span>_</span>
                    <span>□</span>
                    <span @click="closePreview">x</span>
                </div>
            </div>
            <!-- 動態載入的 Vue 元件將會渲染在這裡 -->
            <component :is="dynamicComponent"></component>
        </div>
    </div>
</div>
<script type="module">
  const {loadModule} = window['vue3-sfc-loader'];
  // 用來暫存修改過的檔案內容
  const virtualFileSystem = {};
  // 為了避免重複宣告 `ref`, `onMounted` 導致 SyntaxError
  // 我們在全域環境中先宣告好 Vue 的依賴,只宣告一次
  if (!window.__VUE_SETUP__) {
    window.__VUE_SETUP__ = true;
    const script = document.createElement('script');
    script.textContent = `
                // 全域提供 Vue API,避免在每個動態腳本中重複 let/const
                window.ref = Vue.ref;
                window.reactive = Vue.reactive;
                window.computed = Vue.computed;
                window.onMounted = Vue.onMounted;
                window.onUnmounted = Vue.onUnmounted;
                window.watch = Vue.watch;
                window.defineComponent = Vue.defineComponent;
            `;
    document.head.appendChild(script);
  }
  // SFC Loader 設定,加入對 TS 的編譯支援
  const options = {
    moduleCache: {
      vue: Vue
    },
    async getFile(url) {
      // 處理虛擬 URL
      if (url.startsWith('virtual-url-')) {
        const content = virtualFileSystem[url];
        if (content) {
          return {
            getContentData: asBinary => asBinary ? new TextEncoder().encode(content) : content,
            type: '.vue'
          };
        }
      }
      // 處理相依的 .ts / .js 邏輯檔案
      if (url.endsWith('.ts') || url.endsWith('.js')) {
        const res = await fetch(url);
        if (!res.ok) throw Object.assign(new Error(res.statusText + ' ' + url), {res});
        const code = await res.text();
        // 用 Babel 拔除 TypeScript 型別,並轉成 ES5
        const transpiled = Babel.transform(code, {
          presets: ['typescript'],
          filename: url // 加入 filename 參數解決 Babel 錯誤
        }).code;
        // 將 export 轉化為掛載到 window
        let modifiedCode = transpiled.replace(/export\s+(?:function|const)\s+(use\w+Logic)/g, 'window.$1 = function');
        return {
          getContentData: asBinary => asBinary ? new TextEncoder().encode(modifiedCode) : modifiedCode,
          type: '.js'
        };
      }
      const res = await fetch(url);
      if (!res.ok) throw Object.assign(new Error(res.statusText + ' ' + url), {res});
      return {
        getContentData: asBinary => asBinary ? res.arrayBuffer() : res.text(),
      }
    },
    addStyle(textContent) {
      const style = Object.assign(document.createElement('style'), {textContent});
      const ref = document.head.getElementsByTagName('style')[0] || null;
      document.head.insertBefore(style, ref);
    },
    // 設定處理 `<script lang="ts">` 的勾子
    handleModule(type, getContentData, path, options) {
      switch (type) {
        case '.ts':
          const code = getContentData(false);
          const jsCode = Babel.transform(code, {
            presets: ['typescript'],
            filename: path || 'file.ts' // 加入 filename 參數解決 Babel 錯誤
          }).code;
          return {getContentData: _ => jsCode, type: '.js'};
      }
    }
  };
  const app = Vue.createApp({
    data() {
      return {
        availableComponents: [
          {
            id: 'ErrList',
            name: 'ErrList.vue',
            vuePath: './ErrList/ErrList.vue',
            jsPath: './ErrList/ErrList.ts',
            windowTitle: '檢核失敗原因畫面'
          },
          {
            id: 'PatchFom',
            name: 'PatchFom.vue',
            vuePath: './PatchFom/PatchFom.vue',
            jsPath: './PatchFom/PatchFom.ts',
            windowTitle: '空白頁設定'
          },
          {
            id: 'CB_IMGPSScanImp',
            name: 'CB_IMGPSScanImp.vue',
            vuePath: './CB_IMGPSScanImp/CB_IMGPSScanImp.vue',
            jsPath: './CB_IMGPSScanImp/CB_IMGPSScanImp.ts',
            windowTitle: 'CB_IMGPSScanX'
          }
        ],
        currentComponent: null,
        dynamicComponent: null,
        isLoading: false
      }
    },
    methods: {
      async loadComponent(comp) {
        if (this.currentComponent && this.currentComponent.id === comp.id) return;
        this.isLoading = true;
        this.currentComponent = comp;
        this.dynamicComponent = null;
        try {
          // 1. 載入並執行 TypeScript 邏輯檔案
          const res = await fetch(comp.jsPath);
          if (!res.ok) throw new Error(`Failed to load ${comp.jsPath}`);
          const tsCode = await res.text();
          // 透過 Babel 將 TypeScript 轉譯為 JavaScript
          const jsCode = Babel.transform(tsCode, {
            presets: ['typescript'],
            filename: comp.jsPath
          }).code;
          // 移除 import vue,將 export 改為 window 掛載
          // 注意:這裡不宣告 const { ref, ... } = Vue,因為我們在全域已經掛載了 window.ref
          // 只需要把 ts 轉譯後的 var _vue = require("vue"); 之類的給清除
          let modifiedCode = jsCode
            .replace(/import\s+\{.*?\}\s+from\s+['"]vue['"];/g, '')
            .replace(/(var|let|const)\s+\w+\s*=\s*require\(['"]vue['"]\);/g, '')
            // 將 babel 轉譯後可能產生的 _vue.ref 換回全域的 ref
            .replace(/_vue\./g, '')
            .replace(/export\s+(?:function|const)\s+(use\w+Logic)/g, 'window.$1 = function');
          const scriptId = `script-${comp.id}`;
          let oldScript = document.getElementById(scriptId);
          if (oldScript) oldScript.remove();
          const script = document.createElement('script');
          script.id = scriptId;
          // 使用 IIFE (立即執行函式) 包裝,避免區域變數互相污染
          script.textContent = `
                            (function() {
                                ${modifiedCode}
                            })();
                        `;
          document.head.appendChild(script);
          // 2. 載入 Vue SFC
          this.dynamicComponent = Vue.markRaw(Vue.defineAsyncComponent(() => {
            return fetch(comp.vuePath)
              .then(res => res.text())
              .then(content => {
                // 替換 .vue 裡面的 import
                const modifiedContent = content.replace(
                  /import\s+\{\s*(use\w+Logic)\s*\}\s+from\s+['"].*?\.ts['"];/g,
                  'const { $1 } = window;'
                );
                const virtualUrl = `virtual-url-${comp.id}-${Date.now()}.vue`;
                virtualFileSystem[virtualUrl] = modifiedContent;
                return loadModule(virtualUrl, options);
              });
          }));
        } catch (err) {
          console.error(`Error loading component ${comp.name}:`, err);
          alert(`載入元件失敗: ${err.message}`);
          this.currentComponent = null;
        } finally {
          this.isLoading = false;
        }
      },
      closePreview() {
        this.currentComponent = null;
        this.dynamicComponent = null;
      }
    }
  });
  app.mount('#app');
</script>
</body>
</html>