{ ==============================================================================
|
方法名稱: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;
|