From 868daf94f29ce1ffdd799a68c07bb668cd373bcd Mon Sep 17 00:00:00 2001 From: HP\李良庭 <liliangting@lanpucloud.cn:1111> Date: 星期二, 08 七月 2025 11:49:03 +0800 Subject: [PATCH] 提交分辨率自适应版本V3.1.0.1500 --- src/init/uInit.pas | 616 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 616 insertions(+), 0 deletions(-) diff --git a/src/init/uInit.pas b/src/init/uInit.pas new file mode 100644 index 0000000..843c36a --- /dev/null +++ b/src/init/uInit.pas @@ -0,0 +1,616 @@ +{------------------------------------------------------------------------------} +{单元名称:uInit.pas } +{模块名称:初始化函数库 } +{模块说明:包括主进程启动时,全局变量初始化、系统目录初始化、配置加载 } +{建立日期:2009-12-20 } +{修改修改:2023-02-21 } +{版权所有:李良庭 liangtingli@outlook.com } +{------------------------------------------------------------------------------} + +unit uInit; + +interface + +uses + Windows, Classes, Messages, Forms, Dialogs, SysUtils, StrUtils, DateUtils, + StdCtrls, Variants, ComCtrls, Buttons, Math, IniFiles, Graphics, ShellAPI, + SQLite3, SQLiteTable3; + + {申明全局公共调用函数} + procedure OpenOnScreenKeyboard(); + procedure InitGlobal(); + procedure InitSystemDir(); + procedure InitDatas(); + procedure LoadSystemInfo(); + procedure LoadOptions(); + procedure SaveOptions(); + function GetCurrMsgPos(index:Integer):TPoint; + + //授权文件检查模块 + function GetMachineCode():String; + function CheckLicense(sFilename, sCode:String):Boolean; + procedure RegCheckMode(); + procedure RegCheck1Mode(); + //保存csv数据 + procedure WriteCsvFile(name: string; mois,temp,water: Double); + //刷新故障码 + function RefashFaultCode(cod:Integer):String; + //自动模式下刷新故障码 + function AutoFaultCode(cod:Integer):string; +implementation + +uses + uMain, log4me, uDM, PubUtils, MsgVar, Global, uSaveData, CpuidInfo, UntDes; + + {函数方法} + +//------- 调用三方键盘 ------------------------------------ +//调用osk键盘 +procedure OpenOnScreenKeyboard(); +type TWow64DisableWow64FsRedirection = function(var Wow64FsEnableRedirection: LongBool): LongBool; StdCall; +type TWow64RevertWow64FsRedirection = function(var Wow64RevertWow64FsRedirection: LongBool): LongBool; StdCall; +var + hHandle: THandle; + Wow64DisableWow64FsRedirection: TWow64DisableWow64FsRedirection; + Wow64RevertWow64FsRedirection: TWow64RevertWow64FsRedirection; + OldValue: LongBool; + rs: Integer; +begin + //切换32位文件系统 + try + hHandle := GetModuleHandle('kernel32.dll'); + @Wow64DisableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64DisableWow64FsRedirection'); + if ((hHandle <> 0) and (@Wow64DisableWow64FsRedirection <> nil)) then + Wow64DisableWow64FsRedirection(OldValue); + except + end; + //调用osk屏幕键盘 + rs := ShellExecute(Application.Handle, 'open', 'osk.exe', nil, nil, SW_SHOWNORMAL); + if rs <= 32 then begin + ShowMessage(Format('错误:无法打开屏幕键盘,错误代码-[%d].',[rs])); + log4Info(Format('错误:无法打开屏幕键盘,错误代码-[%d].',[rs])); + end + else + log4Info('系统:上位机软件打开 osk 系统屏幕键盘.'); + //用回64位文件系统 + try + hHandle := GetModuleHandle('kernel32.dll'); + @Wow64RevertWow64FsRedirection := GetProcAddress(hHandle, 'Wow64RevertWow64FsRedirection'); + if ((hHandle <> 0) and (@Wow64RevertWow64FsRedirection <> nil)) then + Wow64RevertWow64FsRedirection(OldValue); + except + end; +end; + +//--------------------------------------------------------------------------- +//初始化全局变量 +procedure InitGlobal(); +begin + //程序路径 + glAppPath := ExtractFilePath(Application.ExeName); + + //configDB file + glConfig_db := glAppPath + CONFIG_DIR + t_Config + '.db'; + glConn_db := glAppPath + CONFIG_DIR + t_Conn + '.db'; + glGrain_db := glAppPath + CONFIG_DIR + t_Grain + '.db'; + glWeight_db := glAppPath + CONFIG_DIR + t_Weight + '.db'; + glManager_db := glAppPath + CONFIG_DIR + t_Manager + '.db'; + glData_db := glAppPath + CONFIG_DIR + t_Data + '.db'; + //初始化Calc全局变量 + glCalcOutput := ''; + glCurrFocus := 0; + //初始化手动模式返回口令值 + frmMain.sLoginPwd := ''; + //初始化样本存储变量 + smp.flag := false; + smp.info := ''; + smp.prefix := ''; + smp.dir := ''; +end; + +//初始化系统目录 +procedure InitSystemDir(); +var + path : String; +begin + //创建配置文件夹 + path := glAppPath + CONFIG_DIR; + if not DirectoryExists(path) then ForceDirectories(path); + + //创建数据文件夹 + path := glAppPath + DATA_DIR; + if not DirectoryExists(path) then ForceDirectories(path); + + //创建日志文件夹 + path := glAppPath + LOG_DIR; + if not DirectoryExists(path) then ForceDirectories(path); +end; + +//初始化数据采集结构 +procedure InitDatas(); +begin + //初始化Datas测量数据 + Datas.Voltage := 0; //原始电平 + Datas.Weight := 0; //重量 + Datas.Temp := 0; //温度 + Datas.Humid:= 0; //湿度 + //初始化自动检测标签 + frmMain.lblAutoRet.Caption := ''; + frmMain.lblAutoRet_error.Caption := ''; +end; + +//加载系统信息界面 +procedure LoadSystemInfo(); +begin + with frmMain do begin + //初始化水分仪串口下拉菜单 + cbSerialPort.Items.Clear; + EnumComPorts(cbSerialPort.Items); + //加载水分仪参数 + cbSerialPort.Text := WrConn.SerialPort; + edtBaud.Text := IntToStr(WrConn.baud); + edtParity.Text := WrConn.parity; + edtData_bit.Text := IntToStr(WrConn.data_bit); + edtStop_bit.Text := IntToStr(WrConn.stop_bit); + cbAutoRun.Checked := glAutoRun; + //增加两个时间设置值 + edtTime1.Text := IntToStr(glTime1); + edtTime2.Text := IntToStr(glTime2); + + //加载扦捡系统参数 + edtIP.Text := PlcConn.ip; + edtPort.Text := IntToStr(PlcConn.port); + edtHeartIP.Text := PlcConn.heart_ip; + edtHeartPort.Text := IntToStr(PlcConn.heart_port); + + //加载手动检测和参数配置界面的数据存储参数 + cbTestAutoSave.Checked := smp.flag; + edtSampleName.Text := smp.info; + cbAutoSave.Checked := smp.flag; + edtPrefix.Text := smp.prefix; + edtDir.Text := smp.dir; + + //加载登录口令 + edtPassword.Text := SysConfig.password; + edtDelay.Text := IntToStr(SysConfig.delay); + end; +end; + +//加载参数到界面 +procedure LoadOptions(); +begin + with frmMain do begin + //手动检测界面 + mtManClock.Value := 0; + edtMoisture.Text := ''; + edtWeightRatio.Text := ''; + edtWeight.Text := ''; + edtTemp.Text := ''; + edtWater.Text := ''; + lbType.ItemIndex := Grain.Code-1; //粮种代码与界面ItemIndex的对应关系 + sLabel15.Caption := Format('粮食种类 - [%s]',[Grain.Name]); + sLabel3.Caption := Format('选择 - [%s]',[Grain.Name]); + //仪器校准界面 + lbType1.ItemIndex := Grain.Code-1; + edtAutoCoef1.Text := Grain.coef[0]; + edtAutoCoef2.Text := Grain.coef[1]; + edtAutoCoef3.Text := Grain.coef[2]; + edtAutoCoef4.Text := Grain.coef[3]; + edtAutoCoef5.Text := Grain.coef[4]; + //参数设置界面 + edtVolume.Text := FloatToStr(SysConfig.Volume); + edtTare.Text := FloatToStr(SysConfig.Tare); + edtFreq.Text := FloatToStr(SysConfig.Freq); + edtDecay.Text:= FloatToStr(SysConfig.Decay); + edtStartFreq.Text := FloatToStr(SysConfig.StartFreq); + edtStopFreq.Text := FloatToStr(SysConfig.StopFreq); + edtStep.Text := IntToStr(SysConfig.Step); + lbASK.ItemIndex := SysConfig.Ask; //ASK代码与界面ItemIndex的对应关系 + //系统信息界面 + lblVersion.Caption := Format('版本 %s ', [glFileVersion]); + end; +end; + +//保存界面参数 +procedure SaveOptions(); +begin + // +end; + +//------ 功能函数 ------------------------------------------------------------- +//获取当前焦点输入框的绝对坐标 +function GetCurrMsgPos(index:Integer):TPoint; +var + x1,y1 : Integer; //修正值 + x3,x45,y2 : Integer; +begin + with frmMain do begin + x1 := edtMois1.Width + 5; + y1 := -100; + x3 := edtMois1.Width - 8; + x45 := -473; + y2 := -250; + case index of + 1:begin + Result.X := Left+edtMois1.Left+x1; + Result.Y := Top+edtMois1.Top+y1; + end; + 2:begin + Result.X := Left+edtMois2.Left+x1; + Result.Y := Top+edtMois2.Top+y1; + end; + 3:begin + Result.X := Left+edtMois3.Left+x3; + Result.Y := Top+edtMois3.Top+y1; + end; + 4:begin + Result.X := Left+edtMois4.Left+x45; + Result.Y := Top+edtMois4.Top+y1; + end; + 5:begin + Result.X := Left+edtMois5.Left+x45; + Result.Y := Top+edtMois5.Top+y1; + end; + 6:begin + Result.X := Left+edtManCoef1.Left+x1; + Result.Y := Top+edtManCoef1.Top+y2; + end; + 7:begin + Result.X := Left+edtManCoef2.Left+x1; + Result.Y := Top+edtManCoef2.Top+y2; + end; + 8:begin + Result.X := Left+edtManCoef3.Left+x3; + Result.Y := Top+edtManCoef3.Top+y2; + end; + 9:begin + Result.X := Left+edtManCoef4.Left+x45; + Result.Y := Top+edtManCoef4.Top+y2; + end; + 10:begin + Result.X := Left+edtManCoef5.Left+x45; + Result.Y := Top+edtManCoef5.Top+y2; + end; + 11:begin + Result.X := Left+edtIp.Left+edtIp.Width+35; + Result.Y := Top+edtIp.Top+edtIp.Height+70; + end; + 12:begin + Result.X := Left+edtPort.Left+edtPort.Width+30; + Result.Y := Top+edtPort.Top+edtPort.Height+70; + end; + 13:begin + Result.X := Left+edtTime1.Left+edtTime1.Width+35; + Result.Y := Top+edtTime1.Top+edtTime1.Height+190; + end; + 14:begin + Result.X := Left+edtTime2.Left+edtTime2.Width+35; + Result.Y := Top+edtTime2.Top+edtTime2.Height+190; + end; + 15:begin + Result.X := Left+edtWeight1.Left+edtWeight1.Width+5; + Result.Y := Top+edtWeight1.Top+edtWeight1.Height-50; + end; + 16:begin + Result.X := Left+edtWeight2.Left+edtWeight2.Width+5; + Result.Y := Top+edtWeight2.Top+edtWeight2.Height-50; + end; + 17:begin + Result.X := Left+edtWeight3.Left-475; + Result.Y := Top+edtWeight3.Top+edtWeight3.Height-50; + end; + 18:begin + Result.X := Left+edtWeight3.Left-220; + Result.Y := Top+edtWeight3.Top+edtWeight3.Height-120; + end; + 19:begin + Result.X := Left+edtWeight3.Left-220; + Result.Y := Top+edtWeight3.Top+edtWeight3.Height-60; + end; + 20:begin + Result.X := Left+edtVolume.Left+edtVolume.Width+5; + Result.Y := Top+edtVolume.Top+edtVolume.Height-45; + end; + 21:begin + Result.X := Left+edtTare.Left+edtTare.Width+5; + Result.Y := Top+edtTare.Top+edtTare.Height-45; + end; + 22:begin + Result.X := Left+edtDelay.Left+edtDelay.Width+35; + Result.Y := Top+edtDelay.Top+edtDelay.Height+140; + end; + 23:begin + Result.X := Left+edtPassword.Left+35; + Result.Y := Top+edtPassword.Top+210; + end; + 24:begin + Result.X := Left+edtManVal.Left+x1; + Result.Y := Top+edtManVal.Top-120; + end; + 25:begin + Result.X := Left+edtIntercept.Left+x1; + Result.Y := Top+edtIntercept.Top-180; + end; + 26:begin + Result.X := Left+edtHeartIp.Left+40; + Result.Y := Top+edtHeartIp.Top+120; + end; + 27:begin + Result.X := Left+edtHeartPort.Left+40; + Result.Y := Top+edtHeartPort.Top+120; + end; + end; + end; +end; + +//------- 系统授权相关函数 ----------------------------------------------------- +//计算本机机器码,输出机器码密文 +function GetMachineCode():String; +var + ss : string; +begin + SetCPU(GetCurrentProcess,1); + ss := GetCnCPUID(); + //生成一个机器码 + Result := EncryStrHex(ss, sConfig); +end; + +//授权文件校验,返回校验结果 +//入参:sfilename-校验文件 +// sCode-计算本机机器码 +//返回:true-校验成功;false-校验失败 +function CheckLicense(sFilename, sCode:String):Boolean; +var + i : Integer; + sDecry : String; //解密后的明文 + sl : TStringList; +begin + //容错处理 + if not FileExists(sFileName) then begin + Result := false; + Exit; + end; + + //获取密文 + sl := TStringlist.Create(); + try + sl.LoadFromFile(sFilename); + sDecry := Trim(sl.Text); + finally + FreeAndNil(sl); + end; + + //对密文信息进行解码,按默认level=8 + for i:=1 to 8 do + sDecry := DecryStrHex(sDecry, sConfig); //编码,生成明文 + + //获取RegCode+RegDate+RegLevel+RegType+RegKey 机器码 + sDESMachineCode := SplitStr(sDecry,' ',0); + sDESDate := SplitStr(sDecry,' ',1); + sDESLevel := SplitStr(sDecry,' ',2); + sDESType := SplitStr(sDecry,' ',3); + sDESKey := SplitStr(sDecry,' ',4); + + //返回比较机器码 + Result := AnsiSameStr(sCode, sDESMachineCode); +end; +//License授权检查模块,如未注册则自动退出 +procedure RegCheckMode(); +var + sl : TStringList; + sLicFile, sMchCod, sLicText : String; +begin + //======验证授权文件=============================== + sLicFile := glAppPath + LICENSE_FILE; + sMchCod := GetMachineCode(); + if CheckLicense(sLicFile, sMchCod) then + glRegSuccess := true + else begin + //存注册码 + sl := TStringList.Create(); + sl.Add('机器码:' + sMchCod); + sl.Add('生成日期:' + FormatDateTime('yyyy-mm-dd hh:nn:ss',Now())); + sl.SaveToFile(glAppPath+'机器码.txt'); + FreeAndNil(sl); + //提示要获取授权文件 + glRegSuccess := false; //注册失败,调整标志,准备释放退出定时器 + sLicText := '警告:系统尚未注册,已在软件目录生成 [机器码] 文件,请将该文件提供给系统供应商,以获取正式授权文件!'; + MessageBox(frmMain.handle,PChar(sLicText),'注册提示对话框',MB_OK+MB_ICONWARNING); + //开启退出定时器, 0.5s内退出 + dm.tmRegFault.Enabled := true; + end; +end; + +//静默授权检查模块 +procedure RegCheck1Mode(); +var + sLicFile, sMchCod : String; +begin + sLicFile := glAppPath + LICENSE_FILE; + sMchCod := GetMachineCode(); + if not CheckLicense(sLicFile, sMchCod) then + dm.tmRegFault.Enabled := true; +end; + +//------------------------------------------------------------------------------ +function GetLastNum(const FileName: string): Integer; +var + FileStream: TextFile; + LastDataLine,Line,Fields: string; +begin + Result := 0; + // 检查文件是否存在 + if not FileExists(FileName) then Exit; + + // 打开文件 + AssignFile(FileStream, FileName); + try + Reset(FileStream); + // 跳过标题行 + if not Eof(FileStream) then ReadLn(FileStream); + // 读取文件的每一行 + LastDataLine := ''; + while not Eof(FileStream) do begin + ReadLn(FileStream, Line); + if Line <> '' then + LastDataLine := Trim(Line); + end; + // 解析最后一行 + if LastDataLine <> '' then begin + Fields := SplitStr(LastDataLine,',',0); + Result := StrToIntDef(Fields,0); + end; + finally + CloseFile(FileStream); + end; +end; + +// 将检测结果保存到 csv文件 +procedure WriteCsvFile(name: string; mois,temp,water: Double); +var + pMyFile: textFile; + sfile,sTitle,sMsg,time : string; + no : integer; +begin + //初始化路径和标题 + sFile := smp.dir + smp.prefix + FormatDateTime('yyyymmdd', Now) + '.csv'; + sTitle:= '序号,样本信息,含水率,温度,湿度,日期'; + + //读取文件历史no序号 + no := GetLastNum(sFile)+1; + time := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now); + sMsg := Format('%d,%s,%.2f,%.2f,%.2f,%s', [no,name,mois,temp,water,time]); + try + AssignFile(pMyFile,sFile); + if FileExists(sFile) then + Append(pMyFile) + else begin + ReWrite(pMyFile); + WriteLn(pMyFile,sTitle); //新建csv,先写入标题 + end; + WriteLn(pMyFile,sMsg); //写入内容 + finally + CloseFile(pMyFile); + end; +end; + +//刷新设备故障码 +function RefashFaultCode(cod:Integer):string; +var + str : string; +begin + //翻译cod + case cod of + -1:str := '通讯故障'; + 0: str := '正常'; + 1: str := '上阀门关故障'; + 2: str := '下阀门关故障'; + 3: str := '双阀门关故障'; + 4: str := '上阀门开故障'; + 5: str := '上阀门开关故障'; + 6: str := '上阀门开、下阀门关故障'; + 7: str := '上阀门开关、下阀门关故障'; + 8: str := '下阀门开故障'; + 9: str := '下阀门开、上阀门关故障'; + 10: str := '下阀门开关故障'; + 11: str := '下阀门开关、上阀门关故障'; + 12: str := '双阀门开故障'; + 13: str := '上阀门开关、下阀门开故障'; + 14: str := '下阀门开关、上阀门开故障'; + 15: str := '双阀门开关故障'; + 16: str := '没有粮食在漏斗中'; + 32: str := '抽屉没有放好'; + 256:str := '故障重启'; + else str := '故障未定义'; + end; + + //返回故障字符串 + result := str; + + //输出到界面 + with frmMain do begin + sLabel72.Caption := Format('设备状态-[%s]',[str]); //更新调整截距界面 + sLabel73.Caption := Format('设备状态-[%s]',[str]); //更新手动检测界面 + sLabel74.Caption := Format('设备状态-[%s]',[str]); //更新自动模式界面 + sLabel75.Caption := Format('设备状态-[%s]',[str]); //更新手动校准界面 + sLabel76.Caption := Format('设备状态-[%s]',[str]); //更新手动模式界面 + sLabel77.Caption := Format('设备状态-[%s]',[str]); //更新仪器维护界面 + + //修改样式 + if cod=0 then begin + sLabel72.Font.Color := clLime; + sLabel73.Font.Color := clLime; + sLabel74.Font.Color := clLime; + sLabel75.Font.Color := clLime; + sLabel76.Font.Color := clLime; + sLabel77.Font.Color := clLime; + end + else if (cod>=1)or(cod<=15) then begin + sLabel72.Font.Color := clRed; + sLabel73.Font.Color := clRed; + sLabel74.Font.Color := clRed; + sLabel75.Font.Color := clRed; + sLabel76.Font.Color := clRed; + sLabel77.Font.Color := clRed; + end + else begin + sLabel72.Font.Color := clSilver; + sLabel73.Font.Color := clSilver; + sLabel74.Font.Color := clSilver; + sLabel75.Font.Color := clSilver; + sLabel76.Font.Color := clSilver; + sLabel77.Font.Color := clSilver; + end; + + //强制刷新标签 + sLabel72.Repaint; + sLabel73.Repaint; + sLabel74.Repaint; + sLabel75.Repaint; + sLabel76.Repaint; + sLabel77.Repaint; + end; +end; + +//自动模式下,刷新设备故障码 +function AutoFaultCode(cod:Integer):string; +var + str : string; +begin + //翻译cod + case cod of + -1:str := '通讯故障'; + 0: str := '未知故障'; + 1: str := '上阀门关故障'; + 2: str := '下阀门关故障'; + 3: str := '双阀门关故障'; + 4: str := '上阀门开故障'; + 5: str := '上阀门开关故障'; + 6: str := '上阀门开、下阀门关故障'; + 7: str := '上阀门开关、下阀门关故障'; + 8: str := '下阀门开故障'; + 9: str := '下阀门开、上阀门关故障'; + 10: str := '下阀门开关故障'; + 11: str := '下阀门开关、上阀门关故障'; + 12: str := '双阀门开故障'; + 13: str := '上阀门开关、下阀门开故障'; + 14: str := '下阀门开关、上阀门开故障'; + 15: str := '双阀门开关故障'; + 16: str := '没有粮食在漏斗中'; + 32: str := '抽屉没有放好'; + 256:str := '故障重启'; + else str := '故障未定义'; + end; + //输出到界面 + with frmMain do begin + //更新自动模式界面 + sLabel74.Caption := Format('设备状态-[%s]',[str]); + //修改样式 + sLabel74.Font.Color := clRed; + sLabel74.Repaint; + end; + //返回故障字符串 + result := str; +end; + +end. -- Gitblit v1.9.3