unit U_QrCodeFun; interface uses Windows, SysUtils, DB, Controls, Forms, DBClient, ADODB, ExtCtrls, RM_GridReport, RM_Dataset, RM_E_llPDF, RM_BarCode, RM_e_Graphic, RM_e_Jpeg, RM_e_Xls, RM_System; type TMakebar = procedure(ucData: pchar; nDataLen: integer; nErrLevel: integer; nMask: integer; nBarEdition: integer; szBmpFileName: pchar; nScale: integer); stdcall; TMixtext = procedure(szSrcBmpFileName: PChar; szDstBmpFileName: PChar; sztext: PChar; fontsize, txtheight, hmargin, vmargin, txtcntoneline: integer); stdcall; function EnsureQrCodeDirectory: Boolean; function ClearQrCodeDirectory: Boolean; procedure IintCDS(SADOQry: TADOQuery; mClientDataset: TclientDataSet); function GetQrCode(Txt: string): string; procedure SetQrCodePath(Cds: TclientDataSet; FQrCodeField: string); implementation procedure SetQrCodePath(Cds: TClientDataSet; FQrCodeField: string); var QrCodeIdField: TField; CurrentQrCodeId, LastQrCodeId, LastQrCodePath: string; begin // 检查二维码ID字段是否存在 QrCodeIdField := Cds.FindField(FQrCodeField); if QrCodeIdField = nil then Exit; // 初始化变量 LastQrCodeId := ''; LastQrCodePath := ''; with Cds do begin DisableControls; try First; while not Eof do begin CurrentQrCodeId := QrCodeIdField.AsString; // 如果当前内容与上一条相同,则复用二维码路径 if (CurrentQrCodeId = LastQrCodeId) and (LastQrCodePath <> '') then begin Edit; FieldByName('QRBARCODE').AsString := LastQrCodePath; Post; end else begin // 生成新的二维码并记录路径 Edit; LastQrCodePath := GetQrCode(CurrentQrCodeId); FieldByName('QRBARCODE').AsString := LastQrCodePath; Post; LastQrCodeId := CurrentQrCodeId; end; Next; end; finally First; EnableControls; end; end; end; function EnsureQrCodeDirectory: Boolean; var QrCodeDir: string; begin Result := False; QrCodeDir := ExtractFilePath(Application.ExeName) + 'QrCode\'; try if not DirectoryExists(QrCodeDir) then begin if not ForceDirectories(QrCodeDir) then raise Exception.Create('无法创建二维码目录: ' + QrCodeDir); end; Result := True; except on E: Exception do begin Application.MessageBox(PChar('创建二维码目录失败: ' + E.Message), '错误', MB_ICONERROR); end; end; end; // 清空二维码目录中的所有文件 function ClearQrCodeDirectory: Boolean; var QrCodeDir: string; SearchRec: TSearchRec; begin Result := False; QrCodeDir := ExtractFilePath(Application.ExeName) + 'QrCode\'; try if not DirectoryExists(QrCodeDir) then Exit; // 目录不存在视为成功 // 删除目录下所有.bmp文件 if FindFirst(QrCodeDir + '*.bmp', faAnyFile, SearchRec) = 0 then begin repeat DeleteFile(QrCodeDir + SearchRec.Name); until FindNext(SearchRec) <> 0; FindClose(SearchRec); end; Result := True; except on E: Exception do begin Application.MessageBox(PChar('清空二维码目录失败: ' + E.Message), '错误', MB_ICONERROR); end; end; end; procedure IintCDS(SADOQry: TADOQuery; mClientDataset: TclientDataSet); var i, k: integer; mfieldName: string; mSize: integer; begin mfieldName := ''; mClientDataset.FieldDefs.Clear; with SADOQry do begin for i := 0 to fieldCount - 1 do begin if (Fields[i].DataType = ftString) and (Fields[i].Size = 0) then begin mSize := 1; end else mSize := Fields[i].Size; mfieldName := trim(fields[i].FieldName); mClientDataset.FieldDefs.Add(mfieldName, Fields[i].DataType, mSize); end; end; mClientDataset.FieldDefs.Add('QRBARCODE', ftString, 200); mClientDataset.Close; mClientDataset.CreateDataSet; if SADOQry.IsEmpty then exit; SADOQry.first; k := 1; try mClientDataset.DisableControls; mClientDataset.Filtered := false; while not SADOQry.Eof do begin with mClientDataset do begin Append; for i := 0 to SADOQry.FieldCount - 1 do begin fields[i].value := SADOQry.Fields[i].Value; end; fieldByName('QRBARCODE').value := ''; inc(k); Post; end; SADOQry.Next; end; if not mClientDataset.IsEmpty then begin mClientDataset.First; end; finally mClientDataset.EnableControls; end; end; function GetQrCode(Txt: string): string; var fPrintFile: string; fImagePath: string; Moudle: THandle; Makebar: TMakebar; Mixtext: TMixtext; CurRow: Integer; TimeStamp: string; begin Result := ''; // 初始化返回路径 try Moudle := LoadLibrary('MakeQRBarcode.dll'); if Moudle = 0 then RaiseLastOSError; @Makebar := GetProcAddress(Moudle, 'Make'); if not Assigned(Makebar) then raise Exception.Create('找不到 Make 函数'); @Mixtext := GetProcAddress(Moudle, 'MixText'); if not Assigned(Mixtext) then raise Exception.Create('找不到 MixText 函数'); // 生成时间戳文件名 (格式: YYYYMMDD_HHMMSSZZZ) Sleep(10); TimeStamp := FormatDateTime('yyyymmdd_hhnnsszzz', Now) + '_' + IntToStr(Random(1000)); fImagePath := ExtractFilePath(Application.ExeName) + 'QrCode\' + TimeStamp + '.bmp'; // 确保目录存在 if not DirectoryExists(ExtractFilePath(fImagePath)) then ForceDirectories(ExtractFilePath(fImagePath)); Makebar(pchar(Txt), Length(Txt), 3, 3, 0, PChar(fImagePath), 3); Result := fImagePath; // 返回生成的文件路径 except on E: Exception do begin application.MessageBox(PChar('条形码生成失败:' + E.Message), '错误', MB_ICONERROR); end; end; end; end.